| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_IA32 | 5 #if V8_TARGET_ARCH_IA32 |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/codegen.h" | 8 #include "src/codegen.h" |
| 9 #include "src/deoptimizer.h" | 9 #include "src/deoptimizer.h" |
| 10 #include "src/full-codegen/full-codegen.h" | 10 #include "src/full-codegen/full-codegen.h" |
| (...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 686 __ Push(Operand(start_address, 0)); | 686 __ Push(Operand(start_address, 0)); |
| 687 __ sub(start_address, Immediate(kPointerSize)); | 687 __ sub(start_address, Immediate(kPointerSize)); |
| 688 __ bind(&loop_check); | 688 __ bind(&loop_check); |
| 689 __ cmp(start_address, array_limit); | 689 __ cmp(start_address, array_limit); |
| 690 __ j(greater, &loop_header, Label::kNear); | 690 __ j(greater, &loop_header, Label::kNear); |
| 691 } | 691 } |
| 692 | 692 |
| 693 // static | 693 // static |
| 694 void Builtins::Generate_InterpreterPushArgsAndCallImpl( | 694 void Builtins::Generate_InterpreterPushArgsAndCallImpl( |
| 695 MacroAssembler* masm, TailCallMode tail_call_mode, | 695 MacroAssembler* masm, TailCallMode tail_call_mode, |
| 696 CallableType function_type) { | 696 InterpreterPushArgsMode mode) { |
| 697 // ----------- S t a t e ------------- | 697 // ----------- S t a t e ------------- |
| 698 // -- eax : the number of arguments (not including the receiver) | 698 // -- eax : the number of arguments (not including the receiver) |
| 699 // -- ebx : the address of the first argument to be pushed. Subsequent | 699 // -- ebx : the address of the first argument to be pushed. Subsequent |
| 700 // arguments should be consecutive above this, in the same order as | 700 // arguments should be consecutive above this, in the same order as |
| 701 // they are to be pushed onto the stack. | 701 // they are to be pushed onto the stack. |
| 702 // -- edi : the target to call (can be any Object). | 702 // -- edi : the target to call (can be any Object). |
| 703 // ----------------------------------- | 703 // ----------------------------------- |
| 704 Label stack_overflow; | 704 Label stack_overflow; |
| 705 // Compute the expected number of arguments. | 705 // Compute the expected number of arguments. |
| 706 __ mov(ecx, eax); | 706 __ mov(ecx, eax); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 718 | 718 |
| 719 // Find the address of the last argument. | 719 // Find the address of the last argument. |
| 720 __ shl(ecx, kPointerSizeLog2); | 720 __ shl(ecx, kPointerSizeLog2); |
| 721 __ neg(ecx); | 721 __ neg(ecx); |
| 722 __ add(ecx, ebx); | 722 __ add(ecx, ebx); |
| 723 Generate_InterpreterPushArgs(masm, ecx, ebx); | 723 Generate_InterpreterPushArgs(masm, ecx, ebx); |
| 724 | 724 |
| 725 // Call the target. | 725 // Call the target. |
| 726 __ Push(edx); // Re-push return address. | 726 __ Push(edx); // Re-push return address. |
| 727 | 727 |
| 728 if (function_type == CallableType::kJSFunction) { | 728 if (mode == InterpreterPushArgsMode::kJSFunction) { |
| 729 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, | 729 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, |
| 730 tail_call_mode), | 730 tail_call_mode), |
| 731 RelocInfo::CODE_TARGET); | 731 RelocInfo::CODE_TARGET); |
| 732 } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { |
| 733 __ Jump(masm->isolate()->builtins()->CallWithSpread(), |
| 734 RelocInfo::CODE_TARGET); |
| 732 } else { | 735 } else { |
| 733 DCHECK_EQ(function_type, CallableType::kAny); | |
| 734 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 736 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 735 tail_call_mode), | 737 tail_call_mode), |
| 736 RelocInfo::CODE_TARGET); | 738 RelocInfo::CODE_TARGET); |
| 737 } | 739 } |
| 738 | 740 |
| 739 __ bind(&stack_overflow); | 741 __ bind(&stack_overflow); |
| 740 { | 742 { |
| 741 // Pop the temporary registers, so that return address is on top of stack. | 743 // Pop the temporary registers, so that return address is on top of stack. |
| 742 __ Pop(edi); | 744 __ Pop(edi); |
| 743 | 745 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 836 __ sub(scratch1, Immediate(1)); | 838 __ sub(scratch1, Immediate(1)); |
| 837 __ bind(&loop_check); | 839 __ bind(&loop_check); |
| 838 __ cmp(scratch1, Immediate(0)); | 840 __ cmp(scratch1, Immediate(0)); |
| 839 __ j(greater, &loop_header, Label::kNear); | 841 __ j(greater, &loop_header, Label::kNear); |
| 840 } | 842 } |
| 841 | 843 |
| 842 } // end anonymous namespace | 844 } // end anonymous namespace |
| 843 | 845 |
| 844 // static | 846 // static |
| 845 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( | 847 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( |
| 846 MacroAssembler* masm, PushArgsConstructMode mode) { | 848 MacroAssembler* masm, InterpreterPushArgsMode mode) { |
| 847 // ----------- S t a t e ------------- | 849 // ----------- S t a t e ------------- |
| 848 // -- eax : the number of arguments (not including the receiver) | 850 // -- eax : the number of arguments (not including the receiver) |
| 849 // -- edx : the new target | 851 // -- edx : the new target |
| 850 // -- edi : the constructor | 852 // -- edi : the constructor |
| 851 // -- ebx : allocation site feedback (if available or undefined) | 853 // -- ebx : allocation site feedback (if available or undefined) |
| 852 // -- ecx : the address of the first argument to be pushed. Subsequent | 854 // -- ecx : the address of the first argument to be pushed. Subsequent |
| 853 // arguments should be consecutive above this, in the same order as | 855 // arguments should be consecutive above this, in the same order as |
| 854 // they are to be pushed onto the stack. | 856 // they are to be pushed onto the stack. |
| 855 // ----------------------------------- | 857 // ----------------------------------- |
| 856 Label stack_overflow; | 858 Label stack_overflow; |
| 857 // We need two scratch registers. Push edi and edx onto stack. | 859 // We need two scratch registers. Push edi and edx onto stack. |
| 858 __ Push(edi); | 860 __ Push(edi); |
| 859 __ Push(edx); | 861 __ Push(edx); |
| 860 | 862 |
| 861 // Push arguments and move return address to the top of stack. | 863 // Push arguments and move return address to the top of stack. |
| 862 // The eax register is readonly. The ecx register will be modified. The edx | 864 // The eax register is readonly. The ecx register will be modified. The edx |
| 863 // and edi registers will be modified but restored to their original values. | 865 // and edi registers will be modified but restored to their original values. |
| 864 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, | 866 Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, |
| 865 2, &stack_overflow); | 867 2, &stack_overflow); |
| 866 | 868 |
| 867 // Restore edi and edx | 869 // Restore edi and edx |
| 868 __ Pop(edx); | 870 __ Pop(edx); |
| 869 __ Pop(edi); | 871 __ Pop(edi); |
| 870 | 872 |
| 871 __ AssertUndefinedOrAllocationSite(ebx); | 873 __ AssertUndefinedOrAllocationSite(ebx); |
| 872 if (mode == PushArgsConstructMode::kJSFunction) { | 874 if (mode == InterpreterPushArgsMode::kJSFunction) { |
| 873 // Tail call to the function-specific construct stub (still in the caller | 875 // Tail call to the function-specific construct stub (still in the caller |
| 874 // context at this point). | 876 // context at this point). |
| 875 __ AssertFunction(edi); | 877 __ AssertFunction(edi); |
| 876 | 878 |
| 877 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | 879 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 878 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | 880 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
| 879 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | 881 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 880 __ jmp(ecx); | 882 __ jmp(ecx); |
| 881 } else if (mode == PushArgsConstructMode::kWithFinalSpread) { | 883 } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { |
| 882 // Call the constructor with unmodified eax, edi, edx values. | 884 // Call the constructor with unmodified eax, edi, edx values. |
| 883 __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), | 885 __ Jump(masm->isolate()->builtins()->ConstructWithSpread(), |
| 884 RelocInfo::CODE_TARGET); | 886 RelocInfo::CODE_TARGET); |
| 885 } else { | 887 } else { |
| 886 DCHECK_EQ(PushArgsConstructMode::kOther, mode); | 888 DCHECK_EQ(InterpreterPushArgsMode::kOther, mode); |
| 887 // Call the constructor with unmodified eax, edi, edx values. | 889 // Call the constructor with unmodified eax, edi, edx values. |
| 888 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 890 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 889 } | 891 } |
| 890 | 892 |
| 891 __ bind(&stack_overflow); | 893 __ bind(&stack_overflow); |
| 892 { | 894 { |
| 893 // Pop the temporary registers, so that return address is on top of stack. | 895 // Pop the temporary registers, so that return address is on top of stack. |
| 894 __ Pop(edx); | 896 __ Pop(edx); |
| 895 __ Pop(edi); | 897 __ Pop(edi); |
| 896 | 898 |
| (...skipping 1769 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2666 | 2668 |
| 2667 // 3. Call to something that is not callable. | 2669 // 3. Call to something that is not callable. |
| 2668 __ bind(&non_callable); | 2670 __ bind(&non_callable); |
| 2669 { | 2671 { |
| 2670 FrameScope scope(masm, StackFrame::INTERNAL); | 2672 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2671 __ Push(edi); | 2673 __ Push(edi); |
| 2672 __ CallRuntime(Runtime::kThrowCalledNonCallable); | 2674 __ CallRuntime(Runtime::kThrowCalledNonCallable); |
| 2673 } | 2675 } |
| 2674 } | 2676 } |
| 2675 | 2677 |
| 2676 // static | 2678 static void CheckSpreadAndPushToStack(MacroAssembler* masm) { |
| 2677 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | |
| 2678 // ----------- S t a t e ------------- | |
| 2679 // -- eax : the number of arguments (not including the receiver) | |
| 2680 // -- edx : the new target (checked to be a constructor) | |
| 2681 // -- edi : the constructor to call (checked to be a JSFunction) | |
| 2682 // ----------------------------------- | |
| 2683 __ AssertFunction(edi); | |
| 2684 | |
| 2685 // Calling convention for function specific ConstructStubs require | |
| 2686 // ebx to contain either an AllocationSite or undefined. | |
| 2687 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); | |
| 2688 | |
| 2689 // Tail call to the function-specific construct stub (still in the caller | |
| 2690 // context at this point). | |
| 2691 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
| 2692 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | |
| 2693 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | |
| 2694 __ jmp(ecx); | |
| 2695 } | |
| 2696 | |
| 2697 // static | |
| 2698 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { | |
| 2699 // ----------- S t a t e ------------- | |
| 2700 // -- eax : the number of arguments (not including the receiver) | |
| 2701 // -- edx : the new target (checked to be a constructor) | |
| 2702 // -- edi : the constructor to call (checked to be a JSBoundFunction) | |
| 2703 // ----------------------------------- | |
| 2704 __ AssertBoundFunction(edi); | |
| 2705 | |
| 2706 // Push the [[BoundArguments]] onto the stack. | |
| 2707 Generate_PushBoundArguments(masm); | |
| 2708 | |
| 2709 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. | |
| 2710 { | |
| 2711 Label done; | |
| 2712 __ cmp(edi, edx); | |
| 2713 __ j(not_equal, &done, Label::kNear); | |
| 2714 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
| 2715 __ bind(&done); | |
| 2716 } | |
| 2717 | |
| 2718 // Construct the [[BoundTargetFunction]] via the Construct builtin. | |
| 2719 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
| 2720 __ mov(ecx, Operand::StaticVariable( | |
| 2721 ExternalReference(Builtins::kConstruct, masm->isolate()))); | |
| 2722 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | |
| 2723 __ jmp(ecx); | |
| 2724 } | |
| 2725 | |
| 2726 // static | |
| 2727 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | |
| 2728 // ----------- S t a t e ------------- | |
| 2729 // -- eax : the number of arguments (not including the receiver) | |
| 2730 // -- edi : the constructor to call (checked to be a JSProxy) | |
| 2731 // -- edx : the new target (either the same as the constructor or | |
| 2732 // the JSFunction on which new was invoked initially) | |
| 2733 // ----------------------------------- | |
| 2734 | |
| 2735 // Call into the Runtime for Proxy [[Construct]]. | |
| 2736 __ PopReturnAddressTo(ecx); | |
| 2737 __ Push(edi); | |
| 2738 __ Push(edx); | |
| 2739 __ PushReturnAddressFrom(ecx); | |
| 2740 // Include the pushed new_target, constructor and the receiver. | |
| 2741 __ add(eax, Immediate(3)); | |
| 2742 // Tail-call to the runtime. | |
| 2743 __ JumpToExternalReference( | |
| 2744 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); | |
| 2745 } | |
| 2746 | |
| 2747 // static | |
| 2748 void Builtins::Generate_Construct(MacroAssembler* masm) { | |
| 2749 // ----------- S t a t e ------------- | |
| 2750 // -- eax : the number of arguments (not including the receiver) | |
| 2751 // -- edx : the new target (either the same as the constructor or | |
| 2752 // the JSFunction on which new was invoked initially) | |
| 2753 // -- edi : the constructor to call (can be any Object) | |
| 2754 // ----------------------------------- | |
| 2755 | |
| 2756 // Check if target is a Smi. | |
| 2757 Label non_constructor; | |
| 2758 __ JumpIfSmi(edi, &non_constructor, Label::kNear); | |
| 2759 | |
| 2760 // Dispatch based on instance type. | |
| 2761 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | |
| 2762 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | |
| 2763 RelocInfo::CODE_TARGET); | |
| 2764 | |
| 2765 // Check if target has a [[Construct]] internal method. | |
| 2766 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | |
| 2767 Immediate(1 << Map::kIsConstructor)); | |
| 2768 __ j(zero, &non_constructor, Label::kNear); | |
| 2769 | |
| 2770 // Only dispatch to bound functions after checking whether they are | |
| 2771 // constructors. | |
| 2772 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); | |
| 2773 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), | |
| 2774 RelocInfo::CODE_TARGET); | |
| 2775 | |
| 2776 // Only dispatch to proxies after checking whether they are constructors. | |
| 2777 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | |
| 2778 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | |
| 2779 RelocInfo::CODE_TARGET); | |
| 2780 | |
| 2781 // Called Construct on an exotic Object with a [[Construct]] internal method. | |
| 2782 { | |
| 2783 // Overwrite the original receiver with the (original) target. | |
| 2784 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); | |
| 2785 // Let the "call_as_constructor_delegate" take care of the rest. | |
| 2786 __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); | |
| 2787 __ Jump(masm->isolate()->builtins()->CallFunction(), | |
| 2788 RelocInfo::CODE_TARGET); | |
| 2789 } | |
| 2790 | |
| 2791 // Called Construct on an Object that doesn't have a [[Construct]] internal | |
| 2792 // method. | |
| 2793 __ bind(&non_constructor); | |
| 2794 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), | |
| 2795 RelocInfo::CODE_TARGET); | |
| 2796 } | |
| 2797 | |
| 2798 // static | |
| 2799 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { | |
| 2800 // ----------- S t a t e ------------- | |
| 2801 // -- eax : the number of arguments (not including the receiver) | |
| 2802 // -- edx : the new target (either the same as the constructor or | |
| 2803 // the JSFunction on which new was invoked initially) | |
| 2804 // -- edi : the constructor to call (can be any Object) | |
| 2805 // ----------------------------------- | |
| 2806 | |
| 2807 // Free up some registers. | 2679 // Free up some registers. |
| 2808 __ movd(xmm0, edx); | 2680 __ movd(xmm0, edx); |
| 2809 __ movd(xmm1, edi); | 2681 __ movd(xmm1, edi); |
| 2810 | 2682 |
| 2811 Register argc = eax; | 2683 Register argc = eax; |
| 2812 | 2684 |
| 2813 Register scratch = ecx; | 2685 Register scratch = ecx; |
| 2814 Register scratch2 = edi; | 2686 Register scratch2 = edi; |
| 2815 | 2687 |
| 2816 Register spread = ebx; | 2688 Register spread = ebx; |
| 2817 Register spread_map = edx; | 2689 Register spread_map = edx; |
| 2818 | 2690 |
| 2691 Register spread_len = edx; |
| 2692 |
| 2819 __ mov(spread, Operand(esp, kPointerSize)); | 2693 __ mov(spread, Operand(esp, kPointerSize)); |
| 2820 __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); | 2694 __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); |
| 2821 | 2695 |
| 2822 Label runtime_call, push_args; | 2696 Label runtime_call, push_args; |
| 2823 // Check that the spread is an array. | 2697 // Check that the spread is an array. |
| 2824 __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); | 2698 __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); |
| 2825 __ j(not_equal, &runtime_call); | 2699 __ j(not_equal, &runtime_call); |
| 2826 | 2700 |
| 2827 // Check that we have the original ArrayPrototype. | 2701 // Check that we have the original ArrayPrototype. |
| 2828 __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); | 2702 __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2861 __ j(equal, &no_protector_check); | 2735 __ j(equal, &no_protector_check); |
| 2862 __ cmp(scratch, Immediate(FAST_ELEMENTS)); | 2736 __ cmp(scratch, Immediate(FAST_ELEMENTS)); |
| 2863 __ j(equal, &no_protector_check); | 2737 __ j(equal, &no_protector_check); |
| 2864 // Check the ArrayProtector cell. | 2738 // Check the ArrayProtector cell. |
| 2865 __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); | 2739 __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); |
| 2866 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 2740 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
| 2867 Immediate(Smi::FromInt(Isolate::kProtectorValid))); | 2741 Immediate(Smi::FromInt(Isolate::kProtectorValid))); |
| 2868 __ j(not_equal, &runtime_call); | 2742 __ j(not_equal, &runtime_call); |
| 2869 | 2743 |
| 2870 __ bind(&no_protector_check); | 2744 __ bind(&no_protector_check); |
| 2871 // Load the FixedArray backing store. | 2745 // Load the FixedArray backing store, but use the length from the array. |
| 2746 __ mov(spread_len, FieldOperand(spread, JSArray::kLengthOffset)); |
| 2747 __ SmiUntag(spread_len); |
| 2872 __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); | 2748 __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); |
| 2873 // Free up some registers. | |
| 2874 __ jmp(&push_args); | 2749 __ jmp(&push_args); |
| 2875 | 2750 |
| 2876 __ bind(&runtime_call); | 2751 __ bind(&runtime_call); |
| 2877 { | 2752 { |
| 2878 // Call the builtin for the result of the spread. | 2753 // Call the builtin for the result of the spread. |
| 2879 FrameScope scope(masm, StackFrame::INTERNAL); | 2754 FrameScope scope(masm, StackFrame::INTERNAL); |
| 2880 // Need to save these on the stack. | 2755 // Need to save these on the stack. |
| 2881 __ movd(edi, xmm1); | 2756 __ movd(edi, xmm1); |
| 2882 __ movd(edx, xmm0); | 2757 __ movd(edx, xmm0); |
| 2883 __ Push(edi); | 2758 __ Push(edi); |
| 2884 __ Push(edx); | 2759 __ Push(edx); |
| 2885 __ SmiTag(argc); | 2760 __ SmiTag(argc); |
| 2886 __ Push(argc); | 2761 __ Push(argc); |
| 2887 __ Push(spread); | 2762 __ Push(spread); |
| 2888 __ CallRuntime(Runtime::kSpreadIterableFixed); | 2763 __ CallRuntime(Runtime::kSpreadIterableFixed); |
| 2889 __ mov(spread, eax); | 2764 __ mov(spread, eax); |
| 2890 __ Pop(argc); | 2765 __ Pop(argc); |
| 2891 __ SmiUntag(argc); | 2766 __ SmiUntag(argc); |
| 2892 __ Pop(edx); | 2767 __ Pop(edx); |
| 2893 __ Pop(edi); | 2768 __ Pop(edi); |
| 2894 // Free up some registers. | 2769 // Free up some registers. |
| 2895 __ movd(xmm0, edx); | 2770 __ movd(xmm0, edx); |
| 2896 __ movd(xmm1, edi); | 2771 __ movd(xmm1, edi); |
| 2897 } | 2772 } |
| 2898 | 2773 |
| 2899 Register spread_len = edx; | |
| 2900 Register return_address = edi; | 2774 Register return_address = edi; |
| 2901 __ bind(&push_args); | |
| 2902 { | 2775 { |
| 2776 // Calculate the new nargs including the result of the spread. |
| 2777 __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); |
| 2778 __ SmiUntag(spread_len); |
| 2779 |
| 2780 __ bind(&push_args); |
| 2781 // argc += spread_len - 1. Subtract 1 for the spread itself. |
| 2782 __ lea(argc, Operand(argc, spread_len, times_1, -1)); |
| 2783 |
| 2903 // Pop the return address and spread argument. | 2784 // Pop the return address and spread argument. |
| 2904 __ PopReturnAddressTo(return_address); | 2785 __ PopReturnAddressTo(return_address); |
| 2905 __ Pop(scratch); | 2786 __ Pop(scratch); |
| 2906 | |
| 2907 // Calculate the new nargs including the result of the spread. | |
| 2908 __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); | |
| 2909 __ SmiUntag(spread_len); | |
| 2910 // argc += spread_len - 1. Subtract 1 for the spread itself. | |
| 2911 __ lea(argc, Operand(argc, spread_len, times_1, -1)); | |
| 2912 } | 2787 } |
| 2913 | 2788 |
| 2914 // Check for stack overflow. | 2789 // Check for stack overflow. |
| 2915 { | 2790 { |
| 2916 // Check the stack for overflow. We are not trying to catch interruptions | 2791 // Check the stack for overflow. We are not trying to catch interruptions |
| 2917 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2792 // (i.e. debug break and preemption) here, so check the "real stack limit". |
| 2918 Label done; | 2793 Label done; |
| 2919 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); | 2794 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); |
| 2920 // Make scratch the space we have left. The stack might already be | 2795 // Make scratch the space we have left. The stack might already be |
| 2921 // overflowed here which will cause scratch to become negative. | 2796 // overflowed here which will cause scratch to become negative. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 2943 FixedArray::kHeaderSize)); | 2818 FixedArray::kHeaderSize)); |
| 2944 __ Push(scratch2); | 2819 __ Push(scratch2); |
| 2945 __ inc(scratch); | 2820 __ inc(scratch); |
| 2946 __ jmp(&loop); | 2821 __ jmp(&loop); |
| 2947 __ bind(&done); | 2822 __ bind(&done); |
| 2948 __ PushReturnAddressFrom(return_address); | 2823 __ PushReturnAddressFrom(return_address); |
| 2949 __ movd(esi, xmm2); | 2824 __ movd(esi, xmm2); |
| 2950 __ movd(edi, xmm1); | 2825 __ movd(edi, xmm1); |
| 2951 __ movd(edx, xmm0); | 2826 __ movd(edx, xmm0); |
| 2952 } | 2827 } |
| 2828 } |
| 2953 | 2829 |
| 2954 // Dispatch. | 2830 // static |
| 2831 void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { |
| 2832 // ----------- S t a t e ------------- |
| 2833 // -- eax : the number of arguments (not including the receiver) |
| 2834 // -- edi : the target to call (can be any Object) |
| 2835 // ----------------------------------- |
| 2836 |
| 2837 // CheckSpreadAndPushToStack will push edx to save it. |
| 2838 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |
| 2839 CheckSpreadAndPushToStack(masm); |
| 2840 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 2841 TailCallMode::kDisallow), |
| 2842 RelocInfo::CODE_TARGET); |
| 2843 } |
| 2844 |
| 2845 // static |
| 2846 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
| 2847 // ----------- S t a t e ------------- |
| 2848 // -- eax : the number of arguments (not including the receiver) |
| 2849 // -- edx : the new target (checked to be a constructor) |
| 2850 // -- edi : the constructor to call (checked to be a JSFunction) |
| 2851 // ----------------------------------- |
| 2852 __ AssertFunction(edi); |
| 2853 |
| 2854 // Calling convention for function specific ConstructStubs require |
| 2855 // ebx to contain either an AllocationSite or undefined. |
| 2856 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); |
| 2857 |
| 2858 // Tail call to the function-specific construct stub (still in the caller |
| 2859 // context at this point). |
| 2860 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 2861 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
| 2862 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 2863 __ jmp(ecx); |
| 2864 } |
| 2865 |
| 2866 // static |
| 2867 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { |
| 2868 // ----------- S t a t e ------------- |
| 2869 // -- eax : the number of arguments (not including the receiver) |
| 2870 // -- edx : the new target (checked to be a constructor) |
| 2871 // -- edi : the constructor to call (checked to be a JSBoundFunction) |
| 2872 // ----------------------------------- |
| 2873 __ AssertBoundFunction(edi); |
| 2874 |
| 2875 // Push the [[BoundArguments]] onto the stack. |
| 2876 Generate_PushBoundArguments(masm); |
| 2877 |
| 2878 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. |
| 2879 { |
| 2880 Label done; |
| 2881 __ cmp(edi, edx); |
| 2882 __ j(not_equal, &done, Label::kNear); |
| 2883 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2884 __ bind(&done); |
| 2885 } |
| 2886 |
| 2887 // Construct the [[BoundTargetFunction]] via the Construct builtin. |
| 2888 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2889 __ mov(ecx, Operand::StaticVariable( |
| 2890 ExternalReference(Builtins::kConstruct, masm->isolate()))); |
| 2891 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 2892 __ jmp(ecx); |
| 2893 } |
| 2894 |
| 2895 // static |
| 2896 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |
| 2897 // ----------- S t a t e ------------- |
| 2898 // -- eax : the number of arguments (not including the receiver) |
| 2899 // -- edi : the constructor to call (checked to be a JSProxy) |
| 2900 // -- edx : the new target (either the same as the constructor or |
| 2901 // the JSFunction on which new was invoked initially) |
| 2902 // ----------------------------------- |
| 2903 |
| 2904 // Call into the Runtime for Proxy [[Construct]]. |
| 2905 __ PopReturnAddressTo(ecx); |
| 2906 __ Push(edi); |
| 2907 __ Push(edx); |
| 2908 __ PushReturnAddressFrom(ecx); |
| 2909 // Include the pushed new_target, constructor and the receiver. |
| 2910 __ add(eax, Immediate(3)); |
| 2911 // Tail-call to the runtime. |
| 2912 __ JumpToExternalReference( |
| 2913 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); |
| 2914 } |
| 2915 |
| 2916 // static |
| 2917 void Builtins::Generate_Construct(MacroAssembler* masm) { |
| 2918 // ----------- S t a t e ------------- |
| 2919 // -- eax : the number of arguments (not including the receiver) |
| 2920 // -- edx : the new target (either the same as the constructor or |
| 2921 // the JSFunction on which new was invoked initially) |
| 2922 // -- edi : the constructor to call (can be any Object) |
| 2923 // ----------------------------------- |
| 2924 |
| 2925 // Check if target is a Smi. |
| 2926 Label non_constructor; |
| 2927 __ JumpIfSmi(edi, &non_constructor, Label::kNear); |
| 2928 |
| 2929 // Dispatch based on instance type. |
| 2930 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 2931 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
| 2932 RelocInfo::CODE_TARGET); |
| 2933 |
| 2934 // Check if target has a [[Construct]] internal method. |
| 2935 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 2936 Immediate(1 << Map::kIsConstructor)); |
| 2937 __ j(zero, &non_constructor, Label::kNear); |
| 2938 |
| 2939 // Only dispatch to bound functions after checking whether they are |
| 2940 // constructors. |
| 2941 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
| 2942 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |
| 2943 RelocInfo::CODE_TARGET); |
| 2944 |
| 2945 // Only dispatch to proxies after checking whether they are constructors. |
| 2946 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
| 2947 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |
| 2948 RelocInfo::CODE_TARGET); |
| 2949 |
| 2950 // Called Construct on an exotic Object with a [[Construct]] internal method. |
| 2951 { |
| 2952 // Overwrite the original receiver with the (original) target. |
| 2953 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); |
| 2954 // Let the "call_as_constructor_delegate" take care of the rest. |
| 2955 __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); |
| 2956 __ Jump(masm->isolate()->builtins()->CallFunction(), |
| 2957 RelocInfo::CODE_TARGET); |
| 2958 } |
| 2959 |
| 2960 // Called Construct on an Object that doesn't have a [[Construct]] internal |
| 2961 // method. |
| 2962 __ bind(&non_constructor); |
| 2963 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), |
| 2964 RelocInfo::CODE_TARGET); |
| 2965 } |
| 2966 |
| 2967 // static |
| 2968 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { |
| 2969 // ----------- S t a t e ------------- |
| 2970 // -- eax : the number of arguments (not including the receiver) |
| 2971 // -- edx : the new target (either the same as the constructor or |
| 2972 // the JSFunction on which new was invoked initially) |
| 2973 // -- edi : the constructor to call (can be any Object) |
| 2974 // ----------------------------------- |
| 2975 |
| 2976 CheckSpreadAndPushToStack(masm); |
| 2955 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 2977 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
| 2956 } | 2978 } |
| 2957 | 2979 |
| 2958 // static | 2980 // static |
| 2959 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { | 2981 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { |
| 2960 // ----------- S t a t e ------------- | 2982 // ----------- S t a t e ------------- |
| 2961 // -- edx : requested object size (untagged) | 2983 // -- edx : requested object size (untagged) |
| 2962 // -- esp[0] : return address | 2984 // -- esp[0] : return address |
| 2963 // ----------------------------------- | 2985 // ----------------------------------- |
| 2964 __ SmiTag(edx); | 2986 __ SmiTag(edx); |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3270 | 3292 |
| 3271 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { | 3293 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { |
| 3272 Generate_OnStackReplacementHelper(masm, true); | 3294 Generate_OnStackReplacementHelper(masm, true); |
| 3273 } | 3295 } |
| 3274 | 3296 |
| 3275 #undef __ | 3297 #undef __ |
| 3276 } // namespace internal | 3298 } // namespace internal |
| 3277 } // namespace v8 | 3299 } // namespace v8 |
| 3278 | 3300 |
| 3279 #endif // V8_TARGET_ARCH_IA32 | 3301 #endif // V8_TARGET_ARCH_IA32 |
| OLD | NEW |