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

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

Issue 2571563004: [Turbofan] Implement super calls with spread bytecode in assembly code. (Closed)
Patch Set: Update builtins for new push args modes Created 3 years, 11 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
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_X64 5 #if V8_TARGET_ARCH_X64
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 797 matching lines...) Expand 10 before | Expand all | Expand 10 after
808 __ bind(&stack_overflow); 808 __ bind(&stack_overflow);
809 { 809 {
810 __ TailCallRuntime(Runtime::kThrowStackOverflow); 810 __ TailCallRuntime(Runtime::kThrowStackOverflow);
811 // This should be unreachable. 811 // This should be unreachable.
812 __ int3(); 812 __ int3();
813 } 813 }
814 } 814 }
815 815
816 // static 816 // static
817 void Builtins::Generate_InterpreterPushArgsAndConstructImpl( 817 void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
818 MacroAssembler* masm, CallableType construct_type) { 818 MacroAssembler* masm, PushArgsConstructMode mode) {
819 // ----------- S t a t e ------------- 819 // ----------- S t a t e -------------
820 // -- rax : the number of arguments (not including the receiver) 820 // -- rax : the number of arguments (not including the receiver)
821 // -- rdx : the new target (either the same as the constructor or 821 // -- rdx : the new target (either the same as the constructor or
822 // the JSFunction on which new was invoked initially) 822 // the JSFunction on which new was invoked initially)
823 // -- rdi : the constructor to call (can be any Object) 823 // -- rdi : the constructor to call (can be any Object)
824 // -- rbx : the allocation site feedback if available, undefined otherwise 824 // -- rbx : the allocation site feedback if available, undefined otherwise
825 // -- rcx : the address of the first argument to be pushed. Subsequent 825 // -- rcx : the address of the first argument to be pushed. Subsequent
826 // arguments should be consecutive above this, in the same order as 826 // arguments should be consecutive above this, in the same order as
827 // they are to be pushed onto the stack. 827 // they are to be pushed onto the stack.
828 // ----------------------------------- 828 // -----------------------------------
829 Label stack_overflow; 829 Label stack_overflow;
830 830
831 // Add a stack check before pushing arguments. 831 // Add a stack check before pushing arguments.
832 Generate_StackOverflowCheck(masm, rax, r8, r9, &stack_overflow); 832 Generate_StackOverflowCheck(masm, rax, r8, r9, &stack_overflow);
833 833
834 // Pop return address to allow tail-call after pushing arguments. 834 // Pop return address to allow tail-call after pushing arguments.
835 __ PopReturnAddressTo(kScratchRegister); 835 __ PopReturnAddressTo(kScratchRegister);
836 836
837 // Push slot for the receiver to be constructed. 837 // Push slot for the receiver to be constructed.
838 __ Push(Immediate(0)); 838 __ Push(Immediate(0));
839 839
840 // rcx and r8 will be modified. 840 // rcx and r8 will be modified.
841 Generate_InterpreterPushArgs(masm, rax, rcx, r8); 841 Generate_InterpreterPushArgs(masm, rax, rcx, r8);
842 842
843 // Push return address in preparation for the tail-call. 843 // Push return address in preparation for the tail-call.
844 __ PushReturnAddressFrom(kScratchRegister); 844 __ PushReturnAddressFrom(kScratchRegister);
845 845
846 __ AssertUndefinedOrAllocationSite(rbx); 846 __ AssertUndefinedOrAllocationSite(rbx);
847 if (construct_type == CallableType::kJSFunction) { 847 if (mode == PushArgsConstructMode::kJSFunction) {
848 // Tail call to the function-specific construct stub (still in the caller 848 // Tail call to the function-specific construct stub (still in the caller
849 // context at this point). 849 // context at this point).
850 __ AssertFunction(rdi); 850 __ AssertFunction(rdi);
851 851
852 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 852 __ movp(rcx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
853 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset)); 853 __ movp(rcx, FieldOperand(rcx, SharedFunctionInfo::kConstructStubOffset));
854 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize)); 854 __ leap(rcx, FieldOperand(rcx, Code::kHeaderSize));
855 // Jump to the constructor function (rax, rbx, rdx passed on). 855 // Jump to the constructor function (rax, rbx, rdx passed on).
856 __ jmp(rcx); 856 __ jmp(rcx);
857 } else if (mode == PushArgsConstructMode::kWithFinalSpread) {
858 // Call the constructor (rax, rdx, rdi passed on).
859 __ Jump(masm->isolate()->builtins()->ConstructWithSpread(),
860 RelocInfo::CODE_TARGET);
857 } else { 861 } else {
858 DCHECK_EQ(construct_type, CallableType::kAny); 862 DCHECK_EQ(PushArgsConstructMode::kOther, mode);
859 // Call the constructor (rax, rdx, rdi passed on). 863 // Call the constructor (rax, rdx, rdi passed on).
860 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET); 864 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
861 } 865 }
862 866
863 // Throw stack overflow exception. 867 // Throw stack overflow exception.
864 __ bind(&stack_overflow); 868 __ bind(&stack_overflow);
865 { 869 {
866 __ TailCallRuntime(Runtime::kThrowStackOverflow); 870 __ TailCallRuntime(Runtime::kThrowStackOverflow);
867 // This should be unreachable. 871 // This should be unreachable.
868 __ int3(); 872 __ int3();
(...skipping 2005 matching lines...) Expand 10 before | Expand all | Expand 10 after
2874 RelocInfo::CODE_TARGET); 2878 RelocInfo::CODE_TARGET);
2875 } 2879 }
2876 2880
2877 // Called Construct on an Object that doesn't have a [[Construct]] internal 2881 // Called Construct on an Object that doesn't have a [[Construct]] internal
2878 // method. 2882 // method.
2879 __ bind(&non_constructor); 2883 __ bind(&non_constructor);
2880 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(), 2884 __ Jump(masm->isolate()->builtins()->ConstructedNonConstructable(),
2881 RelocInfo::CODE_TARGET); 2885 RelocInfo::CODE_TARGET);
2882 } 2886 }
2883 2887
2888 // static
2889 void Builtins::Generate_ConstructWithSpread(MacroAssembler* masm) {
2890 // ----------- S t a t e -------------
2891 // -- rax : the number of arguments (not including the receiver)
2892 // -- rdx : the new target (either the same as the constructor or
2893 // the JSFunction on which new was invoked initially)
2894 // -- rdi : the constructor to call (can be any Object)
2895 // -----------------------------------
2896
2897 // Load the spread argument into rbx.
2898 __ movp(rbx, Operand(rsp, kPointerSize));
2899 // Load the map of the spread into r15.
2900 __ movp(r15, FieldOperand(rbx, HeapObject::kMapOffset));
2901 // Load native context into r14.
2902 __ movp(r14, NativeContextOperand());
2903
2904 Label runtime_call, push_args;
2905 // Check that the spread is an array.
2906 __ CmpInstanceType(r15, JS_ARRAY_TYPE);
2907 __ j(not_equal, &runtime_call);
2908
2909 // Check that we have the original ArrayPrototype.
2910 __ movp(rcx, FieldOperand(r15, Map::kPrototypeOffset));
2911 __ cmpp(rcx, ContextOperand(r14, Context::INITIAL_ARRAY_PROTOTYPE_INDEX));
2912 __ j(not_equal, &runtime_call);
2913
2914 // Check that the ArrayPrototype hasn't been modified in a way that would
2915 // affect iteration.
2916 __ LoadRoot(rcx, Heap::kArrayIteratorProtectorRootIndex);
2917 __ Cmp(FieldOperand(rcx, Cell::kValueOffset),
2918 Smi::FromInt(Isolate::kProtectorValid));
2919 __ j(not_equal, &runtime_call);
2920
2921 // Check that the map of the initial array iterator hasn't changed.
2922 __ movp(rcx,
2923 ContextOperand(r14, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_INDEX));
2924 __ movp(rcx, FieldOperand(rcx, HeapObject::kMapOffset));
2925 __ cmpp(rcx, ContextOperand(
2926 r14, Context::INITIAL_ARRAY_ITERATOR_PROTOTYPE_MAP_INDEX));
2927 __ j(not_equal, &runtime_call);
2928
2929 // For FastPacked kinds, iteration will have the same effect as simply
2930 // accessing each property in order.
2931 Label no_protector_check;
2932 __ movzxbp(rcx, FieldOperand(r15, Map::kBitField2Offset));
2933 __ DecodeField<Map::ElementsKindBits>(rcx);
2934 __ cmpp(rcx, Immediate(LAST_FAST_ELEMENTS_KIND));
2935 __ j(above, &runtime_call);
2936 // For non-FastHoley kinds, we can skip the protector check.
2937 __ cmpp(rcx, Immediate(FAST_SMI_ELEMENTS));
2938 __ j(equal, &no_protector_check);
2939 __ cmpp(rcx, Immediate(FAST_ELEMENTS));
2940 __ j(equal, &no_protector_check);
2941 __ cmpp(rcx, Immediate(FAST_DOUBLE_ELEMENTS));
2942 __ j(equal, &no_protector_check);
2943 // Check the ArrayProtector cell.
2944 __ LoadRoot(rcx, Heap::kArrayProtectorRootIndex);
2945 __ Cmp(FieldOperand(rcx, PropertyCell::kValueOffset),
2946 Smi::FromInt(Isolate::kProtectorValid));
2947 __ j(not_equal, &runtime_call);
2948
2949 __ bind(&no_protector_check);
2950 // Load the FixedArray backing store.
2951 __ movp(rbx, FieldOperand(rbx, JSArray::kElementsOffset));
2952 __ jmp(&push_args);
2953
2954 __ bind(&runtime_call);
2955 {
2956 // Call the builtin for the result of the spread.
2957 FrameScope scope(masm, StackFrame::INTERNAL);
2958 __ Push(rdi); // target
2959 __ Push(rdx); // new target
2960 __ Integer32ToSmi(rax, rax);
2961 __ Push(rax); // nargs
2962 __ Push(rbx);
2963 __ CallRuntime(Runtime::kSpreadIterableFixed);
2964 __ movp(rbx, rax);
2965 __ Pop(rax); // nargs
2966 __ SmiToInteger32(rax, rax);
2967 __ Pop(rdx); // new target
2968 __ Pop(rdi); // target
2969 }
2970
2971 __ bind(&push_args);
2972 {
2973 // Pop the return address and spread argument.
2974 __ PopReturnAddressTo(r8);
2975 __ Pop(rcx);
2976
2977 // Calculate the new nargs including the result of the spread.
2978 __ SmiToInteger32(r9, FieldOperand(rbx, FixedArray::kLengthOffset));
2979 // rax += r9 - 1. Subtract 1 for the spread itself.
2980 __ leap(rax, Operand(rax, r9, times_1, -1));
2981 }
2982
2983 // Check for stack overflow.
2984 {
2985 // Check the stack for overflow. We are not trying to catch interruptions
2986 // (i.e. debug break and preemption) here, so check the "real stack limit".
2987 Label done;
2988 __ LoadRoot(kScratchRegister, Heap::kRealStackLimitRootIndex);
2989 __ movp(rcx, rsp);
2990 // Make rcx the space we have left. The stack might already be overflowed
2991 // here which will cause rcx to become negative.
2992 __ subp(rcx, kScratchRegister);
2993 __ sarp(rcx, Immediate(kPointerSizeLog2));
2994 // Check if the arguments will overflow the stack.
2995 __ cmpp(rcx, r9);
2996 __ j(greater, &done, Label::kNear); // Signed comparison.
2997 __ TailCallRuntime(Runtime::kThrowStackOverflow);
2998 __ bind(&done);
2999 }
3000
3001 // Put the evaluated spread onto the stack as additional arguments.
3002 {
3003 __ Set(rcx, 0);
3004 Label done, loop;
3005 __ bind(&loop);
3006 __ cmpl(rcx, r9);
3007 __ j(equal, &done, Label::kNear);
3008 __ movp(kScratchRegister, FieldOperand(rbx, rcx, times_pointer_size,
3009 FixedArray::kHeaderSize));
3010 __ Push(kScratchRegister);
3011 __ incl(rcx);
3012 __ jmp(&loop);
3013 __ bind(&done);
3014 __ PushReturnAddressFrom(r8);
3015 }
3016 // Dispatch.
3017 __ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
3018 }
3019
2884 static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver, 3020 static void CompatibleReceiverCheck(MacroAssembler* masm, Register receiver,
2885 Register function_template_info, 3021 Register function_template_info,
2886 Register scratch0, Register scratch1, 3022 Register scratch0, Register scratch1,
2887 Register scratch2, 3023 Register scratch2,
2888 Label* receiver_check_failed) { 3024 Label* receiver_check_failed) {
2889 Register signature = scratch0; 3025 Register signature = scratch0;
2890 Register map = scratch1; 3026 Register map = scratch1;
2891 Register constructor = scratch2; 3027 Register constructor = scratch2;
2892 3028
2893 // If there is no signature, return the holder. 3029 // If there is no signature, return the holder.
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
3046 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) { 3182 void Builtins::Generate_InterpreterOnStackReplacement(MacroAssembler* masm) {
3047 Generate_OnStackReplacementHelper(masm, true); 3183 Generate_OnStackReplacementHelper(masm, true);
3048 } 3184 }
3049 3185
3050 #undef __ 3186 #undef __
3051 3187
3052 } // namespace internal 3188 } // namespace internal
3053 } // namespace v8 3189 } // namespace v8
3054 3190
3055 #endif // V8_TARGET_ARCH_X64 3191 #endif // V8_TARGET_ARCH_X64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698