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