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