OLD | NEW |
---|---|
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 | 5 |
6 | 6 |
7 #include "src/v8.h" | 7 #include "src/v8.h" |
8 | 8 |
9 #if V8_TARGET_ARCH_MIPS64 | 9 #if V8_TARGET_ARCH_MIPS64 |
10 | 10 |
(...skipping 329 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
340 if (create_memento) { | 340 if (create_memento) { |
341 __ jmp(count_incremented); | 341 __ jmp(count_incremented); |
342 } else { | 342 } else { |
343 __ jmp(allocated); | 343 __ jmp(allocated); |
344 } | 344 } |
345 } | 345 } |
346 | 346 |
347 | 347 |
348 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 348 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
349 bool is_api_function, | 349 bool is_api_function, |
350 bool use_new_target, | |
350 bool create_memento) { | 351 bool create_memento) { |
351 // ----------- S t a t e ------------- | 352 // ----------- S t a t e ------------- |
352 // -- a0 : number of arguments | 353 // -- a0 : number of arguments |
353 // -- a1 : constructor function | 354 // -- a1 : constructor function |
354 // -- a2 : allocation site or undefined | 355 // -- a2 : allocation site or undefined |
355 // -- a3 : original constructor | 356 // -- a3 : original constructor |
356 // -- ra : return address | 357 // -- ra : return address |
357 // -- sp[...]: constructor arguments | 358 // -- sp[...]: constructor arguments |
358 // ----------------------------------- | 359 // ----------------------------------- |
359 | 360 |
(...skipping 14 matching lines...) Expand all Loading... | |
374 FrameScope scope(masm, StackFrame::CONSTRUCT); | 375 FrameScope scope(masm, StackFrame::CONSTRUCT); |
375 | 376 |
376 if (create_memento) { | 377 if (create_memento) { |
377 __ AssertUndefinedOrAllocationSite(a2, t0); | 378 __ AssertUndefinedOrAllocationSite(a2, t0); |
378 __ push(a2); | 379 __ push(a2); |
379 } | 380 } |
380 | 381 |
381 // Preserve the two incoming parameters on the stack. | 382 // Preserve the two incoming parameters on the stack. |
382 // Tag arguments count. | 383 // Tag arguments count. |
383 __ dsll32(a0, a0, 0); | 384 __ dsll32(a0, a0, 0); |
384 __ MultiPushReversed(a0.bit() | a1.bit()); | 385 if (use_new_target) { |
386 __ MultiPushReversed(a0.bit() | a1.bit() | a3.bit()); | |
paul.l...
2015/06/26 04:02:24
nit: more readable as Push(a0, a1, a2); here and j
| |
387 } else { | |
388 __ MultiPushReversed(a0.bit() | a1.bit()); | |
389 } | |
385 | 390 |
386 Label rt_call, allocated, normal_new, count_incremented; | 391 Label rt_call, allocated, normal_new, count_incremented; |
387 __ Branch(&normal_new, eq, a1, Operand(a3)); | 392 __ Branch(&normal_new, eq, a1, Operand(a3)); |
388 | 393 |
389 // Original constructor and function are different. | 394 // Original constructor and function are different. |
390 Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented, | 395 Generate_Runtime_NewObject(masm, create_memento, a3, &count_incremented, |
391 &allocated); | 396 &allocated); |
392 __ bind(&normal_new); | 397 __ bind(&normal_new); |
393 | 398 |
394 // Try to allocate the object without transitioning into C code. If any of | 399 // Try to allocate the object without transitioning into C code. If any of |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
629 __ bind(&rt_call); | 634 __ bind(&rt_call); |
630 Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented, | 635 Generate_Runtime_NewObject(masm, create_memento, a1, &count_incremented, |
631 &allocated); | 636 &allocated); |
632 | 637 |
633 | 638 |
634 // Receiver for constructor call allocated. | 639 // Receiver for constructor call allocated. |
635 // t0: JSObject | 640 // t0: JSObject |
636 __ bind(&allocated); | 641 __ bind(&allocated); |
637 | 642 |
638 if (create_memento) { | 643 if (create_memento) { |
639 __ ld(a2, MemOperand(sp, kPointerSize * 2)); | 644 int offset = (use_new_target ? 3 : 2) * kPointerSize; |
645 __ ld(a2, MemOperand(sp, offset)); | |
640 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); | 646 __ LoadRoot(t1, Heap::kUndefinedValueRootIndex); |
641 __ Branch(&count_incremented, eq, a2, Operand(t1)); | 647 __ Branch(&count_incremented, eq, a2, Operand(t1)); |
642 // a2 is an AllocationSite. We are creating a memento from it, so we | 648 // a2 is an AllocationSite. We are creating a memento from it, so we |
643 // need to increment the memento create count. | 649 // need to increment the memento create count. |
644 __ ld(a3, FieldMemOperand(a2, | 650 __ ld(a3, FieldMemOperand(a2, |
645 AllocationSite::kPretenureCreateCountOffset)); | 651 AllocationSite::kPretenureCreateCountOffset)); |
646 __ Daddu(a3, a3, Operand(Smi::FromInt(1))); | 652 __ Daddu(a3, a3, Operand(Smi::FromInt(1))); |
647 __ sd(a3, FieldMemOperand(a2, | 653 __ sd(a3, FieldMemOperand(a2, |
648 AllocationSite::kPretenureCreateCountOffset)); | 654 AllocationSite::kPretenureCreateCountOffset)); |
649 __ bind(&count_incremented); | 655 __ bind(&count_incremented); |
650 } | 656 } |
651 | 657 |
658 // Restore the parameters. | |
659 if (use_new_target) { | |
660 __ Pop(a3); // new.target | |
661 } | |
652 __ Pop(a1); | 662 __ Pop(a1); |
653 | 663 |
654 __ Push(t0, t0); | 664 __ ld(a0, MemOperand(sp)); |
665 __ SmiUntag(a0); | |
655 | 666 |
656 // Reload the number of arguments from the stack. | 667 if (use_new_target) { |
657 // sp[0]: receiver | 668 __ Push(a3, t0, t0); |
658 // sp[1]: receiver | 669 } else { |
659 // sp[2]: number of arguments (smi-tagged) | 670 __ Push(t0, t0); |
660 __ ld(a3, MemOperand(sp, 2 * kPointerSize)); | 671 } |
661 | 672 |
662 // Set up pointer to last argument. | 673 // Set up pointer to last argument. |
663 __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 674 __ Daddu(a2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
664 | 675 |
paul.l...
2015/06/26 04:02:24
Move untagged argument count to a3 for loop counte
| |
665 // Set up number of arguments for function call below. | |
666 __ SmiUntag(a0, a3); | |
667 | |
668 // Copy arguments and receiver to the expression stack. | 676 // Copy arguments and receiver to the expression stack. |
669 // a0: number of arguments | 677 // a0: number of arguments |
670 // a1: constructor function | 678 // a1: constructor function |
671 // a2: address of last argument (caller sp) | 679 // a2: address of last argument (caller sp) |
672 // a3: number of arguments (smi-tagged) | 680 // a3: number of arguments (smi-tagged) |
673 // sp[0]: receiver | 681 // sp[0]: receiver |
674 // sp[1]: receiver | 682 // sp[1]: receiver |
675 // sp[2]: number of arguments (smi-tagged) | 683 // sp[2]: new.target (if used) |
684 // sp[2/3]: number of arguments (smi-tagged) | |
676 Label loop, entry; | 685 Label loop, entry; |
677 __ SmiUntag(a3); | 686 __ SmiUntag(a3); |
678 __ jmp(&entry); | 687 __ jmp(&entry); |
679 __ bind(&loop); | 688 __ bind(&loop); |
680 __ dsll(a4, a3, kPointerSizeLog2); | 689 __ dsll(a4, a3, kPointerSizeLog2); |
681 __ Daddu(a4, a2, Operand(a4)); | 690 __ Daddu(a4, a2, Operand(a4)); |
682 __ ld(a5, MemOperand(a4)); | 691 __ ld(a5, MemOperand(a4)); |
683 __ push(a5); | 692 __ push(a5); |
684 __ bind(&entry); | 693 __ bind(&entry); |
685 __ Daddu(a3, a3, Operand(-1)); | 694 __ Daddu(a3, a3, Operand(-1)); |
686 __ Branch(&loop, greater_equal, a3, Operand(zero_reg)); | 695 __ Branch(&loop, greater_equal, a3, Operand(zero_reg)); |
687 | 696 |
688 // Call the function. | 697 // Call the function. |
689 // a0: number of arguments | 698 // a0: number of arguments |
690 // a1: constructor function | 699 // a1: constructor function |
691 if (is_api_function) { | 700 if (is_api_function) { |
692 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); | 701 __ ld(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); |
693 Handle<Code> code = | 702 Handle<Code> code = |
694 masm->isolate()->builtins()->HandleApiCallConstruct(); | 703 masm->isolate()->builtins()->HandleApiCallConstruct(); |
695 __ Call(code, RelocInfo::CODE_TARGET); | 704 __ Call(code, RelocInfo::CODE_TARGET); |
696 } else { | 705 } else { |
697 ParameterCount actual(a0); | 706 ParameterCount actual(a0); |
698 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); | 707 __ InvokeFunction(a1, actual, CALL_FUNCTION, NullCallWrapper()); |
699 } | 708 } |
700 | 709 |
701 // Store offset of return address for deoptimizer. | 710 // Store offset of return address for deoptimizer. |
702 if (!is_api_function) { | 711 // TODO(arv): Remove the "!use_new_target" before supporting optimization |
712 // of functions that reference new.target | |
713 if (!is_api_function && !use_new_target) { | |
703 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 714 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
704 } | 715 } |
705 | 716 |
706 // Restore context from the frame. | 717 // Restore context from the frame. |
707 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 718 __ ld(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
708 | 719 |
709 // If the result is an object (in the ECMA sense), we should get rid | 720 // If the result is an object (in the ECMA sense), we should get rid |
710 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 721 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
711 // on page 74. | 722 // on page 74. |
712 Label use_receiver, exit; | 723 Label use_receiver, exit; |
713 | 724 |
714 // If the result is a smi, it is *not* an object in the ECMA sense. | 725 // If the result is a smi, it is *not* an object in the ECMA sense. |
715 // v0: result | 726 // v0: result |
716 // sp[0]: receiver (newly allocated object) | 727 // sp[0]: receiver (newly allocated object) |
717 // sp[1]: number of arguments (smi-tagged) | 728 // sp[1]: new.target (if used) |
729 // sp[1/2]: number of arguments (smi-tagged) | |
718 __ JumpIfSmi(v0, &use_receiver); | 730 __ JumpIfSmi(v0, &use_receiver); |
719 | 731 |
720 // If the type of the result (stored in its map) is less than | 732 // If the type of the result (stored in its map) is less than |
721 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 733 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
722 __ GetObjectType(v0, a1, a3); | 734 __ GetObjectType(v0, a1, a3); |
723 __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); | 735 __ Branch(&exit, greater_equal, a3, Operand(FIRST_SPEC_OBJECT_TYPE)); |
724 | 736 |
725 // Throw away the result of the constructor invocation and use the | 737 // Throw away the result of the constructor invocation and use the |
726 // on-stack receiver as the result. | 738 // on-stack receiver as the result. |
727 __ bind(&use_receiver); | 739 __ bind(&use_receiver); |
728 __ ld(v0, MemOperand(sp)); | 740 __ ld(v0, MemOperand(sp)); |
729 | 741 |
730 // Remove receiver from the stack, remove caller arguments, and | 742 // Remove receiver from the stack, remove caller arguments, and |
731 // return. | 743 // return. |
732 __ bind(&exit); | 744 __ bind(&exit); |
733 // v0: result | 745 // v0: result |
734 // sp[0]: receiver (newly allocated object) | 746 // sp[0]: receiver (newly allocated object) |
735 // sp[1]: number of arguments (smi-tagged) | 747 // sp[1]: new.target (if used) |
736 __ ld(a1, MemOperand(sp, kPointerSize)); | 748 // sp[1/2]: number of arguments (smi-tagged) |
749 int offset = (use_new_target ? 2 : 1) * kPointerSize; | |
750 __ ld(a1, MemOperand(sp, offset)); | |
737 | 751 |
738 // Leave construct frame. | 752 // Leave construct frame. |
739 } | 753 } |
740 | 754 |
741 __ SmiScale(a4, a1, kPointerSizeLog2); | 755 __ SmiScale(a4, a1, kPointerSizeLog2); |
742 __ Daddu(sp, sp, a4); | 756 __ Daddu(sp, sp, a4); |
743 __ Daddu(sp, sp, kPointerSize); | 757 __ Daddu(sp, sp, kPointerSize); |
744 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2); | 758 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, a1, a2); |
745 __ Ret(); | 759 __ Ret(); |
746 } | 760 } |
747 | 761 |
748 | 762 |
749 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 763 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
750 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 764 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
751 } | 765 } |
752 | 766 |
753 | 767 |
754 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 768 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
755 Generate_JSConstructStubHelper(masm, true, false); | 769 Generate_JSConstructStubHelper(masm, true, false, false); |
756 } | 770 } |
757 | 771 |
758 | 772 |
773 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { | |
774 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); | |
775 } | |
776 | |
777 | |
759 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 778 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
760 // ----------- S t a t e ------------- | 779 // ----------- S t a t e ------------- |
761 // -- a0 : number of arguments | 780 // -- a0 : number of arguments |
762 // -- a1 : constructor function | 781 // -- a1 : constructor function |
763 // -- a2 : allocation site or undefined | 782 // -- a2 : allocation site or undefined |
764 // -- a3 : original constructor | 783 // -- a3 : original constructor |
765 // -- ra : return address | 784 // -- ra : return address |
766 // -- sp[...]: constructor arguments | 785 // -- sp[...]: constructor arguments |
767 // ----------------------------------- | 786 // ----------------------------------- |
768 | 787 |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1843 } | 1862 } |
1844 } | 1863 } |
1845 | 1864 |
1846 | 1865 |
1847 #undef __ | 1866 #undef __ |
1848 | 1867 |
1849 } // namespace internal | 1868 } // namespace internal |
1850 } // namespace v8 | 1869 } // namespace v8 |
1851 | 1870 |
1852 #endif // V8_TARGET_ARCH_MIPS64 | 1871 #endif // V8_TARGET_ARCH_MIPS64 |
OLD | NEW |