Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(469)

Side by Side Diff: src/x64/code-stubs-x64.cc

Issue 426233002: Land the Fan (disabled) (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Review feedback, rebase and "git cl format" Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/deoptimizer-x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « src/x64/assembler-x64.cc ('k') | src/x64/deoptimizer-x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698