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