OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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_PPC | 7 #if V8_TARGET_ARCH_PPC |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 __ Push(r4, original_constructor); | 330 __ Push(r4, original_constructor); |
331 __ CallRuntime(Runtime::kNewObject, 2); | 331 __ CallRuntime(Runtime::kNewObject, 2); |
332 __ mr(result, r3); | 332 __ mr(result, r3); |
333 __ b(allocated); | 333 __ b(allocated); |
334 } | 334 } |
335 } | 335 } |
336 | 336 |
337 | 337 |
338 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 338 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
339 bool is_api_function, | 339 bool is_api_function, |
| 340 bool use_new_target, |
340 bool create_memento) { | 341 bool create_memento) { |
341 // ----------- S t a t e ------------- | 342 // ----------- S t a t e ------------- |
342 // -- r3 : number of arguments | 343 // -- r3 : number of arguments |
343 // -- r4 : constructor function | 344 // -- r4 : constructor function |
344 // -- r5 : allocation site or undefined | 345 // -- r5 : allocation site or undefined |
345 // -- r6 : original constructor | 346 // -- r6 : original constructor |
346 // -- lr : return address | 347 // -- lr : return address |
347 // -- sp[...]: constructor arguments | 348 // -- sp[...]: constructor arguments |
348 // ----------------------------------- | 349 // ----------------------------------- |
349 | 350 |
350 // Should never create mementos for api functions. | 351 // Should never create mementos for api functions. |
351 DCHECK(!is_api_function || !create_memento); | 352 DCHECK(!is_api_function || !create_memento); |
352 | 353 |
353 Isolate* isolate = masm->isolate(); | 354 Isolate* isolate = masm->isolate(); |
354 | 355 |
355 // Enter a construct frame. | 356 // Enter a construct frame. |
356 { | 357 { |
357 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 358 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
358 | 359 |
359 if (create_memento) { | 360 if (create_memento) { |
360 __ AssertUndefinedOrAllocationSite(r5, r7); | 361 __ AssertUndefinedOrAllocationSite(r5, r7); |
361 __ push(r5); | 362 __ push(r5); |
362 } | 363 } |
363 | 364 |
364 // Preserve the two incoming parameters on the stack. | 365 // Preserve the incoming parameters on the stack. |
365 __ SmiTag(r3); | 366 __ SmiTag(r3); |
366 __ Push(r3, r4); | 367 if (use_new_target) { |
| 368 __ Push(r3, r4, r6); |
| 369 } else { |
| 370 __ Push(r3, r4); |
| 371 } |
367 | 372 |
368 Label rt_call, allocated, normal_new, count_incremented; | 373 Label rt_call, allocated, normal_new, count_incremented; |
369 __ cmp(r4, r6); | 374 __ cmp(r4, r6); |
370 __ beq(&normal_new); | 375 __ beq(&normal_new); |
371 | 376 |
372 // Original constructor and function are different. | 377 // Original constructor and function are different. |
373 Generate_Runtime_NewObject(masm, create_memento, r6, &count_incremented, | 378 Generate_Runtime_NewObject(masm, create_memento, r6, &count_incremented, |
374 &allocated); | 379 &allocated); |
375 __ bind(&normal_new); | 380 __ bind(&normal_new); |
376 | 381 |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 // r4: constructor function | 609 // r4: constructor function |
605 __ bind(&rt_call); | 610 __ bind(&rt_call); |
606 Generate_Runtime_NewObject(masm, create_memento, r4, &count_incremented, | 611 Generate_Runtime_NewObject(masm, create_memento, r4, &count_incremented, |
607 &allocated); | 612 &allocated); |
608 | 613 |
609 // Receiver for constructor call allocated. | 614 // Receiver for constructor call allocated. |
610 // r7: JSObject | 615 // r7: JSObject |
611 __ bind(&allocated); | 616 __ bind(&allocated); |
612 | 617 |
613 if (create_memento) { | 618 if (create_memento) { |
614 __ LoadP(r5, MemOperand(sp, kPointerSize * 2)); | 619 int offset = (use_new_target ? 3 : 2) * kPointerSize; |
| 620 __ LoadP(r5, MemOperand(sp, offset)); |
615 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 621 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
616 __ cmp(r5, r8); | 622 __ cmp(r5, r8); |
617 __ beq(&count_incremented); | 623 __ beq(&count_incremented); |
618 // r5 is an AllocationSite. We are creating a memento from it, so we | 624 // r5 is an AllocationSite. We are creating a memento from it, so we |
619 // need to increment the memento create count. | 625 // need to increment the memento create count. |
620 __ LoadP( | 626 __ LoadP( |
621 r6, FieldMemOperand(r5, AllocationSite::kPretenureCreateCountOffset)); | 627 r6, FieldMemOperand(r5, AllocationSite::kPretenureCreateCountOffset)); |
622 __ AddSmiLiteral(r6, r6, Smi::FromInt(1), r0); | 628 __ AddSmiLiteral(r6, r6, Smi::FromInt(1), r0); |
623 __ StoreP( | 629 __ StoreP( |
624 r6, FieldMemOperand(r5, AllocationSite::kPretenureCreateCountOffset), | 630 r6, FieldMemOperand(r5, AllocationSite::kPretenureCreateCountOffset), |
625 r0); | 631 r0); |
626 __ bind(&count_incremented); | 632 __ bind(&count_incremented); |
627 } | 633 } |
628 | 634 |
629 __ pop(r4); // Constructor function. | 635 // Restore the parameters. |
| 636 if (use_new_target) { |
| 637 __ Pop(r4, ip); |
| 638 } else { |
| 639 __ pop(r4); |
| 640 } |
630 | 641 |
631 __ Push(r7, r7); | 642 // Retrieve smi-tagged arguments count from the stack. |
| 643 __ LoadP(r6, MemOperand(sp)); |
| 644 __ SmiUntag(r3, r6); |
632 | 645 |
633 // Reload the number of arguments from the stack. | 646 // Push new.target onto the construct frame. This is stored just below the |
634 // sp[0]: receiver | 647 // receiver on the stack. |
635 // sp[1]: receiver | 648 if (use_new_target) { |
636 // sp[2]: number of arguments (smi-tagged) | 649 __ Push(ip, r7, r7); |
637 __ LoadP(r6, MemOperand(sp, 2 * kPointerSize)); | 650 } else { |
| 651 __ Push(r7, r7); |
| 652 } |
638 | 653 |
639 // Set up pointer to last argument. | 654 // Set up pointer to last argument. |
640 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 655 __ addi(r5, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
641 | 656 |
642 // Set up number of arguments for function call below | |
643 __ SmiUntag(r3, r6); | |
644 | |
645 // Copy arguments and receiver to the expression stack. | 657 // Copy arguments and receiver to the expression stack. |
646 // r3: number of arguments | 658 // r3: number of arguments |
647 // r4: constructor function | 659 // r4: constructor function |
648 // r5: address of last argument (caller sp) | 660 // r5: address of last argument (caller sp) |
649 // r6: number of arguments (smi-tagged) | 661 // r6: number of arguments (smi-tagged) |
650 // sp[0]: receiver | 662 // sp[0]: receiver |
651 // sp[1]: receiver | 663 // sp[1]: receiver |
652 // sp[2]: number of arguments (smi-tagged) | 664 // sp[2]: new.target (if used) |
| 665 // sp[2/3]: number of arguments (smi-tagged) |
653 Label loop, no_args; | 666 Label loop, no_args; |
654 __ cmpi(r3, Operand::Zero()); | 667 __ cmpi(r3, Operand::Zero()); |
655 __ beq(&no_args); | 668 __ beq(&no_args); |
656 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); | 669 __ ShiftLeftImm(ip, r3, Operand(kPointerSizeLog2)); |
657 __ mtctr(r3); | 670 __ mtctr(r3); |
658 __ bind(&loop); | 671 __ bind(&loop); |
659 __ subi(ip, ip, Operand(kPointerSize)); | 672 __ subi(ip, ip, Operand(kPointerSize)); |
660 __ LoadPX(r0, MemOperand(r5, ip)); | 673 __ LoadPX(r0, MemOperand(r5, ip)); |
661 __ push(r0); | 674 __ push(r0); |
662 __ bdnz(&loop); | 675 __ bdnz(&loop); |
663 __ bind(&no_args); | 676 __ bind(&no_args); |
664 | 677 |
665 // Call the function. | 678 // Call the function. |
666 // r3: number of arguments | 679 // r3: number of arguments |
667 // r4: constructor function | 680 // r4: constructor function |
668 if (is_api_function) { | 681 if (is_api_function) { |
669 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); | 682 __ LoadP(cp, FieldMemOperand(r4, JSFunction::kContextOffset)); |
670 Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct(); | 683 Handle<Code> code = masm->isolate()->builtins()->HandleApiCallConstruct(); |
671 __ Call(code, RelocInfo::CODE_TARGET); | 684 __ Call(code, RelocInfo::CODE_TARGET); |
672 } else { | 685 } else { |
673 ParameterCount actual(r3); | 686 ParameterCount actual(r3); |
674 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); | 687 __ InvokeFunction(r4, actual, CALL_FUNCTION, NullCallWrapper()); |
675 } | 688 } |
676 | 689 |
677 // Store offset of return address for deoptimizer. | 690 // Store offset of return address for deoptimizer. |
678 if (!is_api_function) { | 691 // TODO(arv): Remove the "!use_new_target" before supporting optimization |
| 692 // of functions that reference new.target |
| 693 if (!is_api_function && !use_new_target) { |
679 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 694 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
680 } | 695 } |
681 | 696 |
682 // Restore context from the frame. | 697 // Restore context from the frame. |
683 // r3: result | 698 // r3: result |
684 // sp[0]: receiver | 699 // sp[0]: receiver |
685 // sp[1]: number of arguments (smi-tagged) | 700 // sp[1]: new.target (if used) |
| 701 // sp[1/2]: number of arguments (smi-tagged) |
686 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 702 __ LoadP(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
687 | 703 |
688 // If the result is an object (in the ECMA sense), we should get rid | 704 // If the result is an object (in the ECMA sense), we should get rid |
689 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | 705 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
690 // on page 74. | 706 // on page 74. |
691 Label use_receiver, exit; | 707 Label use_receiver, exit; |
692 | 708 |
693 // If the result is a smi, it is *not* an object in the ECMA sense. | 709 // If the result is a smi, it is *not* an object in the ECMA sense. |
694 // r3: result | 710 // r3: result |
695 // sp[0]: receiver (newly allocated object) | 711 // sp[0]: receiver (newly allocated object) |
696 // sp[1]: number of arguments (smi-tagged) | 712 // sp[1]: new.target (if used) |
| 713 // sp[1/2]: number of arguments (smi-tagged) |
697 __ JumpIfSmi(r3, &use_receiver); | 714 __ JumpIfSmi(r3, &use_receiver); |
698 | 715 |
699 // If the type of the result (stored in its map) is less than | 716 // If the type of the result (stored in its map) is less than |
700 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | 717 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
701 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); | 718 __ CompareObjectType(r3, r4, r6, FIRST_SPEC_OBJECT_TYPE); |
702 __ bge(&exit); | 719 __ bge(&exit); |
703 | 720 |
704 // Throw away the result of the constructor invocation and use the | 721 // Throw away the result of the constructor invocation and use the |
705 // on-stack receiver as the result. | 722 // on-stack receiver as the result. |
706 __ bind(&use_receiver); | 723 __ bind(&use_receiver); |
707 __ LoadP(r3, MemOperand(sp)); | 724 __ LoadP(r3, MemOperand(sp)); |
708 | 725 |
709 // Remove receiver from the stack, remove caller arguments, and | 726 // Remove receiver from the stack, remove caller arguments, and |
710 // return. | 727 // return. |
711 __ bind(&exit); | 728 __ bind(&exit); |
712 // r3: result | 729 // r3: result |
713 // sp[0]: receiver (newly allocated object) | 730 // sp[0]: receiver (newly allocated object) |
714 // sp[1]: number of arguments (smi-tagged) | 731 // sp[1]: new.target (if used) |
715 __ LoadP(r4, MemOperand(sp, kPointerSize)); | 732 // sp[1/2]: number of arguments (smi-tagged) |
| 733 int offset = (use_new_target ? 2 : 1) * kPointerSize; |
| 734 __ LoadP(r4, MemOperand(sp, offset)); |
716 | 735 |
717 // Leave construct frame. | 736 // Leave construct frame. |
718 } | 737 } |
719 | 738 |
720 __ SmiToPtrArrayOffset(r4, r4); | 739 __ SmiToPtrArrayOffset(r4, r4); |
721 __ add(sp, sp, r4); | 740 __ add(sp, sp, r4); |
722 __ addi(sp, sp, Operand(kPointerSize)); | 741 __ addi(sp, sp, Operand(kPointerSize)); |
723 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5); | 742 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r4, r5); |
724 __ blr(); | 743 __ blr(); |
725 } | 744 } |
726 | 745 |
727 | 746 |
728 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 747 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
729 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 748 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
730 } | 749 } |
731 | 750 |
732 | 751 |
733 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 752 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
734 Generate_JSConstructStubHelper(masm, true, false); | 753 Generate_JSConstructStubHelper(masm, true, false, false); |
735 } | 754 } |
736 | 755 |
737 | 756 |
| 757 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { |
| 758 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); |
| 759 } |
| 760 |
| 761 |
738 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 762 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
739 // ----------- S t a t e ------------- | 763 // ----------- S t a t e ------------- |
740 // -- r3 : number of arguments | 764 // -- r3 : number of arguments |
741 // -- r4 : constructor function | 765 // -- r4 : constructor function |
742 // -- r5 : allocation site or undefined | 766 // -- r5 : allocation site or undefined |
743 // -- r6 : original constructor | 767 // -- r6 : original constructor |
744 // -- lr : return address | 768 // -- lr : return address |
745 // -- sp[...]: constructor arguments | 769 // -- sp[...]: constructor arguments |
746 // ----------------------------------- | 770 // ----------------------------------- |
747 | 771 |
(...skipping 1127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1875 __ bkpt(0); | 1899 __ bkpt(0); |
1876 } | 1900 } |
1877 } | 1901 } |
1878 | 1902 |
1879 | 1903 |
1880 #undef __ | 1904 #undef __ |
1881 } // namespace internal | 1905 } // namespace internal |
1882 } // namespace v8 | 1906 } // namespace v8 |
1883 | 1907 |
1884 #endif // V8_TARGET_ARCH_PPC | 1908 #endif // V8_TARGET_ARCH_PPC |
OLD | NEW |