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_X87 | 5 #if V8_TARGET_ARCH_X87 |
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 712 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
723 __ add(ecx, ebx); | 723 __ add(ecx, ebx); |
724 Generate_InterpreterPushArgs(masm, ecx, ebx); | 724 Generate_InterpreterPushArgs(masm, ecx, ebx); |
725 | 725 |
726 // Call the target. | 726 // Call the target. |
727 __ Push(edx); // Re-push return address. | 727 __ Push(edx); // Re-push return address. |
728 | 728 |
729 if (mode == InterpreterPushArgsMode::kJSFunction) { | 729 if (mode == InterpreterPushArgsMode::kJSFunction) { |
730 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, | 730 __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, |
731 tail_call_mode), | 731 tail_call_mode), |
732 RelocInfo::CODE_TARGET); | 732 RelocInfo::CODE_TARGET); |
| 733 } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { |
| 734 __ Jump(masm->isolate()->builtins()->CallWithSpread(), |
| 735 RelocInfo::CODE_TARGET); |
733 } else { | 736 } else { |
734 DCHECK_EQ(mode, InterpreterPushArgsMode::kOther); | |
735 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, | 737 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
736 tail_call_mode), | 738 tail_call_mode), |
737 RelocInfo::CODE_TARGET); | 739 RelocInfo::CODE_TARGET); |
738 } | 740 } |
739 | 741 |
740 __ bind(&stack_overflow); | 742 __ bind(&stack_overflow); |
741 { | 743 { |
742 // Pop the temporary registers, so that return address is on top of stack. | 744 // Pop the temporary registers, so that return address is on top of stack. |
743 __ Pop(edi); | 745 __ Pop(edi); |
744 | 746 |
(...skipping 1949 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2694 | 2696 |
2695 // 3. Call to something that is not callable. | 2697 // 3. Call to something that is not callable. |
2696 __ bind(&non_callable); | 2698 __ bind(&non_callable); |
2697 { | 2699 { |
2698 FrameScope scope(masm, StackFrame::INTERNAL); | 2700 FrameScope scope(masm, StackFrame::INTERNAL); |
2699 __ Push(edi); | 2701 __ Push(edi); |
2700 __ CallRuntime(Runtime::kThrowCalledNonCallable); | 2702 __ CallRuntime(Runtime::kThrowCalledNonCallable); |
2701 } | 2703 } |
2702 } | 2704 } |
2703 | 2705 |
2704 // static | 2706 static void CheckSpreadAndPushToStack(MacroAssembler* masm) { |
2705 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { | |
2706 // ----------- S t a t e ------------- | |
2707 // -- eax : the number of arguments (not including the receiver) | |
2708 // -- edx : the new target (checked to be a constructor) | |
2709 // -- edi : the constructor to call (checked to be a JSFunction) | |
2710 // ----------------------------------- | |
2711 __ AssertFunction(edi); | |
2712 | |
2713 // Calling convention for function specific ConstructStubs require | |
2714 // ebx to contain either an AllocationSite or undefined. | |
2715 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); | |
2716 | |
2717 // Tail call to the function-specific construct stub (still in the caller | |
2718 // context at this point). | |
2719 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); | |
2720 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); | |
2721 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | |
2722 __ jmp(ecx); | |
2723 } | |
2724 | |
2725 // static | |
2726 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { | |
2727 // ----------- S t a t e ------------- | |
2728 // -- eax : the number of arguments (not including the receiver) | |
2729 // -- edx : the new target (checked to be a constructor) | |
2730 // -- edi : the constructor to call (checked to be a JSBoundFunction) | |
2731 // ----------------------------------- | |
2732 __ AssertBoundFunction(edi); | |
2733 | |
2734 // Push the [[BoundArguments]] onto the stack. | |
2735 Generate_PushBoundArguments(masm); | |
2736 | |
2737 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. | |
2738 { | |
2739 Label done; | |
2740 __ cmp(edi, edx); | |
2741 __ j(not_equal, &done, Label::kNear); | |
2742 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
2743 __ bind(&done); | |
2744 } | |
2745 | |
2746 // Construct the [[BoundTargetFunction]] via the Construct builtin. | |
2747 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); | |
2748 __ mov(ecx, Operand::StaticVariable( | |
2749 ExternalReference(Builtins::kConstruct, masm->isolate()))); | |
2750 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); | |
2751 __ jmp(ecx); | |
2752 } | |
2753 | |
2754 // static | |
2755 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { | |
2756 // ----------- S t a t e ------------- | |
2757 // -- eax : the number of arguments (not including the receiver) | |
2758 // -- edi : the constructor to call (checked to be a JSProxy) | |
2759 // -- edx : the new target (either the same as the constructor or | |
2760 // the JSFunction on which new was invoked initially) | |
2761 // ----------------------------------- | |
2762 | |
2763 // Call into the Runtime for Proxy [[Construct]]. | |
2764 __ PopReturnAddressTo(ecx); | |
2765 __ Push(edi); | |
2766 __ Push(edx); | |
2767 __ PushReturnAddressFrom(ecx); | |
2768 // Include the pushed new_target, constructor and the receiver. | |
2769 __ add(eax, Immediate(3)); | |
2770 // Tail-call to the runtime. | |
2771 __ JumpToExternalReference( | |
2772 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); | |
2773 } | |
2774 | |
2775 // static | |
2776 void Builtins::Generate_Construct(MacroAssembler* masm) { | |
2777 // ----------- S t a t e ------------- | |
2778 // -- eax : the number of arguments (not including the receiver) | |
2779 // -- edx : the new target (either the same as the constructor or | |
2780 // the JSFunction on which new was invoked initially) | |
2781 // -- edi : the constructor to call (can be any Object) | |
2782 // ----------------------------------- | |
2783 | |
2784 // Check if target is a Smi. | |
2785 Label non_constructor; | |
2786 __ JumpIfSmi(edi, &non_constructor, Label::kNear); | |
2787 | |
2788 // Dispatch based on instance type. | |
2789 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); | |
2790 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), | |
2791 RelocInfo::CODE_TARGET); | |
2792 | |
2793 // Check if target has a [[Construct]] internal method. | |
2794 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), | |
2795 Immediate(1 << Map::kIsConstructor)); | |
2796 __ j(zero, &non_constructor, Label::kNear); | |
2797 | |
2798 // Only dispatch to bound functions after checking whether they are | |
2799 // constructors. | |
2800 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); | |
2801 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), | |
2802 RelocInfo::CODE_TARGET); | |
2803 | |
2804 // Only dispatch to proxies after checking whether they are constructors. | |
2805 __ CmpInstanceType(ecx, JS_PROXY_TYPE); | |
2806 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), | |
2807 RelocInfo::CODE_TARGET); | |
2808 | |
2809 // Called Construct on an exotic Object with a [[Construct]] internal method. | |
2810 { | |
2811 // Overwrite the original receiver with the (original) target. | |
2812 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); | |
2813 // Let the "call_as_constructor_delegate" take care of the rest. | |
2814 __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); | |
2815 __ Jump(masm->isolate()->builtins()->CallFunction(), | |
2816 RelocInfo::CODE_TARGET); | |
2817 } | |
2818 | |
2819 // Called Construct on an Object that doesn't have a [[Construct]] internal | |
2820 // method. | |
2821 __ bind(&non_constructor); | |
2822 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), | |
2823 RelocInfo::CODE_TARGET); | |
2824 } | |
2825 | |
2826 // static | |
2827 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { | |
2828 // ----------- S t a t e ------------- | |
2829 // -- eax : the number of arguments (not including the receiver) | |
2830 // -- edx : the new target (either the same as the constructor or | |
2831 // the JSFunction on which new was invoked initially) | |
2832 // -- edi : the constructor to call (can be any Object) | |
2833 // ----------------------------------- | |
2834 | |
2835 // Free up some registers. | 2707 // Free up some registers. |
2836 // Save edx/edi to stX0/stX1. | 2708 // Save edx/edi to stX0/stX1. |
2837 __ push(edx); | 2709 __ push(edx); |
2838 __ push(edi); | 2710 __ push(edi); |
2839 __ fld_s(MemOperand(esp, 0)); | 2711 __ fld_s(MemOperand(esp, 0)); |
2840 __ fld_s(MemOperand(esp, 4)); | 2712 __ fld_s(MemOperand(esp, 4)); |
2841 __ lea(esp, Operand(esp, 2 * kFloatSize)); | 2713 __ lea(esp, Operand(esp, 2 * kFloatSize)); |
2842 | 2714 |
2843 Register argc = eax; | 2715 Register argc = eax; |
2844 | 2716 |
2845 Register scratch = ecx; | 2717 Register scratch = ecx; |
2846 Register scratch2 = edi; | 2718 Register scratch2 = edi; |
2847 | 2719 |
2848 Register spread = ebx; | 2720 Register spread = ebx; |
2849 Register spread_map = edx; | 2721 Register spread_map = edx; |
2850 | 2722 |
| 2723 Register spread_len = edx; |
| 2724 |
2851 __ mov(spread, Operand(esp, kPointerSize)); | 2725 __ mov(spread, Operand(esp, kPointerSize)); |
2852 __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); | 2726 __ mov(spread_map, FieldOperand(spread, HeapObject::kMapOffset)); |
2853 | 2727 |
2854 Label runtime_call, push_args; | 2728 Label runtime_call, push_args; |
2855 // Check that the spread is an array. | 2729 // Check that the spread is an array. |
2856 __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); | 2730 __ CmpInstanceType(spread_map, JS_ARRAY_TYPE); |
2857 __ j(not_equal, &runtime_call); | 2731 __ j(not_equal, &runtime_call); |
2858 | 2732 |
2859 // Check that we have the original ArrayPrototype. | 2733 // Check that we have the original ArrayPrototype. |
2860 __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); | 2734 __ mov(scratch, FieldOperand(spread_map, Map::kPrototypeOffset)); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2893 __ j(equal, &no_protector_check); | 2767 __ j(equal, &no_protector_check); |
2894 __ cmp(scratch, Immediate(FAST_ELEMENTS)); | 2768 __ cmp(scratch, Immediate(FAST_ELEMENTS)); |
2895 __ j(equal, &no_protector_check); | 2769 __ j(equal, &no_protector_check); |
2896 // Check the ArrayProtector cell. | 2770 // Check the ArrayProtector cell. |
2897 __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); | 2771 __ LoadRoot(scratch, Heap::kArrayProtectorRootIndex); |
2898 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), | 2772 __ cmp(FieldOperand(scratch, PropertyCell::kValueOffset), |
2899 Immediate(Smi::FromInt(Isolate::kProtectorValid))); | 2773 Immediate(Smi::FromInt(Isolate::kProtectorValid))); |
2900 __ j(not_equal, &runtime_call); | 2774 __ j(not_equal, &runtime_call); |
2901 | 2775 |
2902 __ bind(&no_protector_check); | 2776 __ bind(&no_protector_check); |
2903 // Load the FixedArray backing store. | 2777 // Load the FixedArray backing store, but use the length from the array. |
| 2778 __ mov(spread_len, FieldOperand(spread, JSArray::kLengthOffset)); |
| 2779 __ SmiUntag(spread_len); |
2904 __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); | 2780 __ mov(spread, FieldOperand(spread, JSArray::kElementsOffset)); |
2905 // Free up some registers. | |
2906 __ jmp(&push_args); | 2781 __ jmp(&push_args); |
2907 | 2782 |
2908 __ bind(&runtime_call); | 2783 __ bind(&runtime_call); |
2909 { | 2784 { |
2910 // Call the builtin for the result of the spread. | 2785 // Call the builtin for the result of the spread. |
2911 FrameScope scope(masm, StackFrame::INTERNAL); | 2786 FrameScope scope(masm, StackFrame::INTERNAL); |
2912 // Need to save these on the stack. | 2787 // Need to save these on the stack. |
2913 // Restore edx/edi from stX0/stX1. | 2788 // Restore edx/edi from stX0/stX1. |
2914 __ lea(esp, Operand(esp, -2 * kFloatSize)); | 2789 __ lea(esp, Operand(esp, -2 * kFloatSize)); |
2915 __ fstp_s(MemOperand(esp, 0)); | 2790 __ fstp_s(MemOperand(esp, 0)); |
(...skipping 14 matching lines...) Expand all Loading... |
2930 __ Pop(edi); | 2805 __ Pop(edi); |
2931 // Free up some registers. | 2806 // Free up some registers. |
2932 // Save edx/edi to stX0/stX1. | 2807 // Save edx/edi to stX0/stX1. |
2933 __ push(edx); | 2808 __ push(edx); |
2934 __ push(edi); | 2809 __ push(edi); |
2935 __ fld_s(MemOperand(esp, 0)); | 2810 __ fld_s(MemOperand(esp, 0)); |
2936 __ fld_s(MemOperand(esp, 4)); | 2811 __ fld_s(MemOperand(esp, 4)); |
2937 __ lea(esp, Operand(esp, 2 * kFloatSize)); | 2812 __ lea(esp, Operand(esp, 2 * kFloatSize)); |
2938 } | 2813 } |
2939 | 2814 |
2940 Register spread_len = edx; | |
2941 Register return_address = edi; | 2815 Register return_address = edi; |
2942 __ bind(&push_args); | |
2943 { | 2816 { |
| 2817 // Calculate the new nargs including the result of the spread. |
| 2818 __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); |
| 2819 __ SmiUntag(spread_len); |
| 2820 |
| 2821 __ bind(&push_args); |
| 2822 // argc += spread_len - 1. Subtract 1 for the spread itself. |
| 2823 __ lea(argc, Operand(argc, spread_len, times_1, -1)); |
| 2824 |
2944 // Pop the return address and spread argument. | 2825 // Pop the return address and spread argument. |
2945 __ PopReturnAddressTo(return_address); | 2826 __ PopReturnAddressTo(return_address); |
2946 __ Pop(scratch); | 2827 __ Pop(scratch); |
2947 | |
2948 // Calculate the new nargs including the result of the spread. | |
2949 __ mov(spread_len, FieldOperand(spread, FixedArray::kLengthOffset)); | |
2950 __ SmiUntag(spread_len); | |
2951 // argc += spread_len - 1. Subtract 1 for the spread itself. | |
2952 __ lea(argc, Operand(argc, spread_len, times_1, -1)); | |
2953 } | 2828 } |
2954 | 2829 |
2955 // Check for stack overflow. | 2830 // Check for stack overflow. |
2956 { | 2831 { |
2957 // Check the stack for overflow. We are not trying to catch interruptions | 2832 // Check the stack for overflow. We are not trying to catch interruptions |
2958 // (i.e. debug break and preemption) here, so check the "real stack limit". | 2833 // (i.e. debug break and preemption) here, so check the "real stack limit". |
2959 Label done; | 2834 Label done; |
2960 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); | 2835 __ LoadRoot(scratch, Heap::kRealStackLimitRootIndex); |
2961 // Make scratch the space we have left. The stack might already be | 2836 // Make scratch the space we have left. The stack might already be |
2962 // overflowed here which will cause scratch to become negative. | 2837 // overflowed here which will cause scratch to become negative. |
2963 __ neg(scratch); | 2838 __ neg(scratch); |
2964 __ add(scratch, esp); | 2839 __ add(scratch, esp); |
2965 __ sar(scratch, kPointerSizeLog2); | 2840 __ sar(scratch, kPointerSizeLog2); |
2966 // Check if the arguments will overflow the stack. | 2841 // Check if the arguments will overflow the stack. |
2967 __ cmp(scratch, spread_len); | 2842 __ cmp(scratch, spread_len); |
2968 __ j(greater, &done, Label::kNear); // Signed comparison. | 2843 __ j(greater, &done, Label::kNear); // Signed comparison. |
2969 __ TailCallRuntime(Runtime::kThrowStackOverflow); | 2844 __ TailCallRuntime(Runtime::kThrowStackOverflow); |
2970 __ bind(&done); | 2845 __ bind(&done); |
2971 } | 2846 } |
2972 | 2847 |
2973 // Put the evaluated spread onto the stack as additional arguments. | 2848 // Put the evaluated spread onto the stack as additional arguments. |
2974 { | 2849 { |
2975 Register scratch2 = esi; | 2850 Register scratch2 = esi; |
2976 // __ movd(xmm2, esi); | |
2977 // Save esi to stX0, edx/edi in stX1/stX2 now. | 2851 // Save esi to stX0, edx/edi in stX1/stX2 now. |
2978 __ push(esi); | 2852 __ push(esi); |
2979 __ fld_s(MemOperand(esp, 0)); | 2853 __ fld_s(MemOperand(esp, 0)); |
2980 __ lea(esp, Operand(esp, 1 * kFloatSize)); | 2854 __ lea(esp, Operand(esp, 1 * kFloatSize)); |
2981 | 2855 |
2982 __ mov(scratch, Immediate(0)); | 2856 __ mov(scratch, Immediate(0)); |
2983 Label done, loop; | 2857 Label done, loop; |
2984 __ bind(&loop); | 2858 __ bind(&loop); |
2985 __ cmp(scratch, spread_len); | 2859 __ cmp(scratch, spread_len); |
2986 __ j(equal, &done, Label::kNear); | 2860 __ j(equal, &done, Label::kNear); |
2987 __ mov(scratch2, FieldOperand(spread, scratch, times_pointer_size, | 2861 __ mov(scratch2, FieldOperand(spread, scratch, times_pointer_size, |
2988 FixedArray::kHeaderSize)); | 2862 FixedArray::kHeaderSize)); |
2989 __ Push(scratch2); | 2863 __ Push(scratch2); |
2990 __ inc(scratch); | 2864 __ inc(scratch); |
2991 __ jmp(&loop); | 2865 __ jmp(&loop); |
2992 __ bind(&done); | 2866 __ bind(&done); |
2993 __ PushReturnAddressFrom(return_address); | 2867 __ PushReturnAddressFrom(return_address); |
2994 | 2868 |
2995 // Now Restore esi from stX0, edx/edi from stX1/stX2. | 2869 // Now Restore esi from stX0, edx/edi from stX1/stX2. |
2996 __ lea(esp, Operand(esp, -3 * kFloatSize)); | 2870 __ lea(esp, Operand(esp, -3 * kFloatSize)); |
2997 __ fstp_s(MemOperand(esp, 0)); | 2871 __ fstp_s(MemOperand(esp, 0)); |
2998 __ fstp_s(MemOperand(esp, 4)); | 2872 __ fstp_s(MemOperand(esp, 4)); |
2999 __ fstp_s(MemOperand(esp, 8)); | 2873 __ fstp_s(MemOperand(esp, 8)); |
3000 __ pop(esi); | 2874 __ pop(esi); |
3001 __ pop(edx); | 2875 __ pop(edx); |
3002 __ pop(edi); | 2876 __ pop(edi); |
3003 } | 2877 } |
| 2878 } |
3004 | 2879 |
3005 // Dispatch. | 2880 // static |
| 2881 void Builtins::Generate_CallWithSpread(MacroAssembler* masm) { |
| 2882 // ----------- S t a t e ------------- |
| 2883 // -- eax : the number of arguments (not including the receiver) |
| 2884 // -- edi : the target to call (can be any Object) |
| 2885 // ----------------------------------- |
| 2886 |
| 2887 // CheckSpreadAndPushToStack will push edx to save it. |
| 2888 __ LoadRoot(edx, Heap::kUndefinedValueRootIndex); |
| 2889 CheckSpreadAndPushToStack(masm); |
| 2890 __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, |
| 2891 TailCallMode::kDisallow), |
| 2892 RelocInfo::CODE_TARGET); |
| 2893 } |
| 2894 |
| 2895 // static |
| 2896 void Builtins::Generate_ConstructFunction(MacroAssembler* masm) { |
| 2897 // ----------- S t a t e ------------- |
| 2898 // -- eax : the number of arguments (not including the receiver) |
| 2899 // -- edx : the new target (checked to be a constructor) |
| 2900 // -- edi : the constructor to call (checked to be a JSFunction) |
| 2901 // ----------------------------------- |
| 2902 __ AssertFunction(edi); |
| 2903 |
| 2904 // Calling convention for function specific ConstructStubs require |
| 2905 // ebx to contain either an AllocationSite or undefined. |
| 2906 __ LoadRoot(ebx, Heap::kUndefinedValueRootIndex); |
| 2907 |
| 2908 // Tail call to the function-specific construct stub (still in the caller |
| 2909 // context at this point). |
| 2910 __ mov(ecx, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset)); |
| 2911 __ mov(ecx, FieldOperand(ecx, SharedFunctionInfo::kConstructStubOffset)); |
| 2912 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 2913 __ jmp(ecx); |
| 2914 } |
| 2915 |
| 2916 // static |
| 2917 void Builtins::Generate_ConstructBoundFunction(MacroAssembler* masm) { |
| 2918 // ----------- S t a t e ------------- |
| 2919 // -- eax : the number of arguments (not including the receiver) |
| 2920 // -- edx : the new target (checked to be a constructor) |
| 2921 // -- edi : the constructor to call (checked to be a JSBoundFunction) |
| 2922 // ----------------------------------- |
| 2923 __ AssertBoundFunction(edi); |
| 2924 |
| 2925 // Push the [[BoundArguments]] onto the stack. |
| 2926 Generate_PushBoundArguments(masm); |
| 2927 |
| 2928 // Patch new.target to [[BoundTargetFunction]] if new.target equals target. |
| 2929 { |
| 2930 Label done; |
| 2931 __ cmp(edi, edx); |
| 2932 __ j(not_equal, &done, Label::kNear); |
| 2933 __ mov(edx, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2934 __ bind(&done); |
| 2935 } |
| 2936 |
| 2937 // Construct the [[BoundTargetFunction]] via the Construct builtin. |
| 2938 __ mov(edi, FieldOperand(edi, JSBoundFunction::kBoundTargetFunctionOffset)); |
| 2939 __ mov(ecx, Operand::StaticVariable( |
| 2940 ExternalReference(Builtins::kConstruct, masm->isolate()))); |
| 2941 __ lea(ecx, FieldOperand(ecx, Code::kHeaderSize)); |
| 2942 __ jmp(ecx); |
| 2943 } |
| 2944 |
| 2945 // static |
| 2946 void Builtins::Generate_ConstructProxy(MacroAssembler* masm) { |
| 2947 // ----------- S t a t e ------------- |
| 2948 // -- eax : the number of arguments (not including the receiver) |
| 2949 // -- edi : the constructor to call (checked to be a JSProxy) |
| 2950 // -- edx : the new target (either the same as the constructor or |
| 2951 // the JSFunction on which new was invoked initially) |
| 2952 // ----------------------------------- |
| 2953 |
| 2954 // Call into the Runtime for Proxy [[Construct]]. |
| 2955 __ PopReturnAddressTo(ecx); |
| 2956 __ Push(edi); |
| 2957 __ Push(edx); |
| 2958 __ PushReturnAddressFrom(ecx); |
| 2959 // Include the pushed new_target, constructor and the receiver. |
| 2960 __ add(eax, Immediate(3)); |
| 2961 // Tail-call to the runtime. |
| 2962 __ JumpToExternalReference( |
| 2963 ExternalReference(Runtime::kJSProxyConstruct, masm->isolate())); |
| 2964 } |
| 2965 |
| 2966 // static |
| 2967 void Builtins::Generate_Construct(MacroAssembler* masm) { |
| 2968 // ----------- S t a t e ------------- |
| 2969 // -- eax : the number of arguments (not including the receiver) |
| 2970 // -- edx : the new target (either the same as the constructor or |
| 2971 // the JSFunction on which new was invoked initially) |
| 2972 // -- edi : the constructor to call (can be any Object) |
| 2973 // ----------------------------------- |
| 2974 |
| 2975 // Check if target is a Smi. |
| 2976 Label non_constructor; |
| 2977 __ JumpIfSmi(edi, &non_constructor, Label::kNear); |
| 2978 |
| 2979 // Dispatch based on instance type. |
| 2980 __ CmpObjectType(edi, JS_FUNCTION_TYPE, ecx); |
| 2981 __ j(equal, masm->isolate()->builtins()->ConstructFunction(), |
| 2982 RelocInfo::CODE_TARGET); |
| 2983 |
| 2984 // Check if target has a [[Construct]] internal method. |
| 2985 __ test_b(FieldOperand(ecx, Map::kBitFieldOffset), |
| 2986 Immediate(1 << Map::kIsConstructor)); |
| 2987 __ j(zero, &non_constructor, Label::kNear); |
| 2988 |
| 2989 // Only dispatch to bound functions after checking whether they are |
| 2990 // constructors. |
| 2991 __ CmpInstanceType(ecx, JS_BOUND_FUNCTION_TYPE); |
| 2992 __ j(equal, masm->isolate()->builtins()->ConstructBoundFunction(), |
| 2993 RelocInfo::CODE_TARGET); |
| 2994 |
| 2995 // Only dispatch to proxies after checking whether they are constructors. |
| 2996 __ CmpInstanceType(ecx, JS_PROXY_TYPE); |
| 2997 __ j(equal, masm->isolate()->builtins()->ConstructProxy(), |
| 2998 RelocInfo::CODE_TARGET); |
| 2999 |
| 3000 // Called Construct on an exotic Object with a [[Construct]] internal method. |
| 3001 { |
| 3002 // Overwrite the original receiver with the (original) target. |
| 3003 __ mov(Operand(esp, eax, times_pointer_size, kPointerSize), edi); |
| 3004 // Let the "call_as_constructor_delegate" take care of the rest. |
| 3005 __ LoadGlobalFunction(Context::CALL_AS_CONSTRUCTOR_DELEGATE_INDEX, edi); |
| 3006 __ Jump(masm->isolate()->builtins()->CallFunction(), |
| 3007 RelocInfo::CODE_TARGET); |
| 3008 } |
| 3009 |
| 3010 // Called Construct on an Object that doesn't have a [[Construct]] internal |
| 3011 // method. |
| 3012 __ bind(&non_constructor); |
| 3013 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), |
| 3014 RelocInfo::CODE_TARGET); |
| 3015 } |
| 3016 |
| 3017 // static |
| 3018 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) { |
| 3019 // ----------- S t a t e ------------- |
| 3020 // -- eax : the number of arguments (not including the receiver) |
| 3021 // -- edx : the new target (either the same as the constructor or |
| 3022 // the JSFunction on which new was invoked initially) |
| 3023 // -- edi : the constructor to call (can be any Object) |
| 3024 // ----------------------------------- |
| 3025 |
| 3026 CheckSpreadAndPushToStack(masm); |
3006 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); | 3027 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); |
3007 } | 3028 } |
3008 | 3029 |
3009 // static | 3030 // static |
3010 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { | 3031 void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) { |
3011 // ----------- S t a t e ------------- | 3032 // ----------- S t a t e ------------- |
3012 // -- edx : requested object size (untagged) | 3033 // -- edx : requested object size (untagged) |
3013 // -- esp[0] : return address | 3034 // -- esp[0] : return address |
3014 // ----------------------------------- | 3035 // ----------------------------------- |
3015 __ SmiTag(edx); | 3036 __ SmiTag(edx); |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3321 | 3342 |
3322 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { | 3343 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { |
3323 Generate_OnStackReplacementHelper(masm, true); | 3344 Generate_OnStackReplacementHelper(masm, true); |
3324 } | 3345 } |
3325 | 3346 |
3326 #undef __ | 3347 #undef __ |
3327 } // namespace internal | 3348 } // namespace internal |
3328 } // namespace v8 | 3349 } // namespace v8 |
3329 | 3350 |
3330 #endif // V8_TARGET_ARCH_X87 | 3351 #endif // V8_TARGET_ARCH_X87 |
OLD | NEW |