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