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

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: 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
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,
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698