| 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 |