2 * Copyright (C) 2012 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "GetByIdStatus.h"
29 #include "CodeBlock.h"
30 #include "LowLevelInterpreter.h"
34 GetByIdStatus
GetByIdStatus::computeFromLLInt(CodeBlock
* profiledBlock
, unsigned bytecodeIndex
, Identifier
& ident
)
36 UNUSED_PARAM(profiledBlock
);
37 UNUSED_PARAM(bytecodeIndex
);
40 Instruction
* instruction
= profiledBlock
->instructions().begin() + bytecodeIndex
;
42 if (instruction
[0].u
.opcode
== llint_op_method_check
)
45 Structure
* structure
= instruction
[4].u
.structure
.get();
47 return GetByIdStatus(NoInformation
, StructureSet(), notFound
, false);
49 size_t offset
= structure
->get(*profiledBlock
->globalData(), ident
);
50 if (offset
== notFound
)
51 return GetByIdStatus(NoInformation
, StructureSet(), notFound
, false);
53 return GetByIdStatus(SimpleDirect
, StructureSet(structure
), offset
, false);
55 return GetByIdStatus(NoInformation
, StructureSet(), notFound
, false);
59 GetByIdStatus
GetByIdStatus::computeFor(CodeBlock
* profiledBlock
, unsigned bytecodeIndex
, Identifier
& ident
)
61 UNUSED_PARAM(profiledBlock
);
62 UNUSED_PARAM(bytecodeIndex
);
64 #if ENABLE(JIT) && ENABLE(VALUE_PROFILER)
65 if (!profiledBlock
->numberOfStructureStubInfos())
66 return computeFromLLInt(profiledBlock
, bytecodeIndex
, ident
);
68 // First check if it makes either calls, in which case we want to be super careful, or
69 // if it's not set at all, in which case we punt.
70 StructureStubInfo
& stubInfo
= profiledBlock
->getStubInfo(bytecodeIndex
);
72 return computeFromLLInt(profiledBlock
, bytecodeIndex
, ident
);
74 PolymorphicAccessStructureList
* list
;
76 switch (stubInfo
.accessType
) {
77 case access_get_by_id_self_list
:
78 list
= stubInfo
.u
.getByIdSelfList
.structureList
;
79 listSize
= stubInfo
.u
.getByIdSelfList
.listSize
;
81 case access_get_by_id_proto_list
:
82 list
= stubInfo
.u
.getByIdProtoList
.structureList
;
83 listSize
= stubInfo
.u
.getByIdProtoList
.listSize
;
90 for (int i
= 0; i
< listSize
; ++i
) {
91 if (!list
->list
[i
].isDirect
)
92 return GetByIdStatus(MakesCalls
, StructureSet(), notFound
, true);
95 // Next check if it takes slow case, in which case we want to be kind of careful.
96 if (profiledBlock
->likelyToTakeSlowCase(bytecodeIndex
))
97 return GetByIdStatus(TakesSlowPath
, StructureSet(), notFound
, true);
99 // Finally figure out if we can derive an access strategy.
100 GetByIdStatus result
;
101 result
.m_wasSeenInJIT
= true;
102 switch (stubInfo
.accessType
) {
104 return computeFromLLInt(profiledBlock
, bytecodeIndex
, ident
);
106 case access_get_by_id_self
: {
107 Structure
* structure
= stubInfo
.u
.getByIdSelf
.baseObjectStructure
.get();
108 result
.m_offset
= structure
->get(*profiledBlock
->globalData(), ident
);
110 if (result
.m_offset
!= notFound
)
111 result
.m_structureSet
.add(structure
);
113 if (result
.m_offset
!= notFound
)
114 ASSERT(result
.m_structureSet
.size());
118 case access_get_by_id_self_list
: {
119 PolymorphicAccessStructureList
* list
= stubInfo
.u
.getByIdProtoList
.structureList
;
120 unsigned size
= stubInfo
.u
.getByIdProtoList
.listSize
;
121 for (unsigned i
= 0; i
< size
; ++i
) {
122 ASSERT(list
->list
[i
].isDirect
);
124 Structure
* structure
= list
->list
[i
].base
.get();
125 if (result
.m_structureSet
.contains(structure
))
128 size_t myOffset
= structure
->get(*profiledBlock
->globalData(), ident
);
130 if (myOffset
== notFound
) {
131 result
.m_offset
= notFound
;
136 result
.m_offset
= myOffset
;
137 else if (result
.m_offset
!= myOffset
) {
138 result
.m_offset
= notFound
;
142 result
.m_structureSet
.add(structure
);
145 if (result
.m_offset
!= notFound
)
146 ASSERT(result
.m_structureSet
.size());
151 ASSERT(result
.m_offset
== notFound
);
155 if (result
.m_offset
== notFound
) {
156 result
.m_state
= TakesSlowPath
;
157 result
.m_structureSet
.clear();
159 result
.m_state
= SimpleDirect
;
163 return GetByIdStatus(NoInformation
, StructureSet(), notFound
, false);
164 #endif // ENABLE(JIT)