OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/bootstrapper.h" | 9 #include "src/bootstrapper.h" |
10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
11 #include "src/regexp-macro-assembler.h" | 11 #include "src/regexp-macro-assembler.h" |
12 #include "src/stub-cache.h" | 12 #include "src/stub-cache.h" |
13 | 13 |
14 namespace v8 { | 14 namespace v8 { |
15 namespace internal { | 15 namespace internal { |
16 | 16 |
17 | 17 |
18 void FastNewClosureStub::InitializeInterfaceDescriptor( | 18 void FastNewClosureStub::InitializeInterfaceDescriptor( |
19 CodeStubInterfaceDescriptor* descriptor) { | 19 CodeStubInterfaceDescriptor* descriptor) { |
20 Register registers[] = { cp, r2 }; | 20 Register registers[] = { cp, r2 }; |
21 descriptor->Initialize( | 21 descriptor->Initialize( |
22 ARRAY_SIZE(registers), registers, | 22 MajorKey(), ARRAY_SIZE(registers), registers, |
23 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); | 23 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); |
24 } | 24 } |
25 | 25 |
26 | 26 |
27 void FastNewContextStub::InitializeInterfaceDescriptor( | 27 void FastNewContextStub::InitializeInterfaceDescriptor( |
28 CodeStubInterfaceDescriptor* descriptor) { | 28 CodeStubInterfaceDescriptor* descriptor) { |
29 Register registers[] = { cp, r1 }; | 29 Register registers[] = { cp, r1 }; |
30 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 30 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
31 } | 31 } |
32 | 32 |
33 | 33 |
34 void ToNumberStub::InitializeInterfaceDescriptor( | 34 void ToNumberStub::InitializeInterfaceDescriptor( |
35 CodeStubInterfaceDescriptor* descriptor) { | 35 CodeStubInterfaceDescriptor* descriptor) { |
36 Register registers[] = { cp, r0 }; | 36 Register registers[] = { cp, r0 }; |
37 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 37 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
38 } | 38 } |
39 | 39 |
40 | 40 |
41 void NumberToStringStub::InitializeInterfaceDescriptor( | 41 void NumberToStringStub::InitializeInterfaceDescriptor( |
42 CodeStubInterfaceDescriptor* descriptor) { | 42 CodeStubInterfaceDescriptor* descriptor) { |
43 Register registers[] = { cp, r0 }; | 43 Register registers[] = { cp, r0 }; |
44 descriptor->Initialize( | 44 descriptor->Initialize( |
45 ARRAY_SIZE(registers), registers, | 45 MajorKey(), ARRAY_SIZE(registers), registers, |
46 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); | 46 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); |
47 } | 47 } |
48 | 48 |
49 | 49 |
50 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( | 50 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( |
51 CodeStubInterfaceDescriptor* descriptor) { | 51 CodeStubInterfaceDescriptor* descriptor) { |
52 Register registers[] = { cp, r3, r2, r1 }; | 52 Register registers[] = { cp, r3, r2, r1 }; |
53 Representation representations[] = { | 53 Representation representations[] = { |
54 Representation::Tagged(), | 54 Representation::Tagged(), |
55 Representation::Tagged(), | 55 Representation::Tagged(), |
56 Representation::Smi(), | 56 Representation::Smi(), |
57 Representation::Tagged() }; | 57 Representation::Tagged() }; |
58 descriptor->Initialize( | 58 descriptor->Initialize( |
59 ARRAY_SIZE(registers), registers, | 59 MajorKey(), ARRAY_SIZE(registers), registers, |
60 Runtime::FunctionForId( | 60 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry, |
61 Runtime::kCreateArrayLiteralStubBailout)->entry, | |
62 representations); | 61 representations); |
63 } | 62 } |
64 | 63 |
65 | 64 |
66 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( | 65 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( |
67 CodeStubInterfaceDescriptor* descriptor) { | 66 CodeStubInterfaceDescriptor* descriptor) { |
68 Register registers[] = { cp, r3, r2, r1, r0 }; | 67 Register registers[] = { cp, r3, r2, r1, r0 }; |
69 descriptor->Initialize( | 68 descriptor->Initialize( |
70 ARRAY_SIZE(registers), registers, | 69 MajorKey(), ARRAY_SIZE(registers), registers, |
71 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); | 70 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); |
72 } | 71 } |
73 | 72 |
74 | 73 |
75 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | 74 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
76 CodeStubInterfaceDescriptor* descriptor) { | 75 CodeStubInterfaceDescriptor* descriptor) { |
77 Register registers[] = { cp, r2, r3 }; | 76 Register registers[] = { cp, r2, r3 }; |
78 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 77 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
79 } | 78 } |
80 | 79 |
81 | 80 |
| 81 void InstanceofStub::InitializeInterfaceDescriptor( |
| 82 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 83 Register registers[] = {cp, left(), right()}; |
| 84 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 85 } |
| 86 |
| 87 |
| 88 void CallFunctionStub::InitializeInterfaceDescriptor( |
| 89 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 90 // r1 function the function to call |
| 91 Register registers[] = {cp, r1}; |
| 92 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 93 } |
| 94 |
| 95 |
| 96 void CallConstructStub::InitializeInterfaceDescriptor( |
| 97 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 98 // r0 : number of arguments |
| 99 // r1 : the function to call |
| 100 // r2 : feedback vector |
| 101 // r3 : (only if r2 is not the megamorphic symbol) slot in feedback |
| 102 // vector (Smi) |
| 103 // TODO(turbofan): So far we don't gather type feedback and hence skip the |
| 104 // slot parameter, but ArrayConstructStub needs the vector to be undefined. |
| 105 Register registers[] = {cp, r0, r1, r2}; |
| 106 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 107 } |
| 108 |
| 109 |
82 void RegExpConstructResultStub::InitializeInterfaceDescriptor( | 110 void RegExpConstructResultStub::InitializeInterfaceDescriptor( |
83 CodeStubInterfaceDescriptor* descriptor) { | 111 CodeStubInterfaceDescriptor* descriptor) { |
84 Register registers[] = { cp, r2, r1, r0 }; | 112 Register registers[] = { cp, r2, r1, r0 }; |
85 descriptor->Initialize( | 113 descriptor->Initialize( |
86 ARRAY_SIZE(registers), registers, | 114 MajorKey(), ARRAY_SIZE(registers), registers, |
87 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); | 115 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); |
88 } | 116 } |
89 | 117 |
90 | 118 |
91 void TransitionElementsKindStub::InitializeInterfaceDescriptor( | 119 void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
92 CodeStubInterfaceDescriptor* descriptor) { | 120 CodeStubInterfaceDescriptor* descriptor) { |
93 Register registers[] = { cp, r0, r1 }; | 121 Register registers[] = { cp, r0, r1 }; |
94 Address entry = | 122 Address entry = |
95 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; | 123 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry; |
96 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 124 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
97 FUNCTION_ADDR(entry)); | 125 FUNCTION_ADDR(entry)); |
98 } | 126 } |
99 | 127 |
100 | 128 |
101 void CompareNilICStub::InitializeInterfaceDescriptor( | 129 void CompareNilICStub::InitializeInterfaceDescriptor( |
102 CodeStubInterfaceDescriptor* descriptor) { | 130 CodeStubInterfaceDescriptor* descriptor) { |
103 Register registers[] = { cp, r0 }; | 131 Register registers[] = { cp, r0 }; |
104 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 132 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
105 FUNCTION_ADDR(CompareNilIC_Miss)); | 133 FUNCTION_ADDR(CompareNilIC_Miss)); |
106 descriptor->SetMissHandler( | 134 descriptor->SetMissHandler( |
107 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); | 135 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); |
108 } | 136 } |
109 | 137 |
110 | 138 |
111 const Register InterfaceDescriptor::ContextRegister() { return cp; } | 139 const Register InterfaceDescriptor::ContextRegister() { return cp; } |
112 | 140 |
113 | 141 |
114 static void InitializeArrayConstructorDescriptor( | 142 static void InitializeArrayConstructorDescriptor( |
115 CodeStubInterfaceDescriptor* descriptor, | 143 CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, |
116 int constant_stack_parameter_count) { | 144 int constant_stack_parameter_count) { |
117 // register state | 145 // register state |
118 // cp -- context | 146 // cp -- context |
119 // r0 -- number of arguments | 147 // r0 -- number of arguments |
120 // r1 -- function | 148 // r1 -- function |
121 // r2 -- allocation site with elements kind | 149 // r2 -- allocation site with elements kind |
122 Address deopt_handler = Runtime::FunctionForId( | 150 Address deopt_handler = Runtime::FunctionForId( |
123 Runtime::kArrayConstructor)->entry; | 151 Runtime::kArrayConstructor)->entry; |
124 | 152 |
125 if (constant_stack_parameter_count == 0) { | 153 if (constant_stack_parameter_count == 0) { |
126 Register registers[] = { cp, r1, r2 }; | 154 Register registers[] = { cp, r1, r2 }; |
127 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 155 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, |
128 deopt_handler, | 156 deopt_handler, NULL, constant_stack_parameter_count, |
129 NULL, | |
130 constant_stack_parameter_count, | |
131 JS_FUNCTION_STUB_MODE); | 157 JS_FUNCTION_STUB_MODE); |
132 } else { | 158 } else { |
133 // stack param count needs (constructor pointer, and single argument) | 159 // stack param count needs (constructor pointer, and single argument) |
134 Register registers[] = { cp, r1, r2, r0 }; | 160 Register registers[] = { cp, r1, r2, r0 }; |
135 Representation representations[] = { | 161 Representation representations[] = { |
136 Representation::Tagged(), | 162 Representation::Tagged(), |
137 Representation::Tagged(), | 163 Representation::Tagged(), |
138 Representation::Tagged(), | 164 Representation::Tagged(), |
139 Representation::Integer32() }; | 165 Representation::Integer32() }; |
140 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 166 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, r0, |
141 r0, | 167 deopt_handler, representations, |
142 deopt_handler, | |
143 representations, | |
144 constant_stack_parameter_count, | 168 constant_stack_parameter_count, |
145 JS_FUNCTION_STUB_MODE, | 169 JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); |
146 PASS_ARGUMENTS); | |
147 } | 170 } |
148 } | 171 } |
149 | 172 |
150 | 173 |
151 static void InitializeInternalArrayConstructorDescriptor( | 174 static void InitializeInternalArrayConstructorDescriptor( |
152 CodeStubInterfaceDescriptor* descriptor, | 175 CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, |
153 int constant_stack_parameter_count) { | 176 int constant_stack_parameter_count) { |
154 // register state | 177 // register state |
155 // cp -- context | 178 // cp -- context |
156 // r0 -- number of arguments | 179 // r0 -- number of arguments |
157 // r1 -- constructor function | 180 // r1 -- constructor function |
158 Address deopt_handler = Runtime::FunctionForId( | 181 Address deopt_handler = Runtime::FunctionForId( |
159 Runtime::kInternalArrayConstructor)->entry; | 182 Runtime::kInternalArrayConstructor)->entry; |
160 | 183 |
161 if (constant_stack_parameter_count == 0) { | 184 if (constant_stack_parameter_count == 0) { |
162 Register registers[] = { cp, r1 }; | 185 Register registers[] = { cp, r1 }; |
163 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 186 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, |
164 deopt_handler, | 187 deopt_handler, NULL, constant_stack_parameter_count, |
165 NULL, | |
166 constant_stack_parameter_count, | |
167 JS_FUNCTION_STUB_MODE); | 188 JS_FUNCTION_STUB_MODE); |
168 } else { | 189 } else { |
169 // stack param count needs (constructor pointer, and single argument) | 190 // stack param count needs (constructor pointer, and single argument) |
170 Register registers[] = { cp, r1, r0 }; | 191 Register registers[] = { cp, r1, r0 }; |
171 Representation representations[] = { | 192 Representation representations[] = { |
172 Representation::Tagged(), | 193 Representation::Tagged(), |
173 Representation::Tagged(), | 194 Representation::Tagged(), |
174 Representation::Integer32() }; | 195 Representation::Integer32() }; |
175 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 196 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, r0, |
176 r0, | 197 deopt_handler, representations, |
177 deopt_handler, | |
178 representations, | |
179 constant_stack_parameter_count, | 198 constant_stack_parameter_count, |
180 JS_FUNCTION_STUB_MODE, | 199 JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); |
181 PASS_ARGUMENTS); | |
182 } | 200 } |
183 } | 201 } |
184 | 202 |
185 | 203 |
186 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 204 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
187 CodeStubInterfaceDescriptor* descriptor) { | 205 CodeStubInterfaceDescriptor* descriptor) { |
188 InitializeArrayConstructorDescriptor(descriptor, 0); | 206 InitializeArrayConstructorDescriptor(MajorKey(), descriptor, 0); |
189 } | 207 } |
190 | 208 |
191 | 209 |
192 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 210 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
193 CodeStubInterfaceDescriptor* descriptor) { | 211 CodeStubInterfaceDescriptor* descriptor) { |
194 InitializeArrayConstructorDescriptor(descriptor, 1); | 212 InitializeArrayConstructorDescriptor(MajorKey(), descriptor, 1); |
195 } | 213 } |
196 | 214 |
197 | 215 |
198 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 216 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
199 CodeStubInterfaceDescriptor* descriptor) { | 217 CodeStubInterfaceDescriptor* descriptor) { |
200 InitializeArrayConstructorDescriptor(descriptor, -1); | 218 InitializeArrayConstructorDescriptor(MajorKey(), descriptor, -1); |
201 } | 219 } |
202 | 220 |
203 | 221 |
204 void ToBooleanStub::InitializeInterfaceDescriptor( | 222 void ToBooleanStub::InitializeInterfaceDescriptor( |
205 CodeStubInterfaceDescriptor* descriptor) { | 223 CodeStubInterfaceDescriptor* descriptor) { |
206 Register registers[] = { cp, r0 }; | 224 Register registers[] = { cp, r0 }; |
207 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 225 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
208 FUNCTION_ADDR(ToBooleanIC_Miss)); | 226 FUNCTION_ADDR(ToBooleanIC_Miss)); |
209 descriptor->SetMissHandler( | 227 descriptor->SetMissHandler( |
210 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); | 228 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); |
211 } | 229 } |
212 | 230 |
213 | 231 |
214 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 232 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
215 CodeStubInterfaceDescriptor* descriptor) { | 233 CodeStubInterfaceDescriptor* descriptor) { |
216 InitializeInternalArrayConstructorDescriptor(descriptor, 0); | 234 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 0); |
217 } | 235 } |
218 | 236 |
219 | 237 |
220 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 238 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
221 CodeStubInterfaceDescriptor* descriptor) { | 239 CodeStubInterfaceDescriptor* descriptor) { |
222 InitializeInternalArrayConstructorDescriptor(descriptor, 1); | 240 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 1); |
223 } | 241 } |
224 | 242 |
225 | 243 |
226 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 244 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
227 CodeStubInterfaceDescriptor* descriptor) { | 245 CodeStubInterfaceDescriptor* descriptor) { |
228 InitializeInternalArrayConstructorDescriptor(descriptor, -1); | 246 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, -1); |
229 } | 247 } |
230 | 248 |
231 | 249 |
232 void BinaryOpICStub::InitializeInterfaceDescriptor( | 250 void BinaryOpICStub::InitializeInterfaceDescriptor( |
233 CodeStubInterfaceDescriptor* descriptor) { | 251 CodeStubInterfaceDescriptor* descriptor) { |
234 Register registers[] = { cp, r1, r0 }; | 252 Register registers[] = { cp, r1, r0 }; |
235 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 253 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
236 FUNCTION_ADDR(BinaryOpIC_Miss)); | 254 FUNCTION_ADDR(BinaryOpIC_Miss)); |
237 descriptor->SetMissHandler( | 255 descriptor->SetMissHandler( |
238 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); | 256 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); |
239 } | 257 } |
240 | 258 |
241 | 259 |
242 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( | 260 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( |
243 CodeStubInterfaceDescriptor* descriptor) { | 261 CodeStubInterfaceDescriptor* descriptor) { |
244 Register registers[] = { cp, r2, r1, r0 }; | 262 Register registers[] = { cp, r2, r1, r0 }; |
245 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 263 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
246 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); | 264 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); |
247 } | 265 } |
248 | 266 |
249 | 267 |
250 void StringAddStub::InitializeInterfaceDescriptor( | 268 void StringAddStub::InitializeInterfaceDescriptor( |
251 CodeStubInterfaceDescriptor* descriptor) { | 269 CodeStubInterfaceDescriptor* descriptor) { |
252 Register registers[] = { cp, r1, r0 }; | 270 Register registers[] = { cp, r1, r0 }; |
253 descriptor->Initialize( | 271 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
254 ARRAY_SIZE(registers), registers, | 272 Runtime::FunctionForId(Runtime::kStringAdd)->entry); |
255 Runtime::FunctionForId(Runtime::kStringAdd)->entry); | |
256 } | 273 } |
257 | 274 |
258 | 275 |
259 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { | 276 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { |
260 static PlatformInterfaceDescriptor default_descriptor = | 277 static PlatformInterfaceDescriptor default_descriptor = |
261 PlatformInterfaceDescriptor(CAN_INLINE_TARGET_ADDRESS); | 278 PlatformInterfaceDescriptor(CAN_INLINE_TARGET_ADDRESS); |
262 | 279 |
263 static PlatformInterfaceDescriptor noInlineDescriptor = | 280 static PlatformInterfaceDescriptor noInlineDescriptor = |
264 PlatformInterfaceDescriptor(NEVER_INLINE_TARGET_ADDRESS); | 281 PlatformInterfaceDescriptor(NEVER_INLINE_TARGET_ADDRESS); |
265 | 282 |
(...skipping 1399 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1665 // Expected input (depending on whether args are in registers or on the stack): | 1682 // Expected input (depending on whether args are in registers or on the stack): |
1666 // * object: r0 or at sp + 1 * kPointerSize. | 1683 // * object: r0 or at sp + 1 * kPointerSize. |
1667 // * function: r1 or at sp. | 1684 // * function: r1 or at sp. |
1668 // | 1685 // |
1669 // An inlined call site may have been generated before calling this stub. | 1686 // An inlined call site may have been generated before calling this stub. |
1670 // In this case the offset to the inline sites to patch are passed in r5 and r6. | 1687 // In this case the offset to the inline sites to patch are passed in r5 and r6. |
1671 // (See LCodeGen::DoInstanceOfKnownGlobal) | 1688 // (See LCodeGen::DoInstanceOfKnownGlobal) |
1672 void InstanceofStub::Generate(MacroAssembler* masm) { | 1689 void InstanceofStub::Generate(MacroAssembler* masm) { |
1673 // Call site inlining and patching implies arguments in registers. | 1690 // Call site inlining and patching implies arguments in registers. |
1674 ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck()); | 1691 ASSERT(HasArgsInRegisters() || !HasCallSiteInlineCheck()); |
1675 // ReturnTrueFalse is only implemented for inlined call sites. | |
1676 ASSERT(!ReturnTrueFalseObject() || HasCallSiteInlineCheck()); | |
1677 | 1692 |
1678 // Fixed register usage throughout the stub: | 1693 // Fixed register usage throughout the stub: |
1679 const Register object = r0; // Object (lhs). | 1694 const Register object = r0; // Object (lhs). |
1680 Register map = r3; // Map of the object. | 1695 Register map = r3; // Map of the object. |
1681 const Register function = r1; // Function (rhs). | 1696 const Register function = r1; // Function (rhs). |
1682 const Register prototype = r4; // Prototype of the function. | 1697 const Register prototype = r4; // Prototype of the function. |
1683 const Register scratch = r2; | 1698 const Register scratch = r2; |
1684 | 1699 |
1685 Label slow, loop, is_instance, is_not_instance, not_js_object; | 1700 Label slow, loop, is_instance, is_not_instance, not_js_object; |
1686 | 1701 |
1687 if (!HasArgsInRegisters()) { | 1702 if (!HasArgsInRegisters()) { |
1688 __ ldr(object, MemOperand(sp, 1 * kPointerSize)); | 1703 __ ldr(object, MemOperand(sp, 1 * kPointerSize)); |
1689 __ ldr(function, MemOperand(sp, 0)); | 1704 __ ldr(function, MemOperand(sp, 0)); |
1690 } | 1705 } |
1691 | 1706 |
1692 // Check that the left hand is a JS object and load map. | 1707 // Check that the left hand is a JS object and load map. |
1693 __ JumpIfSmi(object, ¬_js_object); | 1708 __ JumpIfSmi(object, ¬_js_object); |
1694 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 1709 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
1695 | 1710 |
1696 // If there is a call site cache don't look in the global cache, but do the | 1711 // If there is a call site cache don't look in the global cache, but do the |
1697 // real lookup and update the call site cache. | 1712 // real lookup and update the call site cache. |
1698 if (!HasCallSiteInlineCheck()) { | 1713 if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { |
1699 Label miss; | 1714 Label miss; |
1700 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); | 1715 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
1701 __ b(ne, &miss); | 1716 __ b(ne, &miss); |
1702 __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); | 1717 __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); |
1703 __ b(ne, &miss); | 1718 __ b(ne, &miss); |
1704 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); | 1719 __ LoadRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); |
1705 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1720 __ Ret(HasArgsInRegisters() ? 0 : 2); |
1706 | 1721 |
1707 __ bind(&miss); | 1722 __ bind(&miss); |
1708 } | 1723 } |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1744 // Loop through the prototype chain looking for the function prototype. | 1759 // Loop through the prototype chain looking for the function prototype. |
1745 __ LoadRoot(scratch2, Heap::kNullValueRootIndex); | 1760 __ LoadRoot(scratch2, Heap::kNullValueRootIndex); |
1746 __ bind(&loop); | 1761 __ bind(&loop); |
1747 __ cmp(scratch, Operand(prototype)); | 1762 __ cmp(scratch, Operand(prototype)); |
1748 __ b(eq, &is_instance); | 1763 __ b(eq, &is_instance); |
1749 __ cmp(scratch, scratch2); | 1764 __ cmp(scratch, scratch2); |
1750 __ b(eq, &is_not_instance); | 1765 __ b(eq, &is_not_instance); |
1751 __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); | 1766 __ ldr(scratch, FieldMemOperand(scratch, HeapObject::kMapOffset)); |
1752 __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); | 1767 __ ldr(scratch, FieldMemOperand(scratch, Map::kPrototypeOffset)); |
1753 __ jmp(&loop); | 1768 __ jmp(&loop); |
| 1769 Factory* factory = isolate()->factory(); |
1754 | 1770 |
1755 __ bind(&is_instance); | 1771 __ bind(&is_instance); |
1756 if (!HasCallSiteInlineCheck()) { | 1772 if (!HasCallSiteInlineCheck()) { |
1757 __ mov(r0, Operand(Smi::FromInt(0))); | 1773 __ mov(r0, Operand(Smi::FromInt(0))); |
1758 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); | 1774 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); |
| 1775 if (ReturnTrueFalseObject()) { |
| 1776 __ Move(r0, factory->true_value()); |
| 1777 } |
1759 } else { | 1778 } else { |
1760 // Patch the call site to return true. | 1779 // Patch the call site to return true. |
1761 __ LoadRoot(r0, Heap::kTrueValueRootIndex); | 1780 __ LoadRoot(r0, Heap::kTrueValueRootIndex); |
1762 // The bool_load_offset was stored in r6 | 1781 // The bool_load_offset was stored in r6 |
1763 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). | 1782 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). |
1764 const Register bool_load_offset = r6; | 1783 const Register bool_load_offset = r6; |
1765 __ sub(r9, lr, bool_load_offset); | 1784 __ sub(r9, lr, bool_load_offset); |
1766 // Get the boolean result location in scratch and patch it. | 1785 // Get the boolean result location in scratch and patch it. |
1767 __ GetRelocatedValueLocation(r9, scratch, scratch2); | 1786 __ GetRelocatedValueLocation(r9, scratch, scratch2); |
1768 __ str(r0, MemOperand(scratch)); | 1787 __ str(r0, MemOperand(scratch)); |
1769 | 1788 |
1770 if (!ReturnTrueFalseObject()) { | 1789 if (!ReturnTrueFalseObject()) { |
1771 __ mov(r0, Operand(Smi::FromInt(0))); | 1790 __ mov(r0, Operand(Smi::FromInt(0))); |
1772 } | 1791 } |
1773 } | 1792 } |
1774 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1793 __ Ret(HasArgsInRegisters() ? 0 : 2); |
1775 | 1794 |
1776 __ bind(&is_not_instance); | 1795 __ bind(&is_not_instance); |
1777 if (!HasCallSiteInlineCheck()) { | 1796 if (!HasCallSiteInlineCheck()) { |
1778 __ mov(r0, Operand(Smi::FromInt(1))); | 1797 __ mov(r0, Operand(Smi::FromInt(1))); |
1779 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); | 1798 __ StoreRoot(r0, Heap::kInstanceofCacheAnswerRootIndex); |
| 1799 if (ReturnTrueFalseObject()) { |
| 1800 __ Move(r0, factory->false_value()); |
| 1801 } |
1780 } else { | 1802 } else { |
1781 // Patch the call site to return false. | 1803 // Patch the call site to return false. |
1782 __ LoadRoot(r0, Heap::kFalseValueRootIndex); | 1804 __ LoadRoot(r0, Heap::kFalseValueRootIndex); |
1783 // The bool_load_offset was stored in r6 | 1805 // The bool_load_offset was stored in r6 |
1784 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). | 1806 // (See LCodeGen::DoDeferredLInstanceOfKnownGlobal). |
1785 const Register bool_load_offset = r6; | 1807 const Register bool_load_offset = r6; |
1786 __ sub(r9, lr, bool_load_offset); | 1808 __ sub(r9, lr, bool_load_offset); |
1787 ; | 1809 ; |
1788 // Get the boolean result location in scratch and patch it. | 1810 // Get the boolean result location in scratch and patch it. |
1789 __ GetRelocatedValueLocation(r9, scratch, scratch2); | 1811 __ GetRelocatedValueLocation(r9, scratch, scratch2); |
1790 __ str(r0, MemOperand(scratch)); | 1812 __ str(r0, MemOperand(scratch)); |
1791 | 1813 |
1792 if (!ReturnTrueFalseObject()) { | 1814 if (!ReturnTrueFalseObject()) { |
1793 __ mov(r0, Operand(Smi::FromInt(1))); | 1815 __ mov(r0, Operand(Smi::FromInt(1))); |
1794 } | 1816 } |
1795 } | 1817 } |
1796 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1818 __ Ret(HasArgsInRegisters() ? 0 : 2); |
1797 | 1819 |
1798 Label object_not_null, object_not_null_or_smi; | 1820 Label object_not_null, object_not_null_or_smi; |
1799 __ bind(¬_js_object); | 1821 __ bind(¬_js_object); |
1800 // Before null, smi and string value checks, check that the rhs is a function | 1822 // Before null, smi and string value checks, check that the rhs is a function |
1801 // as for a non-function rhs an exception needs to be thrown. | 1823 // as for a non-function rhs an exception needs to be thrown. |
1802 __ JumpIfSmi(function, &slow); | 1824 __ JumpIfSmi(function, &slow); |
1803 __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE); | 1825 __ CompareObjectType(function, scratch2, scratch, JS_FUNCTION_TYPE); |
1804 __ b(ne, &slow); | 1826 __ b(ne, &slow); |
1805 | 1827 |
1806 // Null is not instance of anything. | 1828 // Null is not instance of anything. |
1807 __ cmp(scratch, Operand(isolate()->factory()->null_value())); | 1829 __ cmp(scratch, Operand(isolate()->factory()->null_value())); |
1808 __ b(ne, &object_not_null); | 1830 __ b(ne, &object_not_null); |
1809 __ mov(r0, Operand(Smi::FromInt(1))); | 1831 if (ReturnTrueFalseObject()) { |
| 1832 __ Move(r0, factory->false_value()); |
| 1833 } else { |
| 1834 __ mov(r0, Operand(Smi::FromInt(1))); |
| 1835 } |
1810 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1836 __ Ret(HasArgsInRegisters() ? 0 : 2); |
1811 | 1837 |
1812 __ bind(&object_not_null); | 1838 __ bind(&object_not_null); |
1813 // Smi values are not instances of anything. | 1839 // Smi values are not instances of anything. |
1814 __ JumpIfNotSmi(object, &object_not_null_or_smi); | 1840 __ JumpIfNotSmi(object, &object_not_null_or_smi); |
1815 __ mov(r0, Operand(Smi::FromInt(1))); | 1841 if (ReturnTrueFalseObject()) { |
| 1842 __ Move(r0, factory->false_value()); |
| 1843 } else { |
| 1844 __ mov(r0, Operand(Smi::FromInt(1))); |
| 1845 } |
1816 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1846 __ Ret(HasArgsInRegisters() ? 0 : 2); |
1817 | 1847 |
1818 __ bind(&object_not_null_or_smi); | 1848 __ bind(&object_not_null_or_smi); |
1819 // String values are not instances of anything. | 1849 // String values are not instances of anything. |
1820 __ IsObjectJSStringType(object, scratch, &slow); | 1850 __ IsObjectJSStringType(object, scratch, &slow); |
1821 __ mov(r0, Operand(Smi::FromInt(1))); | 1851 if (ReturnTrueFalseObject()) { |
| 1852 __ Move(r0, factory->false_value()); |
| 1853 } else { |
| 1854 __ mov(r0, Operand(Smi::FromInt(1))); |
| 1855 } |
1822 __ Ret(HasArgsInRegisters() ? 0 : 2); | 1856 __ Ret(HasArgsInRegisters() ? 0 : 2); |
1823 | 1857 |
1824 // Slow-case. Tail call builtin. | 1858 // Slow-case. Tail call builtin. |
1825 __ bind(&slow); | 1859 __ bind(&slow); |
1826 if (!ReturnTrueFalseObject()) { | 1860 if (!ReturnTrueFalseObject()) { |
1827 if (HasArgsInRegisters()) { | 1861 if (HasArgsInRegisters()) { |
1828 __ Push(r0, r1); | 1862 __ Push(r0, r1); |
1829 } | 1863 } |
1830 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | 1864 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
1831 } else { | 1865 } else { |
(...skipping 3233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5065 MemOperand(fp, 6 * kPointerSize), | 5099 MemOperand(fp, 6 * kPointerSize), |
5066 NULL); | 5100 NULL); |
5067 } | 5101 } |
5068 | 5102 |
5069 | 5103 |
5070 #undef __ | 5104 #undef __ |
5071 | 5105 |
5072 } } // namespace v8::internal | 5106 } } // namespace v8::internal |
5073 | 5107 |
5074 #endif // V8_TARGET_ARCH_ARM | 5108 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |