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