OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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_X64 | 7 #if V8_TARGET_ARCH_X64 |
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/runtime.h" | 12 #include "src/runtime.h" |
13 #include "src/stub-cache.h" | 13 #include "src/stub-cache.h" |
14 | 14 |
15 namespace v8 { | 15 namespace v8 { |
16 namespace internal { | 16 namespace internal { |
17 | 17 |
18 | 18 |
19 void FastNewClosureStub::InitializeInterfaceDescriptor( | 19 void FastNewClosureStub::InitializeInterfaceDescriptor( |
20 CodeStubInterfaceDescriptor* descriptor) { | 20 CodeStubInterfaceDescriptor* descriptor) { |
21 Register registers[] = { rsi, rbx }; | 21 Register registers[] = { rsi, rbx }; |
22 descriptor->Initialize( | 22 descriptor->Initialize( |
23 ARRAY_SIZE(registers), registers, | 23 MajorKey(), ARRAY_SIZE(registers), registers, |
24 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); | 24 Runtime::FunctionForId(Runtime::kNewClosureFromStubFailure)->entry); |
25 } | 25 } |
26 | 26 |
27 | 27 |
28 void FastNewContextStub::InitializeInterfaceDescriptor( | 28 void FastNewContextStub::InitializeInterfaceDescriptor( |
29 CodeStubInterfaceDescriptor* descriptor) { | 29 CodeStubInterfaceDescriptor* descriptor) { |
30 Register registers[] = { rsi, rdi }; | 30 Register registers[] = { rsi, rdi }; |
31 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 31 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
32 } | 32 } |
33 | 33 |
34 | 34 |
35 void ToNumberStub::InitializeInterfaceDescriptor( | 35 void ToNumberStub::InitializeInterfaceDescriptor( |
36 CodeStubInterfaceDescriptor* descriptor) { | 36 CodeStubInterfaceDescriptor* descriptor) { |
37 Register registers[] = { rsi, rax }; | 37 Register registers[] = { rsi, rax }; |
38 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 38 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
39 } | 39 } |
40 | 40 |
41 | 41 |
42 void NumberToStringStub::InitializeInterfaceDescriptor( | 42 void NumberToStringStub::InitializeInterfaceDescriptor( |
43 CodeStubInterfaceDescriptor* descriptor) { | 43 CodeStubInterfaceDescriptor* descriptor) { |
44 Register registers[] = { rsi, rax }; | 44 Register registers[] = { rsi, rax }; |
45 descriptor->Initialize( | 45 descriptor->Initialize( |
46 ARRAY_SIZE(registers), registers, | 46 MajorKey(), ARRAY_SIZE(registers), registers, |
47 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); | 47 Runtime::FunctionForId(Runtime::kNumberToStringRT)->entry); |
48 } | 48 } |
49 | 49 |
50 | 50 |
51 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( | 51 void FastCloneShallowArrayStub::InitializeInterfaceDescriptor( |
52 CodeStubInterfaceDescriptor* descriptor) { | 52 CodeStubInterfaceDescriptor* descriptor) { |
53 Register registers[] = { rsi, rax, rbx, rcx }; | 53 Register registers[] = { rsi, rax, rbx, rcx }; |
54 Representation representations[] = { | 54 Representation representations[] = { |
55 Representation::Tagged(), | 55 Representation::Tagged(), |
56 Representation::Tagged(), | 56 Representation::Tagged(), |
57 Representation::Smi(), | 57 Representation::Smi(), |
58 Representation::Tagged() }; | 58 Representation::Tagged() }; |
59 | 59 |
60 descriptor->Initialize( | 60 descriptor->Initialize( |
61 ARRAY_SIZE(registers), registers, | 61 MajorKey(), ARRAY_SIZE(registers), registers, |
62 Runtime::FunctionForId( | 62 Runtime::FunctionForId(Runtime::kCreateArrayLiteralStubBailout)->entry, |
63 Runtime::kCreateArrayLiteralStubBailout)->entry, | |
64 representations); | 63 representations); |
65 } | 64 } |
66 | 65 |
67 | 66 |
68 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( | 67 void FastCloneShallowObjectStub::InitializeInterfaceDescriptor( |
69 CodeStubInterfaceDescriptor* descriptor) { | 68 CodeStubInterfaceDescriptor* descriptor) { |
70 Register registers[] = { rsi, rax, rbx, rcx, rdx }; | 69 Register registers[] = { rsi, rax, rbx, rcx, rdx }; |
71 descriptor->Initialize( | 70 descriptor->Initialize( |
72 ARRAY_SIZE(registers), registers, | 71 MajorKey(), ARRAY_SIZE(registers), registers, |
73 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); | 72 Runtime::FunctionForId(Runtime::kCreateObjectLiteral)->entry); |
74 } | 73 } |
75 | 74 |
76 | 75 |
77 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( | 76 void CreateAllocationSiteStub::InitializeInterfaceDescriptor( |
78 CodeStubInterfaceDescriptor* descriptor) { | 77 CodeStubInterfaceDescriptor* descriptor) { |
79 Register registers[] = { rsi, rbx, rdx }; | 78 Register registers[] = { rsi, rbx, rdx }; |
80 descriptor->Initialize(ARRAY_SIZE(registers), registers); | 79 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
81 } | 80 } |
82 | 81 |
83 | 82 |
| 83 void InstanceofStub::InitializeInterfaceDescriptor( |
| 84 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 85 Register registers[] = {rsi, left(), right()}; |
| 86 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 87 } |
| 88 |
| 89 |
| 90 void CallFunctionStub::InitializeInterfaceDescriptor( |
| 91 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 92 Register registers[] = {rsi, rdi}; |
| 93 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 94 } |
| 95 |
| 96 |
| 97 void CallConstructStub::InitializeInterfaceDescriptor( |
| 98 Isolate* isolate, CodeStubInterfaceDescriptor* descriptor) { |
| 99 // rax : number of arguments |
| 100 // rbx : feedback vector |
| 101 // rdx : (only if rbx is not the megamorphic symbol) slot in feedback |
| 102 // vector (Smi) |
| 103 // rdi : constructor function |
| 104 // TODO(turbofan): So far we don't gather type feedback and hence skip the |
| 105 // slot parameter, but ArrayConstructStub needs the vector to be undefined. |
| 106 Register registers[] = {rsi, rax, rdi, rbx}; |
| 107 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers); |
| 108 } |
| 109 |
| 110 |
84 void RegExpConstructResultStub::InitializeInterfaceDescriptor( | 111 void RegExpConstructResultStub::InitializeInterfaceDescriptor( |
85 CodeStubInterfaceDescriptor* descriptor) { | 112 CodeStubInterfaceDescriptor* descriptor) { |
86 Register registers[] = { rsi, rcx, rbx, rax }; | 113 Register registers[] = { rsi, rcx, rbx, rax }; |
87 descriptor->Initialize( | 114 descriptor->Initialize( |
88 ARRAY_SIZE(registers), registers, | 115 MajorKey(), ARRAY_SIZE(registers), registers, |
89 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); | 116 Runtime::FunctionForId(Runtime::kRegExpConstructResult)->entry); |
90 } | 117 } |
91 | 118 |
92 | 119 |
93 void TransitionElementsKindStub::InitializeInterfaceDescriptor( | 120 void TransitionElementsKindStub::InitializeInterfaceDescriptor( |
94 CodeStubInterfaceDescriptor* descriptor) { | 121 CodeStubInterfaceDescriptor* descriptor) { |
95 Register registers[] = { rsi, rax, rbx }; | 122 Register registers[] = { rsi, rax, rbx }; |
96 descriptor->Initialize( | 123 descriptor->Initialize( |
97 ARRAY_SIZE(registers), registers, | 124 MajorKey(), ARRAY_SIZE(registers), registers, |
98 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry); | 125 Runtime::FunctionForId(Runtime::kTransitionElementsKind)->entry); |
99 } | 126 } |
100 | 127 |
101 | 128 |
102 const Register InterfaceDescriptor::ContextRegister() { return rsi; } | 129 const Register InterfaceDescriptor::ContextRegister() { return rsi; } |
103 | 130 |
104 | 131 |
105 static void InitializeArrayConstructorDescriptor( | 132 static void InitializeArrayConstructorDescriptor( |
106 CodeStubInterfaceDescriptor* descriptor, | 133 CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, |
107 int constant_stack_parameter_count) { | 134 int constant_stack_parameter_count) { |
108 // register state | 135 // register state |
109 // rax -- number of arguments | 136 // rax -- number of arguments |
110 // rdi -- function | 137 // rdi -- function |
111 // rbx -- allocation site with elements kind | 138 // rbx -- allocation site with elements kind |
112 Address deopt_handler = Runtime::FunctionForId( | 139 Address deopt_handler = Runtime::FunctionForId( |
113 Runtime::kArrayConstructor)->entry; | 140 Runtime::kArrayConstructor)->entry; |
114 | 141 |
115 if (constant_stack_parameter_count == 0) { | 142 if (constant_stack_parameter_count == 0) { |
116 Register registers[] = { rsi, rdi, rbx }; | 143 Register registers[] = { rsi, rdi, rbx }; |
117 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 144 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, |
118 deopt_handler, | 145 deopt_handler, NULL, constant_stack_parameter_count, |
119 NULL, | |
120 constant_stack_parameter_count, | |
121 JS_FUNCTION_STUB_MODE); | 146 JS_FUNCTION_STUB_MODE); |
122 } else { | 147 } else { |
123 // stack param count needs (constructor pointer, and single argument) | 148 // stack param count needs (constructor pointer, and single argument) |
124 Register registers[] = { rsi, rdi, rbx, rax }; | 149 Register registers[] = { rsi, rdi, rbx, rax }; |
125 Representation representations[] = { | 150 Representation representations[] = { |
126 Representation::Tagged(), | 151 Representation::Tagged(), |
127 Representation::Tagged(), | 152 Representation::Tagged(), |
128 Representation::Tagged(), | 153 Representation::Tagged(), |
129 Representation::Integer32() }; | 154 Representation::Integer32() }; |
130 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 155 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, rax, |
131 rax, | 156 deopt_handler, representations, |
132 deopt_handler, | |
133 representations, | |
134 constant_stack_parameter_count, | 157 constant_stack_parameter_count, |
135 JS_FUNCTION_STUB_MODE, | 158 JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); |
136 PASS_ARGUMENTS); | |
137 } | 159 } |
138 } | 160 } |
139 | 161 |
140 | 162 |
141 static void InitializeInternalArrayConstructorDescriptor( | 163 static void InitializeInternalArrayConstructorDescriptor( |
142 CodeStubInterfaceDescriptor* descriptor, | 164 CodeStub::Major major, CodeStubInterfaceDescriptor* descriptor, |
143 int constant_stack_parameter_count) { | 165 int constant_stack_parameter_count) { |
144 // register state | 166 // register state |
145 // rsi -- context | 167 // rsi -- context |
146 // rax -- number of arguments | 168 // rax -- number of arguments |
147 // rdi -- constructor function | 169 // rdi -- constructor function |
148 Address deopt_handler = Runtime::FunctionForId( | 170 Address deopt_handler = Runtime::FunctionForId( |
149 Runtime::kInternalArrayConstructor)->entry; | 171 Runtime::kInternalArrayConstructor)->entry; |
150 | 172 |
151 if (constant_stack_parameter_count == 0) { | 173 if (constant_stack_parameter_count == 0) { |
152 Register registers[] = { rsi, rdi }; | 174 Register registers[] = { rsi, rdi }; |
153 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 175 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, |
154 deopt_handler, | 176 deopt_handler, NULL, constant_stack_parameter_count, |
155 NULL, | |
156 constant_stack_parameter_count, | |
157 JS_FUNCTION_STUB_MODE); | 177 JS_FUNCTION_STUB_MODE); |
158 } else { | 178 } else { |
159 // stack param count needs (constructor pointer, and single argument) | 179 // stack param count needs (constructor pointer, and single argument) |
160 Register registers[] = { rsi, rdi, rax }; | 180 Register registers[] = { rsi, rdi, rax }; |
161 Representation representations[] = { | 181 Representation representations[] = { |
162 Representation::Tagged(), | 182 Representation::Tagged(), |
163 Representation::Tagged(), | 183 Representation::Tagged(), |
164 Representation::Integer32() }; | 184 Representation::Integer32() }; |
165 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 185 descriptor->Initialize(major, ARRAY_SIZE(registers), registers, rax, |
166 rax, | 186 deopt_handler, representations, |
167 deopt_handler, | |
168 representations, | |
169 constant_stack_parameter_count, | 187 constant_stack_parameter_count, |
170 JS_FUNCTION_STUB_MODE, | 188 JS_FUNCTION_STUB_MODE, PASS_ARGUMENTS); |
171 PASS_ARGUMENTS); | |
172 } | 189 } |
173 } | 190 } |
174 | 191 |
175 | 192 |
176 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 193 void ArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
177 CodeStubInterfaceDescriptor* descriptor) { | 194 CodeStubInterfaceDescriptor* descriptor) { |
178 InitializeArrayConstructorDescriptor(descriptor, 0); | 195 InitializeArrayConstructorDescriptor(MajorKey(), descriptor, 0); |
179 } | 196 } |
180 | 197 |
181 | 198 |
182 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 199 void ArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
183 CodeStubInterfaceDescriptor* descriptor) { | 200 CodeStubInterfaceDescriptor* descriptor) { |
184 InitializeArrayConstructorDescriptor(descriptor, 1); | 201 InitializeArrayConstructorDescriptor(MajorKey(), descriptor, 1); |
185 } | 202 } |
186 | 203 |
187 | 204 |
188 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 205 void ArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
189 CodeStubInterfaceDescriptor* descriptor) { | 206 CodeStubInterfaceDescriptor* descriptor) { |
190 InitializeArrayConstructorDescriptor(descriptor, -1); | 207 InitializeArrayConstructorDescriptor(MajorKey(), descriptor, -1); |
191 } | 208 } |
192 | 209 |
193 | 210 |
194 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( | 211 void InternalArrayNoArgumentConstructorStub::InitializeInterfaceDescriptor( |
195 CodeStubInterfaceDescriptor* descriptor) { | 212 CodeStubInterfaceDescriptor* descriptor) { |
196 InitializeInternalArrayConstructorDescriptor(descriptor, 0); | 213 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 0); |
197 } | 214 } |
198 | 215 |
199 | 216 |
200 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( | 217 void InternalArraySingleArgumentConstructorStub::InitializeInterfaceDescriptor( |
201 CodeStubInterfaceDescriptor* descriptor) { | 218 CodeStubInterfaceDescriptor* descriptor) { |
202 InitializeInternalArrayConstructorDescriptor(descriptor, 1); | 219 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, 1); |
203 } | 220 } |
204 | 221 |
205 | 222 |
206 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( | 223 void InternalArrayNArgumentsConstructorStub::InitializeInterfaceDescriptor( |
207 CodeStubInterfaceDescriptor* descriptor) { | 224 CodeStubInterfaceDescriptor* descriptor) { |
208 InitializeInternalArrayConstructorDescriptor(descriptor, -1); | 225 InitializeInternalArrayConstructorDescriptor(MajorKey(), descriptor, -1); |
209 } | 226 } |
210 | 227 |
211 | 228 |
212 void CompareNilICStub::InitializeInterfaceDescriptor( | 229 void CompareNilICStub::InitializeInterfaceDescriptor( |
213 CodeStubInterfaceDescriptor* descriptor) { | 230 CodeStubInterfaceDescriptor* descriptor) { |
214 Register registers[] = { rsi, rax }; | 231 Register registers[] = { rsi, rax }; |
215 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 232 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
216 FUNCTION_ADDR(CompareNilIC_Miss)); | 233 FUNCTION_ADDR(CompareNilIC_Miss)); |
217 descriptor->SetMissHandler( | 234 descriptor->SetMissHandler( |
218 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); | 235 ExternalReference(IC_Utility(IC::kCompareNilIC_Miss), isolate())); |
219 } | 236 } |
220 | 237 |
221 | 238 |
222 void ToBooleanStub::InitializeInterfaceDescriptor( | 239 void ToBooleanStub::InitializeInterfaceDescriptor( |
223 CodeStubInterfaceDescriptor* descriptor) { | 240 CodeStubInterfaceDescriptor* descriptor) { |
224 Register registers[] = { rsi, rax }; | 241 Register registers[] = { rsi, rax }; |
225 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 242 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
226 FUNCTION_ADDR(ToBooleanIC_Miss)); | 243 FUNCTION_ADDR(ToBooleanIC_Miss)); |
227 descriptor->SetMissHandler( | 244 descriptor->SetMissHandler( |
228 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); | 245 ExternalReference(IC_Utility(IC::kToBooleanIC_Miss), isolate())); |
229 } | 246 } |
230 | 247 |
231 | 248 |
232 void BinaryOpICStub::InitializeInterfaceDescriptor( | 249 void BinaryOpICStub::InitializeInterfaceDescriptor( |
233 CodeStubInterfaceDescriptor* descriptor) { | 250 CodeStubInterfaceDescriptor* descriptor) { |
234 Register registers[] = { rsi, rdx, rax }; | 251 Register registers[] = { rsi, rdx, rax }; |
235 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 252 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
236 FUNCTION_ADDR(BinaryOpIC_Miss)); | 253 FUNCTION_ADDR(BinaryOpIC_Miss)); |
237 descriptor->SetMissHandler( | 254 descriptor->SetMissHandler( |
238 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); | 255 ExternalReference(IC_Utility(IC::kBinaryOpIC_Miss), isolate())); |
239 } | 256 } |
240 | 257 |
241 | 258 |
242 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( | 259 void BinaryOpWithAllocationSiteStub::InitializeInterfaceDescriptor( |
243 CodeStubInterfaceDescriptor* descriptor) { | 260 CodeStubInterfaceDescriptor* descriptor) { |
244 Register registers[] = { rsi, rcx, rdx, rax }; | 261 Register registers[] = { rsi, rcx, rdx, rax }; |
245 descriptor->Initialize(ARRAY_SIZE(registers), registers, | 262 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
246 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); | 263 FUNCTION_ADDR(BinaryOpIC_MissWithAllocationSite)); |
247 } | 264 } |
248 | 265 |
249 | 266 |
250 void StringAddStub::InitializeInterfaceDescriptor( | 267 void StringAddStub::InitializeInterfaceDescriptor( |
251 CodeStubInterfaceDescriptor* descriptor) { | 268 CodeStubInterfaceDescriptor* descriptor) { |
252 Register registers[] = { rsi, rdx, rax }; | 269 Register registers[] = { rsi, rdx, rax }; |
253 descriptor->Initialize( | 270 descriptor->Initialize(MajorKey(), ARRAY_SIZE(registers), registers, |
254 ARRAY_SIZE(registers), registers, | 271 Runtime::FunctionForId(Runtime::kStringAdd)->entry); |
255 Runtime::FunctionForId(Runtime::kStringAdd)->entry); | |
256 } | 272 } |
257 | 273 |
258 | 274 |
259 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { | 275 void CallDescriptors::InitializeForIsolate(Isolate* isolate) { |
260 { | 276 { |
261 CallInterfaceDescriptor* descriptor = | 277 CallInterfaceDescriptor* descriptor = |
262 isolate->call_descriptor(Isolate::ArgumentAdaptorCall); | 278 isolate->call_descriptor(Isolate::ArgumentAdaptorCall); |
263 Register registers[] = { rsi, // context | 279 Register registers[] = { rsi, // context |
264 rdi, // JSFunction | 280 rdi, // JSFunction |
265 rax, // actual number of arguments | 281 rax, // actual number of arguments |
(...skipping 2454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2720 // rsp[16] : value | 2736 // rsp[16] : value |
2721 // Expected input state with an inline one-element cache: | 2737 // Expected input state with an inline one-element cache: |
2722 // rsp[0] : return address | 2738 // rsp[0] : return address |
2723 // rsp[8] : offset from return address to location of inline cache | 2739 // rsp[8] : offset from return address to location of inline cache |
2724 // rsp[16] : function pointer | 2740 // rsp[16] : function pointer |
2725 // rsp[24] : value | 2741 // rsp[24] : value |
2726 // Returns a bitwise zero to indicate that the value | 2742 // Returns a bitwise zero to indicate that the value |
2727 // is and instance of the function and anything else to | 2743 // is and instance of the function and anything else to |
2728 // indicate that the value is not an instance. | 2744 // indicate that the value is not an instance. |
2729 | 2745 |
| 2746 // Fixed register usage throughout the stub. |
| 2747 Register object = rax; // Object (lhs). |
| 2748 Register map = rbx; // Map of the object. |
| 2749 Register function = rdx; // Function (rhs). |
| 2750 Register prototype = rdi; // Prototype of the function. |
| 2751 Register scratch = rcx; |
| 2752 |
2730 static const int kOffsetToMapCheckValue = 2; | 2753 static const int kOffsetToMapCheckValue = 2; |
2731 static const int kOffsetToResultValue = kPointerSize == kInt64Size ? 18 : 14; | 2754 static const int kOffsetToResultValue = kPointerSize == kInt64Size ? 18 : 14; |
2732 // The last 4 bytes of the instruction sequence | 2755 // The last 4 bytes of the instruction sequence |
2733 // movp(rdi, FieldOperand(rax, HeapObject::kMapOffset)) | 2756 // movp(rdi, FieldOperand(rax, HeapObject::kMapOffset)) |
2734 // Move(kScratchRegister, Factory::the_hole_value()) | 2757 // Move(kScratchRegister, Factory::the_hole_value()) |
2735 // in front of the hole value address. | 2758 // in front of the hole value address. |
2736 static const unsigned int kWordBeforeMapCheckValue = | 2759 static const unsigned int kWordBeforeMapCheckValue = |
2737 kPointerSize == kInt64Size ? 0xBA49FF78 : 0xBA41FF78; | 2760 kPointerSize == kInt64Size ? 0xBA49FF78 : 0xBA41FF78; |
2738 // The last 4 bytes of the instruction sequence | 2761 // The last 4 bytes of the instruction sequence |
2739 // __ j(not_equal, &cache_miss); | 2762 // __ j(not_equal, &cache_miss); |
2740 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); | 2763 // __ LoadRoot(ToRegister(instr->result()), Heap::kTheHoleValueRootIndex); |
2741 // before the offset of the hole value in the root array. | 2764 // before the offset of the hole value in the root array. |
2742 static const unsigned int kWordBeforeResultValue = | 2765 static const unsigned int kWordBeforeResultValue = |
2743 kPointerSize == kInt64Size ? 0x458B4906 : 0x458B4106; | 2766 kPointerSize == kInt64Size ? 0x458B4906 : 0x458B4106; |
2744 // Only the inline check flag is supported on X64. | 2767 |
2745 ASSERT(flags_ == kNoFlags || HasCallSiteInlineCheck()); | |
2746 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; | 2768 int extra_argument_offset = HasCallSiteInlineCheck() ? 1 : 0; |
2747 | 2769 |
2748 // Get the object - go slow case if it's a smi. | 2770 ASSERT_EQ(object.code(), InstanceofStub::left().code()); |
| 2771 ASSERT_EQ(function.code(), InstanceofStub::right().code()); |
| 2772 |
| 2773 // Get the object and function - they are always both needed. |
| 2774 // Go slow case if the object is a smi. |
2749 Label slow; | 2775 Label slow; |
2750 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, | 2776 StackArgumentsAccessor args(rsp, 2 + extra_argument_offset, |
2751 ARGUMENTS_DONT_CONTAIN_RECEIVER); | 2777 ARGUMENTS_DONT_CONTAIN_RECEIVER); |
2752 __ movp(rax, args.GetArgumentOperand(0)); | 2778 if (!HasArgsInRegisters()) { |
2753 __ JumpIfSmi(rax, &slow); | 2779 __ movp(object, args.GetArgumentOperand(0)); |
| 2780 __ movp(function, args.GetArgumentOperand(1)); |
| 2781 } |
| 2782 __ JumpIfSmi(object, &slow); |
2754 | 2783 |
2755 // Check that the left hand is a JS object. Leave its map in rax. | 2784 // Check that the left hand is a JS object. Leave its map in rax. |
2756 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rax); | 2785 __ CmpObjectType(object, FIRST_SPEC_OBJECT_TYPE, map); |
2757 __ j(below, &slow); | 2786 __ j(below, &slow); |
2758 __ CmpInstanceType(rax, LAST_SPEC_OBJECT_TYPE); | 2787 __ CmpInstanceType(map, LAST_SPEC_OBJECT_TYPE); |
2759 __ j(above, &slow); | 2788 __ j(above, &slow); |
2760 | 2789 |
2761 // Get the prototype of the function. | |
2762 __ movp(rdx, args.GetArgumentOperand(1)); | |
2763 // rdx is function, rax is map. | |
2764 | |
2765 // If there is a call site cache don't look in the global cache, but do the | 2790 // If there is a call site cache don't look in the global cache, but do the |
2766 // real lookup and update the call site cache. | 2791 // real lookup and update the call site cache. |
2767 if (!HasCallSiteInlineCheck()) { | 2792 if (!HasCallSiteInlineCheck() && !ReturnTrueFalseObject()) { |
2768 // Look up the function and the map in the instanceof cache. | 2793 // Look up the function and the map in the instanceof cache. |
2769 Label miss; | 2794 Label miss; |
2770 __ CompareRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); | 2795 __ CompareRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
2771 __ j(not_equal, &miss, Label::kNear); | 2796 __ j(not_equal, &miss, Label::kNear); |
2772 __ CompareRoot(rax, Heap::kInstanceofCacheMapRootIndex); | 2797 __ CompareRoot(map, Heap::kInstanceofCacheMapRootIndex); |
2773 __ j(not_equal, &miss, Label::kNear); | 2798 __ j(not_equal, &miss, Label::kNear); |
2774 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); | 2799 __ LoadRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
2775 __ ret(2 * kPointerSize); | 2800 __ ret((HasArgsInRegisters() ? 0 : 2) * kPointerSize); |
2776 __ bind(&miss); | 2801 __ bind(&miss); |
2777 } | 2802 } |
2778 | 2803 |
2779 __ TryGetFunctionPrototype(rdx, rbx, &slow, true); | 2804 // Get the prototype of the function. |
| 2805 __ TryGetFunctionPrototype(function, prototype, &slow, true); |
2780 | 2806 |
2781 // Check that the function prototype is a JS object. | 2807 // Check that the function prototype is a JS object. |
2782 __ JumpIfSmi(rbx, &slow); | 2808 __ JumpIfSmi(prototype, &slow); |
2783 __ CmpObjectType(rbx, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); | 2809 __ CmpObjectType(prototype, FIRST_SPEC_OBJECT_TYPE, kScratchRegister); |
2784 __ j(below, &slow); | 2810 __ j(below, &slow); |
2785 __ CmpInstanceType(kScratchRegister, LAST_SPEC_OBJECT_TYPE); | 2811 __ CmpInstanceType(kScratchRegister, LAST_SPEC_OBJECT_TYPE); |
2786 __ j(above, &slow); | 2812 __ j(above, &slow); |
2787 | 2813 |
2788 // Register mapping: | 2814 // Update the global instanceof or call site inlined cache with the current |
2789 // rax is object map. | 2815 // map and function. The cached answer will be set when it is known below. |
2790 // rdx is function. | |
2791 // rbx is function prototype. | |
2792 if (!HasCallSiteInlineCheck()) { | 2816 if (!HasCallSiteInlineCheck()) { |
2793 __ StoreRoot(rdx, Heap::kInstanceofCacheFunctionRootIndex); | 2817 __ StoreRoot(function, Heap::kInstanceofCacheFunctionRootIndex); |
2794 __ StoreRoot(rax, Heap::kInstanceofCacheMapRootIndex); | 2818 __ StoreRoot(map, Heap::kInstanceofCacheMapRootIndex); |
2795 } else { | 2819 } else { |
| 2820 // The constants for the code patching are based on push instructions |
| 2821 // at the call site. |
| 2822 ASSERT(!HasArgsInRegisters()); |
2796 // Get return address and delta to inlined map check. | 2823 // Get return address and delta to inlined map check. |
2797 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); | 2824 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
2798 __ subp(kScratchRegister, args.GetArgumentOperand(2)); | 2825 __ subp(kScratchRegister, args.GetArgumentOperand(2)); |
2799 if (FLAG_debug_code) { | 2826 if (FLAG_debug_code) { |
2800 __ movl(rdi, Immediate(kWordBeforeMapCheckValue)); | 2827 __ movl(scratch, Immediate(kWordBeforeMapCheckValue)); |
2801 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), rdi); | 2828 __ cmpl(Operand(kScratchRegister, kOffsetToMapCheckValue - 4), scratch); |
2802 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); | 2829 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheCheck); |
2803 } | 2830 } |
2804 __ movp(kScratchRegister, | 2831 __ movp(kScratchRegister, |
2805 Operand(kScratchRegister, kOffsetToMapCheckValue)); | 2832 Operand(kScratchRegister, kOffsetToMapCheckValue)); |
2806 __ movp(Operand(kScratchRegister, 0), rax); | 2833 __ movp(Operand(kScratchRegister, 0), map); |
2807 } | 2834 } |
2808 | 2835 |
2809 __ movp(rcx, FieldOperand(rax, Map::kPrototypeOffset)); | |
2810 | |
2811 // Loop through the prototype chain looking for the function prototype. | 2836 // Loop through the prototype chain looking for the function prototype. |
| 2837 __ movp(scratch, FieldOperand(map, Map::kPrototypeOffset)); |
2812 Label loop, is_instance, is_not_instance; | 2838 Label loop, is_instance, is_not_instance; |
2813 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); | 2839 __ LoadRoot(kScratchRegister, Heap::kNullValueRootIndex); |
2814 __ bind(&loop); | 2840 __ bind(&loop); |
2815 __ cmpp(rcx, rbx); | 2841 __ cmpp(scratch, prototype); |
2816 __ j(equal, &is_instance, Label::kNear); | 2842 __ j(equal, &is_instance, Label::kNear); |
2817 __ cmpp(rcx, kScratchRegister); | 2843 __ cmpp(scratch, kScratchRegister); |
2818 // The code at is_not_instance assumes that kScratchRegister contains a | 2844 // The code at is_not_instance assumes that kScratchRegister contains a |
2819 // non-zero GCable value (the null object in this case). | 2845 // non-zero GCable value (the null object in this case). |
2820 __ j(equal, &is_not_instance, Label::kNear); | 2846 __ j(equal, &is_not_instance, Label::kNear); |
2821 __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset)); | 2847 __ movp(scratch, FieldOperand(scratch, HeapObject::kMapOffset)); |
2822 __ movp(rcx, FieldOperand(rcx, Map::kPrototypeOffset)); | 2848 __ movp(scratch, FieldOperand(scratch, Map::kPrototypeOffset)); |
2823 __ jmp(&loop); | 2849 __ jmp(&loop); |
2824 | 2850 |
2825 __ bind(&is_instance); | 2851 __ bind(&is_instance); |
2826 if (!HasCallSiteInlineCheck()) { | 2852 if (!HasCallSiteInlineCheck()) { |
2827 __ xorl(rax, rax); | 2853 __ xorl(rax, rax); |
2828 // Store bitwise zero in the cache. This is a Smi in GC terms. | 2854 // Store bitwise zero in the cache. This is a Smi in GC terms. |
2829 STATIC_ASSERT(kSmiTag == 0); | 2855 STATIC_ASSERT(kSmiTag == 0); |
2830 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); | 2856 __ StoreRoot(rax, Heap::kInstanceofCacheAnswerRootIndex); |
| 2857 if (ReturnTrueFalseObject()) { |
| 2858 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
| 2859 } |
2831 } else { | 2860 } else { |
2832 // Store offset of true in the root array at the inline check site. | 2861 // Store offset of true in the root array at the inline check site. |
2833 int true_offset = 0x100 + | 2862 int true_offset = 0x100 + |
2834 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; | 2863 (Heap::kTrueValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
2835 // Assert it is a 1-byte signed value. | 2864 // Assert it is a 1-byte signed value. |
2836 ASSERT(true_offset >= 0 && true_offset < 0x100); | 2865 ASSERT(true_offset >= 0 && true_offset < 0x100); |
2837 __ movl(rax, Immediate(true_offset)); | 2866 __ movl(rax, Immediate(true_offset)); |
2838 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); | 2867 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
2839 __ subp(kScratchRegister, args.GetArgumentOperand(2)); | 2868 __ subp(kScratchRegister, args.GetArgumentOperand(2)); |
2840 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 2869 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
2841 if (FLAG_debug_code) { | 2870 if (FLAG_debug_code) { |
2842 __ movl(rax, Immediate(kWordBeforeResultValue)); | 2871 __ movl(rax, Immediate(kWordBeforeResultValue)); |
2843 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 2872 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
2844 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2873 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
2845 } | 2874 } |
2846 __ Set(rax, 0); | 2875 if (!ReturnTrueFalseObject()) { |
| 2876 __ Set(rax, 0); |
| 2877 } |
2847 } | 2878 } |
2848 __ ret((2 + extra_argument_offset) * kPointerSize); | 2879 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * |
| 2880 kPointerSize); |
2849 | 2881 |
2850 __ bind(&is_not_instance); | 2882 __ bind(&is_not_instance); |
2851 if (!HasCallSiteInlineCheck()) { | 2883 if (!HasCallSiteInlineCheck()) { |
2852 // We have to store a non-zero value in the cache. | 2884 // We have to store a non-zero value in the cache. |
2853 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); | 2885 __ StoreRoot(kScratchRegister, Heap::kInstanceofCacheAnswerRootIndex); |
| 2886 if (ReturnTrueFalseObject()) { |
| 2887 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
| 2888 } |
2854 } else { | 2889 } else { |
2855 // Store offset of false in the root array at the inline check site. | 2890 // Store offset of false in the root array at the inline check site. |
2856 int false_offset = 0x100 + | 2891 int false_offset = 0x100 + |
2857 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; | 2892 (Heap::kFalseValueRootIndex << kPointerSizeLog2) - kRootRegisterBias; |
2858 // Assert it is a 1-byte signed value. | 2893 // Assert it is a 1-byte signed value. |
2859 ASSERT(false_offset >= 0 && false_offset < 0x100); | 2894 ASSERT(false_offset >= 0 && false_offset < 0x100); |
2860 __ movl(rax, Immediate(false_offset)); | 2895 __ movl(rax, Immediate(false_offset)); |
2861 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); | 2896 __ movq(kScratchRegister, StackOperandForReturnAddress(0)); |
2862 __ subp(kScratchRegister, args.GetArgumentOperand(2)); | 2897 __ subp(kScratchRegister, args.GetArgumentOperand(2)); |
2863 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); | 2898 __ movb(Operand(kScratchRegister, kOffsetToResultValue), rax); |
2864 if (FLAG_debug_code) { | 2899 if (FLAG_debug_code) { |
2865 __ movl(rax, Immediate(kWordBeforeResultValue)); | 2900 __ movl(rax, Immediate(kWordBeforeResultValue)); |
2866 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); | 2901 __ cmpl(Operand(kScratchRegister, kOffsetToResultValue - 4), rax); |
2867 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); | 2902 __ Assert(equal, kInstanceofStubUnexpectedCallSiteCacheMov); |
2868 } | 2903 } |
2869 } | 2904 } |
2870 __ ret((2 + extra_argument_offset) * kPointerSize); | 2905 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * |
| 2906 kPointerSize); |
2871 | 2907 |
2872 // Slow-case: Go through the JavaScript implementation. | 2908 // Slow-case: Go through the JavaScript implementation. |
2873 __ bind(&slow); | 2909 __ bind(&slow); |
2874 if (HasCallSiteInlineCheck()) { | 2910 if (!ReturnTrueFalseObject()) { |
2875 // Remove extra value from the stack. | 2911 // Tail call the builtin which returns 0 or 1. |
2876 __ PopReturnAddressTo(rcx); | 2912 ASSERT(!HasArgsInRegisters()); |
2877 __ Pop(rax); | 2913 if (HasCallSiteInlineCheck()) { |
2878 __ PushReturnAddressFrom(rcx); | 2914 // Remove extra value from the stack. |
| 2915 __ PopReturnAddressTo(rcx); |
| 2916 __ Pop(rax); |
| 2917 __ PushReturnAddressFrom(rcx); |
| 2918 } |
| 2919 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); |
| 2920 } else { |
| 2921 // Call the builtin and convert 0/1 to true/false. |
| 2922 { |
| 2923 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2924 __ Push(object); |
| 2925 __ Push(function); |
| 2926 __ InvokeBuiltin(Builtins::INSTANCE_OF, CALL_FUNCTION); |
| 2927 } |
| 2928 Label true_value, done; |
| 2929 __ testq(rax, rax); |
| 2930 __ j(zero, &true_value, Label::kNear); |
| 2931 __ LoadRoot(rax, Heap::kFalseValueRootIndex); |
| 2932 __ jmp(&done, Label::kNear); |
| 2933 __ bind(&true_value); |
| 2934 __ LoadRoot(rax, Heap::kTrueValueRootIndex); |
| 2935 __ bind(&done); |
| 2936 __ ret(((HasArgsInRegisters() ? 0 : 2) + extra_argument_offset) * |
| 2937 kPointerSize); |
2879 } | 2938 } |
2880 __ InvokeBuiltin(Builtins::INSTANCE_OF, JUMP_FUNCTION); | |
2881 } | 2939 } |
2882 | 2940 |
2883 | 2941 |
2884 // Passing arguments in registers is not supported. | 2942 // Passing arguments in registers is not supported. |
2885 Register InstanceofStub::left() { return no_reg; } | 2943 Register InstanceofStub::left() { return rax; } |
2886 | 2944 |
2887 | 2945 |
2888 Register InstanceofStub::right() { return no_reg; } | 2946 Register InstanceofStub::right() { return rdx; } |
2889 | 2947 |
2890 | 2948 |
2891 // ------------------------------------------------------------------------- | 2949 // ------------------------------------------------------------------------- |
2892 // StringCharCodeAtGenerator | 2950 // StringCharCodeAtGenerator |
2893 | 2951 |
2894 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { | 2952 void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) { |
2895 Label flat_string; | 2953 Label flat_string; |
2896 Label ascii_string; | 2954 Label ascii_string; |
2897 Label got_char_code; | 2955 Label got_char_code; |
2898 Label sliced_string; | 2956 Label sliced_string; |
(...skipping 2023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4922 return_value_operand, | 4980 return_value_operand, |
4923 NULL); | 4981 NULL); |
4924 } | 4982 } |
4925 | 4983 |
4926 | 4984 |
4927 #undef __ | 4985 #undef __ |
4928 | 4986 |
4929 } } // namespace v8::internal | 4987 } } // namespace v8::internal |
4930 | 4988 |
4931 #endif // V8_TARGET_ARCH_X64 | 4989 #endif // V8_TARGET_ARCH_X64 |
OLD | NEW |