diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc index 5a1e28c818..7e56698f00 100644 --- a/src/arm/interface-descriptors-arm.cc +++ b/src/arm/interface-descriptors-arm.cc @@ -324,7 +324,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { r0, // argument count (not including receiver) @@ -334,7 +334,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { r0, // argument count (not including receiver) @@ -346,8 +346,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { r0, // argument count (not including receiver) r1, // target to call checked to be Array function diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc index 3173bac58d..c73d371e8f 100644 --- a/src/arm64/interface-descriptors-arm64.cc +++ b/src/arm64/interface-descriptors-arm64.cc @@ -353,7 +353,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { x0, // argument count (not including receiver) @@ -363,7 +363,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { x0, // argument count (not including receiver) @@ -375,8 +375,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { x0, // argument count (not including receiver) x1, // target to call checked to be Array function diff --git a/src/builtins/arm/builtins-arm.cc b/src/builtins/arm/builtins-arm.cc index 777c73fd90..05593bd419 100644 --- a/src/builtins/arm/builtins-arm.cc +++ b/src/builtins/arm/builtins-arm.cc @@ -1082,11 +1082,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register num_args, Register index, - Register limit, Register scratch, - Label* stack_overflow) { - // Add a stack check before pushing arguments. - Generate_StackOverflowCheck(masm, num_args, scratch, stack_overflow); - + Register limit, Register scratch) { // Find the address of the last argument. __ mov(limit, num_args); __ mov(limit, Operand(limit, LSL, kPointerSizeLog2)); @@ -1103,9 +1099,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { +void Builtins::Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- r0 : the number of arguments (not including the receiver) // -- r2 : the address of the first argument to be pushed. Subsequent @@ -1117,8 +1113,16 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( __ add(r3, r0, Operand(1)); // Add one for receiver. + Generate_StackOverflowCheck(masm, r3, r4, &stack_overflow); + + // Push "undefined" as the receiver arg if we need to. + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + __ PushRoot(Heap::kUndefinedValueRootIndex); + __ mov(r3, r0); // Argument count is correct. + } + // Push the arguments. r2, r4, r5 will be modified. - Generate_InterpreterPushArgs(masm, r3, r2, r4, r5, &stack_overflow); + Generate_InterpreterPushArgs(masm, r3, r2, r4, r5); // Call the target. if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1143,7 +1147,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- r0 : argument count (not including receiver) @@ -1158,8 +1162,10 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( __ mov(ip, Operand::Zero()); __ push(ip); + Generate_StackOverflowCheck(masm, r0, r5, &stack_overflow); + // Push the arguments. r5, r4, r6 will be modified. - Generate_InterpreterPushArgs(masm, r0, r4, r5, r6, &stack_overflow); + Generate_InterpreterPushArgs(masm, r0, r4, r5, r6); __ AssertUndefinedOrAllocationSite(r2, r5); if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1190,7 +1196,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r0 : argument count (not including receiver) @@ -1200,11 +1206,14 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // ----------------------------------- Label stack_overflow; - __ add(r4, r0, Operand(1)); // Add one for receiver. + // Push a slot for the receiver to be constructed. + __ mov(ip, Operand::Zero()); + __ push(ip); + + Generate_StackOverflowCheck(masm, r0, r5, &stack_overflow); - // TODO(mythria): Add a stack check before pushing arguments. // Push the arguments. r3, r5, r6 will be modified. - Generate_InterpreterPushArgs(masm, r4, r3, r5, r6, &stack_overflow); + Generate_InterpreterPushArgs(masm, r0, r3, r5, r6); // Array constructor expects constructor in r3. It is same as r1 here. __ mov(r3, r1); diff --git a/src/builtins/arm64/builtins-arm64.cc b/src/builtins/arm64/builtins-arm64.cc index 1f0b4f7185..9824ab64a4 100644 --- a/src/builtins/arm64/builtins-arm64.cc +++ b/src/builtins/arm64/builtins-arm64.cc @@ -1100,11 +1100,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register num_args, Register index, Register last_arg, Register stack_addr, - Register scratch, - Label* stack_overflow) { - // Add a stack check before pushing arguments. - Generate_StackOverflowCheck(masm, num_args, scratch, stack_overflow); - + Register scratch) { __ Mov(scratch, num_args); __ lsl(scratch, scratch, kPointerSizeLog2); __ sub(last_arg, index, scratch); @@ -1126,9 +1122,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { +void Builtins::Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- x0 : the number of arguments (not including the receiver) // -- x2 : the address of the first argument to be pushed. Subsequent @@ -1141,8 +1137,17 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( // Add one for the receiver. __ add(x3, x0, Operand(1)); + // Add a stack check before pushing arguments. + Generate_StackOverflowCheck(masm, x3, x6, &stack_overflow); + + // Push "undefined" as the receiver arg if we need to. + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + __ PushRoot(Heap::kUndefinedValueRootIndex); + __ Mov(x3, x0); // Argument count is correct. + } + // Push the arguments. x2, x4, x5, x6 will be modified. - Generate_InterpreterPushArgs(masm, x3, x2, x4, x5, x6, &stack_overflow); + Generate_InterpreterPushArgs(masm, x3, x2, x4, x5, x6); // Call the target. if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1166,7 +1171,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- x0 : argument count (not including receiver) @@ -1180,8 +1185,11 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( // Push a slot for the receiver. __ Push(xzr); + // Add a stack check before pushing arguments. + Generate_StackOverflowCheck(masm, x0, x7, &stack_overflow); + // Push the arguments. x5, x4, x6, x7 will be modified. - Generate_InterpreterPushArgs(masm, x0, x4, x5, x6, x7, &stack_overflow); + Generate_InterpreterPushArgs(masm, x0, x4, x5, x6, x7); __ AssertUndefinedOrAllocationSite(x2, x6); if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1211,7 +1219,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- x0 : argument count (not including receiver) @@ -1221,10 +1229,14 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // ----------------------------------- Label stack_overflow; - __ add(x4, x0, Operand(1)); // Add one for the receiver. + // Push a slot for the receiver. + __ Push(xzr); + + // Add a stack check before pushing arguments. + Generate_StackOverflowCheck(masm, x0, x7, &stack_overflow); // Push the arguments. x3, x5, x6, x7 will be modified. - Generate_InterpreterPushArgs(masm, x4, x3, x5, x6, x7, &stack_overflow); + Generate_InterpreterPushArgs(masm, x0, x3, x5, x6, x7); // Array constructor expects constructor in x3. It is same as call target. __ mov(x3, x1); diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h index 6a375fa2cf..c1c84cc243 100644 --- a/src/builtins/builtins-definitions.h +++ b/src/builtins/builtins-definitions.h @@ -133,15 +133,17 @@ namespace internal { \ /* Interpreter */ \ ASM(InterpreterEntryTrampoline) \ - ASM(InterpreterPushArgsAndCall) \ - ASM(InterpreterPushArgsAndCallFunction) \ - ASM(InterpreterPushArgsAndCallWithFinalSpread) \ - ASM(InterpreterPushArgsAndTailCall) \ - ASM(InterpreterPushArgsAndTailCallFunction) \ - ASM(InterpreterPushArgsAndConstruct) \ - ASM(InterpreterPushArgsAndConstructFunction) \ - ASM(InterpreterPushArgsAndConstructArray) \ - ASM(InterpreterPushArgsAndConstructWithFinalSpread) \ + ASM(InterpreterPushArgsThenCall) \ + ASM(InterpreterPushUndefinedAndArgsThenCall) \ + ASM(InterpreterPushArgsThenCallFunction) \ + ASM(InterpreterPushUndefinedAndArgsThenCallFunction) \ + ASM(InterpreterPushArgsThenCallWithFinalSpread) \ + ASM(InterpreterPushArgsThenTailCall) \ + ASM(InterpreterPushArgsThenTailCallFunction) \ + ASM(InterpreterPushArgsThenConstruct) \ + ASM(InterpreterPushArgsThenConstructFunction) \ + ASM(InterpreterPushArgsThenConstructArray) \ + ASM(InterpreterPushArgsThenConstructWithFinalSpread) \ ASM(InterpreterEnterBytecodeAdvance) \ ASM(InterpreterEnterBytecodeDispatch) \ ASM(InterpreterOnStackReplacement) \ diff --git a/src/builtins/builtins-interpreter-gen.cc b/src/builtins/builtins-interpreter-gen.cc index 90e6851f82..d11aa64af0 100644 --- a/src/builtins/builtins-interpreter-gen.cc +++ b/src/builtins/builtins-interpreter-gen.cc @@ -9,48 +9,67 @@ namespace v8 { namespace internal { -void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndCallImpl( - masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kOther); +void Builtins::Generate_InterpreterPushArgsThenCall(MacroAssembler* masm) { + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow, + InterpreterPushArgsMode::kOther); } -void Builtins::Generate_InterpreterPushArgsAndCallFunction( +void Builtins::Generate_InterpreterPushArgsThenCallFunction( MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndCallImpl( - masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kJSFunction); + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow, + InterpreterPushArgsMode::kJSFunction); } -void Builtins::Generate_InterpreterPushArgsAndCallWithFinalSpread( +void Builtins::Generate_InterpreterPushUndefinedAndArgsThenCall( MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndCallImpl( - masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kWithFinalSpread); + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kNullOrUndefined, TailCallMode::kDisallow, + InterpreterPushArgsMode::kOther); } -void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndCallImpl( - masm, TailCallMode::kAllow, InterpreterPushArgsMode::kOther); -} - -void Builtins::Generate_InterpreterPushArgsAndTailCallFunction( +void Builtins::Generate_InterpreterPushUndefinedAndArgsThenCallFunction( MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndCallImpl( - masm, TailCallMode::kAllow, InterpreterPushArgsMode::kJSFunction); + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kNullOrUndefined, TailCallMode::kDisallow, + InterpreterPushArgsMode::kJSFunction); } -void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenCallWithFinalSpread( + MacroAssembler* masm) { + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow, + InterpreterPushArgsMode::kWithFinalSpread); +} + +void Builtins::Generate_InterpreterPushArgsThenTailCall(MacroAssembler* masm) { + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kAny, TailCallMode::kAllow, + InterpreterPushArgsMode::kOther); +} + +void Builtins::Generate_InterpreterPushArgsThenTailCallFunction( + MacroAssembler* masm) { + return Generate_InterpreterPushArgsThenCallImpl( + masm, ConvertReceiverMode::kAny, TailCallMode::kAllow, + InterpreterPushArgsMode::kJSFunction); +} + +void Builtins::Generate_InterpreterPushArgsThenConstruct(MacroAssembler* masm) { + return Generate_InterpreterPushArgsThenConstructImpl( masm, InterpreterPushArgsMode::kOther); } -void Builtins::Generate_InterpreterPushArgsAndConstructWithFinalSpread( +void Builtins::Generate_InterpreterPushArgsThenConstructWithFinalSpread( MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndConstructImpl( + return Generate_InterpreterPushArgsThenConstructImpl( masm, InterpreterPushArgsMode::kWithFinalSpread); } -void Builtins::Generate_InterpreterPushArgsAndConstructFunction( +void Builtins::Generate_InterpreterPushArgsThenConstructFunction( MacroAssembler* masm) { - return Generate_InterpreterPushArgsAndConstructImpl( + return Generate_InterpreterPushArgsThenConstructImpl( masm, InterpreterPushArgsMode::kJSFunction); } diff --git a/src/builtins/builtins-interpreter.cc b/src/builtins/builtins-interpreter.cc index 22843ac89e..dd6ef0d0d0 100644 --- a/src/builtins/builtins-interpreter.cc +++ b/src/builtins/builtins-interpreter.cc @@ -11,38 +11,53 @@ namespace v8 { namespace internal { -Handle Builtins::InterpreterPushArgsAndCall( - TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { +Handle Builtins::InterpreterPushArgsThenCall( + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode, + InterpreterPushArgsMode mode) { switch (mode) { case InterpreterPushArgsMode::kJSFunction: if (tail_call_mode == TailCallMode::kDisallow) { - return InterpreterPushArgsAndCallFunction(); + switch (receiver_mode) { + case ConvertReceiverMode::kNullOrUndefined: + return InterpreterPushUndefinedAndArgsThenCallFunction(); + case ConvertReceiverMode::kNotNullOrUndefined: + case ConvertReceiverMode::kAny: + return InterpreterPushArgsThenCallFunction(); + } } else { - return InterpreterPushArgsAndTailCallFunction(); + CHECK_EQ(receiver_mode, ConvertReceiverMode::kAny); + return InterpreterPushArgsThenTailCallFunction(); } case InterpreterPushArgsMode::kWithFinalSpread: CHECK(tail_call_mode == TailCallMode::kDisallow); - return InterpreterPushArgsAndCallWithFinalSpread(); + return InterpreterPushArgsThenCallWithFinalSpread(); case InterpreterPushArgsMode::kOther: if (tail_call_mode == TailCallMode::kDisallow) { - return InterpreterPushArgsAndCall(); + switch (receiver_mode) { + case ConvertReceiverMode::kNullOrUndefined: + return InterpreterPushUndefinedAndArgsThenCall(); + case ConvertReceiverMode::kNotNullOrUndefined: + case ConvertReceiverMode::kAny: + return InterpreterPushArgsThenCall(); + } } else { - return InterpreterPushArgsAndTailCall(); + CHECK_EQ(receiver_mode, ConvertReceiverMode::kAny); + return InterpreterPushArgsThenTailCall(); } } UNREACHABLE(); return Handle::null(); } -Handle Builtins::InterpreterPushArgsAndConstruct( +Handle Builtins::InterpreterPushArgsThenConstruct( InterpreterPushArgsMode mode) { switch (mode) { case InterpreterPushArgsMode::kJSFunction: - return InterpreterPushArgsAndConstructFunction(); + return InterpreterPushArgsThenConstructFunction(); case InterpreterPushArgsMode::kWithFinalSpread: - return InterpreterPushArgsAndConstructWithFinalSpread(); + return InterpreterPushArgsThenConstructWithFinalSpread(); case InterpreterPushArgsMode::kOther: - return InterpreterPushArgsAndConstruct(); + return InterpreterPushArgsThenConstruct(); } UNREACHABLE(); return Handle::null(); diff --git a/src/builtins/builtins.h b/src/builtins/builtins.h index f895e2b138..9da714bc0f 100644 --- a/src/builtins/builtins.h +++ b/src/builtins/builtins.h @@ -58,9 +58,10 @@ class Builtins { Handle NonPrimitiveToPrimitive( ToPrimitiveHint hint = ToPrimitiveHint::kDefault); Handle OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint); - Handle InterpreterPushArgsAndCall(TailCallMode tail_call_mode, - InterpreterPushArgsMode mode); - Handle InterpreterPushArgsAndConstruct(InterpreterPushArgsMode mode); + Handle InterpreterPushArgsThenCall(ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, + InterpreterPushArgsMode mode); + Handle InterpreterPushArgsThenConstruct(InterpreterPushArgsMode mode); Handle NewFunctionContext(ScopeType scope_type); Handle NewCloneShallowArray(AllocationSiteMode allocation_mode); Handle NewCloneShallowObject(int length); @@ -122,11 +123,11 @@ class Builtins { static void Generate_CallForwardVarargs(MacroAssembler* masm, Handle code); - static void Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode); + static void Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode); - static void Generate_InterpreterPushArgsAndConstructImpl( + static void Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode); #define DECLARE_ASM(Name, ...) \ diff --git a/src/builtins/ia32/builtins-ia32.cc b/src/builtins/ia32/builtins-ia32.cc index f3b0474fd1..00e9e720ae 100644 --- a/src/builtins/ia32/builtins-ia32.cc +++ b/src/builtins/ia32/builtins-ia32.cc @@ -751,9 +751,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { +void Builtins::Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- eax : the number of arguments (not including the receiver) // -- ebx : the address of the first argument to be pushed. Subsequent @@ -776,6 +776,12 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( // Pop return address to allow tail-call after pushing arguments. __ Pop(edx); + // Push "undefined" as the receiver arg if we need to. + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + __ PushRoot(Heap::kUndefinedValueRootIndex); + __ sub(ecx, Immediate(1)); // Subtract one for receiver. + } + // Find the address of the last argument. __ shl(ecx, kPointerSizeLog2); __ neg(ecx); @@ -815,10 +821,10 @@ namespace { // This function modified start_addr, and only reads the contents of num_args // register. scratch1 and scratch2 are used as temporary registers. Their // original values are restored after the use. -void Generate_InterpreterPushArgsAndReturnAddress( +void Generate_InterpreterPushZeroAndArgsAndReturnAddress( MacroAssembler* masm, Register num_args, Register start_addr, - Register scratch1, Register scratch2, bool receiver_in_args, - int num_slots_above_ret_addr, Label* stack_overflow) { + Register scratch1, Register scratch2, int num_slots_above_ret_addr, + Label* stack_overflow) { // We have to move return address and the temporary registers above it // before we can copy arguments onto the stack. To achieve this: // Step 1: Increment the stack pointer by num_args + 1 (for receiver). @@ -831,7 +837,7 @@ void Generate_InterpreterPushArgsAndReturnAddress( // | | | return addr | (2) // | | | arg N | (3) // | scratch1 | <-- esp | .... | - // | .... | | arg 0 | + // | .... | | arg 1 | // | scratch-n | | arg 0 | // | return addr | | receiver slot | @@ -875,17 +881,12 @@ void Generate_InterpreterPushArgsAndReturnAddress( } // Step 3 copy arguments to correct locations. - if (receiver_in_args) { - __ mov(scratch1, num_args); - __ add(scratch1, Immediate(1)); - } else { - // Slot meant for receiver contains return address. Reset it so that - // we will not incorrectly interpret return address as an object. - __ mov(Operand(esp, num_args, times_pointer_size, - (num_slots_above_ret_addr + 1) * kPointerSize), - Immediate(0)); - __ mov(scratch1, num_args); - } + // Slot meant for receiver contains return address. Reset it so that + // we will not incorrectly interpret return address as an object. + __ mov(Operand(esp, num_args, times_pointer_size, + (num_slots_above_ret_addr + 1) * kPointerSize), + Immediate(0)); + __ mov(scratch1, num_args); Label loop_header, loop_check; __ jmp(&loop_check); @@ -904,7 +905,7 @@ void Generate_InterpreterPushArgsAndReturnAddress( } // end anonymous namespace // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- eax : the number of arguments (not including the receiver) @@ -923,8 +924,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( // Push arguments and move return address to the top of stack. // The eax register is readonly. The ecx register will be modified. The edx // and edi registers will be modified but restored to their original values. - Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, - 2, &stack_overflow); + Generate_InterpreterPushZeroAndArgsAndReturnAddress(masm, eax, ecx, edx, edi, + 2, &stack_overflow); // Restore edi and edx __ Pop(edx); @@ -964,7 +965,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : the number of arguments (not including the receiver) @@ -982,8 +983,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // Push arguments and move return address to the top of stack. // The eax register is readonly. The ecx register will be modified. The edx // and edi registers will be modified but restored to their original values. - Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true, - 1, &stack_overflow); + Generate_InterpreterPushZeroAndArgsAndReturnAddress(masm, eax, ecx, edx, edi, + 1, &stack_overflow); // Restore edx. __ Pop(edx); diff --git a/src/builtins/mips/builtins-mips.cc b/src/builtins/mips/builtins-mips.cc index d536138d44..2da3985606 100644 --- a/src/builtins/mips/builtins-mips.cc +++ b/src/builtins/mips/builtins-mips.cc @@ -1077,11 +1077,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register num_args, Register index, - Register scratch, Register scratch2, - Label* stack_overflow) { - Generate_StackOverflowCheck(masm, num_args, scratch, scratch2, - stack_overflow); - + Register scratch, Register scratch2) { // Find the address of the last argument. __ mov(scratch2, num_args); __ sll(scratch2, scratch2, kPointerSizeLog2); @@ -1099,9 +1095,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { +void Builtins::Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- a0 : the number of arguments (not including the receiver) // -- a2 : the address of the first argument to be pushed. Subsequent @@ -1113,8 +1109,16 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( __ Addu(t0, a0, Operand(1)); // Add one for receiver. + Generate_StackOverflowCheck(masm, t0, t4, t1, &stack_overflow); + + // Push "undefined" as the receiver arg if we need to. + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + __ PushRoot(Heap::kUndefinedValueRootIndex); + __ mov(t0, a0); // No receiver. + } + // This function modifies a2, t4 and t1. - Generate_InterpreterPushArgs(masm, t0, a2, t4, t1, &stack_overflow); + Generate_InterpreterPushArgs(masm, t0, a2, t4, t1); // Call the target. if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1139,7 +1143,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- a0 : argument count (not including receiver) @@ -1153,8 +1157,10 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( // Push a slot for the receiver. __ push(zero_reg); + Generate_StackOverflowCheck(masm, a0, t1, t0, &stack_overflow); + // This function modified t4, t1 and t0. - Generate_InterpreterPushArgs(masm, a0, t4, t1, t0, &stack_overflow); + Generate_InterpreterPushArgs(masm, a0, t4, t1, t0); __ AssertUndefinedOrAllocationSite(a2, t0); if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1185,7 +1191,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- a0 : the number of arguments (not including the receiver) @@ -1197,10 +1203,13 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // ----------------------------------- Label stack_overflow; - __ Addu(t0, a0, Operand(1)); // Add one for receiver. + // Push a slot for the receiver. + __ push(zero_reg); - // This function modifies a3, t4, and t1. - Generate_InterpreterPushArgs(masm, t0, a3, t1, t4, &stack_overflow); + Generate_StackOverflowCheck(masm, a0, t1, t4, &stack_overflow); + + // This function modifies a3, t1, and t4. + Generate_InterpreterPushArgs(masm, a0, a3, t1, t4); // ArrayConstructor stub expects constructor in a3. Set it here. __ mov(a3, a1); diff --git a/src/builtins/mips64/builtins-mips64.cc b/src/builtins/mips64/builtins-mips64.cc index 42d291feac..ae1edcae8c 100644 --- a/src/builtins/mips64/builtins-mips64.cc +++ b/src/builtins/mips64/builtins-mips64.cc @@ -1070,11 +1070,7 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args, static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register num_args, Register index, - Register scratch, Register scratch2, - Label* stack_overflow) { - // Generate_StackOverflowCheck(masm, num_args, scratch, scratch2, - // stack_overflow); - + Register scratch, Register scratch2) { // Find the address of the last argument. __ mov(scratch2, num_args); __ dsll(scratch2, scratch2, kPointerSizeLog2); @@ -1092,9 +1088,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { +void Builtins::Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- a0 : the number of arguments (not including the receiver) // -- a2 : the address of the first argument to be pushed. Subsequent @@ -1106,8 +1102,16 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( __ Daddu(a3, a0, Operand(1)); // Add one for receiver. + // Push "undefined" as the receiver arg if we need to. + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + __ PushRoot(Heap::kUndefinedValueRootIndex); + __ Dsubu(a3, a3, Operand(1)); // Subtract one for receiver. + } + + Generate_StackOverflowCheck(masm, a3, a4, t0, &stack_overflow); + // This function modifies a2, t0 and a4. - Generate_InterpreterPushArgs(masm, a3, a2, a4, t0, &stack_overflow); + Generate_InterpreterPushArgs(masm, a3, a2, a4, t0); // Call the target. if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1132,7 +1136,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- a0 : argument count (not including receiver) @@ -1146,8 +1150,10 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( // Push a slot for the receiver. __ push(zero_reg); + Generate_StackOverflowCheck(masm, a0, a5, t0, &stack_overflow); + // This function modifies t0, a4 and a5. - Generate_InterpreterPushArgs(masm, a0, a4, a5, t0, &stack_overflow); + Generate_InterpreterPushArgs(masm, a0, a4, a5, t0); __ AssertUndefinedOrAllocationSite(a2, t0); if (mode == InterpreterPushArgsMode::kJSFunction) { @@ -1178,7 +1184,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- a0 : the number of arguments (not including the receiver) @@ -1190,10 +1196,13 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // ----------------------------------- Label stack_overflow; - __ Daddu(a4, a0, Operand(1)); // Add one for receiver. + // Push a slot for the receiver. + __ push(zero_reg); + + Generate_StackOverflowCheck(masm, a4, a5, a6, &stack_overflow); // This function modifies a3, a5 and a6. - Generate_InterpreterPushArgs(masm, a4, a3, a5, a6, &stack_overflow); + Generate_InterpreterPushArgs(masm, a4, a3, a5, a6); // ArrayConstructor stub expects constructor in a3. Set it here. __ mov(a3, a1); diff --git a/src/builtins/ppc/builtins-ppc.cc b/src/builtins/ppc/builtins-ppc.cc index 6f2c4f71f0..5deb707f9f 100644 --- a/src/builtins/ppc/builtins-ppc.cc +++ b/src/builtins/ppc/builtins-ppc.cc @@ -1112,7 +1112,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( +void Builtins::Generate_InterpreterPushArgsThenCallImpl( MacroAssembler* masm, TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- @@ -1153,7 +1153,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- r3 : argument count (not including receiver) @@ -1206,7 +1206,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r3 : argument count (not including receiver) diff --git a/src/builtins/s390/builtins-s390.cc b/src/builtins/s390/builtins-s390.cc index 98d918550f..ea5b61ca28 100644 --- a/src/builtins/s390/builtins-s390.cc +++ b/src/builtins/s390/builtins-s390.cc @@ -1118,7 +1118,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( +void Builtins::Generate_InterpreterPushArgsThenCallImpl( MacroAssembler* masm, TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- @@ -1159,7 +1159,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- r2 : argument count (not including receiver) @@ -1211,7 +1211,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- r2 : argument count (not including receiver) diff --git a/src/builtins/x64/builtins-x64.cc b/src/builtins/x64/builtins-x64.cc index 51f734567b..f4e298f571 100644 --- a/src/builtins/x64/builtins-x64.cc +++ b/src/builtins/x64/builtins-x64.cc @@ -823,9 +823,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( - MacroAssembler* masm, TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { +void Builtins::Generate_InterpreterPushArgsThenCallImpl( + MacroAssembler* masm, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- rax : the number of arguments (not including the receiver) // -- rbx : the address of the first argument to be pushed. Subsequent @@ -845,6 +845,12 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( // Pop return address to allow tail-call after pushing arguments. __ PopReturnAddressTo(kScratchRegister); + // Push "undefined" as the receiver arg if we need to. + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + __ PushRoot(Heap::kUndefinedValueRootIndex); + __ subp(rcx, Immediate(1)); // Subtract one for receiver. + } + // rbx and rdx will be modified. Generate_InterpreterPushArgs(masm, rcx, rbx, rdx); @@ -852,15 +858,14 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( __ PushReturnAddressFrom(kScratchRegister); // Re-push return address. if (mode == InterpreterPushArgsMode::kJSFunction) { - __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny, + __ Jump(masm->isolate()->builtins()->CallFunction(receiver_mode, tail_call_mode), RelocInfo::CODE_TARGET); } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { __ Jump(masm->isolate()->builtins()->CallWithSpread(), RelocInfo::CODE_TARGET); } else { - __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny, - tail_call_mode), + __ Jump(masm->isolate()->builtins()->Call(receiver_mode, tail_call_mode), RelocInfo::CODE_TARGET); } @@ -874,7 +879,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- rax : the number of arguments (not including the receiver) @@ -934,7 +939,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- rax : the number of arguments (not including the receiver) @@ -948,7 +953,6 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // Number of values to be pushed. __ Move(r8, rax); - __ addp(r8, Immediate(1)); // Add one for receiver. // Add a stack check before pushing arguments. Generate_StackOverflowCheck(masm, r8, rdi, &stack_overflow); @@ -956,6 +960,9 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // Pop return address to allow tail-call after pushing arguments. __ PopReturnAddressTo(kScratchRegister); + // Push slot for the receiver to be constructed. + __ Push(Immediate(0)); + // rcx and rdi will be modified. Generate_InterpreterPushArgs(masm, r8, rcx, rdi); diff --git a/src/builtins/x87/builtins-x87.cc b/src/builtins/x87/builtins-x87.cc index 55aefbcad3..55b5dc4f56 100644 --- a/src/builtins/x87/builtins-x87.cc +++ b/src/builtins/x87/builtins-x87.cc @@ -694,7 +694,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, } // static -void Builtins::Generate_InterpreterPushArgsAndCallImpl( +void Builtins::Generate_InterpreterPushArgsThenCallImpl( MacroAssembler* masm, TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- @@ -758,7 +758,7 @@ namespace { // This function modified start_addr, and only reads the contents of num_args // register. scratch1 and scratch2 are used as temporary registers. Their // original values are restored after the use. -void Generate_InterpreterPushArgsAndReturnAddress( +void Generate_InterpreterPushArgsThenReturnAddress( MacroAssembler* masm, Register num_args, Register start_addr, Register scratch1, Register scratch2, bool receiver_in_args, int num_slots_above_ret_addr, Label* stack_overflow) { @@ -847,7 +847,7 @@ void Generate_InterpreterPushArgsAndReturnAddress( } // end anonymous namespace // static -void Builtins::Generate_InterpreterPushArgsAndConstructImpl( +void Builtins::Generate_InterpreterPushArgsThenConstructImpl( MacroAssembler* masm, InterpreterPushArgsMode mode) { // ----------- S t a t e ------------- // -- eax : the number of arguments (not including the receiver) @@ -866,8 +866,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( // Push arguments and move return address to the top of stack. // The eax register is readonly. The ecx register will be modified. The edx // and edi registers will be modified but restored to their original values. - Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false, - 2, &stack_overflow); + Generate_InterpreterPushArgsThenReturnAddress(masm, eax, ecx, edx, edi, false, + 2, &stack_overflow); // Restore edi and edx __ Pop(edx); @@ -907,7 +907,7 @@ void Builtins::Generate_InterpreterPushArgsAndConstructImpl( } // static -void Builtins::Generate_InterpreterPushArgsAndConstructArray( +void Builtins::Generate_InterpreterPushArgsThenConstructArray( MacroAssembler* masm) { // ----------- S t a t e ------------- // -- eax : the number of arguments (not including the receiver) @@ -925,8 +925,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstructArray( // Push arguments and move return address to the top of stack. // The eax register is readonly. The ecx register will be modified. The edx // and edi registers will be modified but restored to their original values. - Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true, - 1, &stack_overflow); + Generate_InterpreterPushArgsThenReturnAddress(masm, eax, ecx, edx, edi, true, + 1, &stack_overflow); // Restore edx. __ Pop(edx); diff --git a/src/code-factory.cc b/src/code-factory.cc index 1e4c099231..71fbb1dbab 100644 --- a/src/code-factory.cc +++ b/src/code-factory.cc @@ -464,25 +464,25 @@ Callable CodeFactory::ConstructFunction(Isolate* isolate) { } // static -Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate, - TailCallMode tail_call_mode, - InterpreterPushArgsMode mode) { - return Callable( - isolate->builtins()->InterpreterPushArgsAndCall(tail_call_mode, mode), - InterpreterPushArgsAndCallDescriptor(isolate)); +Callable CodeFactory::InterpreterPushArgsThenCall( + Isolate* isolate, ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { + return Callable(isolate->builtins()->InterpreterPushArgsThenCall( + receiver_mode, tail_call_mode, mode), + InterpreterPushArgsThenCallDescriptor(isolate)); } // static -Callable CodeFactory::InterpreterPushArgsAndConstruct( +Callable CodeFactory::InterpreterPushArgsThenConstruct( Isolate* isolate, InterpreterPushArgsMode mode) { - return Callable(isolate->builtins()->InterpreterPushArgsAndConstruct(mode), - InterpreterPushArgsAndConstructDescriptor(isolate)); + return Callable(isolate->builtins()->InterpreterPushArgsThenConstruct(mode), + InterpreterPushArgsThenConstructDescriptor(isolate)); } // static -Callable CodeFactory::InterpreterPushArgsAndConstructArray(Isolate* isolate) { - return Callable(isolate->builtins()->InterpreterPushArgsAndConstructArray(), - InterpreterPushArgsAndConstructArrayDescriptor(isolate)); +Callable CodeFactory::InterpreterPushArgsThenConstructArray(Isolate* isolate) { + return Callable(isolate->builtins()->InterpreterPushArgsThenConstructArray(), + InterpreterPushArgsThenConstructArrayDescriptor(isolate)); } // static diff --git a/src/code-factory.h b/src/code-factory.h index ce23364d0b..669f3798aa 100644 --- a/src/code-factory.h +++ b/src/code-factory.h @@ -173,12 +173,13 @@ class V8_EXPORT_PRIVATE CodeFactory final { static Callable HasProperty(Isolate* isolate); static Callable ForInFilter(Isolate* isolate); - static Callable InterpreterPushArgsAndCall(Isolate* isolate, - TailCallMode tail_call_mode, - InterpreterPushArgsMode mode); - static Callable InterpreterPushArgsAndConstruct(Isolate* isolate, - InterpreterPushArgsMode mode); - static Callable InterpreterPushArgsAndConstructArray(Isolate* isolate); + static Callable InterpreterPushArgsThenCall(Isolate* isolate, + ConvertReceiverMode receiver_mode, + TailCallMode tail_call_mode, + InterpreterPushArgsMode mode); + static Callable InterpreterPushArgsThenConstruct( + Isolate* isolate, InterpreterPushArgsMode mode); + static Callable InterpreterPushArgsThenConstructArray(Isolate* isolate); static Callable InterpreterCEntry(Isolate* isolate, int result_size = 1); static Callable InterpreterOnStackReplacement(Isolate* isolate); diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc index 3b9784a4dc..dcaed97481 100644 --- a/src/compiler/bytecode-graph-builder.cc +++ b/src/compiler/bytecode-graph-builder.cc @@ -1342,37 +1342,55 @@ void BytecodeGraphBuilder::VisitCreateObjectLiteral() { } Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegister( - Node* callee, interpreter::Register receiver, size_t arity) { - Node** all = local_zone()->NewArray(static_cast(arity)); + Node* callee, Node* receiver, interpreter::Register first_arg, + int arg_count) { + // The arity of the Call node -- includes the callee, receiver and function + // arguments. + int arity = 2 + arg_count; + + Node** all = local_zone()->NewArray(static_cast(arity)); + all[0] = callee; - all[1] = environment()->LookupRegister(receiver); - int receiver_index = receiver.index(); - for (int i = 2; i < static_cast(arity); ++i) { - all[i] = environment()->LookupRegister( - interpreter::Register(receiver_index + i - 1)); + all[1] = receiver; + + // The function arguments are in consecutive registers. + int arg_base = first_arg.index(); + for (int i = 0; i < arg_count; ++i) { + all[2 + i] = + environment()->LookupRegister(interpreter::Register(arg_base + i)); } + return all; } Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, Node* const* args, - size_t arg_count) { - return MakeNode(call_op, static_cast(arg_count), args, false); + int arg_count) { + return MakeNode(call_op, arg_count, args, false); } Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, Node* callee, interpreter::Register receiver, - size_t arg_count) { - return ProcessCallArguments( - call_op, GetCallArgumentsFromRegister(callee, receiver, arg_count), - arg_count); + size_t reg_count) { + Node* receiver_node = environment()->LookupRegister(receiver); + // The receiver is followed by the arguments in the consecutive registers. + DCHECK_GE(reg_count, 1); + interpreter::Register first_arg = interpreter::Register(receiver.index() + 1); + int arg_count = static_cast(reg_count) - 1; + + Node* const* call_args = + GetCallArgumentsFromRegister(callee, receiver_node, first_arg, arg_count); + return ProcessCallArguments(call_op, call_args, 2 + arg_count); } void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode, - ConvertReceiverMode receiver_hint, + ConvertReceiverMode receiver_mode, Node* const* args, size_t arg_count, int slot_id) { + DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode( + bytecode_iterator().current_bytecode()), + receiver_mode); PrepareEagerCheckpoint(); // Slot index of 0 is used indicate no feedback slot is available. Assert @@ -1382,63 +1400,51 @@ void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode, float const frequency = ComputeCallFrequency(slot_id); const Operator* call = javascript()->Call(arg_count, frequency, feedback, - receiver_hint, tail_call_mode); - Node* value = ProcessCallArguments(call, args, arg_count); + receiver_mode, tail_call_mode); + Node* value = ProcessCallArguments(call, args, static_cast(arg_count)); environment()->BindAccumulator(value, Environment::kAttachFrameState); } void BytecodeGraphBuilder::BuildCallVarArgs(TailCallMode tail_call_mode, - ConvertReceiverMode receiver_hint) { + ConvertReceiverMode receiver_mode) { + DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode( + bytecode_iterator().current_bytecode()), + receiver_mode); Node* callee = environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); - interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); int const slot_id = bytecode_iterator().GetIndexOperand(3); - BuildCall(tail_call_mode, receiver_hint, - GetCallArgumentsFromRegister(callee, receiver, arg_count + 1), - arg_count + 1, slot_id); + + Node* receiver_node; + interpreter::Register first_arg; + int arg_count; + + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + // The receiver is implicit (and undefined), the arguments are in + // consecutive registers. + receiver_node = jsgraph()->UndefinedConstant(); + first_arg = first_reg; + arg_count = static_cast(reg_count); + } else { + // The receiver is the first register, followed by the arguments in the + // consecutive registers. + DCHECK_GE(reg_count, 1); + receiver_node = environment()->LookupRegister(first_reg); + first_arg = interpreter::Register(first_reg.index() + 1); + arg_count = static_cast(reg_count) - 1; + } + + Node* const* call_args = + GetCallArgumentsFromRegister(callee, receiver_node, first_arg, arg_count); + BuildCall(tail_call_mode, receiver_mode, call_args, + static_cast(2 + arg_count), slot_id); } -void BytecodeGraphBuilder::VisitCall() { +void BytecodeGraphBuilder::VisitCallAnyReceiver() { BuildCallVarArgs(TailCallMode::kDisallow, ConvertReceiverMode::kAny); } -void BytecodeGraphBuilder::VisitCall0() { - Node* callee = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); - Node* receiver = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); - int const slot_id = bytecode_iterator().GetIndexOperand(2); - BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kAny, - {callee, receiver}, slot_id); -} - -void BytecodeGraphBuilder::VisitCall1() { - Node* callee = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); - Node* receiver = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); - Node* arg0 = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); - int const slot_id = bytecode_iterator().GetIndexOperand(3); - BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kAny, - {callee, receiver, arg0}, slot_id); -} - -void BytecodeGraphBuilder::VisitCall2() { - Node* callee = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); - Node* receiver = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); - Node* arg0 = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); - Node* arg1 = - environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(3)); - int const slot_id = bytecode_iterator().GetIndexOperand(4); - BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kAny, - {callee, receiver, arg0, arg1}, slot_id); -} - void BytecodeGraphBuilder::VisitCallProperty() { BuildCallVarArgs(TailCallMode::kDisallow, ConvertReceiverMode::kNotNullOrUndefined); @@ -1480,16 +1486,54 @@ void BytecodeGraphBuilder::VisitCallProperty2() { {callee, receiver, arg0, arg1}, slot_id); } +void BytecodeGraphBuilder::VisitCallUndefinedReceiver() { + BuildCallVarArgs(TailCallMode::kDisallow, + ConvertReceiverMode::kNullOrUndefined); +} + +void BytecodeGraphBuilder::VisitCallUndefinedReceiver0() { + Node* callee = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + Node* receiver = jsgraph()->UndefinedConstant(); + int const slot_id = bytecode_iterator().GetIndexOperand(1); + BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNullOrUndefined, + {callee, receiver}, slot_id); +} + +void BytecodeGraphBuilder::VisitCallUndefinedReceiver1() { + Node* callee = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + Node* receiver = jsgraph()->UndefinedConstant(); + Node* arg0 = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); + int const slot_id = bytecode_iterator().GetIndexOperand(2); + BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNullOrUndefined, + {callee, receiver, arg0}, slot_id); +} + +void BytecodeGraphBuilder::VisitCallUndefinedReceiver2() { + Node* callee = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); + Node* receiver = jsgraph()->UndefinedConstant(); + Node* arg0 = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(1)); + Node* arg1 = + environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(2)); + int const slot_id = bytecode_iterator().GetIndexOperand(3); + BuildCall(TailCallMode::kDisallow, ConvertReceiverMode::kNullOrUndefined, + {callee, receiver, arg0, arg1}, slot_id); +} + void BytecodeGraphBuilder::VisitCallWithSpread() { PrepareEagerCheckpoint(); Node* callee = environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); const Operator* call = - javascript()->CallWithSpread(static_cast(arg_count + 1)); + javascript()->CallWithSpread(static_cast(reg_count + 1)); - Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); + Node* value = ProcessCallArguments(call, callee, receiver, reg_count); environment()->BindAccumulator(value, Environment::kAttachFrameState); } @@ -1506,118 +1550,127 @@ void BytecodeGraphBuilder::VisitCallJSRuntime() { Node* callee = BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0)); interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); // Create node to perform the JS runtime call. - const Operator* call = javascript()->Call(arg_count + 1); - Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1); + const Operator* call = javascript()->Call(reg_count + 1); + Node* value = ProcessCallArguments(call, callee, receiver, reg_count); environment()->BindAccumulator(value, Environment::kAttachFrameState); } Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( - const Operator* call_runtime_op, interpreter::Register first_arg, - size_t arity) { - Node** all = local_zone()->NewArray(arity); - int first_arg_index = first_arg.index(); - for (int i = 0; i < static_cast(arity); ++i) { + const Operator* call_runtime_op, interpreter::Register receiver, + size_t reg_count) { + int arg_count = static_cast(reg_count); + // arity is args. + int arity = arg_count; + Node** all = local_zone()->NewArray(static_cast(arity)); + int first_arg_index = receiver.index(); + for (int i = 0; i < static_cast(reg_count); ++i) { all[i] = environment()->LookupRegister( interpreter::Register(first_arg_index + i)); } - Node* value = MakeNode(call_runtime_op, static_cast(arity), all, false); + Node* value = MakeNode(call_runtime_op, arity, all, false); return value; } void BytecodeGraphBuilder::VisitCallRuntime() { PrepareEagerCheckpoint(); Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); - interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); // Create node to perform the runtime call. - const Operator* call = javascript()->CallRuntime(functionId, arg_count); - Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); + const Operator* call = javascript()->CallRuntime(functionId, reg_count); + Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); environment()->BindAccumulator(value, Environment::kAttachFrameState); } void BytecodeGraphBuilder::VisitCallRuntimeForPair() { PrepareEagerCheckpoint(); Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); - interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); interpreter::Register first_return = bytecode_iterator().GetRegisterOperand(3); // Create node to perform the runtime call. - const Operator* call = javascript()->CallRuntime(functionId, arg_count); - Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count); + const Operator* call = javascript()->CallRuntime(functionId, reg_count); + Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count); environment()->BindRegistersToProjections(first_return, return_pair, Environment::kAttachFrameState); } Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments( const Operator* op, Node* callee, Node* new_target, - interpreter::Register first_arg, size_t arity) { - Node** all = local_zone()->NewArray(arity); + interpreter::Register receiver, size_t reg_count) { + int arg_count = static_cast(reg_count); + // arity is args + callee and new target. + int arity = arg_count + 2; + Node** all = local_zone()->NewArray(static_cast(arity)); all[0] = callee; - int first_arg_index = first_arg.index(); - for (int i = 1; i < static_cast(arity) - 1; ++i) { - all[i] = environment()->LookupRegister( - interpreter::Register(first_arg_index + i - 1)); + int first_arg_index = receiver.index(); + for (int i = 0; i < arg_count; ++i) { + all[1 + i] = environment()->LookupRegister( + interpreter::Register(first_arg_index + i)); } all[arity - 1] = new_target; - Node* value = MakeNode(op, static_cast(arity), all, false); + Node* value = MakeNode(op, arity, all, false); return value; } void BytecodeGraphBuilder::VisitConstructWithSpread() { PrepareEagerCheckpoint(); interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); - interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); Node* new_target = environment()->LookupAccumulator(); Node* callee = environment()->LookupRegister(callee_reg); const Operator* op = - javascript()->ConstructWithSpread(static_cast(arg_count) + 2); + javascript()->ConstructWithSpread(static_cast(reg_count + 2)); Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target, - first_arg, arg_count + 2); + receiver, reg_count); environment()->BindAccumulator(value, Environment::kAttachFrameState); } void BytecodeGraphBuilder::VisitInvokeIntrinsic() { PrepareEagerCheckpoint(); Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); - interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); // Create node to perform the runtime call. Turbofan will take care of the // lowering. - const Operator* call = javascript()->CallRuntime(functionId, arg_count); - Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count); + const Operator* call = javascript()->CallRuntime(functionId, reg_count); + Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); environment()->BindAccumulator(value, Environment::kAttachFrameState); } Node* BytecodeGraphBuilder::ProcessConstructArguments( const Operator* call_new_op, Node* callee, Node* new_target, - interpreter::Register first_arg, size_t arity) { - Node** all = local_zone()->NewArray(arity); + interpreter::Register receiver, size_t reg_count) { + int arg_count = static_cast(reg_count); + // arity is args + callee and new target. + int arity = arg_count + 2; + Node** all = local_zone()->NewArray(static_cast(arity)); all[0] = callee; - int first_arg_index = first_arg.index(); - for (int i = 1; i < static_cast(arity) - 1; ++i) { - all[i] = environment()->LookupRegister( - interpreter::Register(first_arg_index + i - 1)); + int first_arg_index = receiver.index(); + for (int i = 0; i < arg_count; ++i) { + all[1 + i] = environment()->LookupRegister( + interpreter::Register(first_arg_index + i)); } all[arity - 1] = new_target; - Node* value = MakeNode(call_new_op, static_cast(arity), all, false); + Node* value = MakeNode(call_new_op, arity, all, false); return value; } void BytecodeGraphBuilder::VisitConstruct() { PrepareEagerCheckpoint(); interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); - interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1); - size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2); + interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); + size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); // Slot index of 0 is used indicate no feedback slot is available. Assert // the assumption that slot index 0 is never a valid feedback slot. STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); @@ -1629,9 +1682,9 @@ void BytecodeGraphBuilder::VisitConstruct() { float const frequency = ComputeCallFrequency(slot_id); const Operator* call = javascript()->Construct( - static_cast(arg_count) + 2, frequency, feedback); - Node* value = ProcessConstructArguments(call, callee, new_target, first_arg, - arg_count + 2); + static_cast(reg_count + 2), frequency, feedback); + Node* value = + ProcessConstructArguments(call, callee, new_target, receiver, reg_count); environment()->BindAccumulator(value, Environment::kAttachFrameState); } diff --git a/src/compiler/bytecode-graph-builder.h b/src/compiler/bytecode-graph-builder.h index 8e61f575ea..809a995dff 100644 --- a/src/compiler/bytecode-graph-builder.h +++ b/src/compiler/bytecode-graph-builder.h @@ -112,24 +112,24 @@ class BytecodeGraphBuilder { Node** EnsureInputBufferSize(int size); - Node* const* GetCallArgumentsFromRegister(Node* callee, + Node* const* GetCallArgumentsFromRegister(Node* callee, Node* receiver, interpreter::Register first_arg, - size_t arity); + int arg_count); Node* ProcessCallArguments(const Operator* call_op, Node* const* args, - size_t arg_count); + int arg_count); Node* ProcessCallArguments(const Operator* call_op, Node* callee, - interpreter::Register receiver, size_t arity); + interpreter::Register receiver, size_t reg_count); Node* ProcessConstructArguments(const Operator* call_new_op, Node* callee, Node* new_target, - interpreter::Register first_arg, - size_t arity); + interpreter::Register receiver, + size_t reg_count); Node* ProcessConstructWithSpreadArguments(const Operator* op, Node* callee, Node* new_target, - interpreter::Register first_arg, - size_t arity); + interpreter::Register receiver, + size_t reg_count); Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, - interpreter::Register first_arg, - size_t arity); + interpreter::Register receiver, + size_t reg_count); // Prepare information for eager deoptimization. This information is carried // by dedicated {Checkpoint} nodes that are wired into the effect chain. @@ -159,12 +159,12 @@ class BytecodeGraphBuilder { void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode); void BuildStaLookupSlot(LanguageMode language_mode); void BuildCallVarArgs(TailCallMode tail_call_mode, - ConvertReceiverMode receiver_hint); - void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_hint, + ConvertReceiverMode receiver_mode); + void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_mode, Node* const* args, size_t arg_count, int slot_id); - void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_hint, + void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_mode, std::initializer_list args, int slot_id) { - BuildCall(tail_call_mode, receiver_hint, args.begin(), args.size(), + BuildCall(tail_call_mode, receiver_mode, args.begin(), args.size(), slot_id); } void BuildBinaryOp(const Operator* op); diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc index 701db767f0..304191bbd2 100644 --- a/src/ia32/interface-descriptors-ia32.cc +++ b/src/ia32/interface-descriptors-ia32.cc @@ -318,7 +318,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { eax, // argument count (not including receiver) @@ -328,7 +328,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { eax, // argument count (not including receiver) @@ -340,8 +340,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { eax, // argument count (not including receiver) edx, // target to the call. It is checked to be Array function. diff --git a/src/interface-descriptors.cc b/src/interface-descriptors.cc index 55bccf6a64..a5dccc3583 100644 --- a/src/interface-descriptors.cc +++ b/src/interface-descriptors.cc @@ -607,7 +607,7 @@ void InterpreterDispatchDescriptor::InitializePlatformIndependent( machine_types); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformIndependent( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformIndependent( CallInterfaceDescriptorData* data) { // kNumberOfArguments, kFirstArgument, kFunction MachineType machine_types[] = {MachineType::Int32(), MachineType::Pointer(), @@ -616,7 +616,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformIndependent( machine_types); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformIndependent( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformIndependent( CallInterfaceDescriptorData* data) { // kNumberOfArguments, kNewTarget, kConstructor, kFeedbackElement, // kFirstArgument @@ -627,7 +627,7 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformIndependent( machine_types); } -void InterpreterPushArgsAndConstructArrayDescriptor:: +void InterpreterPushArgsThenConstructArrayDescriptor:: InitializePlatformIndependent(CallInterfaceDescriptorData* data) { // kNumberOfArguments, kFunction, kFeedbackElement, kFirstArgument MachineType machine_types[] = {MachineType::Int32(), MachineType::AnyTagged(), diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h index df6a0e8dab..b97c45cd0e 100644 --- a/src/interface-descriptors.h +++ b/src/interface-descriptors.h @@ -79,9 +79,9 @@ class PlatformInterfaceDescriptor; V(GrowArrayElements) \ V(NewArgumentsElements) \ V(InterpreterDispatch) \ - V(InterpreterPushArgsAndCall) \ - V(InterpreterPushArgsAndConstruct) \ - V(InterpreterPushArgsAndConstructArray) \ + V(InterpreterPushArgsThenCall) \ + V(InterpreterPushArgsThenConstruct) \ + V(InterpreterPushArgsThenConstructArray) \ V(InterpreterCEntry) \ V(ResumeGenerator) \ V(FrameDropperTrampoline) \ @@ -839,30 +839,29 @@ class V8_EXPORT_PRIVATE InterpreterDispatchDescriptor CallInterfaceDescriptor) }; -class InterpreterPushArgsAndCallDescriptor : public CallInterfaceDescriptor { +class InterpreterPushArgsThenCallDescriptor : public CallInterfaceDescriptor { public: DEFINE_PARAMETERS(kNumberOfArguments, kFirstArgument, kFunction) DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE( - InterpreterPushArgsAndCallDescriptor, CallInterfaceDescriptor) + InterpreterPushArgsThenCallDescriptor, CallInterfaceDescriptor) }; - -class InterpreterPushArgsAndConstructDescriptor +class InterpreterPushArgsThenConstructDescriptor : public CallInterfaceDescriptor { public: DEFINE_PARAMETERS(kNumberOfArguments, kNewTarget, kConstructor, kFeedbackElement, kFirstArgument) DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE( - InterpreterPushArgsAndConstructDescriptor, CallInterfaceDescriptor) + InterpreterPushArgsThenConstructDescriptor, CallInterfaceDescriptor) }; -class InterpreterPushArgsAndConstructArrayDescriptor +class InterpreterPushArgsThenConstructArrayDescriptor : public CallInterfaceDescriptor { public: DEFINE_PARAMETERS(kNumberOfArguments, kFunction, kFeedbackElement, kFirstArgument) DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE( - InterpreterPushArgsAndConstructArrayDescriptor, CallInterfaceDescriptor) + InterpreterPushArgsThenConstructArrayDescriptor, CallInterfaceDescriptor) }; class InterpreterCEntryDescriptor : public CallInterfaceDescriptor { diff --git a/src/interpreter/bytecode-array-builder.cc b/src/interpreter/bytecode-array-builder.cc index 88f1d5ca65..5634e1a6fd 100644 --- a/src/interpreter/bytecode-array-builder.cc +++ b/src/interpreter/bytecode-array-builder.cc @@ -1242,42 +1242,50 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) { return *this; } -BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable, - RegisterList args, - int feedback_slot, - Call::CallType call_type, - TailCallMode tail_call_mode) { - if (tail_call_mode == TailCallMode::kDisallow) { - if (call_type == Call::NAMED_PROPERTY_CALL || - call_type == Call::KEYED_PROPERTY_CALL) { - if (args.register_count() == 1) { - OutputCallProperty0(callable, args[0], feedback_slot); - } else if (args.register_count() == 2) { - OutputCallProperty1(callable, args[0], args[1], feedback_slot); - } else if (args.register_count() == 3) { - OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot); - } else { - OutputCallProperty(callable, args, args.register_count(), - feedback_slot); - } - } else { - if (args.register_count() == 1) { - OutputCall0(callable, args[0], feedback_slot); - } else if (args.register_count() == 2) { - OutputCall1(callable, args[0], args[1], feedback_slot); - } else if (args.register_count() == 3) { - OutputCall2(callable, args[0], args[1], args[2], feedback_slot); - } else { - OutputCall(callable, args, args.register_count(), feedback_slot); - } - } +BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable, + RegisterList args, + int feedback_slot) { + if (args.register_count() == 1) { + OutputCallProperty0(callable, args[0], feedback_slot); + } else if (args.register_count() == 2) { + OutputCallProperty1(callable, args[0], args[1], feedback_slot); + } else if (args.register_count() == 3) { + OutputCallProperty2(callable, args[0], args[1], args[2], feedback_slot); } else { - DCHECK(tail_call_mode == TailCallMode::kAllow); - OutputTailCall(callable, args, args.register_count(), feedback_slot); + OutputCallProperty(callable, args, args.register_count(), feedback_slot); } return *this; } +BytecodeArrayBuilder& BytecodeArrayBuilder::CallUndefinedReceiver( + Register callable, RegisterList args, int feedback_slot) { + if (args.register_count() == 0) { + OutputCallUndefinedReceiver0(callable, feedback_slot); + } else if (args.register_count() == 1) { + OutputCallUndefinedReceiver1(callable, args[0], feedback_slot); + } else if (args.register_count() == 2) { + OutputCallUndefinedReceiver2(callable, args[0], args[1], feedback_slot); + } else { + OutputCallUndefinedReceiver(callable, args, args.register_count(), + feedback_slot); + } + return *this; +} + +BytecodeArrayBuilder& BytecodeArrayBuilder::CallAnyReceiver(Register callable, + RegisterList args, + int feedback_slot) { + OutputCallAnyReceiver(callable, args, args.register_count(), feedback_slot); + return *this; +} + +BytecodeArrayBuilder& BytecodeArrayBuilder::TailCall(Register callable, + RegisterList args, + int feedback_slot) { + OutputTailCall(callable, args, args.register_count(), feedback_slot); + return *this; +} + BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable, RegisterList args) { OutputCallWithSpread(callable, args, args.register_count()); diff --git a/src/interpreter/bytecode-array-builder.h b/src/interpreter/bytecode-array-builder.h index 82cb748ea0..bc6d5a39d4 100644 --- a/src/interpreter/bytecode-array-builder.h +++ b/src/interpreter/bytecode-array-builder.h @@ -238,14 +238,35 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final // Pop the current context and replace with |context|. BytecodeArrayBuilder& PopContext(Register context); - // Call a JS function. The JSFunction or Callable to be called should be in - // |callable|. The arguments should be in |args|, with the receiver in - // |args[0]|. The call type of the expression is in |call_type|. Type feedback - // is recorded in the |feedback_slot| in the type feedback vector. - BytecodeArrayBuilder& Call( - Register callable, RegisterList args, int feedback_slot, - Call::CallType call_type, - TailCallMode tail_call_mode = TailCallMode::kDisallow); + // Call a JS function which is known to be a property of a JS object. The + // JSFunction or Callable to be called should be in |callable|. The arguments + // should be in |args|, with the receiver in |args[0]|. The call type of the + // expression is in |call_type|. Type feedback is recorded in the + // |feedback_slot| in the type feedback vector. + BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args, + int feedback_slot); + + // Call a JS function with an known undefined receiver. The JSFunction or + // Callable to be called should be in |callable|. The arguments should be in + // |args|, with no receiver as it is implicitly set to undefined. Type + // feedback is recorded in the |feedback_slot| in the type feedback vector. + BytecodeArrayBuilder& CallUndefinedReceiver(Register callable, + RegisterList args, + int feedback_slot); + + // Call a JS function with an any receiver, possibly (but not necessarily) + // undefined. The JSFunction or Callable to be called should be in |callable|. + // The arguments should be in |args|, with the receiver in |args[0]|. Type + // feedback is recorded in the |feedback_slot| in the type feedback vector. + BytecodeArrayBuilder& CallAnyReceiver(Register callable, RegisterList args, + int feedback_slot); + + // Tail call into a JS function. The JSFunction or Callable to be called + // should be in |callable|. The arguments should be in |args|, with the + // receiver in |args[0]|. Type feedback is recorded in the |feedback_slot| in + // the type feedback vector. + BytecodeArrayBuilder& TailCall(Register callable, RegisterList args, + int feedback_slot); // Call a JS function. The JSFunction or Callable to be called should be in // |callable|, the receiver in |args[0]| and the arguments in |args[1]| diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc index 2c9d0c8729..87f2e1f0a6 100644 --- a/src/interpreter/bytecode-generator.cc +++ b/src/interpreter/bytecode-generator.cc @@ -2597,6 +2597,12 @@ void BytecodeGenerator::VisitCall(Call* expr) { Register callee = register_allocator()->NewRegister(); RegisterList args = register_allocator()->NewGrowableRegisterList(); + bool implicit_undefined_receiver = false; + bool is_tail_call = (expr->tail_call_mode() == TailCallMode::kAllow); + // When a call contains a spread, a Call AST node is only created if there is + // exactly one spread, and it is the last argument. + bool is_spread_call = expr->only_last_arg_is_spread(); + // TODO(petermarshall): We have a lot of call bytecodes that are very similar, // see if we can reduce the number by adding a separate argument which // specifies the call type (e.g., property, spread, tailcall, etc.). @@ -2613,7 +2619,13 @@ void BytecodeGenerator::VisitCall(Call* expr) { } case Call::GLOBAL_CALL: { // Receiver is undefined for global calls. - BuildPushUndefinedIntoRegisterList(&args); + if (!is_tail_call && !is_spread_call) { + implicit_undefined_receiver = true; + } else { + // TODO(leszeks): There's no special bytecode for tail calls or spread + // calls with an undefined receiver, so just push undefined ourselves. + BuildPushUndefinedIntoRegisterList(&args); + } // Load callee as a global variable. VariableProxy* proxy = callee_expr->AsVariableProxy(); BuildVariableLoadForAccumulatorValue(proxy->var(), @@ -2633,6 +2645,7 @@ void BytecodeGenerator::VisitCall(Call* expr) { DCHECK(Register::AreContiguous(callee, receiver)); RegisterList result_pair(callee.index(), 2); USE(receiver); + Variable* variable = callee_expr->AsVariableProxy()->var(); builder() ->LoadLiteral(variable->raw_name()) @@ -2643,7 +2656,14 @@ void BytecodeGenerator::VisitCall(Call* expr) { break; } case Call::OTHER_CALL: { - BuildPushUndefinedIntoRegisterList(&args); + // Receiver is undefined for other calls. + if (!is_tail_call && !is_spread_call) { + implicit_undefined_receiver = true; + } else { + // TODO(leszeks): There's no special bytecode for tail calls or spread + // calls with an undefined receiver, so just push undefined ourselves. + BuildPushUndefinedIntoRegisterList(&args); + } VisitForRegisterValue(callee_expr, callee); break; } @@ -2669,7 +2689,9 @@ void BytecodeGenerator::VisitCall(Call* expr) { // Evaluate all arguments to the function call and store in sequential args // registers. VisitArguments(expr->arguments(), &args); - CHECK_EQ(expr->arguments()->length() + 1, args.register_count()); + int reciever_arg_count = implicit_undefined_receiver ? 0 : 1; + CHECK_EQ(reciever_arg_count + expr->arguments()->length(), + args.register_count()); // Resolve callee for a potential direct eval call. This block will mutate the // callee value. @@ -2678,10 +2700,11 @@ void BytecodeGenerator::VisitCall(Call* expr) { // Set up arguments for ResolvePossiblyDirectEval by copying callee, source // strings and function closure, and loading language and // position. + Register first_arg = args[reciever_arg_count]; RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); builder() ->MoveRegister(callee, runtime_call_args[0]) - .MoveRegister(args[1], runtime_call_args[1]) + .MoveRegister(first_arg, runtime_call_args[1]) .MoveRegister(Register::function_closure(), runtime_call_args[2]) .LoadLiteral(Smi::FromInt(language_mode())) .StoreAccumulatorInRegister(runtime_call_args[3]) @@ -2698,15 +2721,23 @@ void BytecodeGenerator::VisitCall(Call* expr) { builder()->SetExpressionPosition(expr); - // When a call contains a spread, a Call AST node is only created if there is - // exactly one spread, and it is the last argument. - if (expr->only_last_arg_is_spread()) { - DCHECK_EQ(TailCallMode::kDisallow, expr->tail_call_mode()); + int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); + + if (is_spread_call) { + DCHECK(!is_tail_call); + DCHECK(!implicit_undefined_receiver); builder()->CallWithSpread(callee, args); + } else if (is_tail_call) { + DCHECK(!implicit_undefined_receiver); + builder()->TailCall(callee, args, feedback_slot_index); + } else if (call_type == Call::NAMED_PROPERTY_CALL || + call_type == Call::KEYED_PROPERTY_CALL) { + DCHECK(!implicit_undefined_receiver); + builder()->CallProperty(callee, args, feedback_slot_index); + } else if (implicit_undefined_receiver) { + builder()->CallUndefinedReceiver(callee, args, feedback_slot_index); } else { - int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); - builder()->Call(callee, args, feedback_slot_index, call_type, - expr->tail_call_mode()); + builder()->CallAnyReceiver(callee, args, feedback_slot_index); } } @@ -2768,6 +2799,8 @@ void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) { if (expr->is_jsruntime()) { RegisterList args = register_allocator()->NewGrowableRegisterList(); // Allocate a register for the receiver and load it with undefined. + // TODO(leszeks): If CallJSRuntime always has an undefined receiver, use the + // same mechanism as CallUndefinedReceiver. BuildPushUndefinedIntoRegisterList(&args); VisitArguments(expr->arguments(), &args); builder()->CallJSRuntime(expr->context_index(), args); @@ -3161,9 +3194,8 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { builder()->JumpIfNull(&async_iterator_null); // Let iterator be Call(method, obj) - builder()->StoreAccumulatorInRegister(method).Call( - method, args, feedback_index(async_call_slot), - Call::NAMED_PROPERTY_CALL); + builder()->StoreAccumulatorInRegister(method).CallProperty( + method, args, feedback_index(async_call_slot)); // If Type(iterator) is not Object, throw a TypeError exception. builder()->JumpIfJSReceiver(&done); @@ -3178,8 +3210,7 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { .StoreAccumulatorInRegister(method); // Let syncIterator be Call(syncMethod, obj) - builder()->Call(method, args, feedback_index(call_slot), - Call::NAMED_PROPERTY_CALL); + builder()->CallProperty(method, args, feedback_index(call_slot)); // Return CreateAsyncFromSyncIterator(syncIterator) // alias `method` register as it's no longer used @@ -3196,8 +3227,7 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) { .StoreAccumulatorInRegister(method); // Let iterator be Call(method, obj). - builder()->Call(method, args, feedback_index(call_slot), - Call::NAMED_PROPERTY_CALL); + builder()->CallProperty(method, args, feedback_index(call_slot)); // If Type(iterator) is not Object, throw a TypeError exception. BytecodeLabel no_type_error; diff --git a/src/interpreter/bytecodes.cc b/src/interpreter/bytecodes.cc index f7fb7edde1..d0665b9ea9 100644 --- a/src/interpreter/bytecodes.cc +++ b/src/interpreter/bytecodes.cc @@ -238,8 +238,15 @@ bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) { case Bytecode::kInc: case Bytecode::kDec: case Bytecode::kTypeOf: - case Bytecode::kCall: + case Bytecode::kCallAnyReceiver: case Bytecode::kCallProperty: + case Bytecode::kCallProperty0: + case Bytecode::kCallProperty1: + case Bytecode::kCallProperty2: + case Bytecode::kCallUndefinedReceiver: + case Bytecode::kCallUndefinedReceiver0: + case Bytecode::kCallUndefinedReceiver1: + case Bytecode::kCallUndefinedReceiver2: case Bytecode::kConstruct: case Bytecode::kConstructWithSpread: return true; diff --git a/src/interpreter/bytecodes.h b/src/interpreter/bytecodes.h index 530e8a748d..baf9e88963 100644 --- a/src/interpreter/bytecodes.h +++ b/src/interpreter/bytecodes.h @@ -158,14 +158,8 @@ namespace interpreter { V(GetSuperConstructor, AccumulatorUse::kRead, OperandType::kRegOut) \ \ /* Call operations */ \ - V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kRegList, \ - OperandType::kRegCount, OperandType::kIdx) \ - V(Call0, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg, \ - OperandType::kIdx) \ - V(Call1, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg, \ - OperandType::kReg, OperandType::kIdx) \ - V(Call2, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kReg, \ - OperandType::kReg, OperandType::kReg, OperandType::kIdx) \ + V(CallAnyReceiver, AccumulatorUse::kWrite, OperandType::kReg, \ + OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \ V(CallProperty, AccumulatorUse::kWrite, OperandType::kReg, \ OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \ V(CallProperty0, AccumulatorUse::kWrite, OperandType::kReg, \ @@ -175,6 +169,14 @@ namespace interpreter { V(CallProperty2, AccumulatorUse::kWrite, OperandType::kReg, \ OperandType::kReg, OperandType::kReg, OperandType::kReg, \ OperandType::kIdx) \ + V(CallUndefinedReceiver, AccumulatorUse::kWrite, OperandType::kReg, \ + OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \ + V(CallUndefinedReceiver0, AccumulatorUse::kWrite, OperandType::kReg, \ + OperandType::kIdx) \ + V(CallUndefinedReceiver1, AccumulatorUse::kWrite, OperandType::kReg, \ + OperandType::kReg, OperandType::kIdx) \ + V(CallUndefinedReceiver2, AccumulatorUse::kWrite, OperandType::kReg, \ + OperandType::kReg, OperandType::kReg, OperandType::kIdx) \ V(CallWithSpread, AccumulatorUse::kWrite, OperandType::kReg, \ OperandType::kRegList, OperandType::kRegCount) \ V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, \ @@ -432,7 +434,7 @@ enum class Bytecode : uint8_t { class V8_EXPORT_PRIVATE Bytecodes final { public: - // The maximum number of operands a bytecode may have. + // The maximum number of operands a bytecode may have. static const int kMaxOperands = 5; // Returns string representation of |bytecode|. @@ -625,13 +627,15 @@ class V8_EXPORT_PRIVATE Bytecodes final { // Returns true if the bytecode is a call or a constructor call. static constexpr bool IsCallOrConstruct(Bytecode bytecode) { - return bytecode == Bytecode::kCall || bytecode == Bytecode::kCallProperty || - bytecode == Bytecode::kCall0 || + return bytecode == Bytecode::kCallAnyReceiver || + bytecode == Bytecode::kCallProperty || bytecode == Bytecode::kCallProperty0 || - bytecode == Bytecode::kCall1 || bytecode == Bytecode::kCallProperty1 || - bytecode == Bytecode::kCall2 || bytecode == Bytecode::kCallProperty2 || + bytecode == Bytecode::kCallUndefinedReceiver || + bytecode == Bytecode::kCallUndefinedReceiver0 || + bytecode == Bytecode::kCallUndefinedReceiver1 || + bytecode == Bytecode::kCallUndefinedReceiver2 || bytecode == Bytecode::kTailCall || bytecode == Bytecode::kConstruct || bytecode == Bytecode::kCallWithSpread || @@ -746,6 +750,34 @@ class V8_EXPORT_PRIVATE Bytecodes final { // through the bytecode's handler. static bool MakesCallAlongCriticalPath(Bytecode bytecode); + // Returns the receiver mode of the given call bytecode. + static ConvertReceiverMode GetReceiverMode(Bytecode bytecode) { + DCHECK(IsCallOrConstruct(bytecode)); + switch (bytecode) { + case Bytecode::kCallProperty: + case Bytecode::kCallProperty0: + case Bytecode::kCallProperty1: + case Bytecode::kCallProperty2: + return ConvertReceiverMode::kNotNullOrUndefined; + case Bytecode::kCallUndefinedReceiver: + case Bytecode::kCallUndefinedReceiver0: + case Bytecode::kCallUndefinedReceiver1: + case Bytecode::kCallUndefinedReceiver2: + return ConvertReceiverMode::kNullOrUndefined; + case Bytecode::kCallAnyReceiver: + case Bytecode::kTailCall: + case Bytecode::kConstruct: + case Bytecode::kCallWithSpread: + case Bytecode::kConstructWithSpread: + case Bytecode::kInvokeIntrinsic: + case Bytecode::kCallJSRuntime: + return ConvertReceiverMode::kAny; + default: + UNREACHABLE(); + return ConvertReceiverMode::kAny; + } + } + // Returns true if the bytecode is a debug break. static bool IsDebugBreak(Bytecode bytecode); diff --git a/src/interpreter/interpreter-assembler.cc b/src/interpreter/interpreter-assembler.cc index 9fdfa615b1..e76a9ed407 100644 --- a/src/interpreter/interpreter-assembler.cc +++ b/src/interpreter/interpreter-assembler.cc @@ -555,11 +555,11 @@ Node* InterpreterAssembler::IncrementCallCount(Node* feedback_vector, SKIP_WRITE_BARRIER); } -Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, - Node* first_arg, Node* arg_count, - Node* slot_id, - Node* feedback_vector, - TailCallMode tail_call_mode) { +Node* InterpreterAssembler::CallJSWithFeedback( + compiler::Node* function, compiler::Node* context, + compiler::Node* first_arg, compiler::Node* arg_count, + compiler::Node* slot_id, compiler::Node* feedback_vector, + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode) { // Static checks to assert it is safe to examine the type feedback element. // We don't know that we have a weak cell. We might have a private symbol // or an AllocationSite, but the memory is safe to examine. @@ -572,6 +572,8 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, // to be a pointer. DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::IsCallOrConstruct(bytecode_)); + DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), receiver_mode); + STATIC_ASSERT(WeakCell::kSize >= kPointerSize); STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == WeakCell::kValueOffset && @@ -598,8 +600,9 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, IncrementCallCount(feedback_vector, slot_id); // Call using call function builtin. - Callable callable = CodeFactory::InterpreterPushArgsAndCall( - isolate(), tail_call_mode, InterpreterPushArgsMode::kJSFunction); + Callable callable = CodeFactory::InterpreterPushArgsThenCall( + isolate(), receiver_mode, tail_call_mode, + InterpreterPushArgsMode::kJSFunction); Node* code_target = HeapConstant(callable.code()); Node* ret_value = CallStub(callable.descriptor(), code_target, context, arg_count, first_arg, function); @@ -623,24 +626,33 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, GotoIfNot(IsAllocationSiteMap(LoadMap(feedback_element)), &check_initialized); - // If it is not the Array() function, mark megamorphic. - Node* context_slot = LoadContextElement(LoadNativeContext(context), - Context::ARRAY_FUNCTION_INDEX); - Node* is_array_function = WordEqual(context_slot, function); - GotoIfNot(is_array_function, &mark_megamorphic); + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + // For undefined receivers (mostly global calls), do an additional check + // for the monomorphic Array function, which would otherwise appear + // megamorphic. - // It is a monomorphic Array function. Increment the call count. - IncrementCallCount(feedback_vector, slot_id); + // If it is not the Array() function, mark megamorphic. + Node* context_slot = LoadContextElement(LoadNativeContext(context), + Context::ARRAY_FUNCTION_INDEX); + Node* is_array_function = WordEqual(context_slot, function); + GotoIfNot(is_array_function, &mark_megamorphic); - // Call ArrayConstructorStub. - Callable callable_call = - CodeFactory::InterpreterPushArgsAndConstructArray(isolate()); - Node* code_target_call = HeapConstant(callable_call.code()); - Node* ret_value = - CallStub(callable_call.descriptor(), code_target_call, context, - arg_count, function, feedback_element, first_arg); - return_value.Bind(ret_value); - Goto(&end); + // It is a monomorphic Array function. Increment the call count. + IncrementCallCount(feedback_vector, slot_id); + + // Call ArrayConstructorStub. + Callable callable_call = + CodeFactory::InterpreterPushArgsThenConstructArray(isolate()); + Node* code_target_call = HeapConstant(callable_call.code()); + Node* ret_value = + CallStub(callable_call.descriptor(), code_target_call, context, + arg_count, function, feedback_element, first_arg); + return_value.Bind(ret_value); + Goto(&end); + + } else { + Goto(&mark_megamorphic); + } Bind(&check_initialized); { @@ -651,7 +663,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, HeapConstant(FeedbackVector::UninitializedSentinel(isolate()))); GotoIfNot(is_uninitialized, &mark_megamorphic); - Comment("handle_unitinitialized"); + Comment("handle_uninitialized"); // If it is not a JSFunction mark it as megamorphic. Node* is_smi = TaggedIsSmi(function); GotoIf(is_smi, &mark_megamorphic); @@ -713,8 +725,9 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, IncrementCallCount(feedback_vector, slot_id); // Call using call builtin. - Callable callable_call = CodeFactory::InterpreterPushArgsAndCall( - isolate(), tail_call_mode, InterpreterPushArgsMode::kOther); + Callable callable_call = CodeFactory::InterpreterPushArgsThenCall( + isolate(), receiver_mode, tail_call_mode, + InterpreterPushArgsMode::kOther); Node* code_target_call = HeapConstant(callable_call.code()); Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, context, arg_count, first_arg, function); @@ -728,11 +741,14 @@ Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context, Node* InterpreterAssembler::CallJS(Node* function, Node* context, Node* first_arg, Node* arg_count, + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode) { DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::IsCallOrConstruct(bytecode_)); - Callable callable = CodeFactory::InterpreterPushArgsAndCall( - isolate(), tail_call_mode, InterpreterPushArgsMode::kOther); + DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), receiver_mode); + Callable callable = CodeFactory::InterpreterPushArgsThenCall( + isolate(), receiver_mode, tail_call_mode, + InterpreterPushArgsMode::kOther); Node* code_target = HeapConstant(callable.code()); return CallStub(callable.descriptor(), code_target, context, arg_count, @@ -742,8 +758,9 @@ Node* InterpreterAssembler::CallJS(Node* function, Node* context, Node* InterpreterAssembler::CallJSWithSpread(Node* function, Node* context, Node* first_arg, Node* arg_count) { DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); - Callable callable = CodeFactory::InterpreterPushArgsAndCall( - isolate(), TailCallMode::kDisallow, + DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), ConvertReceiverMode::kAny); + Callable callable = CodeFactory::InterpreterPushArgsThenCall( + isolate(), ConvertReceiverMode::kAny, TailCallMode::kDisallow, InterpreterPushArgsMode::kWithFinalSpread); Node* code_target = HeapConstant(callable.code()); @@ -787,7 +804,7 @@ Node* InterpreterAssembler::Construct(Node* constructor, Node* context, { Comment("call using ConstructFunction"); IncrementCallCount(feedback_vector, slot_id); - Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct( + Callable callable_function = CodeFactory::InterpreterPushArgsThenConstruct( isolate(), InterpreterPushArgsMode::kJSFunction); return_value.Bind(CallStub(callable_function.descriptor(), HeapConstant(callable_function.code()), context, @@ -890,7 +907,7 @@ Node* InterpreterAssembler::Construct(Node* constructor, Node* context, Bind(&call_construct); { Comment("call using Construct builtin"); - Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( + Callable callable = CodeFactory::InterpreterPushArgsThenConstruct( isolate(), InterpreterPushArgsMode::kOther); Node* code_target = HeapConstant(callable.code()); return_value.Bind(CallStub(callable.descriptor(), code_target, context, @@ -910,7 +927,7 @@ Node* InterpreterAssembler::ConstructWithSpread(Node* constructor, DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); Variable return_value(this, MachineRepresentation::kTagged); Comment("call using ConstructWithSpread"); - Callable callable = CodeFactory::InterpreterPushArgsAndConstruct( + Callable callable = CodeFactory::InterpreterPushArgsThenConstruct( isolate(), InterpreterPushArgsMode::kWithFinalSpread); Node* code_target = HeapConstant(callable.code()); return_value.Bind(CallStub(callable.descriptor(), code_target, context, diff --git a/src/interpreter/interpreter-assembler.h b/src/interpreter/interpreter-assembler.h index 498f50aae5..f534ea3ba7 100644 --- a/src/interpreter/interpreter-assembler.h +++ b/src/interpreter/interpreter-assembler.h @@ -118,23 +118,25 @@ class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler { compiler::Node* IncrementCallCount(compiler::Node* feedback_vector, compiler::Node* slot_id); - // Call JSFunction or Callable |function| with |arg_count| - // arguments (not including receiver) and the first argument - // located at |first_arg|. Type feedback is collected in the - // slot at index |slot_id|. - compiler::Node* CallJSWithFeedback(compiler::Node* function, - compiler::Node* context, - compiler::Node* first_arg, - compiler::Node* arg_count, - compiler::Node* slot_id, - compiler::Node* feedback_vector, - TailCallMode tail_call_mode); + // Call JSFunction or Callable |function| with |arg_count| arguments (not + // including receiver) and the first argument located at |first_arg|. Type + // feedback is collected in the slot at index |slot_id|. + // + // If the |receiver_mode| is kNullOrUndefined, then the receiver is implicitly + // undefined and |first_arg| is the first parameter. Otherwise, |first_arg| is + // the receiver and it is converted according to |receiver_mode|. + compiler::Node* CallJSWithFeedback( + compiler::Node* function, compiler::Node* context, + compiler::Node* first_arg, compiler::Node* arg_count, + compiler::Node* slot_id, compiler::Node* feedback_vector, + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode); - // Call JSFunction or Callable |function| with |arg_count| - // arguments (not including receiver) and the first argument - // located at |first_arg|. + // Call JSFunction or Callable |function| with |arg_count| arguments (not + // including receiver) and the first argument located at |first_arg|, possibly + // including the receiver depending on |receiver_mode|. compiler::Node* CallJS(compiler::Node* function, compiler::Node* context, compiler::Node* first_arg, compiler::Node* arg_count, + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode); // Call JSFunction or Callable |function| with |arg_count| diff --git a/src/interpreter/interpreter-generator.cc b/src/interpreter/interpreter-generator.cc index 9b78a19087..5edcb384b8 100644 --- a/src/interpreter/interpreter-generator.cc +++ b/src/interpreter/interpreter-generator.cc @@ -73,11 +73,13 @@ class InterpreterGenerator { void DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler); // Generates code to perform a JS call that collects type feedback. - void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode); + void DoJSCall(InterpreterAssembler* assembler, + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode); // Generates code to perform a JS call with a known number of arguments that // collects type feedback. - void DoJSCallN(InterpreterAssembler* assembler, int n); + void DoJSCallN(InterpreterAssembler* assembler, int n, + ConvertReceiverMode receiver_mode); // Generates code to perform delete via function_id. void DoDelete(Runtime::FunctionId function_id, @@ -2322,50 +2324,78 @@ void InterpreterGenerator::DoGetSuperConstructor( } void InterpreterGenerator::DoJSCall(InterpreterAssembler* assembler, + ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode) { Node* function_reg = __ BytecodeOperandReg(0); Node* function = __ LoadRegister(function_reg); - Node* receiver_reg = __ BytecodeOperandReg(1); - Node* receiver_arg = __ RegisterLocation(receiver_reg); - Node* receiver_args_count = __ BytecodeOperandCount(2); - Node* receiver_count = __ Int32Constant(1); - Node* args_count = __ Int32Sub(receiver_args_count, receiver_count); + Node* first_arg_reg = __ BytecodeOperandReg(1); + Node* first_arg = __ RegisterLocation(first_arg_reg); + Node* arg_list_count = __ BytecodeOperandCount(2); + Node* args_count; + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + // The receiver is implied, so it is not in the argument list. + args_count = arg_list_count; + } else { + // Subtract the receiver from the argument count. + Node* receiver_count = __ Int32Constant(1); + args_count = __ Int32Sub(arg_list_count, receiver_count); + } Node* slot_id = __ BytecodeOperandIdx(3); Node* feedback_vector = __ LoadFeedbackVector(); Node* context = __ GetContext(); Node* result = - __ CallJSWithFeedback(function, context, receiver_arg, args_count, - slot_id, feedback_vector, tail_call_mode); + __ CallJSWithFeedback(function, context, first_arg, args_count, slot_id, + feedback_vector, receiver_mode, tail_call_mode); __ SetAccumulator(result); __ Dispatch(); } void InterpreterGenerator::DoJSCallN(InterpreterAssembler* assembler, - int arg_count) { - const int kReceiverOperandIndex = 1; - const int kReceiverOperandCount = 1; + int arg_count, + ConvertReceiverMode receiver_mode) { + // Indices and counts of operands on the bytecode. + const int kFirstArgumentOperandIndex = 1; + const int kReceiverOperandCount = + (receiver_mode == ConvertReceiverMode::kNullOrUndefined) ? 0 : 1; const int kSlotOperandIndex = - kReceiverOperandIndex + kReceiverOperandCount + arg_count; - const int kBoilerplatParameterCount = 7; + kFirstArgumentOperandIndex + kReceiverOperandCount + arg_count; + // Indices and counts of parameters to the call stub. + const int kBoilerplateParameterCount = 7; const int kReceiverParameterIndex = 5; + const int kReceiverParameterCount = 1; + // Only used in a DCHECK. + USE(kReceiverParameterCount); Node* function_reg = __ BytecodeOperandReg(0); Node* function = __ LoadRegister(function_reg); - std::array temp; + std::array temp; Callable call_ic = CodeFactory::CallIC(isolate_); temp[0] = __ HeapConstant(call_ic.code()); temp[1] = function; temp[2] = __ Int32Constant(arg_count); temp[3] = __ BytecodeOperandIdxInt32(kSlotOperandIndex); temp[4] = __ LoadFeedbackVector(); - for (int i = 0; i < (arg_count + kReceiverOperandCount); ++i) { - Node* reg = __ BytecodeOperandReg(i + kReceiverOperandIndex); - temp[kReceiverParameterIndex + i] = __ LoadRegister(reg); + + int parameter_index = kReceiverParameterIndex; + if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { + // The first argument parameter (the receiver) is implied to be undefined. + Node* undefined_value = + __ HeapConstant(isolate_->factory()->undefined_value()); + temp[parameter_index++] = undefined_value; } - temp[kReceiverParameterIndex + arg_count + kReceiverOperandCount] = - __ GetContext(); + // The bytecode argument operands are copied into the remaining argument + // parameters. + for (int i = 0; i < (kReceiverOperandCount + arg_count); ++i) { + Node* reg = __ BytecodeOperandReg(kFirstArgumentOperandIndex + i); + temp[parameter_index++] = __ LoadRegister(reg); + } + + DCHECK_EQ(parameter_index, + kReceiverParameterIndex + kReceiverParameterCount + arg_count); + temp[parameter_index] = __ GetContext(); + Node* result = __ CallStubN(call_ic.descriptor(), 1, - arg_count + kBoilerplatParameterCount, &temp[0]); + arg_count + kBoilerplateParameterCount, &temp[0]); __ SetAccumulator(result); __ Dispatch(); } @@ -2375,40 +2405,46 @@ void InterpreterGenerator::DoJSCallN(InterpreterAssembler* assembler, // Call a JSfunction or Callable in |callable| with the |receiver| and // |arg_count| arguments in subsequent registers. Collect type feedback // into |feedback_slot_id| -void InterpreterGenerator::DoCall(InterpreterAssembler* assembler) { - DoJSCall(assembler, TailCallMode::kDisallow); -} - -void InterpreterGenerator::DoCall0(InterpreterAssembler* assembler) { - DoJSCallN(assembler, 0); -} - -void InterpreterGenerator::DoCall1(InterpreterAssembler* assembler) { - DoJSCallN(assembler, 1); -} - -void InterpreterGenerator::DoCall2(InterpreterAssembler* assembler) { - DoJSCallN(assembler, 2); +void InterpreterGenerator::DoCallAnyReceiver(InterpreterAssembler* assembler) { + DoJSCall(assembler, ConvertReceiverMode::kAny, TailCallMode::kDisallow); } void InterpreterGenerator::DoCallProperty(InterpreterAssembler* assembler) { - // Same as Call - UNREACHABLE(); + DoJSCall(assembler, ConvertReceiverMode::kNotNullOrUndefined, + TailCallMode::kDisallow); } void InterpreterGenerator::DoCallProperty0(InterpreterAssembler* assembler) { - // Same as Call0 - UNREACHABLE(); + DoJSCallN(assembler, 0, ConvertReceiverMode::kNotNullOrUndefined); } void InterpreterGenerator::DoCallProperty1(InterpreterAssembler* assembler) { - // Same as Call1 - UNREACHABLE(); + DoJSCallN(assembler, 1, ConvertReceiverMode::kNotNullOrUndefined); } void InterpreterGenerator::DoCallProperty2(InterpreterAssembler* assembler) { - // Same as Call2 - UNREACHABLE(); + DoJSCallN(assembler, 2, ConvertReceiverMode::kNotNullOrUndefined); +} + +void InterpreterGenerator::DoCallUndefinedReceiver( + InterpreterAssembler* assembler) { + DoJSCall(assembler, ConvertReceiverMode::kNullOrUndefined, + TailCallMode::kDisallow); +} + +void InterpreterGenerator::DoCallUndefinedReceiver0( + InterpreterAssembler* assembler) { + DoJSCallN(assembler, 0, ConvertReceiverMode::kNullOrUndefined); +} + +void InterpreterGenerator::DoCallUndefinedReceiver1( + InterpreterAssembler* assembler) { + DoJSCallN(assembler, 1, ConvertReceiverMode::kNullOrUndefined); +} + +void InterpreterGenerator::DoCallUndefinedReceiver2( + InterpreterAssembler* assembler) { + DoJSCallN(assembler, 2, ConvertReceiverMode::kNullOrUndefined); } // TailCall @@ -2417,7 +2453,7 @@ void InterpreterGenerator::DoCallProperty2(InterpreterAssembler* assembler) { // |arg_count| arguments in subsequent registers. Collect type feedback // into |feedback_slot_id| void InterpreterGenerator::DoTailCall(InterpreterAssembler* assembler) { - DoJSCall(assembler, TailCallMode::kAllow); + DoJSCall(assembler, ConvertReceiverMode::kAny, TailCallMode::kAllow); } // CallRuntime @@ -2497,7 +2533,7 @@ void InterpreterGenerator::DoCallJSRuntime(InterpreterAssembler* assembler) { // Call the function. Node* result = __ CallJS(function, context, first_arg, args_count, - TailCallMode::kDisallow); + ConvertReceiverMode::kAny, TailCallMode::kDisallow); __ SetAccumulator(result); __ Dispatch(); } diff --git a/src/interpreter/interpreter-intrinsics-generator.cc b/src/interpreter/interpreter-intrinsics-generator.cc index 923dec97a8..bdd079ab84 100644 --- a/src/interpreter/interpreter-intrinsics-generator.cc +++ b/src/interpreter/interpreter-intrinsics-generator.cc @@ -309,7 +309,7 @@ Node* IntrinsicsGenerator::Call(Node* args_reg, Node* arg_count, } Node* result = __ CallJS(function, context, receiver_arg, target_args_count, - TailCallMode::kDisallow); + ConvertReceiverMode::kAny, TailCallMode::kDisallow); return result; } diff --git a/src/interpreter/setup-interpreter-internal.cc b/src/interpreter/setup-interpreter-internal.cc index 1477ee8c7b..0fb03f8d55 100644 --- a/src/interpreter/setup-interpreter-internal.cc +++ b/src/interpreter/setup-interpreter-internal.cc @@ -52,28 +52,8 @@ void SetupInterpreter::InstallBytecodeHandlers(Interpreter* interpreter) { bool SetupInterpreter::ReuseExistingHandler(Address* dispatch_table, Bytecode bytecode, OperandScale operand_scale) { - size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale); - switch (bytecode) { - case Bytecode::kCallProperty: - case Bytecode::kCallProperty0: - case Bytecode::kCallProperty1: - case Bytecode::kCallProperty2: { - const int offset = static_cast(Bytecode::kCallProperty) - - static_cast(Bytecode::kCall); - STATIC_ASSERT(offset == static_cast(Bytecode::kCallProperty0) - - static_cast(Bytecode::kCall0)); - STATIC_ASSERT(offset == static_cast(Bytecode::kCallProperty1) - - static_cast(Bytecode::kCall1)); - STATIC_ASSERT(offset == static_cast(Bytecode::kCallProperty2) - - static_cast(Bytecode::kCall2)); - CHECK_LT(offset, index); - dispatch_table[index] = dispatch_table[index - offset]; - return true; - break; - } - default: - return false; - } + // TODO(leszeks): reuse Lda[Immutable][Current]ContextSlot + return false; } // static diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc index 0c6a42cb48..6e77ee835a 100644 --- a/src/mips/interface-descriptors-mips.cc +++ b/src/mips/interface-descriptors-mips.cc @@ -314,7 +314,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { a0, // argument count (not including receiver) @@ -324,7 +324,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { a0, // argument count (not including receiver) @@ -336,8 +336,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { a0, // argument count (not including receiver) a1, // the target to call verified to be Array function diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc index 1630851f52..8deb518c3b 100644 --- a/src/mips64/interface-descriptors-mips64.cc +++ b/src/mips64/interface-descriptors-mips64.cc @@ -313,7 +313,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { a0, // argument count (not including receiver) @@ -323,7 +323,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { a0, // argument count (not including receiver) @@ -335,8 +335,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { a0, // argument count (not including receiver) a1, // the target to call verified to be Array function diff --git a/src/ppc/interface-descriptors-ppc.cc b/src/ppc/interface-descriptors-ppc.cc index 73280be373..734ed4af36 100644 --- a/src/ppc/interface-descriptors-ppc.cc +++ b/src/ppc/interface-descriptors-ppc.cc @@ -315,7 +315,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { r3, // argument count (not including receiver) @@ -325,7 +325,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { r3, // argument count (not including receiver) @@ -337,8 +337,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { r3, // argument count (not including receiver) r4, // target to call checked to be Array function diff --git a/src/s390/interface-descriptors-s390.cc b/src/s390/interface-descriptors-s390.cc index 5606f2388b..091a64583a 100644 --- a/src/s390/interface-descriptors-s390.cc +++ b/src/s390/interface-descriptors-s390.cc @@ -299,7 +299,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { r2, // argument count (not including receiver) @@ -309,7 +309,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { r2, // argument count (not including receiver) @@ -321,8 +321,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { r2, // argument count (not including receiver) r3, // target to call checked to be Array function diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc index f47d221df6..dd03f19cbc 100644 --- a/src/x64/interface-descriptors-x64.cc +++ b/src/x64/interface-descriptors-x64.cc @@ -316,7 +316,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { rax, // argument count (not including receiver) @@ -326,7 +326,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { rax, // argument count (not including receiver) @@ -338,8 +338,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { rax, // argument count (not including receiver) rdx, // target to the call. It is checked to be Array function. diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc index 12a90266dd..4601e98785 100644 --- a/src/x87/interface-descriptors-x87.cc +++ b/src/x87/interface-descriptors-x87.cc @@ -330,7 +330,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { eax, // argument count (not including receiver) @@ -340,7 +340,7 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( +void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( CallInterfaceDescriptorData* data) { Register registers[] = { eax, // argument count (not including receiver) @@ -352,8 +352,8 @@ void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific( data->InitializePlatformSpecific(arraysize(registers), registers); } -void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific( - CallInterfaceDescriptorData* data) { +void InterpreterPushArgsThenConstructArrayDescriptor:: + InitializePlatformSpecific(CallInterfaceDescriptorData* data) { Register registers[] = { eax, // argument count (not including receiver) edx, // target to the call. It is checked to be Array function. diff --git a/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden b/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden index 6555c650c3..c9c96e7a1f 100644 --- a/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden +++ b/test/cctest/interpreter/bytecode_expectations/CallGlobal.golden @@ -12,16 +12,14 @@ snippet: " function f() { return t(); } f(); " -frame size: 2 +frame size: 1 parameter count: 1 -bytecode array length: 14 +bytecode array length: 10 bytecodes: [ /* 27 E> */ B(StackCheck), - /* 32 S> */ B(LdaUndefined), - B(Star), R(1), - B(LdaGlobal), U8(0), U8(4), + /* 32 S> */ B(LdaGlobal), U8(0), U8(4), B(Star), R(0), - /* 39 E> */ B(Call0), R(0), R(1), U8(2), + /* 39 E> */ B(CallUndefinedReceiver0), R(0), U8(2), /* 44 S> */ B(Return), ] constant pool: [ @@ -36,22 +34,20 @@ snippet: " function f() { return t(1, 2, 3); } f(); " -frame size: 5 +frame size: 4 parameter count: 1 -bytecode array length: 27 +bytecode array length: 24 bytecodes: [ /* 34 E> */ B(StackCheck), - /* 39 S> */ B(LdaUndefined), - B(Star), R(1), - B(LdaGlobal), U8(0), U8(4), + /* 39 S> */ B(LdaGlobal), U8(0), U8(4), B(Star), R(0), B(LdaSmi), I8(1), - B(Star), R(2), + B(Star), R(1), B(LdaSmi), I8(2), - B(Star), R(3), + B(Star), R(2), B(LdaSmi), I8(3), - B(Star), R(4), - /* 46 E> */ B(Call), R(0), R(1), U8(4), U8(2), + B(Star), R(3), + /* 46 E> */ B(CallUndefinedReceiver), R(0), R(1), U8(3), U8(2), /* 58 S> */ B(Return), ] constant pool: [ diff --git a/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden b/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden index 7625179120..33681df144 100644 --- a/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden +++ b/test/cctest/interpreter/bytecode_expectations/CallLookupSlot.golden @@ -9,9 +9,9 @@ wrap: yes snippet: " g = function(){}; eval(''); return g(); " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 81 +bytecode array length: 73 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -24,29 +24,25 @@ bytecodes: [ /* 30 E> */ B(StackCheck), /* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 36 E> */ B(StaLookupSlotSloppy), U8(1), - /* 52 S> */ B(LdaUndefined), - B(Star), R(2), - /* 52 E> */ B(LdaLookupGlobalSlot), U8(2), U8(5), U8(1), + /* 52 S> */ B(LdaLookupGlobalSlot), U8(2), U8(5), U8(1), B(Star), R(1), B(LdaConstant), U8(3), - B(Star), R(3), - B(LdaZero), - B(Star), R(7), - B(LdaSmi), I8(30), - B(Star), R(8), - B(LdaSmi), I8(52), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), - B(Star), R(1), - /* 52 E> */ B(Call1), R(1), R(2), R(3), U8(3), - /* 62 S> */ B(LdaUndefined), B(Star), R(2), - /* 69 E> */ B(LdaLookupGlobalSlot), U8(1), U8(9), U8(1), + B(LdaZero), + B(Star), R(6), + B(LdaSmi), I8(30), + B(Star), R(7), + B(LdaSmi), I8(52), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 69 E> */ B(Call0), R(1), R(2), U8(7), + /* 52 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(3), + /* 62 S> */ B(LdaLookupGlobalSlot), U8(1), U8(9), U8(1), + B(Star), R(1), + /* 69 E> */ B(CallUndefinedReceiver0), R(1), U8(7), /* 74 S> */ B(Return), ] constant pool: [ diff --git a/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden b/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden index 216ca4060e..6c57aaf3cd 100644 --- a/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden +++ b/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden @@ -22,7 +22,7 @@ snippet: " " frame size: 6 parameter count: 1 -bytecode array length: 33 +bytecode array length: 34 bytecodes: [ B(Mov), R(closure), R(0), /* 99 E> */ B(StackCheck), @@ -34,7 +34,7 @@ bytecodes: [ B(Mov), R(this), R(3), B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3), B(Star), R(1), - /* 117 E> */ B(Call0), R(1), R(this), U8(2), + /* 117 E> */ B(CallAnyReceiver), R(1), R(this), U8(1), U8(2), /* 126 E> */ B(AddSmi), I8(1), U8(8), /* 131 S> */ B(Return), ] diff --git a/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden b/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden index 671c4c7fc3..c763cca3e9 100644 --- a/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden +++ b/test/cctest/interpreter/bytecode_expectations/ContextVariables.golden @@ -75,18 +75,16 @@ handlers: [ snippet: " var a; (function() { a = 2; })(); return a; " -frame size: 3 +frame size: 2 parameter count: 1 -bytecode array length: 21 +bytecode array length: 17 bytecodes: [ B(CreateFunctionContext), U8(1), B(PushContext), R(0), /* 30 E> */ B(StackCheck), - /* 41 S> */ B(LdaUndefined), - B(Star), R(2), - B(CreateClosure), U8(0), U8(4), U8(2), + /* 41 S> */ B(CreateClosure), U8(0), U8(4), U8(2), B(Star), R(1), - /* 64 E> */ B(Call0), R(1), R(2), U8(2), + /* 64 E> */ B(CallUndefinedReceiver0), R(1), U8(2), /* 68 S> */ B(LdaCurrentContextSlot), U8(4), /* 78 S> */ B(Return), ] @@ -388,9 +386,9 @@ snippet: " var b = 100; return b " -frame size: 3 +frame size: 2 parameter count: 1 -bytecode array length: 791 +bytecode array length: 787 bytecodes: [ B(CreateFunctionContext), U8(254), B(PushContext), R(0), @@ -901,11 +899,9 @@ bytecodes: [ /* 3421 E> */ B(StaCurrentContextSlot), U8(254), /* 3435 S> */ B(LdaZero), /* 3435 E> */ B(StaCurrentContextSlot), U8(255), - /* 3438 S> */ B(LdaUndefined), - B(Star), R(2), - B(LdaGlobal), U8(0), U8(4), + /* 3438 S> */ B(LdaGlobal), U8(0), U8(4), B(Star), R(1), - /* 3438 E> */ B(Call0), R(1), R(2), U8(2), + /* 3438 E> */ B(CallUndefinedReceiver0), R(1), U8(2), /* 3454 S> */ B(LdaSmi), I8(100), /* 3454 E> */ B(Wide), B(StaCurrentContextSlot), U16(256), /* 3459 S> */ B(Wide), B(LdaCurrentContextSlot), U16(256), diff --git a/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden b/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden index 1b3ce9a1fd..bf7a371605 100644 --- a/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden +++ b/test/cctest/interpreter/bytecode_expectations/DeclareGlobals.golden @@ -104,7 +104,7 @@ snippet: " " frame size: 4 parameter count: 1 -bytecode array length: 31 +bytecode array length: 27 bytecodes: [ B(LdaConstant), U8(0), B(Star), R(1), @@ -113,11 +113,9 @@ bytecodes: [ B(Mov), R(closure), R(3), B(CallRuntime), U16(Runtime::kDeclareGlobalsForInterpreter), R(1), U8(3), /* 0 E> */ B(StackCheck), - /* 16 S> */ B(LdaUndefined), - B(Star), R(2), - B(LdaGlobal), U8(1), U8(2), + /* 16 S> */ B(LdaGlobal), U8(1), U8(2), B(Star), R(1), - /* 16 E> */ B(Call0), R(1), R(2), U8(5), + /* 16 E> */ B(CallUndefinedReceiver0), R(1), U8(5), B(Star), R(0), /* 20 S> */ B(Return), ] diff --git a/test/cctest/interpreter/bytecode_expectations/Eval.golden b/test/cctest/interpreter/bytecode_expectations/Eval.golden index 05e9517392..4ef1c7654c 100644 --- a/test/cctest/interpreter/bytecode_expectations/Eval.golden +++ b/test/cctest/interpreter/bytecode_expectations/Eval.golden @@ -9,9 +9,9 @@ wrap: yes snippet: " return eval('1;'); " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 62 +bytecode array length: 58 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -22,24 +22,22 @@ bytecodes: [ B(Ldar), R(new_target), B(StaCurrentContextSlot), U8(5), /* 30 E> */ B(StackCheck), - /* 34 S> */ B(LdaUndefined), - B(Star), R(2), - /* 41 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), + /* 34 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), B(Star), R(1), B(LdaConstant), U8(1), - B(Star), R(3), + B(Star), R(2), B(LdaZero), - B(Star), R(7), + B(Star), R(6), B(LdaSmi), I8(30), - B(Star), R(8), + B(Star), R(7), B(LdaSmi), I8(41), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 41 E> */ B(Call1), R(1), R(2), R(3), U8(2), + /* 41 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 53 S> */ B(Return), ] constant pool: [ diff --git a/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden b/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden index a9590edeeb..a9ba5bbf32 100644 --- a/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden +++ b/test/cctest/interpreter/bytecode_expectations/FunctionLiterals.golden @@ -27,16 +27,14 @@ handlers: [ snippet: " return (function(){ })() " -frame size: 2 +frame size: 1 parameter count: 1 -bytecode array length: 15 +bytecode array length: 11 bytecodes: [ /* 30 E> */ B(StackCheck), - /* 34 S> */ B(LdaUndefined), - B(Star), R(1), - B(CreateClosure), U8(0), U8(4), U8(2), + /* 34 S> */ B(CreateClosure), U8(0), U8(4), U8(2), B(Star), R(0), - /* 56 E> */ B(Call0), R(0), R(1), U8(2), + /* 56 E> */ B(CallUndefinedReceiver0), R(0), U8(2), /* 59 S> */ B(Return), ] constant pool: [ @@ -49,18 +47,16 @@ handlers: [ snippet: " return (function(x){ return x; })(1) " -frame size: 3 +frame size: 2 parameter count: 1 -bytecode array length: 20 +bytecode array length: 16 bytecodes: [ /* 30 E> */ B(StackCheck), - /* 34 S> */ B(LdaUndefined), - B(Star), R(1), - B(CreateClosure), U8(0), U8(4), U8(2), + /* 34 S> */ B(CreateClosure), U8(0), U8(4), U8(2), B(Star), R(0), B(LdaSmi), I8(1), - B(Star), R(2), - /* 67 E> */ B(Call1), R(0), R(1), R(2), U8(2), + B(Star), R(1), + /* 67 E> */ B(CallUndefinedReceiver1), R(0), R(1), U8(2), /* 71 S> */ B(Return), ] constant pool: [ diff --git a/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden b/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden index 4256c16a75..8ecf2c316d 100644 --- a/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden +++ b/test/cctest/interpreter/bytecode_expectations/LookupSlot.golden @@ -10,9 +10,9 @@ test function name: f snippet: " eval('var x = 10;'); return x; " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 66 +bytecode array length: 62 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -23,24 +23,22 @@ bytecodes: [ B(Ldar), R(new_target), B(StaCurrentContextSlot), U8(5), /* 10 E> */ B(StackCheck), - /* 14 S> */ B(LdaUndefined), - B(Star), R(2), - /* 14 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), + /* 14 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), B(Star), R(1), B(LdaConstant), U8(1), - B(Star), R(3), + B(Star), R(2), B(LdaZero), - B(Star), R(7), + B(Star), R(6), B(LdaSmi), I8(10), - B(Star), R(8), + B(Star), R(7), B(LdaSmi), I8(14), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 14 E> */ B(Call1), R(1), R(2), R(3), U8(2), + /* 14 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 35 S> */ B(LdaLookupGlobalSlot), U8(2), U8(6), U8(1), /* 45 S> */ B(Return), ] @@ -56,9 +54,9 @@ handlers: [ snippet: " eval('var x = 10;'); return typeof x; " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 67 +bytecode array length: 63 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -69,24 +67,22 @@ bytecodes: [ B(Ldar), R(new_target), B(StaCurrentContextSlot), U8(5), /* 10 E> */ B(StackCheck), - /* 14 S> */ B(LdaUndefined), - B(Star), R(2), - /* 14 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), + /* 14 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), B(Star), R(1), B(LdaConstant), U8(1), - B(Star), R(3), + B(Star), R(2), B(LdaZero), - B(Star), R(7), + B(Star), R(6), B(LdaSmi), I8(10), - B(Star), R(8), + B(Star), R(7), B(LdaSmi), I8(14), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 14 E> */ B(Call1), R(1), R(2), R(3), U8(2), + /* 14 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 35 S> */ B(LdaLookupGlobalSlotInsideTypeof), U8(2), U8(6), U8(1), B(TypeOf), /* 52 S> */ B(Return), @@ -103,9 +99,9 @@ handlers: [ snippet: " x = 20; return eval(''); " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 66 +bytecode array length: 62 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -118,24 +114,22 @@ bytecodes: [ /* 10 E> */ B(StackCheck), /* 14 S> */ B(LdaSmi), I8(20), /* 16 E> */ B(StaLookupSlotSloppy), U8(0), - /* 22 S> */ B(LdaUndefined), - B(Star), R(2), - /* 29 E> */ B(LdaLookupGlobalSlot), U8(1), U8(4), U8(1), + /* 22 S> */ B(LdaLookupGlobalSlot), U8(1), U8(4), U8(1), B(Star), R(1), B(LdaConstant), U8(2), - B(Star), R(3), + B(Star), R(2), B(LdaZero), - B(Star), R(7), + B(Star), R(6), B(LdaSmi), I8(10), - B(Star), R(8), + B(Star), R(7), B(LdaSmi), I8(29), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 29 E> */ B(Call1), R(1), R(2), R(3), U8(2), + /* 29 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 39 S> */ B(Return), ] constant pool: [ @@ -155,9 +149,9 @@ snippet: " } f(); " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 66 +bytecode array length: 62 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -168,24 +162,22 @@ bytecodes: [ B(Ldar), R(new_target), B(StaCurrentContextSlot), U8(5), /* 38 E> */ B(StackCheck), - /* 44 S> */ B(LdaUndefined), - B(Star), R(2), - /* 44 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), + /* 44 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), B(Star), R(1), B(LdaConstant), U8(1), - B(Star), R(3), + B(Star), R(2), B(LdaZero), - B(Star), R(7), + B(Star), R(6), B(LdaSmi), I8(38), - B(Star), R(8), + B(Star), R(7), B(LdaSmi), I8(44), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 44 E> */ B(Call1), R(1), R(2), R(3), U8(2), + /* 44 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 66 S> */ B(LdaLookupContextSlot), U8(2), U8(6), U8(1), /* 76 S> */ B(Return), ] @@ -206,9 +198,9 @@ snippet: " } f(); " -frame size: 10 +frame size: 9 parameter count: 1 -bytecode array length: 66 +bytecode array length: 62 bytecodes: [ B(CreateFunctionContext), U8(3), B(PushContext), R(0), @@ -219,24 +211,22 @@ bytecodes: [ B(Ldar), R(new_target), B(StaCurrentContextSlot), U8(5), /* 34 E> */ B(StackCheck), - /* 40 S> */ B(LdaUndefined), - B(Star), R(2), - /* 40 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), + /* 40 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), B(Star), R(1), B(LdaConstant), U8(1), - B(Star), R(3), + B(Star), R(2), B(LdaZero), - B(Star), R(7), + B(Star), R(6), B(LdaSmi), I8(34), - B(Star), R(8), + B(Star), R(7), B(LdaSmi), I8(40), - B(Star), R(9), - B(Mov), R(1), R(4), - B(Mov), R(3), R(5), - B(Mov), R(closure), R(6), - B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), U8(6), + B(Star), R(8), + B(Mov), R(1), R(3), + B(Mov), R(2), R(4), + B(Mov), R(closure), R(5), + B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), B(Star), R(1), - /* 40 E> */ B(Call1), R(1), R(2), R(3), U8(2), + /* 40 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 62 S> */ B(LdaLookupGlobalSlot), U8(2), U8(6), U8(1), /* 72 S> */ B(Return), ] diff --git a/test/cctest/interpreter/bytecode_expectations/Modules.golden b/test/cctest/interpreter/bytecode_expectations/Modules.golden index 0c31b64cce..510e573f54 100644 --- a/test/cctest/interpreter/bytecode_expectations/Modules.golden +++ b/test/cctest/interpreter/bytecode_expectations/Modules.golden @@ -171,7 +171,7 @@ snippet: " " frame size: 10 parameter count: 2 -bytecode array length: 213 +bytecode array length: 205 bytecodes: [ B(Ldar), R(new_target), B(JumpIfUndefined), U8(27), @@ -228,17 +228,15 @@ bytecodes: [ /* 64 S> */ B(Return), B(Ldar), R(6), /* 0 E> */ B(Throw), - /* 32 S> */ B(LdaUndefined), - B(Star), R(5), - /* 32 E> */ B(LdaModuleVariable), I8(-1), U8(0), + /* 32 S> */ B(LdaModuleVariable), I8(-1), U8(0), B(JumpIfNotHole), U8(11), B(LdaConstant), U8(1), - B(Star), R(6), - B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1), + B(Star), R(5), + B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), B(Star), R(4), B(LdaSmi), I8(42), - B(Star), R(6), - /* 32 E> */ B(Call1), R(4), R(5), R(6), U8(2), + B(Star), R(5), + /* 32 E> */ B(CallUndefinedReceiver1), R(4), R(5), U8(2), B(Ldar), R(closure), B(CreateBlockContext), U8(2), B(PushContext), R(1), @@ -246,17 +244,15 @@ bytecodes: [ B(StaCurrentContextSlot), U8(4), /* 47 S> */ B(LdaUndefined), /* 47 E> */ B(StaCurrentContextSlot), U8(4), - /* 52 S> */ B(LdaUndefined), - B(Star), R(5), - /* 52 E> */ B(LdaModuleVariable), I8(-1), U8(1), + /* 52 S> */ B(LdaModuleVariable), I8(-1), U8(1), B(JumpIfNotHole), U8(11), B(LdaConstant), U8(1), - B(Star), R(6), - B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1), + B(Star), R(5), + B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), B(Star), R(4), B(LdaSmi), I8(42), - B(Star), R(6), - /* 52 E> */ B(Call1), R(4), R(5), R(6), U8(4), + B(Star), R(5), + /* 52 E> */ B(CallUndefinedReceiver1), R(4), R(5), U8(4), B(StaContextSlot), R(1), U8(6), U8(0), B(PopContext), R(1), B(LdaCurrentContextSlot), U8(6), diff --git a/test/cctest/interpreter/test-interpreter.cc b/test/cctest/interpreter/test-interpreter.cc index 973a67c8c5..f58740ea20 100644 --- a/test/cctest/interpreter/test-interpreter.cc +++ b/test/cctest/interpreter/test-interpreter.cc @@ -1298,7 +1298,11 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) { .StoreAccumulatorInRegister(reg) .MoveRegister(builder.Receiver(), args[0]); - builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode); + if (tail_call_mode == TailCallMode::kAllow) { + builder.TailCall(reg, args, call_slot_index); + } else { + builder.CallProperty(reg, args, call_slot_index); + } builder.Return(); ast_factory.Internalize(isolate); @@ -1321,7 +1325,11 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) { builder.LoadNamedProperty(builder.Receiver(), name, slot_index) .StoreAccumulatorInRegister(reg) .MoveRegister(builder.Receiver(), args[0]); - builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode); + if (tail_call_mode == TailCallMode::kAllow) { + builder.TailCall(reg, args, call_slot_index); + } else { + builder.CallProperty(reg, args, call_slot_index); + } builder.Return(); ast_factory.Internalize(isolate); Handle bytecode_array = builder.ToBytecodeArray(isolate); @@ -1353,7 +1361,11 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) { .LoadLiteral(Smi::FromInt(11)) .StoreAccumulatorInRegister(args[2]); - builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode); + if (tail_call_mode == TailCallMode::kAllow) { + builder.TailCall(reg, args, call_slot_index); + } else { + builder.CallProperty(reg, args, call_slot_index); + } builder.Return(); @@ -1402,7 +1414,11 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) { .LoadLiteral(ast_factory.NewString(ast_factory.GetOneByteString("j"))) .StoreAccumulatorInRegister(args[10]); - builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode); + if (tail_call_mode == TailCallMode::kAllow) { + builder.TailCall(reg, args, call_slot_index); + } else { + builder.CallProperty(reg, args, call_slot_index); + } builder.Return(); diff --git a/test/unittests/interpreter/bytecode-array-builder-unittest.cc b/test/unittests/interpreter/bytecode-array-builder-unittest.cc index e12fdcc95c..46270241fe 100644 --- a/test/unittests/interpreter/bytecode-array-builder-unittest.cc +++ b/test/unittests/interpreter/bytecode-array-builder-unittest.cc @@ -39,8 +39,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { Register reg(0); Register other(reg.index() + 1); Register wide(128); - RegisterList reg_list; - RegisterList single(0, 1), pair(0, 2), triple(0, 3); + RegisterList reg_list(0, 10); + RegisterList empty, single(0, 1), pair(0, 2), triple(0, 3); // Emit argument creation operations. builder.CreateArguments(CreateArgumentsType::kMappedArguments) @@ -145,16 +145,16 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) { builder.CreateObjectLiteral(0, 0, 0, reg); // Call operations. - builder.Call(reg, reg_list, 1, Call::GLOBAL_CALL) - .Call(reg, single, 1, Call::GLOBAL_CALL) - .Call(reg, pair, 1, Call::GLOBAL_CALL) - .Call(reg, triple, 1, Call::GLOBAL_CALL) - .Call(reg, reg_list, 1, Call::NAMED_PROPERTY_CALL, - TailCallMode::kDisallow) - .Call(reg, single, 1, Call::NAMED_PROPERTY_CALL) - .Call(reg, pair, 1, Call::NAMED_PROPERTY_CALL) - .Call(reg, triple, 1, Call::NAMED_PROPERTY_CALL) - .Call(reg, reg_list, 1, Call::GLOBAL_CALL, TailCallMode::kAllow) + builder.CallAnyReceiver(reg, reg_list, 1) + .CallProperty(reg, reg_list, 1) + .CallProperty(reg, single, 1) + .CallProperty(reg, pair, 1) + .CallProperty(reg, triple, 1) + .CallUndefinedReceiver(reg, reg_list, 1) + .CallUndefinedReceiver(reg, empty, 1) + .CallUndefinedReceiver(reg, single, 1) + .CallUndefinedReceiver(reg, pair, 1) + .TailCall(reg, reg_list, 1) .CallRuntime(Runtime::kIsArray, reg) .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair) .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg_list) diff --git a/test/unittests/interpreter/bytecode-decoder-unittest.cc b/test/unittests/interpreter/bytecode-decoder-unittest.cc index 14972259da..f9c0877664 100644 --- a/test/unittests/interpreter/bytecode-decoder-unittest.cc +++ b/test/unittests/interpreter/bytecode-decoder-unittest.cc @@ -38,10 +38,10 @@ TEST(BytecodeDecoder, DecodeBytecodeAndOperands) { "LdaSmi.ExtraWide [-100000]"}, {{B(Star), R8(5)}, 2, 0, " Star r5"}, {{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"}, - {{B(Wide), B(Call), R16(134), R16(135), U16(10), U16(177)}, + {{B(Wide), B(CallAnyReceiver), R16(134), R16(135), U16(10), U16(177)}, 10, 0, - "Call.Wide r134, r135-r144, [177]"}, + "CallAnyReceiver.Wide r134, r135-r144, [177]"}, {{B(ForInPrepare), R8(10), R8(11)}, 3, 0, diff --git a/test/unittests/interpreter/interpreter-assembler-unittest.cc b/test/unittests/interpreter/interpreter-assembler-unittest.cc index 1cb1afdbc1..b79f0690b8 100644 --- a/test/unittests/interpreter/interpreter-assembler-unittest.cc +++ b/test/unittests/interpreter/interpreter-assembler-unittest.cc @@ -616,25 +616,27 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) { } TARGET_TEST_F(InterpreterAssemblerTest, CallJS) { - TailCallMode tail_call_modes[] = {TailCallMode::kDisallow, - TailCallMode::kAllow}; - TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) { - TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { - if (Bytecodes::IsCallOrConstruct(bytecode)) { - InterpreterAssemblerTestState state(this, bytecode); - InterpreterAssemblerForTest m(&state, bytecode); - Callable builtin = CodeFactory::InterpreterPushArgsAndCall( - isolate(), tail_call_mode, InterpreterPushArgsMode::kOther); - Node* function = m.IntPtrConstant(0); - Node* first_arg = m.IntPtrConstant(1); - Node* arg_count = m.Int32Constant(2); - Node* context = m.IntPtrConstant(3); - Node* call_js = - m.CallJS(function, context, first_arg, arg_count, tail_call_mode); - EXPECT_THAT(call_js, - IsCall(_, IsHeapConstant(builtin.code()), arg_count, - first_arg, function, context, _, _)); - } + TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { + if (Bytecodes::IsCallOrConstruct(bytecode) && + bytecode != Bytecode::kCallWithSpread) { + InterpreterAssemblerTestState state(this, bytecode); + InterpreterAssemblerForTest m(&state, bytecode); + ConvertReceiverMode receiver_mode = Bytecodes::GetReceiverMode(bytecode); + TailCallMode tail_call_mode = (bytecode == Bytecode::kTailCall) + ? TailCallMode::kAllow + : TailCallMode::kDisallow; + + Callable builtin = CodeFactory::InterpreterPushArgsThenCall( + isolate(), receiver_mode, tail_call_mode, + InterpreterPushArgsMode::kOther); + Node* function = m.IntPtrConstant(0); + Node* first_arg = m.IntPtrConstant(1); + Node* arg_count = m.Int32Constant(2); + Node* context = m.IntPtrConstant(3); + Node* call_js = m.CallJS(function, context, first_arg, arg_count, + receiver_mode, tail_call_mode); + EXPECT_THAT(call_js, IsCall(_, IsHeapConstant(builtin.code()), arg_count, + first_arg, function, context, _, _)); } } }