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