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_IA32 | 7 #if V8_TARGET_ARCH_IA32 |
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/codegen.h" | 11 #include "src/codegen.h" |
12 #include "src/isolate.h" | 12 #include "src/isolate.h" |
13 #include "src/jsregexp.h" | 13 #include "src/jsregexp.h" |
14 #include "src/regexp-macro-assembler.h" | 14 #include "src/regexp-macro-assembler.h" |
15 #include "src/runtime.h" | 15 #include "src/runtime.h" |
16 #include "src/stub-cache.h" | 16 #include "src/stub-cache.h" |
17 | 17 |
18 namespace v8 { | 18 namespace v8 { |
19 namespace internal { | 19 namespace internal { |
20 | 20 |
21 | 21 |
22 void FastNewClosureStub::InitializeInterfaceDescriptor( | 22 void FastNewClosureStub::InitializeInterfaceDescriptor( |
23 CodeStubInterfaceDescriptor* descriptor) { | 23 CodeStubInterfaceDescriptor* descriptor) { |
24 Register registers[] = { esi, ebx }; | 24 Register registers[] = { esi, ebx }; |
25 descriptor->Initialize( | 25 descriptor->Initialize( |
26 ARRAY_SIZE(registers), registers, | 26 MajorKey(), ARRAY_SIZE(registers), registers, |
27 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); | 27 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); |
28 } | 28 } |
29 | 29 |
30 | 30 |
31 void FastNewContextStub::InitializeInterfaceDescriptor( | 31 void FastNewContextStub::InitializeInterfaceDescriptor( |
32 CodeStubInterfaceDescriptor* descriptor) { | 32 CodeStubInterfaceDescriptor* descriptor) { |
33 Register registers[] = { esi, edi }; | 33 Register registers[] = { esi, edi }; |
34 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 34 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
35 } | 35 } |
36 | 36 |
37 | 37 |
38 void ToNumberStub::InitializeInterfaceDescriptor( | 38 void ToNumberStub::InitializeInterfaceDescriptor( |
39 CodeStubInterfaceDescriptor* descriptor) { | 39 CodeStubInterfaceDescriptor* descriptor) { |
40 // ToNumberStub invokes a function, and therefore needs a context. | 40 // ToNumberStub invokes a function, and therefore needs a context. |
41 Register registers[] = { esi, eax }; | 41 Register registers[] = { esi, eax }; |
42 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 42 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
43 } | 43 } |
44 | 44 |
45 | 45 |
46 void NumberToStringStub::InitializeInterfaceDescriptor( | 46 void NumberToStringStub::InitializeInterfaceDescriptor( |
47 CodeStubInterfaceDescriptor* descriptor) { | 47 CodeStubInterfaceDescriptor* descriptor) { |
48 Register registers[] = { esi, eax }; | 48 Register registers[] = { esi, eax }; |
49 descriptor->Initialize( | 49 descriptor->Initialize( |
50 ARRAY_SIZE(registers), registers, | 50 MajorKey(), ARRAY_SIZE(registers), registers, |
51 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); | 51 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); |
52 } | 52 } |
53 | 53 |
54 | 54 |
55 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( | 55 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( |
56 CodeStubInterfaceDescriptor* descriptor) { | 56 CodeStubInterfaceDescriptor* descriptor) { |
57 Register registers[] = { esi, eax, ebx, ecx }; | 57 Register registers[] = { esi, eax, ebx, ecx }; |
58 Representation representations[] = { | 58 Representation representations[] = { |
59 Representation::Tagged(), | 59 Representation::Tagged(), |
60 Representation::Tagged(), | 60 Representation::Tagged(), |
61 Representation::Smi(), | 61 Representation::Smi(), |
62 Representation::Tagged() }; | 62 Representation::Tagged() }; |
63 | 63 |
64 descriptor->Initialize( | 64 descriptor->Initialize( |
65 ARRAY_SIZE(registers), registers, | 65 MajorKey(), ARRAY_SIZE(registers), registers, |
66 Runtime::FunctionForId( | 66 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry, |
67 Runtime::kCreateArrayLiteralStubBailout)->entry, | |
68 representations); | 67 representations); |
69 } | 68 } |
70 | 69 |
71 | 70 |
72 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( | 71 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( |
73 CodeStubInterfaceDescriptor* descriptor) { | 72 CodeStubInterfaceDescriptor* descriptor) { |
74 Register registers[] = { esi, eax, ebx, ecx, edx }; | 73 Register registers[] = { esi, eax, ebx, ecx, edx }; |
75 descriptor->Initialize( | 74 descriptor->Initialize( |
76 ARRAY_SIZE(registers), registers, | 75 MajorKey(), ARRAY_SIZE(registers), registers, |
77 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); | 76 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); |
78 } | 77 } |
79 | 78 |
80 | 79 |
81 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | 80 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
82 CodeStubInterfaceDescriptor* descriptor) { | 81 CodeStubInterfaceDescriptor* descriptor) { |
83 Register registers[] = { esi, ebx, edx }; | 82 Register registers[] = { esi, ebx, edx }; |
84 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 83 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
85 } | 84 } |
86 | 85 |
87 | 86 |
| 87 void InstanceofStub::InitializeInterfaceDescriptor( |
| 88 Isolate* isolate, |
| 89 CodeStubInterfaceDescriptor* descriptor) { |
| 90 Register registers[] = { esi, left(), right() }; |
| 91 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 92 } |
| 93 |
| 94 |
| 95 void CallFunctionStub::InitializeInterfaceDescriptor( |
| 96 Isolate* isolate, |
| 97 CodeStubInterfaceDescriptor* descriptor) { |
| 98 Register registers[] = { esi, edi }; |
| 99 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 100 } |
| 101 |
| 102 |
| 103 void CallConstructStub::InitializeInterfaceDescriptor( |
| 104 Isolate* isolate, |
| 105 CodeStubInterfaceDescriptor* descriptor) { |
| 106 // eax : number of arguments |
| 107 // ebx : feedback vector |
| 108 // edx : (only if ebx is not the megamorphic symbol) slot in feedback |
| 109 // vector (Smi) |
| 110 // edi : constructor function |
| 111 // TODO(turbofan): So far we don't gather type feedback and hence skip the |
| 112 // slot parameter, but ArrayConstructStub needs the vector to be undefined. |
| 113 Register registers[] = { esi, eax, edi, ebx }; |
| 114 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 115 } |
| 116 |
| 117 |
88 void RegExpConstructResultStub::InitializeInterfaceDescriptor( | 118 void RegExpConstructResultStub::InitializeInterfaceDescriptor( |
89 CodeStubInterfaceDescriptor* descriptor) { | 119 CodeStubInterfaceDescriptor* descriptor) { |
90 Register registers[] = { esi, ecx, ebx, eax }; | 120 Register registers[] = { esi, ecx, ebx, eax }; |
91 descriptor->Initialize( | 121 descriptor->Initialize( |
92 ARRAY_SIZE(registers), registers, | 122 MajorKey(), ARRAY_SIZE(registers), registers, |
93 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); | 123 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); |
94 } | 124 } |
95 | 125 |
96 | 126 |
97 void TransitionElementsKindStub::InitializeInterfaceDescriptor( | 127 void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
98 CodeStubInterfaceDescriptor* descriptor) { | 128 CodeStubInterfaceDescriptor* descriptor) { |
99 Register registers[] = { esi, eax, ebx }; | 129 Register registers[] = { esi, eax, ebx }; |
100 descriptor->Initialize( | 130 descriptor->Initialize( |
101 ARRAY_SIZE(registers), registers, | 131 MajorKey(), ARRAY_SIZE(registers), registers, |
102 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry); | 132 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry); |
103 } | 133 } |
104 | 134 |
105 | 135 |
106 const Register InterfaceDescriptor::ContextRegister() { return esi; } | 136 const Register InterfaceDescriptor::ContextRegister() { return esi; } |
107 | 137 |
108 | 138 |
109 static void InitializeArrayConstructorDescriptor( | 139 static void InitializeArrayConstructorDescriptor( |
110 Isolate* isolate, | 140 Isolate* isolate, CodeStub::Major major, |
111 CodeStubInterfaceDescriptor* descriptor, | 141 CodeStubInterfaceDescriptor* descriptor, |
112 int constant_stack_parameter_count) { | 142 int constant_stack_parameter_count) { |
113 // register state | 143 // register state |
114 // eax -- number of arguments | 144 // eax -- number of arguments |
115 // edi -- function | 145 // edi -- function |
116 // ebx -- allocation site with elements kind | 146 // ebx -- allocation site with elements kind |
117 Address deopt_handler = Runtime::FunctionForId( | 147 Address deopt_handler = Runtime::FunctionForId( |
118 Runtime::kArrayConstructor)->entry; | 148 Runtime::kArrayConstructor)->entry; |
119 | 149 |
120 if (constant_stack_parameter_count == 0) { | 150 if (constant_stack_parameter_count == 0) { |
121 Register registers[] = { esi, edi, ebx }; | 151 Register registers[] = { esi, edi, ebx }; |
122 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 152 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, |
123 deopt_handler, | 153 deopt_handler, NULL, constant_stack_parameter_count, |
124 NULL, | |
125 constant_stack_parameter_count, | |
126 JS_FUNCTION_STUB_MODE); | 154 JS_FUNCTION_STUB_MODE); |
127 } else { | 155 } else { |
128 // stack param count needs (constructor pointer, and single argument) | 156 // stack param count needs (constructor pointer, and single argument) |
129 Register registers[] = { esi, edi, ebx, eax }; | 157 Register registers[] = { esi, edi, ebx, eax }; |
130 Representation representations[] = { | 158 Representation representations[] = { |
131 Representation::Tagged(), | 159 Representation::Tagged(), |
132 Representation::Tagged(), | 160 Representation::Tagged(), |
133 Representation::Tagged(), | 161 Representation::Tagged(), |
134 Representation::Integer32() }; | 162 Representation::Integer32() }; |
135 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 163 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, eax, |
136 eax, | 164 deopt_handler, representations, |
137 deopt_handler, | |
138 representations, | |
139 constant_stack_parameter_count, | 165 constant_stack_parameter_count, |
140 JS_FUNCTION_STUB_MODE, | 166 JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); |
141 PASS_ARGUMENTS); | |
142 } | 167 } |
143 } | 168 } |
144 | 169 |
145 | 170 |
146 static void InitializeInternalArrayConstructorDescriptor( | 171 static void InitializeInternalArrayConstructorDescriptor( |
147 CodeStubInterfaceDescriptor* descriptor, | 172 CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, |
148 int constant_stack_parameter_count) { | 173 int constant_stack_parameter_count) { |
149 // register state | 174 // register state |
150 // eax -- number of arguments | 175 // eax -- number of arguments |
151 // edi -- constructor function | 176 // edi -- constructor function |
152 Address deopt_handler = Runtime::FunctionForId( | 177 Address deopt_handler = Runtime::FunctionForId( |
153 Runtime::kInternalArrayConstructor)->entry; | 178 Runtime::kInternalArrayConstructor)->entry; |
154 | 179 |
155 if (constant_stack_parameter_count == 0) { | 180 if (constant_stack_parameter_count == 0) { |
156 Register registers[] = { esi, edi }; | 181 Register registers[] = { esi, edi }; |
157 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 182 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, |
158 deopt_handler, | 183 deopt_handler, NULL, constant_stack_parameter_count, |
159 NULL, | |
160 constant_stack_parameter_count, | |
161 JS_FUNCTION_STUB_MODE); | 184 JS_FUNCTION_STUB_MODE); |
162 } else { | 185 } else { |
163 // stack param count needs (constructor pointer, and single argument) | 186 // stack param count needs (constructor pointer, and single argument) |
164 Register registers[] = { esi, edi, eax }; | 187 Register registers[] = { esi, edi, eax }; |
165 Representation representations[] = { | 188 Representation representations[] = { |
166 Representation::Tagged(), | 189 Representation::Tagged(), |
167 Representation::Tagged(), | 190 Representation::Tagged(), |
168 Representation::Integer32() }; | 191 Representation::Integer32() }; |
169 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 192 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, eax, |
170 eax, | 193 deopt_handler, representations, |
171 deopt_handler, | |
172 representations, | |
173 constant_stack_parameter_count, | 194 constant_stack_parameter_count, |
174 JS_FUNCTION_STUB_MODE, | 195 JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); |
175 PASS_ARGUMENTS); | |
176 } | 196 } |
177 } | 197 } |
178 | 198 |
179 | 199 |
180 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 200 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
181 CodeStubInterfaceDescriptor* descriptor) { | 201 CodeStubInterfaceDescriptor* descriptor) { |
182 InitializeArrayConstructorDescriptor(isolate(), descriptor, 0); | 202 InitializeArrayConstructorDescriptor(isolate(), MajorKey(), descriptor, 0); |
183 } | 203 } |
184 | 204 |
185 | 205 |
186 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 206 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
187 CodeStubInterfaceDescriptor* descriptor) { | 207 CodeStubInterfaceDescriptor* descriptor) { |
188 InitializeArrayConstructorDescriptor(isolate(), descriptor, 1); | 208 InitializeArrayConstructorDescriptor(isolate(), MajorKey(), descriptor, 1); |
189 } | 209 } |
190 | 210 |
191 | 211 |
192 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 212 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
193 CodeStubInterfaceDescriptor* descriptor) { | 213 CodeStubInterfaceDescriptor* descriptor) { |
194 InitializeArrayConstructorDescriptor(isolate(), descriptor, -1); | 214 InitializeArrayConstructorDescriptor(isolate(), MajorKey(), descriptor, -1); |
195 } | 215 } |
196 | 216 |
197 | 217 |
198 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 218 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
199 CodeStubInterfaceDescriptor* descriptor) { | 219 CodeStubInterfaceDescriptor* descriptor) { |
200 InitializeInternalArrayConstructorDescriptor(descriptor, 0); | 220 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 0); |
201 } | 221 } |
202 | 222 |
203 | 223 |
204 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 224 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
205 CodeStubInterfaceDescriptor* descriptor) { | 225 CodeStubInterfaceDescriptor* descriptor) { |
206 InitializeInternalArrayConstructorDescriptor(descriptor, 1); | 226 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 1); |
207 } | 227 } |
208 | 228 |
209 | 229 |
210 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 230 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
211 CodeStubInterfaceDescriptor* descriptor) { | 231 CodeStubInterfaceDescriptor* descriptor) { |
212 InitializeInternalArrayConstructorDescriptor(descriptor, -1); | 232 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, -1); |
213 } | 233 } |
214 | 234 |
215 | 235 |
216 void CompareNilICStub::InitializeInterfaceDescriptor( | 236 void CompareNilICStub::InitializeInterfaceDescriptor( |
217 CodeStubInterfaceDescriptor* descriptor) { | 237 CodeStubInterfaceDescriptor* descriptor) { |
218 Register registers[] = { esi, eax }; | 238 Register registers[] = { esi, eax }; |
219 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 239 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
220 FUNCTION_ADDR(CompareNilIC_Miss)); | 240 FUNCTION_ADDR(CompareNilIC_Miss)); |
221 descriptor->SetMissHandler( | 241 descriptor->SetMissHandler( |
222 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); | 242 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); |
223 } | 243 } |
224 | 244 |
225 void ToBooleanStub::InitializeInterfaceDescriptor( | 245 void ToBooleanStub::InitializeInterfaceDescriptor( |
226 CodeStubInterfaceDescriptor* descriptor) { | 246 CodeStubInterfaceDescriptor* descriptor) { |
227 Register registers[] = { esi, eax }; | 247 Register registers[] = { esi, eax }; |
228 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 248 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
229 FUNCTION_ADDR(ToBooleanIC_Miss)); | 249 FUNCTION_ADDR(ToBooleanIC_Miss)); |
230 descriptor->SetMissHandler( | 250 descriptor->SetMissHandler( |
231 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); | 251 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); |
232 } | 252 } |
233 | 253 |
234 | 254 |
235 void BinaryOpICStub::InitializeInterfaceDescriptor( | 255 void BinaryOpICStub::InitializeInterfaceDescriptor( |
236 CodeStubInterfaceDescriptor* descriptor) { | 256 CodeStubInterfaceDescriptor* descriptor) { |
237 Register registers[] = { esi, edx, eax }; | 257 Register registers[] = { esi, edx, eax }; |
238 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 258 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
239 FUNCTION_ADDR(BinaryOpIC_Miss)); | 259 FUNCTION_ADDR(BinaryOpIC_Miss)); |
240 descriptor->SetMissHandler( | 260 descriptor->SetMissHandler( |
241 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); | 261 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); |
242 } | 262 } |
243 | 263 |
244 | 264 |
245 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( | 265 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( |
246 CodeStubInterfaceDescriptor* descriptor) { | 266 CodeStubInterfaceDescriptor* descriptor) { |
247 Register registers[] = { esi, ecx, edx, eax }; | 267 Register registers[] = { esi, ecx, edx, eax }; |
248 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 268 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
249 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); | 269 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); |
250 } | 270 } |
251 | 271 |
252 | 272 |
253 void StringAddStub::InitializeInterfaceDescriptor( | 273 void StringAddStub::InitializeInterfaceDescriptor( |
254 CodeStubInterfaceDescriptor* descriptor) { | 274 CodeStubInterfaceDescriptor* descriptor) { |
255 Register registers[] = { esi, edx, eax }; | 275 Register registers[] = { esi, edx, eax }; |
256 descriptor->Initialize( | 276 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
257 ARRAY_SIZE(registers), registers, | 277 Runtime::FunctionForId(Runtime::kStringAdd)->entry); |
258 Runtime::FunctionForId(Runtime::kStringAdd)->entry); | |
259 } | 278 } |
260 | 279 |
261 | 280 |
262 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { | 281 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { |
263 { | 282 { |
264 CallInterfaceDescriptor* descriptor = | 283 CallInterfaceDescriptor* descriptor = |
265 isolate->call_descriptor(Isolate::ArgumentAdaptorCall); | 284 isolate->call_descriptor(Isolate::ArgumentAdaptorCall); |
266 Register registers[] = { esi, // context | 285 Register registers[] = { esi, // context |
267 edi, // JSFunction | 286 edi, // JSFunction |
268 eax, // actual number of arguments | 287 eax, // actual number of arguments |
(...skipping 2507 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2776 __ mov(object, Operand(esp, 2 * kPointerSize)); | 2795 __ mov(object, Operand(esp, 2 * kPointerSize)); |
2777 __ mov(function, Operand(esp, 1 * kPointerSize)); | 2796 __ mov(function, Operand(esp, 1 * kPointerSize)); |
2778 } | 2797 } |
2779 | 2798 |
2780 // Check that the left hand is a JS object. | 2799 // Check that the left hand is a JS object. |
2781 __ JumpIfSmi(object, ¬_js_object); | 2800 __ JumpIfSmi(object, ¬_js_object); |
2782 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); | 2801 __ IsObjectJSObjectType(object, map, scratch, ¬_js_object); |
2783 | 2802 |
2784 // If there is a call site cache don't look in the global cache, but do the | 2803 // If there is a call site cache don't look in the global cache, but do the |
2785 // real lookup and update the call site cache. | 2804 // real lookup and update the call site cache. |
2786 if (!HasCallSiteInlineCheck()) { | 2805 if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { |
2787 // Look up the function and the map in the instanceof cache. | 2806 // Look up the function and the map in the instanceof cache. |
2788 Label miss; | 2807 Label miss; |
2789 __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); | 2808 __ CompareRoot(function, scratch, Heap::kInstanceofCacheFunctionRootIndex); |
2790 __ j(not_equal, &miss, Label::kNear); | 2809 __ j(not_equal, &miss, Label::kNear); |
2791 __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); | 2810 __ CompareRoot(map, scratch, Heap::kInstanceofCacheMapRootIndex); |
2792 __ j(not_equal, &miss, Label::kNear); | 2811 __ j(not_equal, &miss, Label::kNear); |
2793 __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); | 2812 __ LoadRoot(eax, Heap::kInstanceofCacheAnswerRootIndex); |
2794 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2813 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2795 __ bind(&miss); | 2814 __ bind(&miss); |
2796 } | 2815 } |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2835 __ cmp(scratch, Immediate(factory->null_value())); | 2854 __ cmp(scratch, Immediate(factory->null_value())); |
2836 __ j(equal, &is_not_instance, Label::kNear); | 2855 __ j(equal, &is_not_instance, Label::kNear); |
2837 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); | 2856 __ mov(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
2838 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); | 2857 __ mov(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
2839 __ jmp(&loop); | 2858 __ jmp(&loop); |
2840 | 2859 |
2841 __ bind(&is_instance); | 2860 __ bind(&is_instance); |
2842 if (!HasCallSiteInlineCheck()) { | 2861 if (!HasCallSiteInlineCheck()) { |
2843 __ mov(eax, Immediate(0)); | 2862 __ mov(eax, Immediate(0)); |
2844 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); | 2863 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |
| 2864 if (ReturnTrueFalseObject()) { |
| 2865 __ mov(eax, factory->true_value()); |
| 2866 } |
2845 } else { | 2867 } else { |
2846 // Get return address and delta to inlined map check. | 2868 // Get return address and delta to inlined map check. |
2847 __ mov(eax, factory->true_value()); | 2869 __ mov(eax, factory->true_value()); |
2848 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 2870 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
2849 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 2871 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
2850 if (FLAG_debug_code) { | 2872 if (FLAG_debug_code) { |
2851 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 2873 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
2852 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2874 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
2853 } | 2875 } |
2854 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 2876 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
2855 if (!ReturnTrueFalseObject()) { | 2877 if (!ReturnTrueFalseObject()) { |
2856 __ Move(eax, Immediate(0)); | 2878 __ Move(eax, Immediate(0)); |
2857 } | 2879 } |
2858 } | 2880 } |
2859 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2881 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2860 | 2882 |
2861 __ bind(&is_not_instance); | 2883 __ bind(&is_not_instance); |
2862 if (!HasCallSiteInlineCheck()) { | 2884 if (!HasCallSiteInlineCheck()) { |
2863 __ mov(eax, Immediate(Smi::FromInt(1))); | 2885 __ mov(eax, Immediate(Smi::FromInt(1))); |
2864 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); | 2886 __ StoreRoot(eax, scratch, Heap::kInstanceofCacheAnswerRootIndex); |
| 2887 if (ReturnTrueFalseObject()) { |
| 2888 __ mov(eax, factory->false_value()); |
| 2889 } |
2865 } else { | 2890 } else { |
2866 // Get return address and delta to inlined map check. | 2891 // Get return address and delta to inlined map check. |
2867 __ mov(eax, factory->false_value()); | 2892 __ mov(eax, factory->false_value()); |
2868 __ mov(scratch, Operand(esp, 0 * kPointerSize)); | 2893 __ mov(scratch, Operand(esp, 0 * kPointerSize)); |
2869 __ sub(scratch, Operand(esp, 1 * kPointerSize)); | 2894 __ sub(scratch, Operand(esp, 1 * kPointerSize)); |
2870 if (FLAG_debug_code) { | 2895 if (FLAG_debug_code) { |
2871 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); | 2896 __ cmpb(Operand(scratch, kDeltaToMov), kMovEaxImmediateByte); |
2872 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2897 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
2873 } | 2898 } |
2874 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); | 2899 __ mov(Operand(scratch, kDeltaToMovImmediate), eax); |
2875 if (!ReturnTrueFalseObject()) { | 2900 if (!ReturnTrueFalseObject()) { |
2876 __ Move(eax, Immediate(Smi::FromInt(1))); | 2901 __ Move(eax, Immediate(Smi::FromInt(1))); |
2877 } | 2902 } |
2878 } | 2903 } |
2879 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2904 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2880 | 2905 |
2881 Label object_not_null, object_not_null_or_smi; | 2906 Label object_not_null, object_not_null_or_smi; |
2882 __ bind(¬_js_object); | 2907 __ bind(¬_js_object); |
2883 // Before null, smi and string value checks, check that the rhs is a function | 2908 // Before null, smi and string value checks, check that the rhs is a function |
2884 // as for a non-function rhs an exception needs to be thrown. | 2909 // as for a non-function rhs an exception needs to be thrown. |
2885 __ JumpIfSmi(function, &slow, Label::kNear); | 2910 __ JumpIfSmi(function, &slow, Label::kNear); |
2886 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); | 2911 __ CmpObjectType(function, JS_FUNCTION_TYPE, scratch); |
2887 __ j(not_equal, &slow, Label::kNear); | 2912 __ j(not_equal, &slow, Label::kNear); |
2888 | 2913 |
2889 // Null is not instance of anything. | 2914 // Null is not instance of anything. |
2890 __ cmp(object, factory->null_value()); | 2915 __ cmp(object, factory->null_value()); |
2891 __ j(not_equal, &object_not_null, Label::kNear); | 2916 __ j(not_equal, &object_not_null, Label::kNear); |
2892 __ Move(eax, Immediate(Smi::FromInt(1))); | 2917 if (ReturnTrueFalseObject()) { |
| 2918 __ mov(eax, factory->false_value()); |
| 2919 } else { |
| 2920 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2921 } |
2893 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2922 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2894 | 2923 |
2895 __ bind(&object_not_null); | 2924 __ bind(&object_not_null); |
2896 // Smi values is not instance of anything. | 2925 // Smi values is not instance of anything. |
2897 __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear); | 2926 __ JumpIfNotSmi(object, &object_not_null_or_smi, Label::kNear); |
2898 __ Move(eax, Immediate(Smi::FromInt(1))); | 2927 if (ReturnTrueFalseObject()) { |
| 2928 __ mov(eax, factory->false_value()); |
| 2929 } else { |
| 2930 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2931 } |
2899 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2932 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2900 | 2933 |
2901 __ bind(&object_not_null_or_smi); | 2934 __ bind(&object_not_null_or_smi); |
2902 // String values is not instance of anything. | 2935 // String values is not instance of anything. |
2903 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); | 2936 Condition is_string = masm->IsObjectStringType(object, scratch, scratch); |
2904 __ j(NegateCondition(is_string), &slow, Label::kNear); | 2937 __ j(NegateCondition(is_string), &slow, Label::kNear); |
2905 __ Move(eax, Immediate(Smi::FromInt(1))); | 2938 if (ReturnTrueFalseObject()) { |
| 2939 __ mov(eax, factory->false_value()); |
| 2940 } else { |
| 2941 __ Move(eax, Immediate(Smi::FromInt(1))); |
| 2942 } |
2906 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); | 2943 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2907 | 2944 |
2908 // Slow-case: Go through the JavaScript implementation. | 2945 // Slow-case: Go through the JavaScript implementation. |
2909 __ bind(&slow); | 2946 __ bind(&slow); |
2910 if (!ReturnTrueFalseObject()) { | 2947 if (!ReturnTrueFalseObject()) { |
2911 // Tail call the builtin which returns 0 or 1. | 2948 // Tail call the builtin which returns 0 or 1. |
2912 if (HasArgsInRegisters()) { | 2949 if (HasArgsInRegisters()) { |
2913 // Push arguments below return address. | 2950 // Push arguments below return address. |
2914 __ pop(scratch); | 2951 __ pop(scratch); |
2915 __ push(object); | 2952 __ push(object); |
(...skipping 2062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4978 Operand(ebp, 7 * kPointerSize), | 5015 Operand(ebp, 7 * kPointerSize), |
4979 NULL); | 5016 NULL); |
4980 } | 5017 } |
4981 | 5018 |
4982 | 5019 |
4983 #undef __ | 5020 #undef __ |
4984 | 5021 |
4985 } } // namespace v8::internal | 5022 } } // namespace v8::internal |
4986 | 5023 |
4987 #endif // V8_TARGET_ARCH_IA32 | 5024 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |