OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 564 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 __ tst(r3, Operand(kIsNotStringMask)); | 575 __ tst(r3, Operand(kIsNotStringMask)); |
576 __ b(ne, &convert_argument); | 576 __ b(ne, &convert_argument); |
577 __ mov(argument, r0); | 577 __ mov(argument, r0); |
578 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); | 578 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); |
579 __ b(&argument_is_string); | 579 __ b(&argument_is_string); |
580 | 580 |
581 // Invoke the conversion builtin and put the result into r2. | 581 // Invoke the conversion builtin and put the result into r2. |
582 __ bind(&convert_argument); | 582 __ bind(&convert_argument); |
583 __ push(function); // Preserve the function. | 583 __ push(function); // Preserve the function. |
584 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); | 584 __ IncrementCounter(counters->string_ctor_conversions(), 1, r3, r4); |
585 __ EnterInternalFrame(); | 585 { |
586 __ push(r0); | 586 FrameScope scope(masm, StackFrame::INTERNAL); |
587 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); | 587 __ push(r0); |
588 __ LeaveInternalFrame(); | 588 __ InvokeBuiltin(Builtins::TO_STRING, CALL_FUNCTION); |
| 589 } |
589 __ pop(function); | 590 __ pop(function); |
590 __ mov(argument, r0); | 591 __ mov(argument, r0); |
591 __ b(&argument_is_string); | 592 __ b(&argument_is_string); |
592 | 593 |
593 // Load the empty string into r2, remove the receiver from the | 594 // Load the empty string into r2, remove the receiver from the |
594 // stack, and jump back to the case where the argument is a string. | 595 // stack, and jump back to the case where the argument is a string. |
595 __ bind(&no_arguments); | 596 __ bind(&no_arguments); |
596 __ LoadRoot(argument, Heap::kEmptyStringRootIndex); | 597 __ LoadRoot(argument, Heap::kEmptyStringRootIndex); |
597 __ Drop(1); | 598 __ Drop(1); |
598 __ b(&argument_is_string); | 599 __ b(&argument_is_string); |
599 | 600 |
600 // At this point the argument is already a string. Call runtime to | 601 // At this point the argument is already a string. Call runtime to |
601 // create a string wrapper. | 602 // create a string wrapper. |
602 __ bind(&gc_required); | 603 __ bind(&gc_required); |
603 __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); | 604 __ IncrementCounter(counters->string_ctor_gc_required(), 1, r3, r4); |
604 __ EnterInternalFrame(); | 605 { |
605 __ push(argument); | 606 FrameScope scope(masm, StackFrame::INTERNAL); |
606 __ CallRuntime(Runtime::kNewStringWrapper, 1); | 607 __ push(argument); |
607 __ LeaveInternalFrame(); | 608 __ CallRuntime(Runtime::kNewStringWrapper, 1); |
| 609 } |
608 __ Ret(); | 610 __ Ret(); |
609 } | 611 } |
610 | 612 |
611 | 613 |
612 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { | 614 void Builtins::Generate_JSConstructCall(MacroAssembler* masm) { |
613 // ----------- S t a t e ------------- | 615 // ----------- S t a t e ------------- |
614 // -- r0 : number of arguments | 616 // -- r0 : number of arguments |
615 // -- r1 : constructor function | 617 // -- r1 : constructor function |
616 // -- lr : return address | 618 // -- lr : return address |
617 // -- sp[...]: constructor arguments | 619 // -- sp[...]: constructor arguments |
618 // ----------------------------------- | 620 // ----------------------------------- |
619 | 621 |
620 Label non_function_call; | 622 Label slow, non_function_call; |
621 // Check that the function is not a smi. | 623 // Check that the function is not a smi. |
622 __ JumpIfSmi(r1, &non_function_call); | 624 __ JumpIfSmi(r1, &non_function_call); |
623 // Check that the function is a JSFunction. | 625 // Check that the function is a JSFunction. |
624 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 626 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
625 __ b(ne, &non_function_call); | 627 __ b(ne, &slow); |
626 | 628 |
627 // Jump to the function-specific construct stub. | 629 // Jump to the function-specific construct stub. |
628 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 630 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
629 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); | 631 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kConstructStubOffset)); |
630 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); | 632 __ add(pc, r2, Operand(Code::kHeaderSize - kHeapObjectTag)); |
631 | 633 |
632 // r0: number of arguments | 634 // r0: number of arguments |
633 // r1: called object | 635 // r1: called object |
| 636 // r2: object type |
| 637 Label do_call; |
| 638 __ bind(&slow); |
| 639 __ cmp(r2, Operand(JS_FUNCTION_PROXY_TYPE)); |
| 640 __ b(ne, &non_function_call); |
| 641 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY_AS_CONSTRUCTOR); |
| 642 __ jmp(&do_call); |
| 643 |
634 __ bind(&non_function_call); | 644 __ bind(&non_function_call); |
| 645 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); |
| 646 __ bind(&do_call); |
635 // Set expected number of arguments to zero (not changing r0). | 647 // Set expected number of arguments to zero (not changing r0). |
636 __ mov(r2, Operand(0, RelocInfo::NONE)); | 648 __ mov(r2, Operand(0, RelocInfo::NONE)); |
637 __ GetBuiltinEntry(r3, Builtins::CALL_NON_FUNCTION_AS_CONSTRUCTOR); | |
638 __ SetCallKind(r5, CALL_AS_METHOD); | 649 __ SetCallKind(r5, CALL_AS_METHOD); |
639 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 650 __ Jump(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
640 RelocInfo::CODE_TARGET); | 651 RelocInfo::CODE_TARGET); |
641 } | 652 } |
642 | 653 |
643 | 654 |
644 static void Generate_JSConstructStubHelper(MacroAssembler* masm, | 655 static void Generate_JSConstructStubHelper(MacroAssembler* masm, |
645 bool is_api_function, | 656 bool is_api_function, |
646 bool count_constructions) { | 657 bool count_constructions) { |
647 // Should never count constructions for api objects. | 658 // Should never count constructions for api objects. |
648 ASSERT(!is_api_function || !count_constructions); | 659 ASSERT(!is_api_function || !count_constructions); |
649 | 660 |
650 Isolate* isolate = masm->isolate(); | 661 Isolate* isolate = masm->isolate(); |
651 | 662 |
652 // Enter a construct frame. | 663 // Enter a construct frame. |
653 __ EnterConstructFrame(); | 664 { |
654 | 665 FrameScope scope(masm, StackFrame::CONSTRUCT); |
655 // Preserve the two incoming parameters on the stack. | 666 |
656 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 667 // Preserve the two incoming parameters on the stack. |
657 __ push(r0); // Smi-tagged arguments count. | 668 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
658 __ push(r1); // Constructor function. | 669 __ push(r0); // Smi-tagged arguments count. |
659 | 670 __ push(r1); // Constructor function. |
660 // Try to allocate the object without transitioning into C code. If any of the | 671 |
661 // preconditions is not met, the code bails out to the runtime call. | 672 // Try to allocate the object without transitioning into C code. If any of |
662 Label rt_call, allocated; | 673 // the preconditions is not met, the code bails out to the runtime call. |
663 if (FLAG_inline_new) { | 674 Label rt_call, allocated; |
664 Label undo_allocation; | 675 if (FLAG_inline_new) { |
| 676 Label undo_allocation; |
665 #ifdef ENABLE_DEBUGGER_SUPPORT | 677 #ifdef ENABLE_DEBUGGER_SUPPORT |
666 ExternalReference debug_step_in_fp = | 678 ExternalReference debug_step_in_fp = |
667 ExternalReference::debug_step_in_fp_address(isolate); | 679 ExternalReference::debug_step_in_fp_address(isolate); |
668 __ mov(r2, Operand(debug_step_in_fp)); | 680 __ mov(r2, Operand(debug_step_in_fp)); |
669 __ ldr(r2, MemOperand(r2)); | 681 __ ldr(r2, MemOperand(r2)); |
670 __ tst(r2, r2); | 682 __ tst(r2, r2); |
671 __ b(ne, &rt_call); | 683 __ b(ne, &rt_call); |
672 #endif | 684 #endif |
673 | 685 |
674 // Load the initial map and verify that it is in fact a map. | 686 // Load the initial map and verify that it is in fact a map. |
675 // r1: constructor function | 687 // r1: constructor function |
676 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); | 688 __ ldr(r2, FieldMemOperand(r1, JSFunction::kPrototypeOrInitialMapOffset)); |
677 __ JumpIfSmi(r2, &rt_call); | 689 __ JumpIfSmi(r2, &rt_call); |
678 __ CompareObjectType(r2, r3, r4, MAP_TYPE); | 690 __ CompareObjectType(r2, r3, r4, MAP_TYPE); |
679 __ b(ne, &rt_call); | 691 __ b(ne, &rt_call); |
680 | 692 |
681 // Check that the constructor is not constructing a JSFunction (see comments | 693 // Check that the constructor is not constructing a JSFunction (see |
682 // in Runtime_NewObject in runtime.cc). In which case the initial map's | 694 // comments in Runtime_NewObject in runtime.cc). In which case the |
683 // instance type would be JS_FUNCTION_TYPE. | 695 // initial map's instance type would be JS_FUNCTION_TYPE. |
684 // r1: constructor function | 696 // r1: constructor function |
685 // r2: initial map | 697 // r2: initial map |
686 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); | 698 __ CompareInstanceType(r2, r3, JS_FUNCTION_TYPE); |
687 __ b(eq, &rt_call); | 699 __ b(eq, &rt_call); |
688 | 700 |
689 if (count_constructions) { | |
690 Label allocate; | |
691 // Decrease generous allocation count. | |
692 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | |
693 MemOperand constructor_count = | |
694 FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); | |
695 __ ldrb(r4, constructor_count); | |
696 __ sub(r4, r4, Operand(1), SetCC); | |
697 __ strb(r4, constructor_count); | |
698 __ b(ne, &allocate); | |
699 | |
700 __ Push(r1, r2); | |
701 | |
702 __ push(r1); // constructor | |
703 // The call will replace the stub, so the countdown is only done once. | |
704 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); | |
705 | |
706 __ pop(r2); | |
707 __ pop(r1); | |
708 | |
709 __ bind(&allocate); | |
710 } | |
711 | |
712 // Now allocate the JSObject on the heap. | |
713 // r1: constructor function | |
714 // r2: initial map | |
715 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); | |
716 __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); | |
717 | |
718 // Allocated the JSObject, now initialize the fields. Map is set to initial | |
719 // map and properties and elements are set to empty fixed array. | |
720 // r1: constructor function | |
721 // r2: initial map | |
722 // r3: object size | |
723 // r4: JSObject (not tagged) | |
724 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); | |
725 __ mov(r5, r4); | |
726 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); | |
727 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); | |
728 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); | |
729 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | |
730 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); | |
731 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); | |
732 | |
733 // Fill all the in-object properties with the appropriate filler. | |
734 // r1: constructor function | |
735 // r2: initial map | |
736 // r3: object size (in words) | |
737 // r4: JSObject (not tagged) | |
738 // r5: First in-object property of JSObject (not tagged) | |
739 __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | |
740 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); | |
741 { Label loop, entry; | |
742 if (count_constructions) { | 701 if (count_constructions) { |
| 702 Label allocate; |
| 703 // Decrease generous allocation count. |
| 704 __ ldr(r3, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
| 705 MemOperand constructor_count = |
| 706 FieldMemOperand(r3, SharedFunctionInfo::kConstructionCountOffset); |
| 707 __ ldrb(r4, constructor_count); |
| 708 __ sub(r4, r4, Operand(1), SetCC); |
| 709 __ strb(r4, constructor_count); |
| 710 __ b(ne, &allocate); |
| 711 |
| 712 __ Push(r1, r2); |
| 713 |
| 714 __ push(r1); // constructor |
| 715 // The call will replace the stub, so the countdown is only done once. |
| 716 __ CallRuntime(Runtime::kFinalizeInstanceSize, 1); |
| 717 |
| 718 __ pop(r2); |
| 719 __ pop(r1); |
| 720 |
| 721 __ bind(&allocate); |
| 722 } |
| 723 |
| 724 // Now allocate the JSObject on the heap. |
| 725 // r1: constructor function |
| 726 // r2: initial map |
| 727 __ ldrb(r3, FieldMemOperand(r2, Map::kInstanceSizeOffset)); |
| 728 __ AllocateInNewSpace(r3, r4, r5, r6, &rt_call, SIZE_IN_WORDS); |
| 729 |
| 730 // Allocated the JSObject, now initialize the fields. Map is set to |
| 731 // initial map and properties and elements are set to empty fixed array. |
| 732 // r1: constructor function |
| 733 // r2: initial map |
| 734 // r3: object size |
| 735 // r4: JSObject (not tagged) |
| 736 __ LoadRoot(r6, Heap::kEmptyFixedArrayRootIndex); |
| 737 __ mov(r5, r4); |
| 738 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
| 739 __ str(r2, MemOperand(r5, kPointerSize, PostIndex)); |
| 740 ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); |
| 741 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
| 742 ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); |
| 743 __ str(r6, MemOperand(r5, kPointerSize, PostIndex)); |
| 744 |
| 745 // Fill all the in-object properties with the appropriate filler. |
| 746 // r1: constructor function |
| 747 // r2: initial map |
| 748 // r3: object size (in words) |
| 749 // r4: JSObject (not tagged) |
| 750 // r5: First in-object property of JSObject (not tagged) |
| 751 __ add(r6, r4, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
| 752 ASSERT_EQ(3 * kPointerSize, JSObject::kHeaderSize); |
| 753 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); |
| 754 if (count_constructions) { |
| 755 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); |
| 756 __ Ubfx(r0, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, |
| 757 kBitsPerByte); |
| 758 __ add(r0, r5, Operand(r0, LSL, kPointerSizeLog2)); |
| 759 // r0: offset of first field after pre-allocated fields |
| 760 if (FLAG_debug_code) { |
| 761 __ cmp(r0, r6); |
| 762 __ Assert(le, "Unexpected number of pre-allocated property fields."); |
| 763 } |
| 764 __ InitializeFieldsWithFiller(r5, r0, r7); |
743 // To allow for truncation. | 765 // To allow for truncation. |
744 __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); | 766 __ LoadRoot(r7, Heap::kOnePointerFillerMapRootIndex); |
745 } else { | |
746 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); | |
747 } | 767 } |
748 __ b(&entry); | 768 __ InitializeFieldsWithFiller(r5, r6, r7); |
749 __ bind(&loop); | 769 |
750 __ str(r7, MemOperand(r5, kPointerSize, PostIndex)); | 770 // Add the object tag to make the JSObject real, so that we can continue |
751 __ bind(&entry); | 771 // and jump into the continuation code at any time from now on. Any |
752 __ cmp(r5, r6); | 772 // failures need to undo the allocation, so that the heap is in a |
753 __ b(lt, &loop); | 773 // consistent state and verifiable. |
| 774 __ add(r4, r4, Operand(kHeapObjectTag)); |
| 775 |
| 776 // Check if a non-empty properties array is needed. Continue with |
| 777 // allocated object if not fall through to runtime call if it is. |
| 778 // r1: constructor function |
| 779 // r4: JSObject |
| 780 // r5: start of next object (not tagged) |
| 781 __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); |
| 782 // The field instance sizes contains both pre-allocated property fields |
| 783 // and in-object properties. |
| 784 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); |
| 785 __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * kBitsPerByte, |
| 786 kBitsPerByte); |
| 787 __ add(r3, r3, Operand(r6)); |
| 788 __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * kBitsPerByte, |
| 789 kBitsPerByte); |
| 790 __ sub(r3, r3, Operand(r6), SetCC); |
| 791 |
| 792 // Done if no extra properties are to be allocated. |
| 793 __ b(eq, &allocated); |
| 794 __ Assert(pl, "Property allocation count failed."); |
| 795 |
| 796 // Scale the number of elements by pointer size and add the header for |
| 797 // FixedArrays to the start of the next object calculation from above. |
| 798 // r1: constructor |
| 799 // r3: number of elements in properties array |
| 800 // r4: JSObject |
| 801 // r5: start of next object |
| 802 __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); |
| 803 __ AllocateInNewSpace( |
| 804 r0, |
| 805 r5, |
| 806 r6, |
| 807 r2, |
| 808 &undo_allocation, |
| 809 static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); |
| 810 |
| 811 // Initialize the FixedArray. |
| 812 // r1: constructor |
| 813 // r3: number of elements in properties array |
| 814 // r4: JSObject |
| 815 // r5: FixedArray (not tagged) |
| 816 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); |
| 817 __ mov(r2, r5); |
| 818 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); |
| 819 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); |
| 820 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); |
| 821 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); |
| 822 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); |
| 823 |
| 824 // Initialize the fields to undefined. |
| 825 // r1: constructor function |
| 826 // r2: First element of FixedArray (not tagged) |
| 827 // r3: number of elements in properties array |
| 828 // r4: JSObject |
| 829 // r5: FixedArray (not tagged) |
| 830 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. |
| 831 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); |
| 832 { Label loop, entry; |
| 833 if (count_constructions) { |
| 834 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); |
| 835 } else if (FLAG_debug_code) { |
| 836 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); |
| 837 __ cmp(r7, r8); |
| 838 __ Assert(eq, "Undefined value not loaded."); |
| 839 } |
| 840 __ b(&entry); |
| 841 __ bind(&loop); |
| 842 __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); |
| 843 __ bind(&entry); |
| 844 __ cmp(r2, r6); |
| 845 __ b(lt, &loop); |
| 846 } |
| 847 |
| 848 // Store the initialized FixedArray into the properties field of |
| 849 // the JSObject |
| 850 // r1: constructor function |
| 851 // r4: JSObject |
| 852 // r5: FixedArray (not tagged) |
| 853 __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. |
| 854 __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); |
| 855 |
| 856 // Continue with JSObject being successfully allocated |
| 857 // r1: constructor function |
| 858 // r4: JSObject |
| 859 __ jmp(&allocated); |
| 860 |
| 861 // Undo the setting of the new top so that the heap is verifiable. For |
| 862 // example, the map's unused properties potentially do not match the |
| 863 // allocated objects unused properties. |
| 864 // r4: JSObject (previous new top) |
| 865 __ bind(&undo_allocation); |
| 866 __ UndoAllocationInNewSpace(r4, r5); |
754 } | 867 } |
755 | 868 |
756 // Add the object tag to make the JSObject real, so that we can continue and | 869 // Allocate the new receiver object using the runtime call. |
757 // jump into the continuation code at any time from now on. Any failures | |
758 // need to undo the allocation, so that the heap is in a consistent state | |
759 // and verifiable. | |
760 __ add(r4, r4, Operand(kHeapObjectTag)); | |
761 | |
762 // Check if a non-empty properties array is needed. Continue with allocated | |
763 // object if not fall through to runtime call if it is. | |
764 // r1: constructor function | 870 // r1: constructor function |
| 871 __ bind(&rt_call); |
| 872 __ push(r1); // argument for Runtime_NewObject |
| 873 __ CallRuntime(Runtime::kNewObject, 1); |
| 874 __ mov(r4, r0); |
| 875 |
| 876 // Receiver for constructor call allocated. |
765 // r4: JSObject | 877 // r4: JSObject |
766 // r5: start of next object (not tagged) | 878 __ bind(&allocated); |
767 __ ldrb(r3, FieldMemOperand(r2, Map::kUnusedPropertyFieldsOffset)); | 879 __ push(r4); |
768 // The field instance sizes contains both pre-allocated property fields and | 880 |
769 // in-object properties. | 881 // Push the function and the allocated receiver from the stack. |
770 __ ldr(r0, FieldMemOperand(r2, Map::kInstanceSizesOffset)); | 882 // sp[0]: receiver (newly allocated object) |
771 __ Ubfx(r6, r0, Map::kPreAllocatedPropertyFieldsByte * 8, 8); | 883 // sp[1]: constructor function |
772 __ add(r3, r3, Operand(r6)); | 884 // sp[2]: number of arguments (smi-tagged) |
773 __ Ubfx(r6, r0, Map::kInObjectPropertiesByte * 8, 8); | 885 __ ldr(r1, MemOperand(sp, kPointerSize)); |
774 __ sub(r3, r3, Operand(r6), SetCC); | 886 __ push(r1); // Constructor function. |
775 | 887 __ push(r4); // Receiver. |
776 // Done if no extra properties are to be allocated. | 888 |
777 __ b(eq, &allocated); | 889 // Reload the number of arguments from the stack. |
778 __ Assert(pl, "Property allocation count failed."); | |
779 | |
780 // Scale the number of elements by pointer size and add the header for | |
781 // FixedArrays to the start of the next object calculation from above. | |
782 // r1: constructor | |
783 // r3: number of elements in properties array | |
784 // r4: JSObject | |
785 // r5: start of next object | |
786 __ add(r0, r3, Operand(FixedArray::kHeaderSize / kPointerSize)); | |
787 __ AllocateInNewSpace( | |
788 r0, | |
789 r5, | |
790 r6, | |
791 r2, | |
792 &undo_allocation, | |
793 static_cast<AllocationFlags>(RESULT_CONTAINS_TOP | SIZE_IN_WORDS)); | |
794 | |
795 // Initialize the FixedArray. | |
796 // r1: constructor | |
797 // r3: number of elements in properties array | |
798 // r4: JSObject | |
799 // r5: FixedArray (not tagged) | |
800 __ LoadRoot(r6, Heap::kFixedArrayMapRootIndex); | |
801 __ mov(r2, r5); | |
802 ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); | |
803 __ str(r6, MemOperand(r2, kPointerSize, PostIndex)); | |
804 ASSERT_EQ(1 * kPointerSize, FixedArray::kLengthOffset); | |
805 __ mov(r0, Operand(r3, LSL, kSmiTagSize)); | |
806 __ str(r0, MemOperand(r2, kPointerSize, PostIndex)); | |
807 | |
808 // Initialize the fields to undefined. | |
809 // r1: constructor function | 890 // r1: constructor function |
810 // r2: First element of FixedArray (not tagged) | 891 // sp[0]: receiver |
811 // r3: number of elements in properties array | 892 // sp[1]: constructor function |
812 // r4: JSObject | 893 // sp[2]: receiver |
813 // r5: FixedArray (not tagged) | 894 // sp[3]: constructor function |
814 __ add(r6, r2, Operand(r3, LSL, kPointerSizeLog2)); // End of object. | 895 // sp[4]: number of arguments (smi-tagged) |
815 ASSERT_EQ(2 * kPointerSize, FixedArray::kHeaderSize); | 896 __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); |
816 { Label loop, entry; | 897 |
817 if (count_constructions) { | 898 // Setup pointer to last argument. |
818 __ LoadRoot(r7, Heap::kUndefinedValueRootIndex); | 899 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); |
819 } else if (FLAG_debug_code) { | 900 |
820 __ LoadRoot(r8, Heap::kUndefinedValueRootIndex); | 901 // Setup number of arguments for function call below |
821 __ cmp(r7, r8); | 902 __ mov(r0, Operand(r3, LSR, kSmiTagSize)); |
822 __ Assert(eq, "Undefined value not loaded."); | 903 |
823 } | 904 // Copy arguments and receiver to the expression stack. |
824 __ b(&entry); | 905 // r0: number of arguments |
825 __ bind(&loop); | 906 // r2: address of last argument (caller sp) |
826 __ str(r7, MemOperand(r2, kPointerSize, PostIndex)); | 907 // r1: constructor function |
827 __ bind(&entry); | 908 // r3: number of arguments (smi-tagged) |
828 __ cmp(r2, r6); | 909 // sp[0]: receiver |
829 __ b(lt, &loop); | 910 // sp[1]: constructor function |
| 911 // sp[2]: receiver |
| 912 // sp[3]: constructor function |
| 913 // sp[4]: number of arguments (smi-tagged) |
| 914 Label loop, entry; |
| 915 __ b(&entry); |
| 916 __ bind(&loop); |
| 917 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); |
| 918 __ push(ip); |
| 919 __ bind(&entry); |
| 920 __ sub(r3, r3, Operand(2), SetCC); |
| 921 __ b(ge, &loop); |
| 922 |
| 923 // Call the function. |
| 924 // r0: number of arguments |
| 925 // r1: constructor function |
| 926 if (is_api_function) { |
| 927 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
| 928 Handle<Code> code = |
| 929 masm->isolate()->builtins()->HandleApiCallConstruct(); |
| 930 ParameterCount expected(0); |
| 931 __ InvokeCode(code, expected, expected, |
| 932 RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); |
| 933 } else { |
| 934 ParameterCount actual(r0); |
| 935 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
| 936 NullCallWrapper(), CALL_AS_METHOD); |
830 } | 937 } |
831 | 938 |
832 // Store the initialized FixedArray into the properties field of | 939 // Pop the function from the stack. |
833 // the JSObject | 940 // sp[0]: constructor function |
834 // r1: constructor function | 941 // sp[2]: receiver |
835 // r4: JSObject | 942 // sp[3]: constructor function |
836 // r5: FixedArray (not tagged) | 943 // sp[4]: number of arguments (smi-tagged) |
837 __ add(r5, r5, Operand(kHeapObjectTag)); // Add the heap tag. | 944 __ pop(); |
838 __ str(r5, FieldMemOperand(r4, JSObject::kPropertiesOffset)); | 945 |
839 | 946 // Restore context from the frame. |
840 // Continue with JSObject being successfully allocated | 947 // r0: result |
841 // r1: constructor function | 948 // sp[0]: receiver |
842 // r4: JSObject | 949 // sp[1]: constructor function |
843 __ jmp(&allocated); | 950 // sp[2]: number of arguments (smi-tagged) |
844 | 951 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); |
845 // Undo the setting of the new top so that the heap is verifiable. For | 952 |
846 // example, the map's unused properties potentially do not match the | 953 // If the result is an object (in the ECMA sense), we should get rid |
847 // allocated objects unused properties. | 954 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 |
848 // r4: JSObject (previous new top) | 955 // on page 74. |
849 __ bind(&undo_allocation); | 956 Label use_receiver, exit; |
850 __ UndoAllocationInNewSpace(r4, r5); | 957 |
| 958 // If the result is a smi, it is *not* an object in the ECMA sense. |
| 959 // r0: result |
| 960 // sp[0]: receiver (newly allocated object) |
| 961 // sp[1]: constructor function |
| 962 // sp[2]: number of arguments (smi-tagged) |
| 963 __ JumpIfSmi(r0, &use_receiver); |
| 964 |
| 965 // If the type of the result (stored in its map) is less than |
| 966 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. |
| 967 __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
| 968 __ b(ge, &exit); |
| 969 |
| 970 // Throw away the result of the constructor invocation and use the |
| 971 // on-stack receiver as the result. |
| 972 __ bind(&use_receiver); |
| 973 __ ldr(r0, MemOperand(sp)); |
| 974 |
| 975 // Remove receiver from the stack, remove caller arguments, and |
| 976 // return. |
| 977 __ bind(&exit); |
| 978 // r0: result |
| 979 // sp[0]: receiver (newly allocated object) |
| 980 // sp[1]: constructor function |
| 981 // sp[2]: number of arguments (smi-tagged) |
| 982 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); |
| 983 |
| 984 // Leave construct frame. |
851 } | 985 } |
852 | 986 |
853 // Allocate the new receiver object using the runtime call. | |
854 // r1: constructor function | |
855 __ bind(&rt_call); | |
856 __ push(r1); // argument for Runtime_NewObject | |
857 __ CallRuntime(Runtime::kNewObject, 1); | |
858 __ mov(r4, r0); | |
859 | |
860 // Receiver for constructor call allocated. | |
861 // r4: JSObject | |
862 __ bind(&allocated); | |
863 __ push(r4); | |
864 | |
865 // Push the function and the allocated receiver from the stack. | |
866 // sp[0]: receiver (newly allocated object) | |
867 // sp[1]: constructor function | |
868 // sp[2]: number of arguments (smi-tagged) | |
869 __ ldr(r1, MemOperand(sp, kPointerSize)); | |
870 __ push(r1); // Constructor function. | |
871 __ push(r4); // Receiver. | |
872 | |
873 // Reload the number of arguments from the stack. | |
874 // r1: constructor function | |
875 // sp[0]: receiver | |
876 // sp[1]: constructor function | |
877 // sp[2]: receiver | |
878 // sp[3]: constructor function | |
879 // sp[4]: number of arguments (smi-tagged) | |
880 __ ldr(r3, MemOperand(sp, 4 * kPointerSize)); | |
881 | |
882 // Setup pointer to last argument. | |
883 __ add(r2, fp, Operand(StandardFrameConstants::kCallerSPOffset)); | |
884 | |
885 // Setup number of arguments for function call below | |
886 __ mov(r0, Operand(r3, LSR, kSmiTagSize)); | |
887 | |
888 // Copy arguments and receiver to the expression stack. | |
889 // r0: number of arguments | |
890 // r2: address of last argument (caller sp) | |
891 // r1: constructor function | |
892 // r3: number of arguments (smi-tagged) | |
893 // sp[0]: receiver | |
894 // sp[1]: constructor function | |
895 // sp[2]: receiver | |
896 // sp[3]: constructor function | |
897 // sp[4]: number of arguments (smi-tagged) | |
898 Label loop, entry; | |
899 __ b(&entry); | |
900 __ bind(&loop); | |
901 __ ldr(ip, MemOperand(r2, r3, LSL, kPointerSizeLog2 - 1)); | |
902 __ push(ip); | |
903 __ bind(&entry); | |
904 __ sub(r3, r3, Operand(2), SetCC); | |
905 __ b(ge, &loop); | |
906 | |
907 // Call the function. | |
908 // r0: number of arguments | |
909 // r1: constructor function | |
910 if (is_api_function) { | |
911 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | |
912 Handle<Code> code = | |
913 masm->isolate()->builtins()->HandleApiCallConstruct(); | |
914 ParameterCount expected(0); | |
915 __ InvokeCode(code, expected, expected, | |
916 RelocInfo::CODE_TARGET, CALL_FUNCTION, CALL_AS_METHOD); | |
917 } else { | |
918 ParameterCount actual(r0); | |
919 __ InvokeFunction(r1, actual, CALL_FUNCTION, | |
920 NullCallWrapper(), CALL_AS_METHOD); | |
921 } | |
922 | |
923 // Pop the function from the stack. | |
924 // sp[0]: constructor function | |
925 // sp[2]: receiver | |
926 // sp[3]: constructor function | |
927 // sp[4]: number of arguments (smi-tagged) | |
928 __ pop(); | |
929 | |
930 // Restore context from the frame. | |
931 // r0: result | |
932 // sp[0]: receiver | |
933 // sp[1]: constructor function | |
934 // sp[2]: number of arguments (smi-tagged) | |
935 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | |
936 | |
937 // If the result is an object (in the ECMA sense), we should get rid | |
938 // of the receiver and use the result; see ECMA-262 section 13.2.2-7 | |
939 // on page 74. | |
940 Label use_receiver, exit; | |
941 | |
942 // If the result is a smi, it is *not* an object in the ECMA sense. | |
943 // r0: result | |
944 // sp[0]: receiver (newly allocated object) | |
945 // sp[1]: constructor function | |
946 // sp[2]: number of arguments (smi-tagged) | |
947 __ JumpIfSmi(r0, &use_receiver); | |
948 | |
949 // If the type of the result (stored in its map) is less than | |
950 // FIRST_SPEC_OBJECT_TYPE, it is not an object in the ECMA sense. | |
951 __ CompareObjectType(r0, r3, r3, FIRST_SPEC_OBJECT_TYPE); | |
952 __ b(ge, &exit); | |
953 | |
954 // Throw away the result of the constructor invocation and use the | |
955 // on-stack receiver as the result. | |
956 __ bind(&use_receiver); | |
957 __ ldr(r0, MemOperand(sp)); | |
958 | |
959 // Remove receiver from the stack, remove caller arguments, and | |
960 // return. | |
961 __ bind(&exit); | |
962 // r0: result | |
963 // sp[0]: receiver (newly allocated object) | |
964 // sp[1]: constructor function | |
965 // sp[2]: number of arguments (smi-tagged) | |
966 __ ldr(r1, MemOperand(sp, 2 * kPointerSize)); | |
967 __ LeaveConstructFrame(); | |
968 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); | 987 __ add(sp, sp, Operand(r1, LSL, kPointerSizeLog2 - 1)); |
969 __ add(sp, sp, Operand(kPointerSize)); | 988 __ add(sp, sp, Operand(kPointerSize)); |
970 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); | 989 __ IncrementCounter(isolate->counters()->constructed_objects(), 1, r1, r2); |
971 __ Jump(lr); | 990 __ Jump(lr); |
972 } | 991 } |
973 | 992 |
974 | 993 |
975 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { | 994 void Builtins::Generate_JSConstructStubCountdown(MacroAssembler* masm) { |
976 Generate_JSConstructStubHelper(masm, false, true); | 995 Generate_JSConstructStubHelper(masm, false, true); |
977 } | 996 } |
(...skipping 12 matching lines...) Expand all Loading... |
990 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, | 1009 static void Generate_JSEntryTrampolineHelper(MacroAssembler* masm, |
991 bool is_construct) { | 1010 bool is_construct) { |
992 // Called from Generate_JS_Entry | 1011 // Called from Generate_JS_Entry |
993 // r0: code entry | 1012 // r0: code entry |
994 // r1: function | 1013 // r1: function |
995 // r2: receiver | 1014 // r2: receiver |
996 // r3: argc | 1015 // r3: argc |
997 // r4: argv | 1016 // r4: argv |
998 // r5-r7, cp may be clobbered | 1017 // r5-r7, cp may be clobbered |
999 | 1018 |
1000 // Clear the context before we push it when entering the JS frame. | 1019 // Clear the context before we push it when entering the internal frame. |
1001 __ mov(cp, Operand(0, RelocInfo::NONE)); | 1020 __ mov(cp, Operand(0, RelocInfo::NONE)); |
1002 | 1021 |
1003 // Enter an internal frame. | 1022 // Enter an internal frame. |
1004 __ EnterInternalFrame(); | 1023 { |
| 1024 FrameScope scope(masm, StackFrame::INTERNAL); |
1005 | 1025 |
1006 // Set up the context from the function argument. | 1026 // Set up the context from the function argument. |
1007 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1027 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1008 | 1028 |
1009 // Set up the roots register. | 1029 // Set up the roots register. |
1010 ExternalReference roots_address = | 1030 ExternalReference roots_address = |
1011 ExternalReference::roots_address(masm->isolate()); | 1031 ExternalReference::roots_address(masm->isolate()); |
1012 __ mov(r10, Operand(roots_address)); | 1032 __ mov(r10, Operand(roots_address)); |
1013 | 1033 |
1014 // Push the function and the receiver onto the stack. | 1034 // Push the function and the receiver onto the stack. |
1015 __ push(r1); | 1035 __ push(r1); |
1016 __ push(r2); | 1036 __ push(r2); |
1017 | 1037 |
1018 // Copy arguments to the stack in a loop. | 1038 // Copy arguments to the stack in a loop. |
1019 // r1: function | 1039 // r1: function |
1020 // r3: argc | 1040 // r3: argc |
1021 // r4: argv, i.e. points to first arg | 1041 // r4: argv, i.e. points to first arg |
1022 Label loop, entry; | 1042 Label loop, entry; |
1023 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); | 1043 __ add(r2, r4, Operand(r3, LSL, kPointerSizeLog2)); |
1024 // r2 points past last arg. | 1044 // r2 points past last arg. |
1025 __ b(&entry); | 1045 __ b(&entry); |
1026 __ bind(&loop); | 1046 __ bind(&loop); |
1027 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter | 1047 __ ldr(r0, MemOperand(r4, kPointerSize, PostIndex)); // read next parameter |
1028 __ ldr(r0, MemOperand(r0)); // dereference handle | 1048 __ ldr(r0, MemOperand(r0)); // dereference handle |
1029 __ push(r0); // push parameter | 1049 __ push(r0); // push parameter |
1030 __ bind(&entry); | 1050 __ bind(&entry); |
1031 __ cmp(r4, r2); | 1051 __ cmp(r4, r2); |
1032 __ b(ne, &loop); | 1052 __ b(ne, &loop); |
1033 | 1053 |
1034 // Initialize all JavaScript callee-saved registers, since they will be seen | 1054 // Initialize all JavaScript callee-saved registers, since they will be seen |
1035 // by the garbage collector as part of handlers. | 1055 // by the garbage collector as part of handlers. |
1036 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); | 1056 __ LoadRoot(r4, Heap::kUndefinedValueRootIndex); |
1037 __ mov(r5, Operand(r4)); | 1057 __ mov(r5, Operand(r4)); |
1038 __ mov(r6, Operand(r4)); | 1058 __ mov(r6, Operand(r4)); |
1039 __ mov(r7, Operand(r4)); | 1059 __ mov(r7, Operand(r4)); |
1040 if (kR9Available == 1) { | 1060 if (kR9Available == 1) { |
1041 __ mov(r9, Operand(r4)); | 1061 __ mov(r9, Operand(r4)); |
| 1062 } |
| 1063 |
| 1064 // Invoke the code and pass argc as r0. |
| 1065 __ mov(r0, Operand(r3)); |
| 1066 if (is_construct) { |
| 1067 __ Call(masm->isolate()->builtins()->JSConstructCall()); |
| 1068 } else { |
| 1069 ParameterCount actual(r0); |
| 1070 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
| 1071 NullCallWrapper(), CALL_AS_METHOD); |
| 1072 } |
| 1073 // Exit the JS frame and remove the parameters (except function), and |
| 1074 // return. |
| 1075 // Respect ABI stack constraint. |
1042 } | 1076 } |
1043 | |
1044 // Invoke the code and pass argc as r0. | |
1045 __ mov(r0, Operand(r3)); | |
1046 if (is_construct) { | |
1047 __ Call(masm->isolate()->builtins()->JSConstructCall()); | |
1048 } else { | |
1049 ParameterCount actual(r0); | |
1050 __ InvokeFunction(r1, actual, CALL_FUNCTION, | |
1051 NullCallWrapper(), CALL_AS_METHOD); | |
1052 } | |
1053 | |
1054 // Exit the JS frame and remove the parameters (except function), and return. | |
1055 // Respect ABI stack constraint. | |
1056 __ LeaveInternalFrame(); | |
1057 __ Jump(lr); | 1077 __ Jump(lr); |
1058 | 1078 |
1059 // r0: result | 1079 // r0: result |
1060 } | 1080 } |
1061 | 1081 |
1062 | 1082 |
1063 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { | 1083 void Builtins::Generate_JSEntryTrampoline(MacroAssembler* masm) { |
1064 Generate_JSEntryTrampolineHelper(masm, false); | 1084 Generate_JSEntryTrampolineHelper(masm, false); |
1065 } | 1085 } |
1066 | 1086 |
1067 | 1087 |
1068 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { | 1088 void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) { |
1069 Generate_JSEntryTrampolineHelper(masm, true); | 1089 Generate_JSEntryTrampolineHelper(masm, true); |
1070 } | 1090 } |
1071 | 1091 |
1072 | 1092 |
1073 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { | 1093 void Builtins::Generate_LazyCompile(MacroAssembler* masm) { |
1074 // Enter an internal frame. | 1094 // Enter an internal frame. |
1075 __ EnterInternalFrame(); | 1095 { |
| 1096 FrameScope scope(masm, StackFrame::INTERNAL); |
1076 | 1097 |
1077 // Preserve the function. | 1098 // Preserve the function. |
1078 __ push(r1); | 1099 __ push(r1); |
1079 // Push call kind information. | 1100 // Push call kind information. |
1080 __ push(r5); | 1101 __ push(r5); |
1081 | 1102 |
1082 // Push the function on the stack as the argument to the runtime function. | 1103 // Push the function on the stack as the argument to the runtime function. |
1083 __ push(r1); | 1104 __ push(r1); |
1084 __ CallRuntime(Runtime::kLazyCompile, 1); | 1105 __ CallRuntime(Runtime::kLazyCompile, 1); |
1085 // Calculate the entry point. | 1106 // Calculate the entry point. |
1086 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1107 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1087 | 1108 |
1088 // Restore call kind information. | 1109 // Restore call kind information. |
1089 __ pop(r5); | 1110 __ pop(r5); |
1090 // Restore saved function. | 1111 // Restore saved function. |
1091 __ pop(r1); | 1112 __ pop(r1); |
1092 | 1113 |
1093 // Tear down temporary frame. | 1114 // Tear down internal frame. |
1094 __ LeaveInternalFrame(); | 1115 } |
1095 | 1116 |
1096 // Do a tail-call of the compiled function. | 1117 // Do a tail-call of the compiled function. |
1097 __ Jump(r2); | 1118 __ Jump(r2); |
1098 } | 1119 } |
1099 | 1120 |
1100 | 1121 |
1101 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { | 1122 void Builtins::Generate_LazyRecompile(MacroAssembler* masm) { |
1102 // Enter an internal frame. | 1123 // Enter an internal frame. |
1103 __ EnterInternalFrame(); | 1124 { |
| 1125 FrameScope scope(masm, StackFrame::INTERNAL); |
1104 | 1126 |
1105 // Preserve the function. | 1127 // Preserve the function. |
1106 __ push(r1); | 1128 __ push(r1); |
1107 // Push call kind information. | 1129 // Push call kind information. |
1108 __ push(r5); | 1130 __ push(r5); |
1109 | 1131 |
1110 // Push the function on the stack as the argument to the runtime function. | 1132 // Push the function on the stack as the argument to the runtime function. |
1111 __ push(r1); | 1133 __ push(r1); |
1112 __ CallRuntime(Runtime::kLazyRecompile, 1); | 1134 __ CallRuntime(Runtime::kLazyRecompile, 1); |
1113 // Calculate the entry point. | 1135 // Calculate the entry point. |
1114 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); | 1136 __ add(r2, r0, Operand(Code::kHeaderSize - kHeapObjectTag)); |
1115 | 1137 |
1116 // Restore call kind information. | 1138 // Restore call kind information. |
1117 __ pop(r5); | 1139 __ pop(r5); |
1118 // Restore saved function. | 1140 // Restore saved function. |
1119 __ pop(r1); | 1141 __ pop(r1); |
1120 | 1142 |
1121 // Tear down temporary frame. | 1143 // Tear down internal frame. |
1122 __ LeaveInternalFrame(); | 1144 } |
1123 | 1145 |
1124 // Do a tail-call of the compiled function. | 1146 // Do a tail-call of the compiled function. |
1125 __ Jump(r2); | 1147 __ Jump(r2); |
1126 } | 1148 } |
1127 | 1149 |
1128 | 1150 |
1129 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, | 1151 static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm, |
1130 Deoptimizer::BailoutType type) { | 1152 Deoptimizer::BailoutType type) { |
1131 __ EnterInternalFrame(); | 1153 { |
1132 // Pass the function and deoptimization type to the runtime system. | 1154 FrameScope scope(masm, StackFrame::INTERNAL); |
1133 __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); | 1155 // Pass the function and deoptimization type to the runtime system. |
1134 __ push(r0); | 1156 __ mov(r0, Operand(Smi::FromInt(static_cast<int>(type)))); |
1135 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); | 1157 __ push(r0); |
1136 __ LeaveInternalFrame(); | 1158 __ CallRuntime(Runtime::kNotifyDeoptimized, 1); |
| 1159 } |
1137 | 1160 |
1138 // Get the full codegen state from the stack and untag it -> r6. | 1161 // Get the full codegen state from the stack and untag it -> r6. |
1139 __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); | 1162 __ ldr(r6, MemOperand(sp, 0 * kPointerSize)); |
1140 __ SmiUntag(r6); | 1163 __ SmiUntag(r6); |
1141 // Switch on the state. | 1164 // Switch on the state. |
1142 Label with_tos_register, unknown_state; | 1165 Label with_tos_register, unknown_state; |
1143 __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); | 1166 __ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS)); |
1144 __ b(ne, &with_tos_register); | 1167 __ b(ne, &with_tos_register); |
1145 __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. | 1168 __ add(sp, sp, Operand(1 * kPointerSize)); // Remove state. |
1146 __ Ret(); | 1169 __ Ret(); |
(...skipping 19 matching lines...) Expand all Loading... |
1166 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); | 1189 Generate_NotifyDeoptimizedHelper(masm, Deoptimizer::LAZY); |
1167 } | 1190 } |
1168 | 1191 |
1169 | 1192 |
1170 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { | 1193 void Builtins::Generate_NotifyOSR(MacroAssembler* masm) { |
1171 // For now, we are relying on the fact that Runtime::NotifyOSR | 1194 // For now, we are relying on the fact that Runtime::NotifyOSR |
1172 // doesn't do any garbage collection which allows us to save/restore | 1195 // doesn't do any garbage collection which allows us to save/restore |
1173 // the registers without worrying about which of them contain | 1196 // the registers without worrying about which of them contain |
1174 // pointers. This seems a bit fragile. | 1197 // pointers. This seems a bit fragile. |
1175 __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); | 1198 __ stm(db_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); |
1176 __ EnterInternalFrame(); | 1199 { |
1177 __ CallRuntime(Runtime::kNotifyOSR, 0); | 1200 FrameScope scope(masm, StackFrame::INTERNAL); |
1178 __ LeaveInternalFrame(); | 1201 __ CallRuntime(Runtime::kNotifyOSR, 0); |
| 1202 } |
1179 __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); | 1203 __ ldm(ia_w, sp, kJSCallerSaved | kCalleeSaved | lr.bit() | fp.bit()); |
1180 __ Ret(); | 1204 __ Ret(); |
1181 } | 1205 } |
1182 | 1206 |
1183 | 1207 |
1184 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { | 1208 void Builtins::Generate_OnStackReplacement(MacroAssembler* masm) { |
1185 CpuFeatures::TryForceFeatureScope scope(VFP3); | 1209 CpuFeatures::TryForceFeatureScope scope(VFP3); |
1186 if (!CpuFeatures::IsSupported(VFP3)) { | 1210 if (!CpuFeatures::IsSupported(VFP3)) { |
1187 __ Abort("Unreachable code: Cannot optimize without VFP3 support."); | 1211 __ Abort("Unreachable code: Cannot optimize without VFP3 support."); |
1188 return; | 1212 return; |
1189 } | 1213 } |
1190 | 1214 |
1191 // Lookup the function in the JavaScript frame and push it as an | 1215 // Lookup the function in the JavaScript frame and push it as an |
1192 // argument to the on-stack replacement function. | 1216 // argument to the on-stack replacement function. |
1193 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 1217 __ ldr(r0, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); |
1194 __ EnterInternalFrame(); | 1218 { |
1195 __ push(r0); | 1219 FrameScope scope(masm, StackFrame::INTERNAL); |
1196 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); | 1220 __ push(r0); |
1197 __ LeaveInternalFrame(); | 1221 __ CallRuntime(Runtime::kCompileForOnStackReplacement, 1); |
| 1222 } |
1198 | 1223 |
1199 // If the result was -1 it means that we couldn't optimize the | 1224 // If the result was -1 it means that we couldn't optimize the |
1200 // function. Just return and continue in the unoptimized version. | 1225 // function. Just return and continue in the unoptimized version. |
1201 Label skip; | 1226 Label skip; |
1202 __ cmp(r0, Operand(Smi::FromInt(-1))); | 1227 __ cmp(r0, Operand(Smi::FromInt(-1))); |
1203 __ b(ne, &skip); | 1228 __ b(ne, &skip); |
1204 __ Ret(); | 1229 __ Ret(); |
1205 | 1230 |
1206 __ bind(&skip); | 1231 __ bind(&skip); |
1207 // Untag the AST id and push it on the stack. | 1232 // Untag the AST id and push it on the stack. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1269 __ b(eq, &use_global_receiver); | 1294 __ b(eq, &use_global_receiver); |
1270 __ LoadRoot(r3, Heap::kNullValueRootIndex); | 1295 __ LoadRoot(r3, Heap::kNullValueRootIndex); |
1271 __ cmp(r2, r3); | 1296 __ cmp(r2, r3); |
1272 __ b(eq, &use_global_receiver); | 1297 __ b(eq, &use_global_receiver); |
1273 | 1298 |
1274 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1299 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
1275 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); | 1300 __ CompareObjectType(r2, r3, r3, FIRST_SPEC_OBJECT_TYPE); |
1276 __ b(ge, &shift_arguments); | 1301 __ b(ge, &shift_arguments); |
1277 | 1302 |
1278 __ bind(&convert_to_object); | 1303 __ bind(&convert_to_object); |
1279 __ EnterInternalFrame(); // In order to preserve argument count. | |
1280 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. | |
1281 __ push(r0); | |
1282 | 1304 |
1283 __ push(r2); | 1305 { |
1284 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1306 // Enter an internal frame in order to preserve argument count. |
1285 __ mov(r2, r0); | 1307 FrameScope scope(masm, StackFrame::INTERNAL); |
| 1308 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); // Smi-tagged. |
| 1309 __ push(r0); |
1286 | 1310 |
1287 __ pop(r0); | 1311 __ push(r2); |
1288 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 1312 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
1289 __ LeaveInternalFrame(); | 1313 __ mov(r2, r0); |
| 1314 |
| 1315 __ pop(r0); |
| 1316 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
| 1317 |
| 1318 // Exit the internal frame. |
| 1319 } |
| 1320 |
1290 // Restore the function to r1, and the flag to r4. | 1321 // Restore the function to r1, and the flag to r4. |
1291 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); | 1322 __ ldr(r1, MemOperand(sp, r0, LSL, kPointerSizeLog2)); |
1292 __ mov(r4, Operand(0, RelocInfo::NONE)); | 1323 __ mov(r4, Operand(0, RelocInfo::NONE)); |
1293 __ jmp(&patch_receiver); | 1324 __ jmp(&patch_receiver); |
1294 | 1325 |
1295 // Use the global receiver object from the called function as the | 1326 // Use the global receiver object from the called function as the |
1296 // receiver. | 1327 // receiver. |
1297 __ bind(&use_global_receiver); | 1328 __ bind(&use_global_receiver); |
1298 const int kGlobalIndex = | 1329 const int kGlobalIndex = |
1299 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 1330 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1399 } | 1430 } |
1400 | 1431 |
1401 | 1432 |
1402 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { | 1433 void Builtins::Generate_FunctionApply(MacroAssembler* masm) { |
1403 const int kIndexOffset = -5 * kPointerSize; | 1434 const int kIndexOffset = -5 * kPointerSize; |
1404 const int kLimitOffset = -4 * kPointerSize; | 1435 const int kLimitOffset = -4 * kPointerSize; |
1405 const int kArgsOffset = 2 * kPointerSize; | 1436 const int kArgsOffset = 2 * kPointerSize; |
1406 const int kRecvOffset = 3 * kPointerSize; | 1437 const int kRecvOffset = 3 * kPointerSize; |
1407 const int kFunctionOffset = 4 * kPointerSize; | 1438 const int kFunctionOffset = 4 * kPointerSize; |
1408 | 1439 |
1409 __ EnterInternalFrame(); | 1440 { |
| 1441 FrameScope frame_scope(masm, StackFrame::INTERNAL); |
1410 | 1442 |
1411 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function | 1443 __ ldr(r0, MemOperand(fp, kFunctionOffset)); // get the function |
1412 __ push(r0); | 1444 __ push(r0); |
1413 __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array | 1445 __ ldr(r0, MemOperand(fp, kArgsOffset)); // get the args array |
1414 __ push(r0); | 1446 __ push(r0); |
1415 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); | 1447 __ InvokeBuiltin(Builtins::APPLY_PREPARE, CALL_FUNCTION); |
1416 | 1448 |
1417 // Check the stack for overflow. We are not trying to catch | 1449 // Check the stack for overflow. We are not trying to catch |
1418 // interruptions (e.g. debug break and preemption) here, so the "real stack | 1450 // interruptions (e.g. debug break and preemption) here, so the "real stack |
1419 // limit" is checked. | 1451 // limit" is checked. |
1420 Label okay; | 1452 Label okay; |
1421 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); | 1453 __ LoadRoot(r2, Heap::kRealStackLimitRootIndex); |
1422 // Make r2 the space we have left. The stack might already be overflowed | 1454 // Make r2 the space we have left. The stack might already be overflowed |
1423 // here which will cause r2 to become negative. | 1455 // here which will cause r2 to become negative. |
1424 __ sub(r2, sp, r2); | 1456 __ sub(r2, sp, r2); |
1425 // Check if the arguments will overflow the stack. | 1457 // Check if the arguments will overflow the stack. |
1426 __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); | 1458 __ cmp(r2, Operand(r0, LSL, kPointerSizeLog2 - kSmiTagSize)); |
1427 __ b(gt, &okay); // Signed comparison. | 1459 __ b(gt, &okay); // Signed comparison. |
1428 | 1460 |
1429 // Out of stack space. | 1461 // Out of stack space. |
1430 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1462 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
1431 __ push(r1); | 1463 __ push(r1); |
1432 __ push(r0); | 1464 __ push(r0); |
1433 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); | 1465 __ InvokeBuiltin(Builtins::APPLY_OVERFLOW, CALL_FUNCTION); |
1434 // End of stack check. | 1466 // End of stack check. |
1435 | 1467 |
1436 // Push current limit and index. | 1468 // Push current limit and index. |
1437 __ bind(&okay); | 1469 __ bind(&okay); |
1438 __ push(r0); // limit | 1470 __ push(r0); // limit |
1439 __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index | 1471 __ mov(r1, Operand(0, RelocInfo::NONE)); // initial index |
1440 __ push(r1); | 1472 __ push(r1); |
1441 | 1473 |
1442 // Get the receiver. | 1474 // Get the receiver. |
1443 __ ldr(r0, MemOperand(fp, kRecvOffset)); | 1475 __ ldr(r0, MemOperand(fp, kRecvOffset)); |
1444 | 1476 |
1445 // Check that the function is a JS function (otherwise it must be a proxy). | 1477 // Check that the function is a JS function (otherwise it must be a proxy). |
1446 Label push_receiver; | 1478 Label push_receiver; |
1447 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1479 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
1448 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1480 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
1449 __ b(ne, &push_receiver); | 1481 __ b(ne, &push_receiver); |
1450 | 1482 |
1451 // Change context eagerly to get the right global object if necessary. | 1483 // Change context eagerly to get the right global object if necessary. |
1452 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); | 1484 __ ldr(cp, FieldMemOperand(r1, JSFunction::kContextOffset)); |
1453 // Load the shared function info while the function is still in r1. | 1485 // Load the shared function info while the function is still in r1. |
1454 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); | 1486 __ ldr(r2, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset)); |
1455 | 1487 |
1456 // Compute the receiver. | 1488 // Compute the receiver. |
1457 // Do not transform the receiver for strict mode functions. | 1489 // Do not transform the receiver for strict mode functions. |
1458 Label call_to_object, use_global_receiver; | 1490 Label call_to_object, use_global_receiver; |
1459 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); | 1491 __ ldr(r2, FieldMemOperand(r2, SharedFunctionInfo::kCompilerHintsOffset)); |
1460 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + | 1492 __ tst(r2, Operand(1 << (SharedFunctionInfo::kStrictModeFunction + |
1461 kSmiTagSize))); | 1493 kSmiTagSize))); |
1462 __ b(ne, &push_receiver); | 1494 __ b(ne, &push_receiver); |
1463 | 1495 |
1464 // Do not transform the receiver for strict mode functions. | 1496 // Do not transform the receiver for strict mode functions. |
1465 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); | 1497 __ tst(r2, Operand(1 << (SharedFunctionInfo::kNative + kSmiTagSize))); |
1466 __ b(ne, &push_receiver); | 1498 __ b(ne, &push_receiver); |
1467 | 1499 |
1468 // Compute the receiver in non-strict mode. | 1500 // Compute the receiver in non-strict mode. |
1469 __ JumpIfSmi(r0, &call_to_object); | 1501 __ JumpIfSmi(r0, &call_to_object); |
1470 __ LoadRoot(r1, Heap::kNullValueRootIndex); | 1502 __ LoadRoot(r1, Heap::kNullValueRootIndex); |
1471 __ cmp(r0, r1); | 1503 __ cmp(r0, r1); |
1472 __ b(eq, &use_global_receiver); | 1504 __ b(eq, &use_global_receiver); |
1473 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); | 1505 __ LoadRoot(r1, Heap::kUndefinedValueRootIndex); |
1474 __ cmp(r0, r1); | 1506 __ cmp(r0, r1); |
1475 __ b(eq, &use_global_receiver); | 1507 __ b(eq, &use_global_receiver); |
1476 | 1508 |
1477 // Check if the receiver is already a JavaScript object. | 1509 // Check if the receiver is already a JavaScript object. |
1478 // r0: receiver | 1510 // r0: receiver |
1479 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); | 1511 STATIC_ASSERT(LAST_SPEC_OBJECT_TYPE == LAST_TYPE); |
1480 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); | 1512 __ CompareObjectType(r0, r1, r1, FIRST_SPEC_OBJECT_TYPE); |
1481 __ b(ge, &push_receiver); | 1513 __ b(ge, &push_receiver); |
1482 | 1514 |
1483 // Convert the receiver to a regular object. | 1515 // Convert the receiver to a regular object. |
1484 // r0: receiver | 1516 // r0: receiver |
1485 __ bind(&call_to_object); | 1517 __ bind(&call_to_object); |
1486 __ push(r0); | 1518 __ push(r0); |
1487 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); | 1519 __ InvokeBuiltin(Builtins::TO_OBJECT, CALL_FUNCTION); |
1488 __ b(&push_receiver); | 1520 __ b(&push_receiver); |
1489 | 1521 |
1490 // Use the current global receiver object as the receiver. | 1522 // Use the current global receiver object as the receiver. |
1491 __ bind(&use_global_receiver); | 1523 __ bind(&use_global_receiver); |
1492 const int kGlobalOffset = | 1524 const int kGlobalOffset = |
1493 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; | 1525 Context::kHeaderSize + Context::GLOBAL_INDEX * kPointerSize; |
1494 __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); | 1526 __ ldr(r0, FieldMemOperand(cp, kGlobalOffset)); |
1495 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); | 1527 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalContextOffset)); |
1496 __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); | 1528 __ ldr(r0, FieldMemOperand(r0, kGlobalOffset)); |
1497 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); | 1529 __ ldr(r0, FieldMemOperand(r0, GlobalObject::kGlobalReceiverOffset)); |
1498 | 1530 |
1499 // Push the receiver. | 1531 // Push the receiver. |
1500 // r0: receiver | 1532 // r0: receiver |
1501 __ bind(&push_receiver); | 1533 __ bind(&push_receiver); |
1502 __ push(r0); | 1534 __ push(r0); |
1503 | 1535 |
1504 // Copy all arguments from the array to the stack. | 1536 // Copy all arguments from the array to the stack. |
1505 Label entry, loop; | 1537 Label entry, loop; |
1506 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1538 __ ldr(r0, MemOperand(fp, kIndexOffset)); |
1507 __ b(&entry); | 1539 __ b(&entry); |
1508 | 1540 |
1509 // Load the current argument from the arguments array and push it to the | 1541 // Load the current argument from the arguments array and push it to the |
1510 // stack. | 1542 // stack. |
1511 // r0: current argument index | 1543 // r0: current argument index |
1512 __ bind(&loop); | 1544 __ bind(&loop); |
1513 __ ldr(r1, MemOperand(fp, kArgsOffset)); | 1545 __ ldr(r1, MemOperand(fp, kArgsOffset)); |
1514 __ push(r1); | 1546 __ push(r1); |
1515 __ push(r0); | 1547 __ push(r0); |
1516 | 1548 |
1517 // Call the runtime to access the property in the arguments array. | 1549 // Call the runtime to access the property in the arguments array. |
1518 __ CallRuntime(Runtime::kGetProperty, 2); | 1550 __ CallRuntime(Runtime::kGetProperty, 2); |
1519 __ push(r0); | 1551 __ push(r0); |
1520 | 1552 |
1521 // Use inline caching to access the arguments. | 1553 // Use inline caching to access the arguments. |
1522 __ ldr(r0, MemOperand(fp, kIndexOffset)); | 1554 __ ldr(r0, MemOperand(fp, kIndexOffset)); |
1523 __ add(r0, r0, Operand(1 << kSmiTagSize)); | 1555 __ add(r0, r0, Operand(1 << kSmiTagSize)); |
1524 __ str(r0, MemOperand(fp, kIndexOffset)); | 1556 __ str(r0, MemOperand(fp, kIndexOffset)); |
1525 | 1557 |
1526 // Test if the copy loop has finished copying all the elements from the | 1558 // Test if the copy loop has finished copying all the elements from the |
1527 // arguments object. | 1559 // arguments object. |
1528 __ bind(&entry); | 1560 __ bind(&entry); |
1529 __ ldr(r1, MemOperand(fp, kLimitOffset)); | 1561 __ ldr(r1, MemOperand(fp, kLimitOffset)); |
1530 __ cmp(r0, r1); | 1562 __ cmp(r0, r1); |
1531 __ b(ne, &loop); | 1563 __ b(ne, &loop); |
1532 | 1564 |
1533 // Invoke the function. | 1565 // Invoke the function. |
1534 Label call_proxy; | 1566 Label call_proxy; |
1535 ParameterCount actual(r0); | 1567 ParameterCount actual(r0); |
1536 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); | 1568 __ mov(r0, Operand(r0, ASR, kSmiTagSize)); |
1537 __ ldr(r1, MemOperand(fp, kFunctionOffset)); | 1569 __ ldr(r1, MemOperand(fp, kFunctionOffset)); |
1538 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); | 1570 __ CompareObjectType(r1, r2, r2, JS_FUNCTION_TYPE); |
1539 __ b(ne, &call_proxy); | 1571 __ b(ne, &call_proxy); |
1540 __ InvokeFunction(r1, actual, CALL_FUNCTION, | 1572 __ InvokeFunction(r1, actual, CALL_FUNCTION, |
1541 NullCallWrapper(), CALL_AS_METHOD); | 1573 NullCallWrapper(), CALL_AS_METHOD); |
1542 | 1574 |
1543 // Tear down the internal frame and remove function, receiver and args. | 1575 frame_scope.GenerateLeaveFrame(); |
1544 __ LeaveInternalFrame(); | 1576 __ add(sp, sp, Operand(3 * kPointerSize)); |
1545 __ add(sp, sp, Operand(3 * kPointerSize)); | 1577 __ Jump(lr); |
1546 __ Jump(lr); | |
1547 | 1578 |
1548 // Invoke the function proxy. | 1579 // Invoke the function proxy. |
1549 __ bind(&call_proxy); | 1580 __ bind(&call_proxy); |
1550 __ push(r1); // add function proxy as last argument | 1581 __ push(r1); // add function proxy as last argument |
1551 __ add(r0, r0, Operand(1)); | 1582 __ add(r0, r0, Operand(1)); |
1552 __ mov(r2, Operand(0, RelocInfo::NONE)); | 1583 __ mov(r2, Operand(0, RelocInfo::NONE)); |
1553 __ SetCallKind(r5, CALL_AS_METHOD); | 1584 __ SetCallKind(r5, CALL_AS_METHOD); |
1554 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); | 1585 __ GetBuiltinEntry(r3, Builtins::CALL_FUNCTION_PROXY); |
1555 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), | 1586 __ Call(masm->isolate()->builtins()->ArgumentsAdaptorTrampoline(), |
1556 RelocInfo::CODE_TARGET); | 1587 RelocInfo::CODE_TARGET); |
1557 | 1588 |
1558 __ LeaveInternalFrame(); | 1589 // Tear down the internal frame and remove function, receiver and args. |
| 1590 } |
1559 __ add(sp, sp, Operand(3 * kPointerSize)); | 1591 __ add(sp, sp, Operand(3 * kPointerSize)); |
1560 __ Jump(lr); | 1592 __ Jump(lr); |
1561 } | 1593 } |
1562 | 1594 |
1563 | 1595 |
1564 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { | 1596 static void EnterArgumentsAdaptorFrame(MacroAssembler* masm) { |
1565 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); | 1597 __ mov(r0, Operand(r0, LSL, kSmiTagSize)); |
1566 __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 1598 __ mov(r4, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
1567 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); | 1599 __ stm(db_w, sp, r0.bit() | r1.bit() | r4.bit() | fp.bit() | lr.bit()); |
1568 __ add(fp, sp, Operand(3 * kPointerSize)); | 1600 __ add(fp, sp, Operand(3 * kPointerSize)); |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1686 __ bind(&dont_adapt_arguments); | 1718 __ bind(&dont_adapt_arguments); |
1687 __ Jump(r3); | 1719 __ Jump(r3); |
1688 } | 1720 } |
1689 | 1721 |
1690 | 1722 |
1691 #undef __ | 1723 #undef __ |
1692 | 1724 |
1693 } } // namespace v8::internal | 1725 } } // namespace v8::internal |
1694 | 1726 |
1695 #endif // V8_TARGET_ARCH_ARM | 1727 #endif // V8_TARGET_ARCH_ARM |
OLD | NEW |