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