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

Side by Side Diff: src/x64/builtins-x64.cc

Issue 1448933002: Introduce a BuiltinsConstructStub that sets up new.target and does a [[call]] per ES6 9.3.2 (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 1 month 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
« no previous file with comments | « src/types.cc ('k') | test/mjsunit/es6/classes-subclass-builtins.js » ('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 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #if V8_TARGET_ARCH_X64 5 #if V8_TARGET_ARCH_X64
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/codegen.h" 8 #include "src/codegen.h"
9 #include "src/deoptimizer.h" 9 #include "src/deoptimizer.h"
10 #include "src/full-codegen/full-codegen.h" 10 #include "src/full-codegen/full-codegen.h"
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 112
113 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); 113 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
114 GenerateTailCallToReturnedCode(masm); 114 GenerateTailCallToReturnedCode(masm);
115 115
116 __ bind(&ok); 116 __ bind(&ok);
117 GenerateTailCallToSharedCode(masm); 117 GenerateTailCallToSharedCode(masm);
118 } 118 }
119 119
120 120
121 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 121 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
122 bool is_api_function) { 122 bool is_api_function,
123 bool create_implicit_receiver) {
123 // ----------- S t a t e ------------- 124 // ----------- S t a t e -------------
124 // -- rax: number of arguments 125 // -- rax: number of arguments
125 // -- rdi: constructor function 126 // -- rdi: constructor function
126 // -- rbx: allocation site or undefined 127 // -- rbx: allocation site or undefined
127 // -- rdx: new target 128 // -- rdx: new target
128 // ----------------------------------- 129 // -----------------------------------
129 130
130 // Enter a construct frame. 131 // Enter a construct frame.
131 { 132 {
132 FrameScope scope(masm, StackFrame::CONSTRUCT); 133 FrameScope scope(masm, StackFrame::CONSTRUCT);
133 134
134 // Preserve the incoming parameters on the stack. 135 // Preserve the incoming parameters on the stack.
135 __ AssertUndefinedOrAllocationSite(rbx); 136 __ AssertUndefinedOrAllocationSite(rbx);
136 __ Push(rbx); 137 __ Push(rbx);
137 __ Integer32ToSmi(rax, rax); 138 __ Integer32ToSmi(rcx, rax);
138 __ Push(rax); 139 __ Push(rcx);
139 __ Push(rdi);
140 __ Push(rdx);
141 140
142 // Try to allocate the object without transitioning into C code. If any of 141 if (create_implicit_receiver) {
143 // the preconditions is not met, the code bails out to the runtime call. 142 __ Push(rdi);
144 Label rt_call, allocated; 143 __ Push(rdx);
145 if (FLAG_inline_new) {
146 // Verify that the new target is a JSFunction.
147 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx);
148 __ j(not_equal, &rt_call);
149 144
150 // Load the initial map and verify that it is in fact a map. 145 // Try to allocate the object without transitioning into C code. If any of
151 // rdx: new target 146 // the preconditions is not met, the code bails out to the runtime call.
152 __ movp(rax, FieldOperand(rdx, JSFunction::kPrototypeOrInitialMapOffset)); 147 Label rt_call, allocated;
153 // Will both indicate a NULL and a Smi 148 if (FLAG_inline_new) {
154 DCHECK(kSmiTag == 0); 149 // Verify that the new target is a JSFunction.
155 __ JumpIfSmi(rax, &rt_call); 150 __ CmpObjectType(rdx, JS_FUNCTION_TYPE, rbx);
156 // rdi: constructor 151 __ j(not_equal, &rt_call);
157 // rax: initial map (if proven valid below)
158 __ CmpObjectType(rax, MAP_TYPE, rbx);
159 __ j(not_equal, &rt_call);
160 152
161 // Fall back to runtime if the expected base constructor and base 153 // Load the initial map and verify that it is in fact a map.
162 // constructor differ. 154 // rdx: new target
163 __ cmpp(rdi, FieldOperand(rax, Map::kConstructorOrBackPointerOffset)); 155 __ movp(rax,
164 __ j(not_equal, &rt_call); 156 FieldOperand(rdx, JSFunction::kPrototypeOrInitialMapOffset));
157 // Will both indicate a NULL and a Smi
158 DCHECK(kSmiTag == 0);
159 __ JumpIfSmi(rax, &rt_call);
160 // rdi: constructor
161 // rax: initial map (if proven valid below)
162 __ CmpObjectType(rax, MAP_TYPE, rbx);
163 __ j(not_equal, &rt_call);
165 164
166 // Check that the constructor is not constructing a JSFunction (see 165 // Fall back to runtime if the expected base constructor and base
167 // comments in Runtime_NewObject in runtime.cc). In which case the 166 // constructor differ.
168 // initial map's instance type would be JS_FUNCTION_TYPE. 167 __ cmpp(rdi, FieldOperand(rax, Map::kConstructorOrBackPointerOffset));
169 // rdi: constructor 168 __ j(not_equal, &rt_call);
170 // rax: initial map
171 __ CmpInstanceType(rax, JS_FUNCTION_TYPE);
172 __ j(equal, &rt_call);
173 if (!is_api_function) {
174 Label allocate;
175 // The code below relies on these assumptions.
176 STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
177 // Check if slack tracking is enabled.
178 __ movl(rsi, FieldOperand(rax, Map::kBitField3Offset));
179 __ shrl(rsi, Immediate(Map::Counter::kShift));
180 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
181 __ j(less, &allocate);
182 // Decrease generous allocation count.
183 __ subl(FieldOperand(rax, Map::kBitField3Offset),
184 Immediate(1 << Map::Counter::kShift));
185 169
186 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); 170 if (!is_api_function) {
187 __ j(not_equal, &allocate); 171 Label allocate;
172 // The code below relies on these assumptions.
173 STATIC_ASSERT(Map::Counter::kShift + Map::Counter::kSize == 32);
174 // Check if slack tracking is enabled.
175 __ movl(rsi, FieldOperand(rax, Map::kBitField3Offset));
176 __ shrl(rsi, Immediate(Map::Counter::kShift));
177 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
178 __ j(less, &allocate);
179 // Decrease generous allocation count.
180 __ subl(FieldOperand(rax, Map::kBitField3Offset),
181 Immediate(1 << Map::Counter::kShift));
188 182
189 __ Push(rax); 183 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
190 __ Push(rdx); 184 __ j(not_equal, &allocate);
191 __ Push(rdi);
192 185
193 __ Push(rax); // initial map 186 __ Push(rax);
194 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); 187 __ Push(rdx);
188 __ Push(rdi);
195 189
196 __ Pop(rdi); 190 __ Push(rax); // initial map
197 __ Pop(rdx); 191 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
198 __ Pop(rax);
199 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1));
200 192
201 __ bind(&allocate); 193 __ Pop(rdi);
194 __ Pop(rdx);
195 __ Pop(rax);
196 __ movl(rsi, Immediate(Map::kSlackTrackingCounterEnd - 1));
197
198 __ bind(&allocate);
199 }
200
201 // Now allocate the JSObject on the heap.
202 __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset));
203 __ shlp(rdi, Immediate(kPointerSizeLog2));
204 // rdi: size of new object
205 __ Allocate(rdi, rbx, rdi, no_reg, &rt_call, NO_ALLOCATION_FLAGS);
206 // Allocated the JSObject, now initialize the fields.
207 // rax: initial map
208 // rbx: JSObject (not HeapObject tagged - the actual address).
209 // rdi: start of next object
210 __ movp(Operand(rbx, JSObject::kMapOffset), rax);
211 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
212 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx);
213 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx);
214 // Set extra fields in the newly allocated object.
215 // rax: initial map
216 // rbx: JSObject
217 // rdi: start of next object
218 // rsi: slack tracking counter (non-API function case)
219 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize));
220 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
221 if (!is_api_function) {
222 Label no_inobject_slack_tracking;
223
224 // Check if slack tracking is enabled.
225 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd));
226 __ j(less, &no_inobject_slack_tracking);
227
228 // Allocate object with a slack.
229 __ movzxbp(
230 rsi,
231 FieldOperand(
232 rax,
233 Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
234 __ movzxbp(rax, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
235 __ subp(rsi, rax);
236 __ leap(rsi,
237 Operand(rbx, rsi, times_pointer_size, JSObject::kHeaderSize));
238 // rsi: offset of first field after pre-allocated fields
239 if (FLAG_debug_code) {
240 __ cmpp(rsi, rdi);
241 __ Assert(less_equal,
242 kUnexpectedNumberOfPreAllocatedPropertyFields);
243 }
244 __ InitializeFieldsWithFiller(rcx, rsi, rdx);
245 __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
246 // Fill the remaining fields with one pointer filler map.
247
248 __ bind(&no_inobject_slack_tracking);
249 }
250
251 __ InitializeFieldsWithFiller(rcx, rdi, rdx);
252
253 // Add the object tag to make the JSObject real, so that we can continue
254 // and jump into the continuation code at any time from now on.
255 // rbx: JSObject (untagged)
256 __ orp(rbx, Immediate(kHeapObjectTag));
257
258 // Continue with JSObject being successfully allocated
259 // rbx: JSObject (tagged)
260 __ jmp(&allocated);
202 } 261 }
203 262
204 // Now allocate the JSObject on the heap. 263 // Allocate the new receiver object using the runtime call.
205 __ movzxbp(rdi, FieldOperand(rax, Map::kInstanceSizeOffset)); 264 // rdx: new target
206 __ shlp(rdi, Immediate(kPointerSizeLog2)); 265 __ bind(&rt_call);
207 // rdi: size of new object 266 int offset = kPointerSize;
208 __ Allocate(rdi,
209 rbx,
210 rdi,
211 no_reg,
212 &rt_call,
213 NO_ALLOCATION_FLAGS);
214 // Allocated the JSObject, now initialize the fields.
215 // rax: initial map
216 // rbx: JSObject (not HeapObject tagged - the actual address).
217 // rdi: start of next object
218 __ movp(Operand(rbx, JSObject::kMapOffset), rax);
219 __ LoadRoot(rcx, Heap::kEmptyFixedArrayRootIndex);
220 __ movp(Operand(rbx, JSObject::kPropertiesOffset), rcx);
221 __ movp(Operand(rbx, JSObject::kElementsOffset), rcx);
222 // Set extra fields in the newly allocated object.
223 // rax: initial map
224 // rbx: JSObject
225 // rdi: start of next object
226 // rsi: slack tracking counter (non-API function case)
227 __ leap(rcx, Operand(rbx, JSObject::kHeaderSize));
228 __ LoadRoot(rdx, Heap::kUndefinedValueRootIndex);
229 if (!is_api_function) {
230 Label no_inobject_slack_tracking;
231 267
232 // Check if slack tracking is enabled. 268 // Must restore rsi (context) and rdi (constructor) before calling
233 __ cmpl(rsi, Immediate(Map::kSlackTrackingCounterEnd)); 269 // runtime.
234 __ j(less, &no_inobject_slack_tracking); 270 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
271 __ movp(rdi, Operand(rsp, offset));
272 __ Push(rdi); // constructor function
273 __ Push(rdx); // new target
274 __ CallRuntime(Runtime::kNewObject, 2);
275 __ movp(rbx, rax); // store result in rbx
235 276
236 // Allocate object with a slack. 277 // New object allocated.
237 __ movzxbp( 278 // rbx: newly allocated object
238 rsi, 279 __ bind(&allocated);
239 FieldOperand(
240 rax, Map::kInObjectPropertiesOrConstructorFunctionIndexOffset));
241 __ movzxbp(rax, FieldOperand(rax, Map::kUnusedPropertyFieldsOffset));
242 __ subp(rsi, rax);
243 __ leap(rsi,
244 Operand(rbx, rsi, times_pointer_size, JSObject::kHeaderSize));
245 // rsi: offset of first field after pre-allocated fields
246 if (FLAG_debug_code) {
247 __ cmpp(rsi, rdi);
248 __ Assert(less_equal,
249 kUnexpectedNumberOfPreAllocatedPropertyFields);
250 }
251 __ InitializeFieldsWithFiller(rcx, rsi, rdx);
252 __ LoadRoot(rdx, Heap::kOnePointerFillerMapRootIndex);
253 // Fill the remaining fields with one pointer filler map.
254 280
255 __ bind(&no_inobject_slack_tracking); 281 // Restore the parameters.
256 } 282 __ Pop(rdx);
283 __ Pop(rdi);
257 284
258 __ InitializeFieldsWithFiller(rcx, rdi, rdx); 285 // Retrieve smi-tagged arguments count from the stack.
259 286 __ movp(rax, Operand(rsp, 0));
260 // Add the object tag to make the JSObject real, so that we can continue 287 __ SmiToInteger32(rax, rax);
261 // and jump into the continuation code at any time from now on.
262 // rbx: JSObject (untagged)
263 __ orp(rbx, Immediate(kHeapObjectTag));
264
265 // Continue with JSObject being successfully allocated
266 // rbx: JSObject (tagged)
267 __ jmp(&allocated);
268 } 288 }
269 289
270 // Allocate the new receiver object using the runtime call.
271 // rdx: new target
272 __ bind(&rt_call);
273 int offset = kPointerSize;
274
275 // Must restore rsi (context) and rdi (constructor) before calling runtime.
276 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
277 __ movp(rdi, Operand(rsp, offset));
278 __ Push(rdi); // constructor function
279 __ Push(rdx); // new target
280 __ CallRuntime(Runtime::kNewObject, 2);
281 __ movp(rbx, rax); // store result in rbx
282
283 // New object allocated.
284 // rbx: newly allocated object
285 __ bind(&allocated);
286
287 // Restore the parameters.
288 __ Pop(rdx);
289 __ Pop(rdi);
290
291 // Retrieve smi-tagged arguments count from the stack.
292 __ movp(rax, Operand(rsp, 0));
293 __ SmiToInteger32(rax, rax);
294
295 // Push new.target onto the construct frame. This is stored just below the 290 // Push new.target onto the construct frame. This is stored just below the
296 // receiver on the stack. 291 // receiver on the stack.
297 __ Push(rdx); 292 __ Push(rdx);
298 293
299 // Push the allocated receiver to the stack. We need two copies 294 if (create_implicit_receiver) {
300 // because we may have to return the original one and the calling 295 // Push the allocated receiver to the stack. We need two copies
301 // conventions dictate that the called function pops the receiver. 296 // because we may have to return the original one and the calling
302 __ Push(rbx); 297 // conventions dictate that the called function pops the receiver.
303 __ Push(rbx); 298 __ Push(rbx);
299 __ Push(rbx);
300 } else {
301 __ PushRoot(Heap::kTheHoleValueRootIndex);
302 }
304 303
305 // Set up pointer to last argument. 304 // Set up pointer to last argument.
306 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset)); 305 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
307 306
308 // Copy arguments and receiver to the expression stack. 307 // Copy arguments and receiver to the expression stack.
309 Label loop, entry; 308 Label loop, entry;
310 __ movp(rcx, rax); 309 __ movp(rcx, rax);
311 __ jmp(&entry); 310 __ jmp(&entry);
312 __ bind(&loop); 311 __ bind(&loop);
313 __ Push(Operand(rbx, rcx, times_pointer_size, 0)); 312 __ Push(Operand(rbx, rcx, times_pointer_size, 0));
314 __ bind(&entry); 313 __ bind(&entry);
315 __ decp(rcx); 314 __ decp(rcx);
316 __ j(greater_equal, &loop); 315 __ j(greater_equal, &loop);
317 316
318 // Call the function. 317 // Call the function.
319 if (is_api_function) { 318 if (is_api_function) {
320 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 319 __ movp(rsi, FieldOperand(rdi, JSFunction::kContextOffset));
321 Handle<Code> code = 320 Handle<Code> code =
322 masm->isolate()->builtins()->HandleApiCallConstruct(); 321 masm->isolate()->builtins()->HandleApiCallConstruct();
323 __ Call(code, RelocInfo::CODE_TARGET); 322 __ Call(code, RelocInfo::CODE_TARGET);
324 } else { 323 } else {
325 ParameterCount actual(rax); 324 ParameterCount actual(rax);
326 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper()); 325 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
327 } 326 }
328 327
329 // Store offset of return address for deoptimizer. 328 // Store offset of return address for deoptimizer.
330 if (!is_api_function) { 329 if (create_implicit_receiver && !is_api_function) {
331 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 330 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
332 } 331 }
333 332
334 // Restore context from the frame. 333 // Restore context from the frame.
335 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); 334 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
336 335
337 // If the result is an object (in the ECMA sense), we should get rid 336 if (create_implicit_receiver) {
338 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 337 // If the result is an object (in the ECMA sense), we should get rid
339 // on page 74. 338 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
340 Label use_receiver, exit; 339 // on page 74.
341 // If the result is a smi, it is *not* an object in the ECMA sense. 340 Label use_receiver, exit;
342 __ JumpIfSmi(rax, &use_receiver); 341 // If the result is a smi, it is *not* an object in the ECMA sense.
342 __ JumpIfSmi(rax, &use_receiver);
343 343
344 // If the type of the result (stored in its map) is less than 344 // If the type of the result (stored in its map) is less than
345 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 345 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
346 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); 346 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE);
347 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx); 347 __ CmpObjectType(rax, FIRST_SPEC_OBJECT_TYPE, rcx);
348 __ j(above_equal, &exit); 348 __ j(above_equal, &exit);
349 349
350 // Throw away the result of the constructor invocation and use the 350 // Throw away the result of the constructor invocation and use the
351 // on-stack receiver as the result. 351 // on-stack receiver as the result.
352 __ bind(&use_receiver); 352 __ bind(&use_receiver);
353 __ movp(rax, Operand(rsp, 0)); 353 __ movp(rax, Operand(rsp, 0));
354 354
355 // Restore the arguments count and leave the construct frame. The arguments 355 // Restore the arguments count and leave the construct frame. The
356 // count is stored below the reciever and the new.target. 356 // arguments count is stored below the reciever and the new.target.
357 __ bind(&exit); 357 __ bind(&exit);
358 __ movp(rbx, Operand(rsp, 2 * kPointerSize)); 358 __ movp(rbx, Operand(rsp, 2 * kPointerSize));
359 } else {
360 __ movp(rbx, Operand(rsp, kPointerSize));
361 }
359 362
360 // Leave construct frame. 363 // Leave construct frame.
361 } 364 }
362 365
363 // Remove caller arguments from the stack and return. 366 // Remove caller arguments from the stack and return.
364 __ PopReturnAddressTo(rcx); 367 __ PopReturnAddressTo(rcx);
365 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2); 368 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
366 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize)); 369 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
367 __ PushReturnAddressFrom(rcx); 370 __ PushReturnAddressFrom(rcx);
368 Counters* counters = masm->isolate()->counters(); 371 if (create_implicit_receiver) {
369 __ IncrementCounter(counters->constructed_objects(), 1); 372 Counters* counters = masm->isolate()->counters();
373 __ IncrementCounter(counters->constructed_objects(), 1);
374 }
370 __ ret(0); 375 __ ret(0);
371 } 376 }
372 377
373 378
374 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 379 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
375 Generate_JSConstructStubHelper(masm, false); 380 Generate_JSConstructStubHelper(masm, false, true);
376 } 381 }
377 382
378 383
379 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 384 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
380 Generate_JSConstructStubHelper(masm, true); 385 Generate_JSConstructStubHelper(masm, true, true);
381 } 386 }
382 387
383 388
384 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 389 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
385 // ----------- S t a t e ------------- 390 Generate_JSConstructStubHelper(masm, false, false);
386 // -- rax: number of arguments
387 // -- rdi: constructor function
388 // -- rbx: allocation site or undefined
389 // -- rdx: new target
390 // -----------------------------------
391
392 {
393 FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
394
395 // Preserve allocation site.
396 __ AssertUndefinedOrAllocationSite(rbx);
397 __ Push(rbx);
398
399 // Store a smi-tagged arguments count on the stack.
400 __ Integer32ToSmi(rax, rax);
401 __ Push(rax);
402 __ SmiToInteger32(rax, rax);
403
404 // Push new.target
405 __ Push(rdx);
406
407 // receiver is the hole.
408 __ Push(masm->isolate()->factory()->the_hole_value());
409
410 // Set up pointer to last argument.
411 __ leap(rbx, Operand(rbp, StandardFrameConstants::kCallerSPOffset));
412
413 // Copy arguments and receiver to the expression stack.
414 Label loop, entry;
415 __ movp(rcx, rax);
416 __ jmp(&entry);
417 __ bind(&loop);
418 __ Push(Operand(rbx, rcx, times_pointer_size, 0));
419 __ bind(&entry);
420 __ decp(rcx);
421 __ j(greater_equal, &loop);
422
423 // Call the function.
424 ParameterCount actual(rax);
425 __ InvokeFunction(rdi, actual, CALL_FUNCTION, NullCallWrapper());
426
427 // Restore context from the frame.
428 __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
429
430 // Get arguments count, skipping over new.target.
431 __ movp(rbx, Operand(rsp, kPointerSize)); // Get arguments count.
432 } // Leave construct frame.
433
434 // Remove caller arguments from the stack and return.
435 __ PopReturnAddressTo(rcx);
436 SmiIndex index = masm->SmiToIndex(rbx, rbx, kPointerSizeLog2);
437 __ leap(rsp, Operand(rsp, index.reg, index.scale, 1 * kPointerSize));
438 __ PushReturnAddressFrom(rcx);
439 __ ret(0);
440 } 391 }
441 392
442 393
443 enum IsTagged { kRaxIsSmiTagged, kRaxIsUntaggedInt }; 394 enum IsTagged { kRaxIsSmiTagged, kRaxIsUntaggedInt };
444 395
445 396
446 // Clobbers rcx, r11, kScratchRegister; preserves all other registers. 397 // Clobbers rcx, r11, kScratchRegister; preserves all other registers.
447 static void Generate_CheckStackOverflow(MacroAssembler* masm, 398 static void Generate_CheckStackOverflow(MacroAssembler* masm,
448 IsTagged rax_is_tagged) { 399 IsTagged rax_is_tagged) {
449 // rax : the number of items to be pushed to the stack 400 // rax : the number of items to be pushed to the stack
(...skipping 1528 matching lines...) Expand 10 before | Expand all | Expand 10 after
1978 __ ret(0); 1929 __ ret(0);
1979 } 1930 }
1980 1931
1981 1932
1982 #undef __ 1933 #undef __
1983 1934
1984 } // namespace internal 1935 } // namespace internal
1985 } // namespace v8 1936 } // namespace v8
1986 1937
1987 #endif // V8_TARGET_ARCH_X64 1938 #endif // V8_TARGET_ARCH_X64
OLDNEW
« no previous file with comments | « src/types.cc ('k') | test/mjsunit/es6/classes-subclass-builtins.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698