Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(394)

Side by Side Diff: src/builtins/x87/builtins-x87.cc

Issue 2652153002: X87: [Turbofan] Implement call with spread bytecode in assembly code. (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698