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

Side by Side Diff: src/arm/builtins-arm.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/api.cc ('k') | src/arm64/builtins-arm64.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 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_ARM 5 #if V8_TARGET_ARCH_ARM
6 6
7 #include "src/codegen.h" 7 #include "src/codegen.h"
8 #include "src/debug/debug.h" 8 #include "src/debug/debug.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 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 331
332 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode); 332 CallRuntimePassFunction(masm, Runtime::kTryInstallOptimizedCode);
333 GenerateTailCallToReturnedCode(masm); 333 GenerateTailCallToReturnedCode(masm);
334 334
335 __ bind(&ok); 335 __ bind(&ok);
336 GenerateTailCallToSharedCode(masm); 336 GenerateTailCallToSharedCode(masm);
337 } 337 }
338 338
339 339
340 static void Generate_JSConstructStubHelper(MacroAssembler* masm, 340 static void Generate_JSConstructStubHelper(MacroAssembler* masm,
341 bool is_api_function) { 341 bool is_api_function,
342 bool create_implicit_receiver) {
342 // ----------- S t a t e ------------- 343 // ----------- S t a t e -------------
343 // -- r0 : number of arguments 344 // -- r0 : number of arguments
344 // -- r1 : constructor function 345 // -- r1 : constructor function
345 // -- r2 : allocation site or undefined 346 // -- r2 : allocation site or undefined
346 // -- r3 : new target 347 // -- r3 : new target
347 // -- lr : return address 348 // -- lr : return address
348 // -- sp[...]: constructor arguments 349 // -- sp[...]: constructor arguments
349 // ----------------------------------- 350 // -----------------------------------
350 351
351 Isolate* isolate = masm->isolate(); 352 Isolate* isolate = masm->isolate();
352 353
353 // Enter a construct frame. 354 // Enter a construct frame.
354 { 355 {
355 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); 356 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT);
356 357
357 // Preserve the incoming parameters on the stack. 358 // Preserve the incoming parameters on the stack.
358 __ AssertUndefinedOrAllocationSite(r2, r4); 359 __ AssertUndefinedOrAllocationSite(r2, r4);
359 __ push(r2); 360 __ push(r2);
360 __ SmiTag(r0); 361 __ SmiTag(r0);
361 __ push(r0); 362 __ push(r0);
362 __ push(r1);
363 __ push(r3);
364 363
365 // Try to allocate the object without transitioning into C code. If any of 364 if (create_implicit_receiver) {
366 // the preconditions is not met, the code bails out to the runtime call. 365 __ push(r1);
367 Label rt_call, allocated; 366 __ push(r3);
368 if (FLAG_inline_new) {
369 // Verify that the new target is a JSFunction.
370 __ CompareObjectType(r3, r5, r4, JS_FUNCTION_TYPE);
371 __ b(ne, &rt_call);
372 367
373 // Load the initial map and verify that it is in fact a map. 368 // Try to allocate the object without transitioning into C code. If any of
374 // r3: new target 369 // the preconditions is not met, the code bails out to the runtime call.
375 __ ldr(r2, FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset)); 370 Label rt_call, allocated;
376 __ JumpIfSmi(r2, &rt_call); 371 if (FLAG_inline_new) {
377 __ CompareObjectType(r2, r5, r4, MAP_TYPE); 372 // Verify that the new target is a JSFunction.
378 __ b(ne, &rt_call); 373 __ CompareObjectType(r3, r5, r4, JS_FUNCTION_TYPE);
374 __ b(ne, &rt_call);
379 375
380 // Fall back to runtime if the expected base constructor and base 376 // Load the initial map and verify that it is in fact a map.
381 // constructor differ. 377 // r3: new target
382 __ ldr(r5, FieldMemOperand(r2, Map::kConstructorOrBackPointerOffset)); 378 __ ldr(r2,
383 __ cmp(r1, r5); 379 FieldMemOperand(r3, JSFunction::kPrototypeOrInitialMapOffset));
384 __ b(ne, &rt_call); 380 __ JumpIfSmi(r2, &rt_call);
381 __ CompareObjectType(r2, r5, r4, MAP_TYPE);
382 __ b(ne, &rt_call);
385 383
386 // Check that the constructor is not constructing a JSFunction (see 384 // Fall back to runtime if the expected base constructor and base
387 // comments in Runtime_NewObject in runtime.cc). In which case the 385 // constructor differ.
388 // initial map's instance type would be JS_FUNCTION_TYPE. 386 __ ldr(r5, FieldMemOperand(r2, Map::kConstructorOrBackPointerOffset));
389 // r1: constructor function 387 __ cmp(r1, r5);
390 // r2: initial map 388 __ b(ne, &rt_call);
391 __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE);
392 __ b(eq, &rt_call);
393 389
394 if (!is_api_function) { 390 // Check that the constructor is not constructing a JSFunction (see
395 Label allocate; 391 // comments in Runtime_NewObject in runtime.cc). In which case the
396 MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset); 392 // initial map's instance type would be JS_FUNCTION_TYPE.
397 // Check if slack tracking is enabled. 393 // r1: constructor function
398 __ ldr(r4, bit_field3); 394 // r2: initial map
399 __ DecodeField<Map::Counter>(r3, r4); 395 __ CompareInstanceType(r2, r5, JS_FUNCTION_TYPE);
400 __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd)); 396 __ b(eq, &rt_call);
401 __ b(lt, &allocate);
402 // Decrease generous allocation count.
403 __ sub(r4, r4, Operand(1 << Map::Counter::kShift));
404 __ str(r4, bit_field3);
405 __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
406 __ b(ne, &allocate);
407 397
408 __ Push(r1, r2); 398 if (!is_api_function) {
399 Label allocate;
400 MemOperand bit_field3 = FieldMemOperand(r2, Map::kBitField3Offset);
401 // Check if slack tracking is enabled.
402 __ ldr(r4, bit_field3);
403 __ DecodeField<Map::Counter>(r3, r4);
404 __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
405 __ b(lt, &allocate);
406 // Decrease generous allocation count.
407 __ sub(r4, r4, Operand(1 << Map::Counter::kShift));
408 __ str(r4, bit_field3);
409 __ cmp(r3, Operand(Map::kSlackTrackingCounterEnd));
410 __ b(ne, &allocate);
409 411
410 __ push(r2); // r2 = intial map 412 __ Push(r1, r2);
411 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
412 413
413 __ pop(r2); 414 __ push(r2); // r2 = intial map
414 __ pop(r1); 415 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1);
415 416
416 __ bind(&allocate); 417 __ pop(r2);
418 __ pop(r1);
419
420 __ bind(&allocate);
421 }
422
423 // Now allocate the JSObject on the heap.
424 // r1: constructor function
425 // r2: initial map
426 Label rt_call_reload_new_target;
427 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
428
429 __ Allocate(r3, r4, r5, r6, &rt_call_reload_new_target, SIZE_IN_WORDS);
430
431 // Allocated the JSObject, now initialize the fields. Map is set to
432 // initial map and properties and elements are set to empty fixed array.
433 // r1: constructor function
434 // r2: initial map
435 // r3: object size
436 // r4: JSObject (not tagged)
437 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
438 __ mov(r5, r4);
439 DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
440 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
441 DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
442 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
443 DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
444 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
445
446 // Fill all the in-object properties with the appropriate filler.
447 // r1: constructor function
448 // r2: initial map
449 // r3: object size
450 // r4: JSObject (not tagged)
451 // r5: First in-object property of JSObject (not tagged)
452 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
453 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
454
455 if (!is_api_function) {
456 Label no_inobject_slack_tracking;
457
458 // Check if slack tracking is enabled.
459 __ ldr(ip, FieldMemOperand(r2, Map::kBitField3Offset));
460 __ DecodeField<Map::Counter>(ip);
461 __ cmp(ip, Operand(Map::kSlackTrackingCounterEnd));
462 __ b(lt, &no_inobject_slack_tracking);
463
464 // Allocate object with a slack.
465 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
466 __ Ubfx(r0, r0,
467 Map::kInObjectPropertiesOrConstructorFunctionIndexByte *
468 kBitsPerByte,
469 kBitsPerByte);
470 __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset));
471 __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
472 kBitsPerByte);
473 __ sub(r0, r0, Operand(r2));
474 __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
475 // r0: offset of first field after pre-allocated fields
476 if (FLAG_debug_code) {
477 __ add(ip, r4,
478 Operand(r3, LSL, kPointerSizeLog2)); // End of object.
479 __ cmp(r0, ip);
480 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
481 }
482 __ InitializeFieldsWithFiller(r5, r0, r6);
483 // To allow for truncation.
484 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
485 // Fill the remaining fields with one pointer filler map.
486
487 __ bind(&no_inobject_slack_tracking);
488 }
489
490 __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
491 __ InitializeFieldsWithFiller(r5, r0, r6);
492
493 // Add the object tag to make the JSObject real, so that we can continue
494 // and jump into the continuation code at any time from now on.
495 __ add(r4, r4, Operand(kHeapObjectTag));
496
497 // Continue with JSObject being successfully allocated
498 // r4: JSObject
499 __ jmp(&allocated);
500
501 // Reload the new target and fall-through.
502 __ bind(&rt_call_reload_new_target);
503 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
417 } 504 }
418 505
419 // Now allocate the JSObject on the heap. 506 // Allocate the new receiver object using the runtime call.
420 // r1: constructor function 507 // r1: constructor function
421 // r2: initial map 508 // r3: new target
422 Label rt_call_reload_new_target; 509 __ bind(&rt_call);
423 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset));
424 510
425 __ Allocate(r3, r4, r5, r6, &rt_call_reload_new_target, SIZE_IN_WORDS); 511 __ push(r1); // constructor function
512 __ push(r3); // new target
513 __ CallRuntime(Runtime::kNewObject, 2);
514 __ mov(r4, r0);
426 515
427 // Allocated the JSObject, now initialize the fields. Map is set to 516 // Receiver for constructor call allocated.
428 // initial map and properties and elements are set to empty fixed array. 517 // r4: JSObject
429 // r1: constructor function 518 __ bind(&allocated);
430 // r2: initial map
431 // r3: object size
432 // r4: JSObject (not tagged)
433 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex);
434 __ mov(r5, r4);
435 DCHECK_EQ(0 * kPointerSize, JSObject::kMapOffset);
436 __ str(r2, MemOperand(r5, kPointerSize, PostIndex));
437 DCHECK_EQ(1 * kPointerSize, JSObject::kPropertiesOffset);
438 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
439 DCHECK_EQ(2 * kPointerSize, JSObject::kElementsOffset);
440 __ str(r6, MemOperand(r5, kPointerSize, PostIndex));
441 519
442 // Fill all the in-object properties with the appropriate filler. 520 // Restore the parameters.
443 // r1: constructor function 521 __ pop(r3);
444 // r2: initial map 522 __ pop(r1);
445 // r3: object size
446 // r4: JSObject (not tagged)
447 // r5: First in-object property of JSObject (not tagged)
448 DCHECK_EQ(3 * kPointerSize, JSObject::kHeaderSize);
449 __ LoadRoot(r6, Heap::kUndefinedValueRootIndex);
450 523
451 if (!is_api_function) { 524 // Retrieve smi-tagged arguments count from the stack.
452 Label no_inobject_slack_tracking; 525 __ ldr(r0, MemOperand(sp));
453
454 // Check if slack tracking is enabled.
455 __ ldr(ip, FieldMemOperand(r2, Map::kBitField3Offset));
456 __ DecodeField<Map::Counter>(ip);
457 __ cmp(ip, Operand(Map::kSlackTrackingCounterEnd));
458 __ b(lt, &no_inobject_slack_tracking);
459
460 // Allocate object with a slack.
461 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset));
462 __ Ubfx(r0, r0, Map::kInObjectPropertiesOrConstructorFunctionIndexByte *
463 kBitsPerByte,
464 kBitsPerByte);
465 __ ldr(r2, FieldMemOperand(r2, Map::kInstanceAttributesOffset));
466 __ Ubfx(r2, r2, Map::kUnusedPropertyFieldsByte * kBitsPerByte,
467 kBitsPerByte);
468 __ sub(r0, r0, Operand(r2));
469 __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2));
470 // r0: offset of first field after pre-allocated fields
471 if (FLAG_debug_code) {
472 __ add(ip, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
473 __ cmp(r0, ip);
474 __ Assert(le, kUnexpectedNumberOfPreAllocatedPropertyFields);
475 }
476 __ InitializeFieldsWithFiller(r5, r0, r6);
477 // To allow for truncation.
478 __ LoadRoot(r6, Heap::kOnePointerFillerMapRootIndex);
479 // Fill the remaining fields with one pointer filler map.
480
481 __ bind(&no_inobject_slack_tracking);
482 }
483
484 __ add(r0, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object.
485 __ InitializeFieldsWithFiller(r5, r0, r6);
486
487 // Add the object tag to make the JSObject real, so that we can continue
488 // and jump into the continuation code at any time from now on.
489 __ add(r4, r4, Operand(kHeapObjectTag));
490
491 // Continue with JSObject being successfully allocated
492 // r4: JSObject
493 __ jmp(&allocated);
494
495 // Reload the new target and fall-through.
496 __ bind(&rt_call_reload_new_target);
497 __ ldr(r3, MemOperand(sp, 0 * kPointerSize));
498 } 526 }
499 527
500 // Allocate the new receiver object using the runtime call.
501 // r1: constructor function
502 // r3: new target
503 __ bind(&rt_call);
504
505 __ push(r1); // constructor function
506 __ push(r3); // new target
507 __ CallRuntime(Runtime::kNewObject, 2);
508 __ mov(r4, r0);
509
510 // Receiver for constructor call allocated.
511 // r4: JSObject
512 __ bind(&allocated);
513
514 // Restore the parameters.
515 __ pop(r3);
516 __ pop(r1);
517
518 // Retrieve smi-tagged arguments count from the stack.
519 __ ldr(r0, MemOperand(sp));
520 __ SmiUntag(r0); 528 __ SmiUntag(r0);
521 529
522 // Push new.target onto the construct frame. This is stored just below the 530 // Push new.target onto the construct frame. This is stored just below the
523 // receiver on the stack. 531 // receiver on the stack.
524 __ push(r3); 532 __ push(r3);
525 __ push(r4); 533
526 __ push(r4); 534 if (create_implicit_receiver) {
535 // Push the allocated receiver to the stack. We need two copies
536 // because we may have to return the original one and the calling
537 // conventions dictate that the called function pops the receiver.
538 __ push(r4);
539 __ push(r4);
540 } else {
541 __ PushRoot(Heap::kTheHoleValueRootIndex);
542 }
527 543
528 // Set up pointer to last argument. 544 // Set up pointer to last argument.
529 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); 545 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
530 546
531 // Copy arguments and receiver to the expression stack. 547 // Copy arguments and receiver to the expression stack.
532 // r0: number of arguments 548 // r0: number of arguments
533 // r1: constructor function 549 // r1: constructor function
534 // r2: address of last argument (caller sp) 550 // r2: address of last argument (caller sp)
535 // r3: number of arguments (smi-tagged) 551 // r3: number of arguments (smi-tagged)
536 // sp[0]: receiver 552 // sp[0]: receiver
(...skipping 17 matching lines...) Expand all
554 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); 570 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset));
555 Handle<Code> code = 571 Handle<Code> code =
556 masm->isolate()->builtins()->HandleApiCallConstruct(); 572 masm->isolate()->builtins()->HandleApiCallConstruct();
557 __ Call(code, RelocInfo::CODE_TARGET); 573 __ Call(code, RelocInfo::CODE_TARGET);
558 } else { 574 } else {
559 ParameterCount actual(r0); 575 ParameterCount actual(r0);
560 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); 576 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper());
561 } 577 }
562 578
563 // Store offset of return address for deoptimizer. 579 // Store offset of return address for deoptimizer.
564 if (!is_api_function) { 580 if (create_implicit_receiver && !is_api_function) {
565 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); 581 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset());
566 } 582 }
567 583
568 // Restore context from the frame. 584 // Restore context from the frame.
569 // r0: result 585 // r0: result
570 // sp[0]: receiver 586 // sp[0]: receiver
571 // sp[1]: new.target 587 // sp[1]: new.target
572 // sp[2]: number of arguments (smi-tagged) 588 // sp[2]: number of arguments (smi-tagged)
573 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); 589 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
574 590
575 // If the result is an object (in the ECMA sense), we should get rid 591 if (create_implicit_receiver) {
576 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 592 // If the result is an object (in the ECMA sense), we should get rid
577 // on page 74. 593 // of the receiver and use the result; see ECMA-262 section 13.2.2-7
578 Label use_receiver, exit; 594 // on page 74.
595 Label use_receiver, exit;
579 596
580 // If the result is a smi, it is *not* an object in the ECMA sense. 597 // If the result is a smi, it is *not* an object in the ECMA sense.
581 // r0: result 598 // r0: result
582 // sp[0]: receiver 599 // sp[0]: receiver
583 // sp[1]: new.target 600 // sp[1]: new.target
584 // sp[2]: number of arguments (smi-tagged) 601 // sp[2]: number of arguments (smi-tagged)
585 __ JumpIfSmi(r0, &use_receiver); 602 __ JumpIfSmi(r0, &use_receiver);
586 603
587 // If the type of the result (stored in its map) is less than 604 // If the type of the result (stored in its map) is less than
588 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. 605 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense.
589 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); 606 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE);
590 __ b(ge, &exit); 607 __ b(ge, &exit);
591 608
592 // Throw away the result of the constructor invocation and use the 609 // Throw away the result of the constructor invocation and use the
593 // on-stack receiver as the result. 610 // on-stack receiver as the result.
594 __ bind(&use_receiver); 611 __ bind(&use_receiver);
595 __ ldr(r0, MemOperand(sp)); 612 __ ldr(r0, MemOperand(sp));
596 613
597 // Remove receiver from the stack, remove caller arguments, and 614 // Remove receiver from the stack, remove caller arguments, and
598 // return. 615 // return.
599 __ bind(&exit); 616 __ bind(&exit);
600 // r0: result 617 // r0: result
601 // sp[0]: receiver (newly allocated object) 618 // sp[0]: receiver (newly allocated object)
602 // sp[1]: new target 619 // sp[1]: new target
603 // sp[2]: number of arguments (smi-tagged) 620 // sp[2]: number of arguments (smi-tagged)
604 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); 621 __ ldr(r1, MemOperand(sp, 2 * kPointerSize));
622 } else {
623 __ ldr(r1, MemOperand(sp, kPointerSize));
624 }
605 625
606 // Leave construct frame. 626 // Leave construct frame.
607 } 627 }
608 628
609 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); 629 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
610 __ add(sp, sp, Operand(kPointerSize)); 630 __ add(sp, sp, Operand(kPointerSize));
611 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); 631 if (create_implicit_receiver) {
632 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2);
633 }
612 __ Jump(lr); 634 __ Jump(lr);
613 } 635 }
614 636
615 637
616 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { 638 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) {
617 Generate_JSConstructStubHelper(masm, false); 639 Generate_JSConstructStubHelper(masm, false, true);
618 } 640 }
619 641
620 642
621 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { 643 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) {
622 Generate_JSConstructStubHelper(masm, true); 644 Generate_JSConstructStubHelper(masm, true, true);
623 } 645 }
624 646
625 647
626 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { 648 void Builtins::Generate_JSBuiltinsConstructStub(MacroAssembler* masm) {
627 // ----------- S t a t e ------------- 649 Generate_JSConstructStubHelper(masm, false, false);
628 // -- r0 : number of arguments
629 // -- r1 : constructor function
630 // -- r2 : allocation site or undefined
631 // -- r3 : new target
632 // -- lr : return address
633 // -- sp[...]: constructor arguments
634 // -----------------------------------
635
636 {
637 FrameScope frame_scope(masm, StackFrame::CONSTRUCT);
638
639 __ AssertUndefinedOrAllocationSite(r2, r4);
640 __ push(r2);
641
642 __ mov(r4, r0);
643 __ SmiTag(r4);
644 __ push(r4); // Smi-tagged arguments count.
645
646 // Push new.target.
647 __ push(r3);
648
649 // receiver is the hole.
650 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex);
651 __ push(ip);
652
653 // Set up pointer to last argument.
654 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset));
655
656 // Copy arguments and receiver to the expression stack.
657 // r0: number of arguments
658 // r1: constructor function
659 // r2: address of last argument (caller sp)
660 // r4: number of arguments (smi-tagged)
661 // sp[0]: receiver
662 // sp[1]: new.target
663 // sp[2]: number of arguments (smi-tagged)
664 Label loop, entry;
665 __ b(&entry);
666 __ bind(&loop);
667 __ ldr(ip, MemOperand(r2, r4, LSL, kPointerSizeLog2 - 1));
668 __ push(ip);
669 __ bind(&entry);
670 __ sub(r4, r4, Operand(2), SetCC);
671 __ b(ge, &loop);
672
673 // Call the function.
674 // r0: number of arguments
675 // r1: constructor function
676 ParameterCount actual(r0);
677 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper());
678
679 // Restore context from the frame.
680 // r0: result
681 // sp[0]: number of arguments (smi-tagged)
682 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset));
683 // Get arguments count, skipping over new.target.
684 __ ldr(r1, MemOperand(sp, kPointerSize));
685
686 // Leave construct frame.
687 }
688
689 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1));
690 __ add(sp, sp, Operand(kPointerSize));
691 __ Jump(lr);
692 } 650 }
693 651
694 652
695 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt }; 653 enum IsTagged { kArgcIsSmiTagged, kArgcIsUntaggedInt };
696 654
697 655
698 // Clobbers r2; preserves all other registers. 656 // Clobbers r2; preserves all other registers.
699 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc, 657 static void Generate_CheckStackOverflow(MacroAssembler* masm, Register argc,
700 IsTagged argc_is_tagged) { 658 IsTagged argc_is_tagged) {
701 // Check the stack for overflow. We are not trying to catch 659 // Check the stack for overflow. We are not trying to catch
(...skipping 1200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1902 } 1860 }
1903 } 1861 }
1904 1862
1905 1863
1906 #undef __ 1864 #undef __
1907 1865
1908 } // namespace internal 1866 } // namespace internal
1909 } // namespace v8 1867 } // namespace v8
1910 1868
1911 #endif // V8_TARGET_ARCH_ARM 1869 #endif // V8_TARGET_ARCH_ARM
OLDNEW
« no previous file with comments | « src/api.cc ('k') | src/arm64/builtins-arm64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698