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 #include "src/v8.h" | 5 #include "src/v8.h" |
6 | 6 |
7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
8 | 8 |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/debug.h" | 10 #include "src/debug.h" |
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 if (create_memento) { | 336 if (create_memento) { |
337 __ jmp(count_incremented); | 337 __ jmp(count_incremented); |
338 } else { | 338 } else { |
339 __ jmp(allocated); | 339 __ jmp(allocated); |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 | 343 |
344 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 344 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
345 bool is_api_function, | 345 bool is_api_function, |
| 346 bool use_new_target, |
346 bool create_memento) { | 347 bool create_memento) { |
347 // ----------- S t a t e ------------- | 348 // ----------- S t a t e ------------- |
348 // -- r0 : number of arguments | 349 // -- r0 : number of arguments |
349 // -- r1 : constructor function | 350 // -- r1 : constructor function |
350 // -- r2 : allocation site or undefined | 351 // -- r2 : allocation site or undefined |
351 // -- r3 : original constructor | 352 // -- r3 : original constructor |
352 // -- lr : return address | 353 // -- lr : return address |
353 // -- sp[...]: constructor arguments | 354 // -- sp[...]: constructor arguments |
354 // ----------------------------------- | 355 // ----------------------------------- |
355 | 356 |
356 // Should never create mementos for api functions. | 357 // Should never create mementos for api functions. |
357 DCHECK(!is_api_function || !create_memento); | 358 DCHECK(!is_api_function || !create_memento); |
358 | 359 |
359 Isolate* isolate = masm->isolate(); | 360 Isolate* isolate = masm->isolate(); |
360 | 361 |
361 // Enter a construct frame. | 362 // Enter a construct frame. |
362 { | 363 { |
363 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); | 364 FrameAndConstantPoolScope scope(masm, StackFrame::CONSTRUCT); |
364 | 365 |
365 if (create_memento) { | 366 if (create_memento) { |
366 __ AssertUndefinedOrAllocationSite(r2, r4); | 367 __ AssertUndefinedOrAllocationSite(r2, r4); |
367 __ push(r2); | 368 __ push(r2); |
368 } | 369 } |
369 | 370 |
370 // Preserve the two incoming parameters on the stack. | 371 // Preserve the incoming parameters on the stack. |
371 __ SmiTag(r0); | 372 __ SmiTag(r0); |
372 __ push(r0); // Smi-tagged arguments count. | 373 __ push(r0); |
373 __ push(r1); // Constructor function. | 374 __ push(r1); |
| 375 if (use_new_target) { |
| 376 __ push(r3); |
| 377 } |
374 | 378 |
375 Label rt_call, allocated, normal_new, count_incremented; | 379 Label rt_call, allocated, normal_new, count_incremented; |
376 __ cmp(r1, r3); | 380 __ cmp(r1, r3); |
377 __ b(eq, &normal_new); | 381 __ b(eq, &normal_new); |
378 | 382 |
379 // Original constructor and function are different. | 383 // Original constructor and function are different. |
380 Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented, | 384 Generate_Runtime_NewObject(masm, create_memento, r3, &count_incremented, |
381 &allocated); | 385 &allocated); |
382 __ bind(&normal_new); | 386 __ bind(&normal_new); |
383 | 387 |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 // r1: constructor function | 607 // r1: constructor function |
604 __ bind(&rt_call); | 608 __ bind(&rt_call); |
605 Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented, | 609 Generate_Runtime_NewObject(masm, create_memento, r1, &count_incremented, |
606 &allocated); | 610 &allocated); |
607 | 611 |
608 // Receiver for constructor call allocated. | 612 // Receiver for constructor call allocated. |
609 // r4: JSObject | 613 // r4: JSObject |
610 __ bind(&allocated); | 614 __ bind(&allocated); |
611 | 615 |
612 if (create_memento) { | 616 if (create_memento) { |
613 __ ldr(r2, MemOperand(sp, kPointerSize * 2)); | 617 int offset = (use_new_target ? 3 : 2) * kPointerSize; |
| 618 __ ldr(r2, MemOperand(sp, offset)); |
614 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); | 619 __ LoadRoot(r5, Heap::kUndefinedValueRootIndex); |
615 __ cmp(r2, r5); | 620 __ cmp(r2, r5); |
616 __ b(eq, &count_incremented); | 621 __ b(eq, &count_incremented); |
617 // r2 is an AllocationSite. We are creating a memento from it, so we | 622 // r2 is an AllocationSite. We are creating a memento from it, so we |
618 // need to increment the memento create count. | 623 // need to increment the memento create count. |
619 __ ldr(r3, FieldMemOperand(r2, | 624 __ ldr(r3, FieldMemOperand(r2, |
620 AllocationSite::kPretenureCreateCountOffset)); | 625 AllocationSite::kPretenureCreateCountOffset)); |
621 __ add(r3, r3, Operand(Smi::FromInt(1))); | 626 __ add(r3, r3, Operand(Smi::FromInt(1))); |
622 __ str(r3, FieldMemOperand(r2, | 627 __ str(r3, FieldMemOperand(r2, |
623 AllocationSite::kPretenureCreateCountOffset)); | 628 AllocationSite::kPretenureCreateCountOffset)); |
624 __ bind(&count_incremented); | 629 __ bind(&count_incremented); |
625 } | 630 } |
626 | 631 |
627 __ pop(r1); // Constructor function. | 632 // Restore the parameters. |
| 633 if (use_new_target) { |
| 634 __ pop(r3); |
| 635 } |
| 636 __ pop(r1); |
628 | 637 |
| 638 // Retrieve smi-tagged arguments count from the stack. |
| 639 __ ldr(r0, MemOperand(sp)); |
| 640 __ SmiUntag(r0); |
| 641 |
| 642 // Push new.target onto the construct frame. This is stored just below the |
| 643 // receiver on the stack. |
| 644 if (use_new_target) { |
| 645 __ push(r3); |
| 646 } |
629 __ push(r4); | 647 __ push(r4); |
630 __ push(r4); | 648 __ push(r4); |
631 | 649 |
632 // Reload the number of arguments from the stack. | |
633 // sp[0]: receiver | |
634 // sp[1]: receiver | |
635 // sp[2]: number of arguments (smi-tagged) | |
636 __ ldr(r3, MemOperand(sp, 2 * kPointerSize)); | |
637 | |
638 // Set up pointer to last argument. | 650 // Set up pointer to last argument. |
639 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | 651 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
640 | 652 |
641 // Set up number of arguments for function call below | |
642 __ SmiUntag(r0, r3); | |
643 | |
644 // Copy arguments and receiver to the expression stack. | 653 // Copy arguments and receiver to the expression stack. |
645 // r0: number of arguments | 654 // r0: number of arguments |
646 // r1: constructor function | 655 // r1: constructor function |
647 // r2: address of last argument (caller sp) | 656 // r2: address of last argument (caller sp) |
648 // r3: number of arguments (smi-tagged) | 657 // r3: number of arguments (smi-tagged) |
649 // sp[0]: receiver | 658 // sp[0]: receiver |
650 // sp[1]: receiver | 659 // sp[1]: receiver |
651 // sp[2]: number of arguments (smi-tagged) | 660 // sp[2]: new.target (if used) |
| 661 // sp[2/3]: number of arguments (smi-tagged) |
652 Label loop, entry; | 662 Label loop, entry; |
| 663 __ SmiTag(r3, r0); |
653 __ b(&entry); | 664 __ b(&entry); |
654 __ bind(&loop); | 665 __ bind(&loop); |
655 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); | 666 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); |
656 __ push(ip); | 667 __ push(ip); |
657 __ bind(&entry); | 668 __ bind(&entry); |
658 __ sub(r3, r3, Operand(2), SetCC); | 669 __ sub(r3, r3, Operand(2), SetCC); |
659 __ b(ge, &loop); | 670 __ b(ge, &loop); |
660 | 671 |
661 // Call the function. | 672 // Call the function. |
662 // r0: number of arguments | 673 // r0: number of arguments |
663 // r1: constructor function | 674 // r1: constructor function |
664 if (is_api_function) { | 675 if (is_api_function) { |
665 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 676 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
666 Handle<Code> code = | 677 Handle<Code> code = |
667 masm->isolate()->builtins()->HandleApiCallConstruct(); | 678 masm->isolate()->builtins()->HandleApiCallConstruct(); |
668 __ Call(code, RelocInfo::CODE_TARGET); | 679 __ Call(code, RelocInfo::CODE_TARGET); |
669 } else { | 680 } else { |
670 ParameterCount actual(r0); | 681 ParameterCount actual(r0); |
671 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); | 682 __ InvokeFunction(r1, actual, CALL_FUNCTION, NullCallWrapper()); |
672 } | 683 } |
673 | 684 |
674 // Store offset of return address for deoptimizer. | 685 // Store offset of return address for deoptimizer. |
675 if (!is_api_function) { | 686 // TODO(arv): Remove the "!use_new_target" before supporting optimization |
| 687 // of functions that reference new.target |
| 688 if (!is_api_function && !use_new_target) { |
676 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); | 689 masm->isolate()->heap()->SetConstructStubDeoptPCOffset(masm->pc_offset()); |
677 } | 690 } |
678 | 691 |
679 // Restore context from the frame. | 692 // Restore context from the frame. |
680 // r0: result | 693 // r0: result |
681 // sp[0]: receiver | 694 // sp[0]: receiver |
682 // sp[1]: number of arguments (smi-tagged) | 695 // sp[1]: new.target (if used) |
| 696 // sp[1/2]: number of arguments (smi-tagged) |
683 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 697 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
684 | 698 |
685 // 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 |
686 // 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 |
687 // on page 74. | 701 // on page 74. |
688 Label use_receiver, exit; | 702 Label use_receiver, exit; |
689 | 703 |
690 // 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. |
691 // r0: result | 705 // r0: result |
692 // sp[0]: receiver (newly allocated object) | 706 // sp[0]: receiver (newly allocated object) |
693 // sp[1]: number of arguments (smi-tagged) | 707 // sp[1]: new.target (if used) |
| 708 // sp[1/2]: number of arguments (smi-tagged) |
694 __ JumpIfSmi(r0, &use_receiver); | 709 __ JumpIfSmi(r0, &use_receiver); |
695 | 710 |
696 // 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 |
697 // 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. |
698 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); | 713 __ CompareObjectType(r0, r1, r3, FIRST_SPEC_OBJECT_TYPE); |
699 __ b(ge, &exit); | 714 __ b(ge, &exit); |
700 | 715 |
701 // Throw away the result of the constructor invocation and use the | 716 // Throw away the result of the constructor invocation and use the |
702 // on-stack receiver as the result. | 717 // on-stack receiver as the result. |
703 __ bind(&use_receiver); | 718 __ bind(&use_receiver); |
704 __ ldr(r0, MemOperand(sp)); | 719 __ ldr(r0, MemOperand(sp)); |
705 | 720 |
706 // Remove receiver from the stack, remove caller arguments, and | 721 // Remove receiver from the stack, remove caller arguments, and |
707 // return. | 722 // return. |
708 __ bind(&exit); | 723 __ bind(&exit); |
709 // r0: result | 724 // r0: result |
710 // sp[0]: receiver (newly allocated object) | 725 // sp[0]: receiver (newly allocated object) |
711 // sp[1]: number of arguments (smi-tagged) | 726 // sp[1]: new.target (if used) |
712 __ ldr(r1, MemOperand(sp, kPointerSize)); | 727 // sp[1/2]: number of arguments (smi-tagged) |
| 728 int offset = (use_new_target ? 2 : 1) * kPointerSize; |
| 729 __ ldr(r1, MemOperand(sp, offset)); |
713 | 730 |
714 // Leave construct frame. | 731 // Leave construct frame. |
715 } | 732 } |
716 | 733 |
717 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 734 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
718 __ add(sp, sp, Operand(kPointerSize)); | 735 __ add(sp, sp, Operand(kPointerSize)); |
719 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); | 736 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
720 __ Jump(lr); | 737 __ Jump(lr); |
721 } | 738 } |
722 | 739 |
723 | 740 |
724 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { | 741 void Builtins::Generate_JSConstructStubGeneric(MacroAssembler* masm) { |
725 Generate_JSConstructStubHelper(masm, false, FLAG_pretenuring_call_new); | 742 Generate_JSConstructStubHelper(masm, false, false, FLAG_pretenuring_call_new); |
726 } | 743 } |
727 | 744 |
728 | 745 |
729 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { | 746 void Builtins::Generate_JSConstructStubApi(MacroAssembler* masm) { |
730 Generate_JSConstructStubHelper(masm, true, false); | 747 Generate_JSConstructStubHelper(masm, true, false, false); |
731 } | 748 } |
732 | 749 |
733 | 750 |
| 751 void Builtins::Generate_JSConstructStubNewTarget(MacroAssembler* masm) { |
| 752 Generate_JSConstructStubHelper(masm, false, true, FLAG_pretenuring_call_new); |
| 753 } |
| 754 |
| 755 |
734 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { | 756 void Builtins::Generate_JSConstructStubForDerived(MacroAssembler* masm) { |
735 // ----------- S t a t e ------------- | 757 // ----------- S t a t e ------------- |
736 // -- r0 : number of arguments | 758 // -- r0 : number of arguments |
737 // -- r1 : constructor function | 759 // -- r1 : constructor function |
738 // -- r2 : allocation site or undefined | 760 // -- r2 : allocation site or undefined |
739 // -- r3 : original constructor | 761 // -- r3 : original constructor |
740 // -- lr : return address | 762 // -- lr : return address |
741 // -- sp[...]: constructor arguments | 763 // -- sp[...]: constructor arguments |
742 // ----------------------------------- | 764 // ----------------------------------- |
743 | 765 |
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1806 } | 1828 } |
1807 } | 1829 } |
1808 | 1830 |
1809 | 1831 |
1810 #undef __ | 1832 #undef __ |
1811 | 1833 |
1812 } // namespace internal | 1834 } // namespace internal |
1813 } // namespace v8 | 1835 } // namespace v8 |
1814 | 1836 |
1815 #endif // V8_TARGET_ARCH_ARM | 1837 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |