OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
324 __ Push(original_constructor); | 324 __ Push(original_constructor); |
325 __ CallRuntime(Runtime::kNewObject, 2); | 325 __ CallRuntime(Runtime::kNewObject, 2); |
326 __ Mov(x4, x0); | 326 __ Mov(x4, x0); |
327 __ jmp(allocated); | 327 __ jmp(allocated); |
328 } | 328 } |
329 } | 329 } |
330 | 330 |
331 | 331 |
332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 332 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
333 bool is_api_function, | 333 bool is_api_function, |
| 334 bool use_new_target, |
334 bool create_memento) { | 335 bool create_memento) { |
335 // ----------- S t a t e ------------- | 336 // ----------- S t a t e ------------- |
336 // -- x0 : number of arguments | 337 // -- x0 : number of arguments |
337 // -- x1 : constructor function | 338 // -- x1 : constructor function |
338 // -- x2 : allocation site or undefined | 339 // -- x2 : allocation site or undefined |
339 // -- x3 : original constructor | 340 // -- x3 : original constructor |
340 // -- lr : return address | 341 // -- lr : return address |
341 // -- sp[...]: constructor arguments | 342 // -- sp[...]: constructor arguments |
342 // ----------------------------------- | 343 // ----------------------------------- |
343 | 344 |
(...skipping 11 matching lines...) Expand all Loading... |
355 if (create_memento) { | 356 if (create_memento) { |
356 __ AssertUndefinedOrAllocationSite(x2, x10); | 357 __ AssertUndefinedOrAllocationSite(x2, x10); |
357 __ Push(x2); | 358 __ Push(x2); |
358 } | 359 } |
359 | 360 |
360 Register argc = x0; | 361 Register argc = x0; |
361 Register constructor = x1; | 362 Register constructor = x1; |
362 Register original_constructor = x3; | 363 Register original_constructor = x3; |
363 // x1: constructor function | 364 // x1: constructor function |
364 __ SmiTag(argc); | 365 __ SmiTag(argc); |
365 __ Push(argc, constructor); | 366 if (use_new_target) { |
366 // sp[0] : Constructor function. | 367 __ Push(argc, constructor, original_constructor); |
367 // sp[1]: number of arguments (smi-tagged) | 368 } else { |
| 369 __ Push(argc, constructor); |
| 370 } |
| 371 // sp[0]: new.target (if used) |
| 372 // sp[0/1]: Constructor function. |
| 373 // sp[1/2]: number of arguments (smi-tagged) |
368 | 374 |
369 Label rt_call, count_incremented, allocated, normal_new; | 375 Label rt_call, count_incremented, allocated, normal_new; |
370 __ Cmp(constructor, original_constructor); | 376 __ Cmp(constructor, original_constructor); |
371 __ B(eq, &normal_new); | 377 __ B(eq, &normal_new); |
372 Generate_Runtime_NewObject(masm, create_memento, original_constructor, | 378 Generate_Runtime_NewObject(masm, create_memento, original_constructor, |
373 &count_incremented, &allocated); | 379 &count_incremented, &allocated); |
374 | 380 |
375 __ Bind(&normal_new); | 381 __ Bind(&normal_new); |
376 | 382 |
377 // Try to allocate the object without transitioning into C code. If any of | 383 // Try to allocate the object without transitioning into C code. If any of |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
573 // Allocate the new receiver object using the runtime call. | 579 // Allocate the new receiver object using the runtime call. |
574 __ Bind(&rt_call); | 580 __ Bind(&rt_call); |
575 Generate_Runtime_NewObject(masm, create_memento, constructor, | 581 Generate_Runtime_NewObject(masm, create_memento, constructor, |
576 &count_incremented, &allocated); | 582 &count_incremented, &allocated); |
577 | 583 |
578 // Receiver for constructor call allocated. | 584 // Receiver for constructor call allocated. |
579 // x4: JSObject | 585 // x4: JSObject |
580 __ Bind(&allocated); | 586 __ Bind(&allocated); |
581 | 587 |
582 if (create_memento) { | 588 if (create_memento) { |
583 __ Peek(x10, 2 * kXRegSize); | 589 int offset = (use_new_target ? 3 : 2) * kXRegSize; |
| 590 __ Peek(x10, offset); |
584 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); | 591 __ JumpIfRoot(x10, Heap::kUndefinedValueRootIndex, &count_incremented); |
585 // r2 is an AllocationSite. We are creating a memento from it, so we | 592 // r2 is an AllocationSite. We are creating a memento from it, so we |
586 // need to increment the memento create count. | 593 // need to increment the memento create count. |
587 __ Ldr(x5, FieldMemOperand(x10, | 594 __ Ldr(x5, FieldMemOperand(x10, |
588 AllocationSite::kPretenureCreateCountOffset)); | 595 AllocationSite::kPretenureCreateCountOffset)); |
589 __ Add(x5, x5, Operand(Smi::FromInt(1))); | 596 __ Add(x5, x5, Operand(Smi::FromInt(1))); |
590 __ Str(x5, FieldMemOperand(x10, | 597 __ Str(x5, FieldMemOperand(x10, |
591 AllocationSite::kPretenureCreateCountOffset)); | 598 AllocationSite::kPretenureCreateCountOffset)); |
592 __ bind(&count_incremented); | 599 __ bind(&count_incremented); |
593 } | 600 } |
594 | 601 |
| 602 if (use_new_target) { |
| 603 __ Pop(original_constructor); |
| 604 } |
595 __ Pop(constructor); | 605 __ Pop(constructor); |
596 | 606 |
597 __ Push(x4, x4); | |
598 | |
599 // Reload the number of arguments from the stack. | 607 // Reload the number of arguments from the stack. |
600 // Set it up in x0 for the function call below. | 608 // Set it up in x0 for the function call below. |
601 // jssp[0]: receiver | 609 // jssp[0]: number of arguments (smi-tagged) |
602 // jssp[1]: receiver | 610 __ Peek(argc, 0); // Load number of arguments. |
603 // jssp[2]: number of arguments (smi-tagged) | |
604 __ Peek(argc, 2 * kXRegSize); // Load number of arguments. | |
605 __ SmiUntag(argc); | 611 __ SmiUntag(argc); |
606 | 612 |
| 613 if (use_new_target) { |
| 614 __ Push(original_constructor, x4, x4); |
| 615 } else { |
| 616 __ Push(x4, x4); |
| 617 } |
| 618 |
607 // Set up pointer to last argument. | 619 // Set up pointer to last argument. |
608 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); | 620 __ Add(x2, fp, StandardFrameConstants::kCallerSPOffset); |
609 | 621 |
610 // Copy arguments and receiver to the expression stack. | 622 // Copy arguments and receiver to the expression stack. |
611 // Copy 2 values every loop to use ldp/stp. | 623 // Copy 2 values every loop to use ldp/stp. |
612 // x0: number of arguments | 624 // x0: number of arguments |
613 // x1: constructor function | 625 // x1: constructor function |
614 // x2: address of last argument (caller sp) | 626 // x2: address of last argument (caller sp) |
615 // jssp[0]: receiver | 627 // jssp[0]: receiver |
616 // jssp[1]: receiver | 628 // jssp[1]: receiver |
617 // jssp[2]: number of arguments (smi-tagged) | 629 // jssp[2]: new.target (if used) |
| 630 // jssp[2/3]: number of arguments (smi-tagged) |
618 // Compute the start address of the copy in x3. | 631 // Compute the start address of the copy in x3. |
619 __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); | 632 __ Add(x3, x2, Operand(argc, LSL, kPointerSizeLog2)); |
620 Label loop, entry, done_copying_arguments; | 633 Label loop, entry, done_copying_arguments; |
621 __ B(&entry); | 634 __ B(&entry); |
622 __ Bind(&loop); | 635 __ Bind(&loop); |
623 __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); | 636 __ Ldp(x10, x11, MemOperand(x3, -2 * kPointerSize, PreIndex)); |
624 __ Push(x11, x10); | 637 __ Push(x11, x10); |
625 __ Bind(&entry); | 638 __ Bind(&entry); |
626 __ Cmp(x3, x2); | 639 __ Cmp(x3, x2); |
627 __ B(gt, &loop); | 640 __ B(gt, &loop); |
(...skipping 10 matching lines...) Expand all Loading... |
638 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); | 651 __ Ldr(cp, FieldMemOperand(constructor, JSFunction::kContextOffset)); |
639 Handle<Code> code = | 652 Handle<Code> code = |
640 masm->isolate()->builtins()->HandleApiCallConstruct(); | 653 masm->isolate()->builtins()->HandleApiCallConstruct(); |
641 __ Call(code, RelocInfo::CODE_TARGET); | 654 __ Call(code, RelocInfo::CODE_TARGET); |
642 } else { | 655 } else { |
643 ParameterCount actual(argc); | 656 ParameterCount actual(argc); |
644 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); | 657 __ InvokeFunction(constructor, actual, CALL_FUNCTION, NullCallWrapper()); |
645 } | 658 } |
646 | 659 |
647 // Store offset of return address for deoptimizer. | 660 // Store offset of return address for deoptimizer. |
648 if (!is_api_function) { | 661 // TODO(arv): Remove the "!use_new_target" before supporting optimization |
| 662 // of functions that reference new.target |
| 663 if (!is_api_function && !use_new_target) { |
649 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 664 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
650 } | 665 } |
651 | 666 |
652 // Restore the context from the frame. | 667 // Restore the context from the frame. |
653 // x0: result | 668 // x0: result |
654 // jssp[0]: receiver | 669 // jssp[0]: receiver |
655 // jssp[1]: number of arguments (smi-tagged) | 670 // jssp[1]: new.target (if used) |
| 671 // jssp[1/2]: number of arguments (smi-tagged) |
656 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 672 __ Ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
657 | 673 |
658 // If the result is an object (in the ECMA sense), we should get rid | 674 // If the result is an object (in the ECMA sense), we should get rid |
659 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 675 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
660 // on page 74. | 676 // on page 74. |
661 Label use_receiver, exit; | 677 Label use_receiver, exit; |
662 | 678 |
663 // If the result is a smi, it is *not* an object in the ECMA sense. | 679 // If the result is a smi, it is *not* an object in the ECMA sense. |
664 // x0: result | 680 // x0: result |
665 // jssp[0]: receiver (newly allocated object) | 681 // jssp[0]: receiver (newly allocated object) |
666 // jssp[1]: number of arguments (smi-tagged) | 682 // jssp[1]: number of arguments (smi-tagged) |
667 __ JumpIfSmi(x0, &use_receiver); | 683 __ JumpIfSmi(x0, &use_receiver); |
668 | 684 |
669 // If the type of the result (stored in its map) is less than | 685 // If the type of the result (stored in its map) is less than |
670 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 686 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
671 __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); | 687 __ JumpIfObjectType(x0, x1, x3, FIRST_SPEC_OBJECT_TYPE, &exit, ge); |
672 | 688 |
673 // Throw away the result of the constructor invocation and use the | 689 // Throw away the result of the constructor invocation and use the |
674 // on-stack receiver as the result. | 690 // on-stack receiver as the result. |
675 __ Bind(&use_receiver); | 691 __ Bind(&use_receiver); |
676 __ Peek(x0, 0); | 692 __ Peek(x0, 0); |
677 | 693 |
678 // Remove the receiver from the stack, remove caller arguments, and | 694 // Remove the receiver from the stack, remove caller arguments, and |
679 // return. | 695 // return. |
680 __ Bind(&exit); | 696 __ Bind(&exit); |
681 // x0: result | 697 // x0: result |
682 // jssp[0]: receiver (newly allocated object) | 698 // jssp[0]: receiver (newly allocated object) |
683 // jssp[1]: number of arguments (smi-tagged) | 699 // jssp[1]: new.target (if used) |
684 __ Peek(x1, kXRegSize); | 700 // jssp[1/2]: number of arguments (smi-tagged) |
| 701 int offset = (use_new_target ? 2 : 1) * kXRegSize; |
| 702 __ Peek(x1, offset); |
685 | 703 |
686 // Leave construct frame. | 704 // Leave construct frame. |
687 } | 705 } |
688 | 706 |
689 __ DropBySMI(x1); | 707 __ DropBySMI(x1); |
690 __ Drop(1); | 708 __ Drop(1); |
691 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); | 709 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, x1, x2); |
692 __ Ret(); | 710 __ Ret(); |
693 } | 711 } |
694 | 712 |
695 | 713 |
696 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 714 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
697 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 715 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
698 } | 716 } |
699 | 717 |
700 | 718 |
701 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 719 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
702 Generate_JSConstructStubHelper(masm, true, false); | 720 Generate_JSConstructStubHelper(masm, true, false, false); |
703 } | 721 } |
704 | 722 |
705 | 723 |
| 724 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { |
| 725 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); |
| 726 } |
| 727 |
| 728 |
706 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 729 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
707 // ----------- S t a t e ------------- | 730 // ----------- S t a t e ------------- |
708 // -- x0 : number of arguments | 731 // -- x0 : number of arguments |
709 // -- x1 : constructor function | 732 // -- x1 : constructor function |
710 // -- x2 : allocation site or undefined | 733 // -- x2 : allocation site or undefined |
711 // -- x3 : original constructor | 734 // -- x3 : original constructor |
712 // -- lr : return address | 735 // -- lr : return address |
713 // -- sp[...]: constructor arguments | 736 // -- sp[...]: constructor arguments |
714 // ----------------------------------- | 737 // ----------------------------------- |
715 ASM_LOCATION("Builtins::Generate_JSConstructStubForDerived"); | 738 ASM_LOCATION("Builtins::Generate_JSConstructStubForDerived"); |
(...skipping 1117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1833 } | 1856 } |
1834 } | 1857 } |
1835 | 1858 |
1836 | 1859 |
1837 #undef __ | 1860 #undef __ |
1838 | 1861 |
1839 } // namespace internal | 1862 } // namespace internal |
1840 } // namespace v8 | 1863 } // namespace v8 |
1841 | 1864 |
1842 #endif // V8_TARGET_ARCH_ARM | 1865 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |