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