Revert "[ignition] Add call bytecodes for undefined receiver"

This reverts commit 751e893591.

Reason for revert: Breaks layout tests:
https://build.chromium.org/p/client.v8.fyi/builders/V8-Blink%20Linux%2064/builds/14885

See:
https://github.com/v8/v8/wiki/Blink-layout-tests

Original change's description:
> [ignition] Add call bytecodes for undefined receiver
> 
> Adds a collection of call bytecodes which have an implicit undefined
> receiver argument, for cases such as global calls where we know that the
> receiver has to be undefined. This way we can skip an LdaUndefined,
> decrease bytecode register pressure, and set a more accurate
> ConvertReceiverMode on the interpreter and TurboFan call.
> 
> As a side effect, the "normal" Call bytecode now becomes a rare case
> (only with calls and super property calls), so we get rid of its 0-2
> argument special cases and modify CallProperty[N] to use the
> NotNullOrUndefined ConvertReceiverMode.
> 
> Change-Id: I9374a32fefd66fc0251b5193bae7a6b7dc31eefc
> Reviewed-on: https://chromium-review.googlesource.com/463287
> Commit-Queue: Leszek Swirski <leszeks@chromium.org>
> Reviewed-by: Michael Starzinger <mstarzinger@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#44530}

TBR=rmcilroy@chromium.org,mstarzinger@chromium.org,leszeks@chromium.org,v8-reviews@googlegroups.com,v8-mips-ports@googlegroups.com,v8-ppc-ports@googlegroups.com,v8-x87-ports@googlegroups.com,bmeurer@chromium.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true

Change-Id: I7629dec609d0ec938ce7105d6c1c74884e5f9272
Reviewed-on: https://chromium-review.googlesource.com/474744
Commit-Queue: Michael Achenbach <machenbach@chromium.org>
Reviewed-by: Michael Achenbach <machenbach@chromium.org>
Cr-Commit-Position: refs/heads/master@{#44548}
This commit is contained in:
Michael Achenbach 2017-04-11 06:26:10 +00:00 committed by Commit Bot
parent 817a5c0a32
commit 925212a1cf
51 changed files with 729 additions and 983 deletions

View File

@ -324,7 +324,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r0, // argument count (not including receiver) r0, // argument count (not including receiver)
@ -334,7 +334,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r0, // argument count (not including receiver) r0, // argument count (not including receiver)
@ -346,8 +346,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r0, // argument count (not including receiver) r0, // argument count (not including receiver)
r1, // target to call checked to be Array function r1, // target to call checked to be Array function

View File

@ -353,7 +353,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
x0, // argument count (not including receiver) x0, // argument count (not including receiver)
@ -363,7 +363,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
x0, // argument count (not including receiver) x0, // argument count (not including receiver)
@ -375,8 +375,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
x0, // argument count (not including receiver) x0, // argument count (not including receiver)
x1, // target to call checked to be Array function x1, // target to call checked to be Array function

View File

@ -1082,7 +1082,11 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
static void Generate_InterpreterPushArgs(MacroAssembler* masm, static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register num_args, Register index, Register num_args, Register index,
Register limit, Register scratch) { Register limit, Register scratch,
Label* stack_overflow) {
// Add a stack check before pushing arguments.
Generate_StackOverflowCheck(masm, num_args, scratch, stack_overflow);
// Find the address of the last argument. // Find the address of the last argument.
__ mov(limit, num_args); __ mov(limit, num_args);
__ mov(limit, Operand(limit, LSL, kPointerSizeLog2)); __ mov(limit, Operand(limit, LSL, kPointerSizeLog2));
@ -1099,9 +1103,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : the number of arguments (not including the receiver) // -- r0 : the number of arguments (not including the receiver)
// -- r2 : the address of the first argument to be pushed. Subsequent // -- r2 : the address of the first argument to be pushed. Subsequent
@ -1113,16 +1117,8 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
__ add(r3, r0, Operand(1)); // Add one for receiver. __ 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. // Push the arguments. r2, r4, r5 will be modified.
Generate_InterpreterPushArgs(masm, r3, r2, r4, r5); Generate_InterpreterPushArgs(masm, r3, r2, r4, r5, &stack_overflow);
// Call the target. // Call the target.
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1147,7 +1143,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : argument count (not including receiver) // -- r0 : argument count (not including receiver)
@ -1162,10 +1158,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
__ mov(ip, Operand::Zero()); __ mov(ip, Operand::Zero());
__ push(ip); __ push(ip);
Generate_StackOverflowCheck(masm, r0, r5, &stack_overflow);
// Push the arguments. r5, r4, r6 will be modified. // Push the arguments. r5, r4, r6 will be modified.
Generate_InterpreterPushArgs(masm, r0, r4, r5, r6); Generate_InterpreterPushArgs(masm, r0, r4, r5, r6, &stack_overflow);
__ AssertUndefinedOrAllocationSite(r2, r5); __ AssertUndefinedOrAllocationSite(r2, r5);
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1196,7 +1190,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r0 : argument count (not including receiver) // -- r0 : argument count (not including receiver)
@ -1206,14 +1200,11 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// ----------------------------------- // -----------------------------------
Label stack_overflow; Label stack_overflow;
// Push a slot for the receiver to be constructed. __ add(r4, r0, Operand(1)); // Add one for receiver.
__ 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. // Push the arguments. r3, r5, r6 will be modified.
Generate_InterpreterPushArgs(masm, r0, r3, r5, r6); Generate_InterpreterPushArgs(masm, r4, r3, r5, r6, &stack_overflow);
// Array constructor expects constructor in r3. It is same as r1 here. // Array constructor expects constructor in r3. It is same as r1 here.
__ mov(r3, r1); __ mov(r3, r1);

View File

@ -1100,7 +1100,11 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
static void Generate_InterpreterPushArgs(MacroAssembler* masm, static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register num_args, Register index, Register num_args, Register index,
Register last_arg, Register stack_addr, Register last_arg, Register stack_addr,
Register scratch) { Register scratch,
Label* stack_overflow) {
// Add a stack check before pushing arguments.
Generate_StackOverflowCheck(masm, num_args, scratch, stack_overflow);
__ Mov(scratch, num_args); __ Mov(scratch, num_args);
__ lsl(scratch, scratch, kPointerSizeLog2); __ lsl(scratch, scratch, kPointerSizeLog2);
__ sub(last_arg, index, scratch); __ sub(last_arg, index, scratch);
@ -1122,9 +1126,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- x0 : the number of arguments (not including the receiver) // -- x0 : the number of arguments (not including the receiver)
// -- x2 : the address of the first argument to be pushed. Subsequent // -- x2 : the address of the first argument to be pushed. Subsequent
@ -1137,17 +1141,8 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
// Add one for the receiver. // Add one for the receiver.
__ add(x3, x0, Operand(1)); __ 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. // Push the arguments. x2, x4, x5, x6 will be modified.
Generate_InterpreterPushArgs(masm, x3, x2, x4, x5, x6); Generate_InterpreterPushArgs(masm, x3, x2, x4, x5, x6, &stack_overflow);
// Call the target. // Call the target.
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1171,7 +1166,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- x0 : argument count (not including receiver) // -- x0 : argument count (not including receiver)
@ -1185,11 +1180,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Push a slot for the receiver. // Push a slot for the receiver.
__ Push(xzr); __ 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. // Push the arguments. x5, x4, x6, x7 will be modified.
Generate_InterpreterPushArgs(masm, x0, x4, x5, x6, x7); Generate_InterpreterPushArgs(masm, x0, x4, x5, x6, x7, &stack_overflow);
__ AssertUndefinedOrAllocationSite(x2, x6); __ AssertUndefinedOrAllocationSite(x2, x6);
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1219,7 +1211,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- x0 : argument count (not including receiver) // -- x0 : argument count (not including receiver)
@ -1229,14 +1221,10 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// ----------------------------------- // -----------------------------------
Label stack_overflow; Label stack_overflow;
// Push a slot for the receiver. __ add(x4, x0, Operand(1)); // Add one 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. // Push the arguments. x3, x5, x6, x7 will be modified.
Generate_InterpreterPushArgs(masm, x0, x3, x5, x6, x7); Generate_InterpreterPushArgs(masm, x4, x3, x5, x6, x7, &stack_overflow);
// Array constructor expects constructor in x3. It is same as call target. // Array constructor expects constructor in x3. It is same as call target.
__ mov(x3, x1); __ mov(x3, x1);

View File

@ -133,17 +133,15 @@ namespace internal {
\ \
/* Interpreter */ \ /* Interpreter */ \
ASM(InterpreterEntryTrampoline) \ ASM(InterpreterEntryTrampoline) \
ASM(InterpreterPushArgsThenCall) \ ASM(InterpreterPushArgsAndCall) \
ASM(InterpreterPushUndefinedAndArgsThenCall) \ ASM(InterpreterPushArgsAndCallFunction) \
ASM(InterpreterPushArgsThenCallFunction) \ ASM(InterpreterPushArgsAndCallWithFinalSpread) \
ASM(InterpreterPushUndefinedAndArgsThenCallFunction) \ ASM(InterpreterPushArgsAndTailCall) \
ASM(InterpreterPushArgsThenCallWithFinalSpread) \ ASM(InterpreterPushArgsAndTailCallFunction) \
ASM(InterpreterPushArgsThenTailCall) \ ASM(InterpreterPushArgsAndConstruct) \
ASM(InterpreterPushArgsThenTailCallFunction) \ ASM(InterpreterPushArgsAndConstructFunction) \
ASM(InterpreterPushArgsThenConstruct) \ ASM(InterpreterPushArgsAndConstructArray) \
ASM(InterpreterPushArgsThenConstructFunction) \ ASM(InterpreterPushArgsAndConstructWithFinalSpread) \
ASM(InterpreterPushArgsThenConstructArray) \
ASM(InterpreterPushArgsThenConstructWithFinalSpread) \
ASM(InterpreterEnterBytecodeAdvance) \ ASM(InterpreterEnterBytecodeAdvance) \
ASM(InterpreterEnterBytecodeDispatch) \ ASM(InterpreterEnterBytecodeDispatch) \
ASM(InterpreterOnStackReplacement) \ ASM(InterpreterOnStackReplacement) \

View File

@ -9,67 +9,48 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
void Builtins::Generate_InterpreterPushArgsThenCall(MacroAssembler* masm) { void Builtins::Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsThenCallImpl( return Generate_InterpreterPushArgsAndCallImpl(
masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow, masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kOther);
InterpreterPushArgsMode::kOther);
} }
void Builtins::Generate_InterpreterPushArgsThenCallFunction( void Builtins::Generate_InterpreterPushArgsAndCallFunction(
MacroAssembler* masm) { MacroAssembler* masm) {
return Generate_InterpreterPushArgsThenCallImpl( return Generate_InterpreterPushArgsAndCallImpl(
masm, ConvertReceiverMode::kAny, TailCallMode::kDisallow, masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kJSFunction);
InterpreterPushArgsMode::kJSFunction);
} }
void Builtins::Generate_InterpreterPushUndefinedAndArgsThenCall( void Builtins::Generate_InterpreterPushArgsAndCallWithFinalSpread(
MacroAssembler* masm) { MacroAssembler* masm) {
return Generate_InterpreterPushArgsThenCallImpl( return Generate_InterpreterPushArgsAndCallImpl(
masm, ConvertReceiverMode::kNullOrUndefined, TailCallMode::kDisallow, masm, TailCallMode::kDisallow, InterpreterPushArgsMode::kWithFinalSpread);
InterpreterPushArgsMode::kOther);
} }
void Builtins::Generate_InterpreterPushUndefinedAndArgsThenCallFunction( void Builtins::Generate_InterpreterPushArgsAndTailCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(
masm, TailCallMode::kAllow, InterpreterPushArgsMode::kOther);
}
void Builtins::Generate_InterpreterPushArgsAndTailCallFunction(
MacroAssembler* masm) { MacroAssembler* masm) {
return Generate_InterpreterPushArgsThenCallImpl( return Generate_InterpreterPushArgsAndCallImpl(
masm, ConvertReceiverMode::kNullOrUndefined, TailCallMode::kDisallow, masm, TailCallMode::kAllow, InterpreterPushArgsMode::kJSFunction);
InterpreterPushArgsMode::kJSFunction);
} }
void Builtins::Generate_InterpreterPushArgsThenCallWithFinalSpread( void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
MacroAssembler* masm) { return Generate_InterpreterPushArgsAndConstructImpl(
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); masm, InterpreterPushArgsMode::kOther);
} }
void Builtins::Generate_InterpreterPushArgsThenConstructWithFinalSpread( void Builtins::Generate_InterpreterPushArgsAndConstructWithFinalSpread(
MacroAssembler* masm) { MacroAssembler* masm) {
return Generate_InterpreterPushArgsThenConstructImpl( return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kWithFinalSpread); masm, InterpreterPushArgsMode::kWithFinalSpread);
} }
void Builtins::Generate_InterpreterPushArgsThenConstructFunction( void Builtins::Generate_InterpreterPushArgsAndConstructFunction(
MacroAssembler* masm) { MacroAssembler* masm) {
return Generate_InterpreterPushArgsThenConstructImpl( return Generate_InterpreterPushArgsAndConstructImpl(
masm, InterpreterPushArgsMode::kJSFunction); masm, InterpreterPushArgsMode::kJSFunction);
} }

View File

@ -11,53 +11,38 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
Handle<Code> Builtins::InterpreterPushArgsThenCall( Handle<Code> Builtins::InterpreterPushArgsAndCall(
ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode, TailCallMode tail_call_mode, InterpreterPushArgsMode mode) {
InterpreterPushArgsMode mode) {
switch (mode) { switch (mode) {
case InterpreterPushArgsMode::kJSFunction: case InterpreterPushArgsMode::kJSFunction:
if (tail_call_mode == TailCallMode::kDisallow) { if (tail_call_mode == TailCallMode::kDisallow) {
switch (receiver_mode) { return InterpreterPushArgsAndCallFunction();
case ConvertReceiverMode::kNullOrUndefined:
return InterpreterPushUndefinedAndArgsThenCallFunction();
case ConvertReceiverMode::kNotNullOrUndefined:
case ConvertReceiverMode::kAny:
return InterpreterPushArgsThenCallFunction();
}
} else { } else {
CHECK_EQ(receiver_mode, ConvertReceiverMode::kAny); return InterpreterPushArgsAndTailCallFunction();
return InterpreterPushArgsThenTailCallFunction();
} }
case InterpreterPushArgsMode::kWithFinalSpread: case InterpreterPushArgsMode::kWithFinalSpread:
CHECK(tail_call_mode == TailCallMode::kDisallow); CHECK(tail_call_mode == TailCallMode::kDisallow);
return InterpreterPushArgsThenCallWithFinalSpread(); return InterpreterPushArgsAndCallWithFinalSpread();
case InterpreterPushArgsMode::kOther: case InterpreterPushArgsMode::kOther:
if (tail_call_mode == TailCallMode::kDisallow) { if (tail_call_mode == TailCallMode::kDisallow) {
switch (receiver_mode) { return InterpreterPushArgsAndCall();
case ConvertReceiverMode::kNullOrUndefined:
return InterpreterPushUndefinedAndArgsThenCall();
case ConvertReceiverMode::kNotNullOrUndefined:
case ConvertReceiverMode::kAny:
return InterpreterPushArgsThenCall();
}
} else { } else {
CHECK_EQ(receiver_mode, ConvertReceiverMode::kAny); return InterpreterPushArgsAndTailCall();
return InterpreterPushArgsThenTailCall();
} }
} }
UNREACHABLE(); UNREACHABLE();
return Handle<Code>::null(); return Handle<Code>::null();
} }
Handle<Code> Builtins::InterpreterPushArgsThenConstruct( Handle<Code> Builtins::InterpreterPushArgsAndConstruct(
InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
switch (mode) { switch (mode) {
case InterpreterPushArgsMode::kJSFunction: case InterpreterPushArgsMode::kJSFunction:
return InterpreterPushArgsThenConstructFunction(); return InterpreterPushArgsAndConstructFunction();
case InterpreterPushArgsMode::kWithFinalSpread: case InterpreterPushArgsMode::kWithFinalSpread:
return InterpreterPushArgsThenConstructWithFinalSpread(); return InterpreterPushArgsAndConstructWithFinalSpread();
case InterpreterPushArgsMode::kOther: case InterpreterPushArgsMode::kOther:
return InterpreterPushArgsThenConstruct(); return InterpreterPushArgsAndConstruct();
} }
UNREACHABLE(); UNREACHABLE();
return Handle<Code>::null(); return Handle<Code>::null();

View File

@ -58,10 +58,9 @@ class Builtins {
Handle<Code> NonPrimitiveToPrimitive( Handle<Code> NonPrimitiveToPrimitive(
ToPrimitiveHint hint = ToPrimitiveHint::kDefault); ToPrimitiveHint hint = ToPrimitiveHint::kDefault);
Handle<Code> OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint); Handle<Code> OrdinaryToPrimitive(OrdinaryToPrimitiveHint hint);
Handle<Code> InterpreterPushArgsThenCall(ConvertReceiverMode receiver_mode, Handle<Code> InterpreterPushArgsAndCall(TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode);
InterpreterPushArgsMode mode); Handle<Code> InterpreterPushArgsAndConstruct(InterpreterPushArgsMode mode);
Handle<Code> InterpreterPushArgsThenConstruct(InterpreterPushArgsMode mode);
Handle<Code> NewFunctionContext(ScopeType scope_type); Handle<Code> NewFunctionContext(ScopeType scope_type);
Handle<Code> NewCloneShallowArray(AllocationSiteMode allocation_mode); Handle<Code> NewCloneShallowArray(AllocationSiteMode allocation_mode);
Handle<Code> NewCloneShallowObject(int length); Handle<Code> NewCloneShallowObject(int length);
@ -123,11 +122,11 @@ class Builtins {
static void Generate_CallForwardVarargs(MacroAssembler* masm, static void Generate_CallForwardVarargs(MacroAssembler* masm,
Handle<Code> code); Handle<Code> code);
static void Generate_InterpreterPushArgsThenCallImpl( static void Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode); InterpreterPushArgsMode mode);
static void Generate_InterpreterPushArgsThenConstructImpl( static void Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode); MacroAssembler* masm, InterpreterPushArgsMode mode);
#define DECLARE_ASM(Name, ...) \ #define DECLARE_ASM(Name, ...) \

View File

@ -751,9 +751,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
// -- ebx : the address of the first argument to be pushed. Subsequent // -- ebx : the address of the first argument to be pushed. Subsequent
@ -776,12 +776,6 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
// Pop return address to allow tail-call after pushing arguments. // Pop return address to allow tail-call after pushing arguments.
__ Pop(edx); __ 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. // Find the address of the last argument.
__ shl(ecx, kPointerSizeLog2); __ shl(ecx, kPointerSizeLog2);
__ neg(ecx); __ neg(ecx);
@ -821,10 +815,10 @@ namespace {
// This function modified start_addr, and only reads the contents of num_args // This function modified start_addr, and only reads the contents of num_args
// register. scratch1 and scratch2 are used as temporary registers. Their // register. scratch1 and scratch2 are used as temporary registers. Their
// original values are restored after the use. // original values are restored after the use.
void Generate_InterpreterPushZeroAndArgsAndReturnAddress( void Generate_InterpreterPushArgsAndReturnAddress(
MacroAssembler* masm, Register num_args, Register start_addr, MacroAssembler* masm, Register num_args, Register start_addr,
Register scratch1, Register scratch2, int num_slots_above_ret_addr, Register scratch1, Register scratch2, bool receiver_in_args,
Label* stack_overflow) { int num_slots_above_ret_addr, Label* stack_overflow) {
// We have to move return address and the temporary registers above it // We have to move return address and the temporary registers above it
// before we can copy arguments onto the stack. To achieve this: // before we can copy arguments onto the stack. To achieve this:
// Step 1: Increment the stack pointer by num_args + 1 (for receiver). // Step 1: Increment the stack pointer by num_args + 1 (for receiver).
@ -837,7 +831,7 @@ void Generate_InterpreterPushZeroAndArgsAndReturnAddress(
// | | | return addr | (2) // | | | return addr | (2)
// | | | arg N | (3) // | | | arg N | (3)
// | scratch1 | <-- esp | .... | // | scratch1 | <-- esp | .... |
// | .... | | arg 1 | // | .... | | arg 0 |
// | scratch-n | | arg 0 | // | scratch-n | | arg 0 |
// | return addr | | receiver slot | // | return addr | | receiver slot |
@ -881,12 +875,17 @@ void Generate_InterpreterPushZeroAndArgsAndReturnAddress(
} }
// Step 3 copy arguments to correct locations. // Step 3 copy arguments to correct locations.
// Slot meant for receiver contains return address. Reset it so that if (receiver_in_args) {
// we will not incorrectly interpret return address as an object. __ mov(scratch1, num_args);
__ mov(Operand(esp, num_args, times_pointer_size, __ add(scratch1, Immediate(1));
(num_slots_above_ret_addr + 1) * kPointerSize), } else {
Immediate(0)); // Slot meant for receiver contains return address. Reset it so that
__ mov(scratch1, num_args); // 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; Label loop_header, loop_check;
__ jmp(&loop_check); __ jmp(&loop_check);
@ -905,7 +904,7 @@ void Generate_InterpreterPushZeroAndArgsAndReturnAddress(
} // end anonymous namespace } // end anonymous namespace
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
@ -924,8 +923,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Push arguments and move return address to the top of stack. // Push arguments and move return address to the top of stack.
// The eax register is readonly. The ecx register will be modified. The edx // 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. // and edi registers will be modified but restored to their original values.
Generate_InterpreterPushZeroAndArgsAndReturnAddress(masm, eax, ecx, edx, edi, Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false,
2, &stack_overflow); 2, &stack_overflow);
// Restore edi and edx // Restore edi and edx
__ Pop(edx); __ Pop(edx);
@ -965,7 +964,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
@ -983,8 +982,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// Push arguments and move return address to the top of stack. // Push arguments and move return address to the top of stack.
// The eax register is readonly. The ecx register will be modified. The edx // 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. // and edi registers will be modified but restored to their original values.
Generate_InterpreterPushZeroAndArgsAndReturnAddress(masm, eax, ecx, edx, edi, Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true,
1, &stack_overflow); 1, &stack_overflow);
// Restore edx. // Restore edx.
__ Pop(edx); __ Pop(edx);

View File

@ -1077,7 +1077,11 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
static void Generate_InterpreterPushArgs(MacroAssembler* masm, static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register num_args, Register index, Register num_args, Register index,
Register scratch, Register scratch2) { Register scratch, Register scratch2,
Label* stack_overflow) {
Generate_StackOverflowCheck(masm, num_args, scratch, scratch2,
stack_overflow);
// Find the address of the last argument. // Find the address of the last argument.
__ mov(scratch2, num_args); __ mov(scratch2, num_args);
__ sll(scratch2, scratch2, kPointerSizeLog2); __ sll(scratch2, scratch2, kPointerSizeLog2);
@ -1095,9 +1099,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver) // -- a0 : the number of arguments (not including the receiver)
// -- a2 : the address of the first argument to be pushed. Subsequent // -- a2 : the address of the first argument to be pushed. Subsequent
@ -1109,16 +1113,8 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
__ Addu(t0, a0, Operand(1)); // Add one for receiver. __ 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. // This function modifies a2, t4 and t1.
Generate_InterpreterPushArgs(masm, t0, a2, t4, t1); Generate_InterpreterPushArgs(masm, t0, a2, t4, t1, &stack_overflow);
// Call the target. // Call the target.
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1143,7 +1139,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : argument count (not including receiver) // -- a0 : argument count (not including receiver)
@ -1157,10 +1153,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Push a slot for the receiver. // Push a slot for the receiver.
__ push(zero_reg); __ push(zero_reg);
Generate_StackOverflowCheck(masm, a0, t1, t0, &stack_overflow);
// This function modified t4, t1 and t0. // This function modified t4, t1 and t0.
Generate_InterpreterPushArgs(masm, a0, t4, t1, t0); Generate_InterpreterPushArgs(masm, a0, t4, t1, t0, &stack_overflow);
__ AssertUndefinedOrAllocationSite(a2, t0); __ AssertUndefinedOrAllocationSite(a2, t0);
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1191,7 +1185,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver) // -- a0 : the number of arguments (not including the receiver)
@ -1203,13 +1197,10 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// ----------------------------------- // -----------------------------------
Label stack_overflow; Label stack_overflow;
// Push a slot for the receiver. __ Addu(t0, a0, Operand(1)); // Add one for receiver.
__ push(zero_reg);
Generate_StackOverflowCheck(masm, a0, t1, t4, &stack_overflow); // This function modifies a3, t4, and t1.
Generate_InterpreterPushArgs(masm, t0, a3, 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. // ArrayConstructor stub expects constructor in a3. Set it here.
__ mov(a3, a1); __ mov(a3, a1);

View File

@ -1070,7 +1070,11 @@ static void Generate_StackOverflowCheck(MacroAssembler* masm, Register num_args,
static void Generate_InterpreterPushArgs(MacroAssembler* masm, static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register num_args, Register index, Register num_args, Register index,
Register scratch, Register scratch2) { Register scratch, Register scratch2,
Label* stack_overflow) {
// Generate_StackOverflowCheck(masm, num_args, scratch, scratch2,
// stack_overflow);
// Find the address of the last argument. // Find the address of the last argument.
__ mov(scratch2, num_args); __ mov(scratch2, num_args);
__ dsll(scratch2, scratch2, kPointerSizeLog2); __ dsll(scratch2, scratch2, kPointerSizeLog2);
@ -1088,9 +1092,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver) // -- a0 : the number of arguments (not including the receiver)
// -- a2 : the address of the first argument to be pushed. Subsequent // -- a2 : the address of the first argument to be pushed. Subsequent
@ -1102,16 +1106,8 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
__ Daddu(a3, a0, Operand(1)); // Add one for receiver. __ 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. // This function modifies a2, t0 and a4.
Generate_InterpreterPushArgs(masm, a3, a2, a4, t0); Generate_InterpreterPushArgs(masm, a3, a2, a4, t0, &stack_overflow);
// Call the target. // Call the target.
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1136,7 +1132,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : argument count (not including receiver) // -- a0 : argument count (not including receiver)
@ -1150,10 +1146,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Push a slot for the receiver. // Push a slot for the receiver.
__ push(zero_reg); __ push(zero_reg);
Generate_StackOverflowCheck(masm, a0, a5, t0, &stack_overflow);
// This function modifies t0, a4 and a5. // This function modifies t0, a4 and a5.
Generate_InterpreterPushArgs(masm, a0, a4, a5, t0); Generate_InterpreterPushArgs(masm, a0, a4, a5, t0, &stack_overflow);
__ AssertUndefinedOrAllocationSite(a2, t0); __ AssertUndefinedOrAllocationSite(a2, t0);
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
@ -1184,7 +1178,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- a0 : the number of arguments (not including the receiver) // -- a0 : the number of arguments (not including the receiver)
@ -1196,13 +1190,10 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// ----------------------------------- // -----------------------------------
Label stack_overflow; Label stack_overflow;
// Push a slot for the receiver. __ Daddu(a4, a0, Operand(1)); // Add one for receiver.
__ push(zero_reg);
Generate_StackOverflowCheck(masm, a4, a5, a6, &stack_overflow);
// This function modifies a3, a5 and a6. // This function modifies a3, a5 and a6.
Generate_InterpreterPushArgs(masm, a4, a3, a5, a6); Generate_InterpreterPushArgs(masm, a4, a3, a5, a6, &stack_overflow);
// ArrayConstructor stub expects constructor in a3. Set it here. // ArrayConstructor stub expects constructor in a3. Set it here.
__ mov(a3, a1); __ mov(a3, a1);

View File

@ -1112,7 +1112,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
@ -1153,7 +1153,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : argument count (not including receiver) // -- r3 : argument count (not including receiver)
@ -1206,7 +1206,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r3 : argument count (not including receiver) // -- r3 : argument count (not including receiver)

View File

@ -1118,7 +1118,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
@ -1159,7 +1159,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : argument count (not including receiver) // -- r2 : argument count (not including receiver)
@ -1211,7 +1211,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- r2 : argument count (not including receiver) // -- r2 : argument count (not including receiver)

View File

@ -823,9 +823,9 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, ConvertReceiverMode receiver_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver) // -- rax : the number of arguments (not including the receiver)
// -- rbx : the address of the first argument to be pushed. Subsequent // -- rbx : the address of the first argument to be pushed. Subsequent
@ -845,12 +845,6 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
// Pop return address to allow tail-call after pushing arguments. // Pop return address to allow tail-call after pushing arguments.
__ PopReturnAddressTo(kScratchRegister); __ 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. // rbx and rdx will be modified.
Generate_InterpreterPushArgs(masm, rcx, rbx, rdx); Generate_InterpreterPushArgs(masm, rcx, rbx, rdx);
@ -858,14 +852,15 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
__ PushReturnAddressFrom(kScratchRegister); // Re-push return address. __ PushReturnAddressFrom(kScratchRegister); // Re-push return address.
if (mode == InterpreterPushArgsMode::kJSFunction) { if (mode == InterpreterPushArgsMode::kJSFunction) {
__ Jump(masm->isolate()->builtins()->CallFunction(receiver_mode, __ Jump(masm->isolate()->builtins()->CallFunction(ConvertReceiverMode::kAny,
tail_call_mode), tail_call_mode),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} else if (mode == InterpreterPushArgsMode::kWithFinalSpread) { } else if (mode == InterpreterPushArgsMode::kWithFinalSpread) {
__ Jump(masm->isolate()->builtins()->CallWithSpread(), __ Jump(masm->isolate()->builtins()->CallWithSpread(),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} else { } else {
__ Jump(masm->isolate()->builtins()->Call(receiver_mode, tail_call_mode), __ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
tail_call_mode),
RelocInfo::CODE_TARGET); RelocInfo::CODE_TARGET);
} }
@ -879,7 +874,7 @@ void Builtins::Generate_InterpreterPushArgsThenCallImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver) // -- rax : the number of arguments (not including the receiver)
@ -939,7 +934,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- rax : the number of arguments (not including the receiver) // -- rax : the number of arguments (not including the receiver)
@ -953,6 +948,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// Number of values to be pushed. // Number of values to be pushed.
__ Move(r8, rax); __ Move(r8, rax);
__ addp(r8, Immediate(1)); // Add one for receiver.
// Add a stack check before pushing arguments. // Add a stack check before pushing arguments.
Generate_StackOverflowCheck(masm, r8, rdi, &stack_overflow); Generate_StackOverflowCheck(masm, r8, rdi, &stack_overflow);
@ -960,9 +956,6 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// Pop return address to allow tail-call after pushing arguments. // Pop return address to allow tail-call after pushing arguments.
__ PopReturnAddressTo(kScratchRegister); __ PopReturnAddressTo(kScratchRegister);
// Push slot for the receiver to be constructed.
__ Push(Immediate(0));
// rcx and rdi will be modified. // rcx and rdi will be modified.
Generate_InterpreterPushArgs(masm, r8, rcx, rdi); Generate_InterpreterPushArgs(masm, r8, rcx, rdi);

View File

@ -694,7 +694,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenCallImpl( void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode, MacroAssembler* masm, TailCallMode tail_call_mode,
InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
@ -758,7 +758,7 @@ namespace {
// This function modified start_addr, and only reads the contents of num_args // This function modified start_addr, and only reads the contents of num_args
// register. scratch1 and scratch2 are used as temporary registers. Their // register. scratch1 and scratch2 are used as temporary registers. Their
// original values are restored after the use. // original values are restored after the use.
void Generate_InterpreterPushArgsThenReturnAddress( void Generate_InterpreterPushArgsAndReturnAddress(
MacroAssembler* masm, Register num_args, Register start_addr, MacroAssembler* masm, Register num_args, Register start_addr,
Register scratch1, Register scratch2, bool receiver_in_args, Register scratch1, Register scratch2, bool receiver_in_args,
int num_slots_above_ret_addr, Label* stack_overflow) { int num_slots_above_ret_addr, Label* stack_overflow) {
@ -847,7 +847,7 @@ void Generate_InterpreterPushArgsThenReturnAddress(
} // end anonymous namespace } // end anonymous namespace
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructImpl( void Builtins::Generate_InterpreterPushArgsAndConstructImpl(
MacroAssembler* masm, InterpreterPushArgsMode mode) { MacroAssembler* masm, InterpreterPushArgsMode mode) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
@ -866,8 +866,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
// Push arguments and move return address to the top of stack. // Push arguments and move return address to the top of stack.
// The eax register is readonly. The ecx register will be modified. The edx // 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. // and edi registers will be modified but restored to their original values.
Generate_InterpreterPushArgsThenReturnAddress(masm, eax, ecx, edx, edi, false, Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, false,
2, &stack_overflow); 2, &stack_overflow);
// Restore edi and edx // Restore edi and edx
__ Pop(edx); __ Pop(edx);
@ -907,7 +907,7 @@ void Builtins::Generate_InterpreterPushArgsThenConstructImpl(
} }
// static // static
void Builtins::Generate_InterpreterPushArgsThenConstructArray( void Builtins::Generate_InterpreterPushArgsAndConstructArray(
MacroAssembler* masm) { MacroAssembler* masm) {
// ----------- S t a t e ------------- // ----------- S t a t e -------------
// -- eax : the number of arguments (not including the receiver) // -- eax : the number of arguments (not including the receiver)
@ -925,8 +925,8 @@ void Builtins::Generate_InterpreterPushArgsThenConstructArray(
// Push arguments and move return address to the top of stack. // Push arguments and move return address to the top of stack.
// The eax register is readonly. The ecx register will be modified. The edx // 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. // and edi registers will be modified but restored to their original values.
Generate_InterpreterPushArgsThenReturnAddress(masm, eax, ecx, edx, edi, true, Generate_InterpreterPushArgsAndReturnAddress(masm, eax, ecx, edx, edi, true,
1, &stack_overflow); 1, &stack_overflow);
// Restore edx. // Restore edx.
__ Pop(edx); __ Pop(edx);

View File

@ -464,25 +464,25 @@ Callable CodeFactory::ConstructFunction(Isolate* isolate) {
} }
// static // static
Callable CodeFactory::InterpreterPushArgsThenCall( Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
Isolate* isolate, ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode) { InterpreterPushArgsMode mode) {
return Callable(isolate->builtins()->InterpreterPushArgsThenCall( return Callable(
receiver_mode, tail_call_mode, mode), isolate->builtins()->InterpreterPushArgsAndCall(tail_call_mode, mode),
InterpreterPushArgsThenCallDescriptor(isolate)); InterpreterPushArgsAndCallDescriptor(isolate));
} }
// static // static
Callable CodeFactory::InterpreterPushArgsThenConstruct( Callable CodeFactory::InterpreterPushArgsAndConstruct(
Isolate* isolate, InterpreterPushArgsMode mode) { Isolate* isolate, InterpreterPushArgsMode mode) {
return Callable(isolate->builtins()->InterpreterPushArgsThenConstruct(mode), return Callable(isolate->builtins()->InterpreterPushArgsAndConstruct(mode),
InterpreterPushArgsThenConstructDescriptor(isolate)); InterpreterPushArgsAndConstructDescriptor(isolate));
} }
// static // static
Callable CodeFactory::InterpreterPushArgsThenConstructArray(Isolate* isolate) { Callable CodeFactory::InterpreterPushArgsAndConstructArray(Isolate* isolate) {
return Callable(isolate->builtins()->InterpreterPushArgsThenConstructArray(), return Callable(isolate->builtins()->InterpreterPushArgsAndConstructArray(),
InterpreterPushArgsThenConstructArrayDescriptor(isolate)); InterpreterPushArgsAndConstructArrayDescriptor(isolate));
} }
// static // static

View File

@ -173,13 +173,12 @@ class V8_EXPORT_PRIVATE CodeFactory final {
static Callable HasProperty(Isolate* isolate); static Callable HasProperty(Isolate* isolate);
static Callable ForInFilter(Isolate* isolate); static Callable ForInFilter(Isolate* isolate);
static Callable InterpreterPushArgsThenCall(Isolate* isolate, static Callable InterpreterPushArgsAndCall(Isolate* isolate,
ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode,
TailCallMode tail_call_mode, InterpreterPushArgsMode mode);
InterpreterPushArgsMode mode); static Callable InterpreterPushArgsAndConstruct(Isolate* isolate,
static Callable InterpreterPushArgsThenConstruct( InterpreterPushArgsMode mode);
Isolate* isolate, InterpreterPushArgsMode mode); static Callable InterpreterPushArgsAndConstructArray(Isolate* isolate);
static Callable InterpreterPushArgsThenConstructArray(Isolate* isolate);
static Callable InterpreterCEntry(Isolate* isolate, int result_size = 1); static Callable InterpreterCEntry(Isolate* isolate, int result_size = 1);
static Callable InterpreterOnStackReplacement(Isolate* isolate); static Callable InterpreterOnStackReplacement(Isolate* isolate);

View File

@ -1342,55 +1342,37 @@ void BytecodeGraphBuilder::VisitCreateObjectLiteral() {
} }
Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegister( Node* const* BytecodeGraphBuilder::GetCallArgumentsFromRegister(
Node* callee, Node* receiver, interpreter::Register first_arg, Node* callee, interpreter::Register receiver, size_t arity) {
int arg_count) { Node** all = local_zone()->NewArray<Node*>(static_cast<int>(arity));
// The arity of the Call node -- includes the callee, receiver and function
// arguments.
int arity = 2 + arg_count;
Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
all[0] = callee; all[0] = callee;
all[1] = receiver; all[1] = environment()->LookupRegister(receiver);
int receiver_index = receiver.index();
// The function arguments are in consecutive registers. for (int i = 2; i < static_cast<int>(arity); ++i) {
int arg_base = first_arg.index(); all[i] = environment()->LookupRegister(
for (int i = 0; i < arg_count; ++i) { interpreter::Register(receiver_index + i - 1));
all[2 + i] =
environment()->LookupRegister(interpreter::Register(arg_base + i));
} }
return all; return all;
} }
Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
Node* const* args, Node* const* args,
int arg_count) { size_t arg_count) {
return MakeNode(call_op, arg_count, args, false); return MakeNode(call_op, static_cast<int>(arg_count), args, false);
} }
Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op, Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
Node* callee, Node* callee,
interpreter::Register receiver, interpreter::Register receiver,
size_t reg_count) { size_t arg_count) {
Node* receiver_node = environment()->LookupRegister(receiver); return ProcessCallArguments(
// The receiver is followed by the arguments in the consecutive registers. call_op, GetCallArgumentsFromRegister(callee, receiver, arg_count),
DCHECK_GE(reg_count, 1); arg_count);
interpreter::Register first_arg = interpreter::Register(receiver.index() + 1);
int arg_count = static_cast<int>(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, void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode,
ConvertReceiverMode receiver_mode, ConvertReceiverMode receiver_hint,
Node* const* args, size_t arg_count, Node* const* args, size_t arg_count,
int slot_id) { int slot_id) {
DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
bytecode_iterator().current_bytecode()),
receiver_mode);
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
// Slot index of 0 is used indicate no feedback slot is available. Assert // Slot index of 0 is used indicate no feedback slot is available. Assert
@ -1400,51 +1382,63 @@ void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode,
float const frequency = ComputeCallFrequency(slot_id); float const frequency = ComputeCallFrequency(slot_id);
const Operator* call = javascript()->Call(arg_count, frequency, feedback, const Operator* call = javascript()->Call(arg_count, frequency, feedback,
receiver_mode, tail_call_mode); receiver_hint, tail_call_mode);
Node* value = ProcessCallArguments(call, args, static_cast<int>(arg_count)); Node* value = ProcessCallArguments(call, args, arg_count);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
void BytecodeGraphBuilder::BuildCallVarArgs(TailCallMode tail_call_mode, void BytecodeGraphBuilder::BuildCallVarArgs(TailCallMode tail_call_mode,
ConvertReceiverMode receiver_mode) { ConvertReceiverMode receiver_hint) {
DCHECK_EQ(interpreter::Bytecodes::GetReceiverMode(
bytecode_iterator().current_bytecode()),
receiver_mode);
Node* callee = Node* callee =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
int const slot_id = bytecode_iterator().GetIndexOperand(3); int const slot_id = bytecode_iterator().GetIndexOperand(3);
BuildCall(tail_call_mode, receiver_hint,
Node* receiver_node; GetCallArgumentsFromRegister(callee, receiver, arg_count + 1),
interpreter::Register first_arg; arg_count + 1, slot_id);
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<int>(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<int>(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<size_t>(2 + arg_count), slot_id);
} }
void BytecodeGraphBuilder::VisitCallAnyReceiver() { void BytecodeGraphBuilder::VisitCall() {
BuildCallVarArgs(TailCallMode::kDisallow, ConvertReceiverMode::kAny); 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() { void BytecodeGraphBuilder::VisitCallProperty() {
BuildCallVarArgs(TailCallMode::kDisallow, BuildCallVarArgs(TailCallMode::kDisallow,
ConvertReceiverMode::kNotNullOrUndefined); ConvertReceiverMode::kNotNullOrUndefined);
@ -1486,54 +1480,16 @@ void BytecodeGraphBuilder::VisitCallProperty2() {
{callee, receiver, arg0, arg1}, slot_id); {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() { void BytecodeGraphBuilder::VisitCallWithSpread() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Node* callee = Node* callee =
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
const Operator* call = const Operator* call =
javascript()->CallWithSpread(static_cast<int>(reg_count + 1)); javascript()->CallWithSpread(static_cast<int>(arg_count + 1));
Node* value = ProcessCallArguments(call, callee, receiver, reg_count); Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
@ -1550,127 +1506,118 @@ void BytecodeGraphBuilder::VisitCallJSRuntime() {
Node* callee = Node* callee =
BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0)); BuildLoadNativeContextField(bytecode_iterator().GetIndexOperand(0));
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
// Create node to perform the JS runtime call. // Create node to perform the JS runtime call.
const Operator* call = javascript()->Call(reg_count + 1); const Operator* call = javascript()->Call(arg_count + 1);
Node* value = ProcessCallArguments(call, callee, receiver, reg_count); Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments( Node* BytecodeGraphBuilder::ProcessCallRuntimeArguments(
const Operator* call_runtime_op, interpreter::Register receiver, const Operator* call_runtime_op, interpreter::Register first_arg,
size_t reg_count) { size_t arity) {
int arg_count = static_cast<int>(reg_count); Node** all = local_zone()->NewArray<Node*>(arity);
// arity is args. int first_arg_index = first_arg.index();
int arity = arg_count; for (int i = 0; i < static_cast<int>(arity); ++i) {
Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
int first_arg_index = receiver.index();
for (int i = 0; i < static_cast<int>(reg_count); ++i) {
all[i] = environment()->LookupRegister( all[i] = environment()->LookupRegister(
interpreter::Register(first_arg_index + i)); interpreter::Register(first_arg_index + i));
} }
Node* value = MakeNode(call_runtime_op, arity, all, false); Node* value = MakeNode(call_runtime_op, static_cast<int>(arity), all, false);
return value; return value;
} }
void BytecodeGraphBuilder::VisitCallRuntime() { void BytecodeGraphBuilder::VisitCallRuntime() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
// Create node to perform the runtime call. // Create node to perform the runtime call.
const Operator* call = javascript()->CallRuntime(functionId, reg_count); const Operator* call = javascript()->CallRuntime(functionId, arg_count);
Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
void BytecodeGraphBuilder::VisitCallRuntimeForPair() { void BytecodeGraphBuilder::VisitCallRuntimeForPair() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0); Runtime::FunctionId functionId = bytecode_iterator().GetRuntimeIdOperand(0);
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
interpreter::Register first_return = interpreter::Register first_return =
bytecode_iterator().GetRegisterOperand(3); bytecode_iterator().GetRegisterOperand(3);
// Create node to perform the runtime call. // Create node to perform the runtime call.
const Operator* call = javascript()->CallRuntime(functionId, reg_count); const Operator* call = javascript()->CallRuntime(functionId, arg_count);
Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count); Node* return_pair = ProcessCallRuntimeArguments(call, first_arg, arg_count);
environment()->BindRegistersToProjections(first_return, return_pair, environment()->BindRegistersToProjections(first_return, return_pair,
Environment::kAttachFrameState); Environment::kAttachFrameState);
} }
Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments( Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments(
const Operator* op, Node* callee, Node* new_target, const Operator* op, Node* callee, Node* new_target,
interpreter::Register receiver, size_t reg_count) { interpreter::Register first_arg, size_t arity) {
int arg_count = static_cast<int>(reg_count); Node** all = local_zone()->NewArray<Node*>(arity);
// arity is args + callee and new target.
int arity = arg_count + 2;
Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
all[0] = callee; all[0] = callee;
int first_arg_index = receiver.index(); int first_arg_index = first_arg.index();
for (int i = 0; i < arg_count; ++i) { for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
all[1 + i] = environment()->LookupRegister( all[i] = environment()->LookupRegister(
interpreter::Register(first_arg_index + i)); interpreter::Register(first_arg_index + i - 1));
} }
all[arity - 1] = new_target; all[arity - 1] = new_target;
Node* value = MakeNode(op, arity, all, false); Node* value = MakeNode(op, static_cast<int>(arity), all, false);
return value; return value;
} }
void BytecodeGraphBuilder::VisitConstructWithSpread() { void BytecodeGraphBuilder::VisitConstructWithSpread() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
Node* new_target = environment()->LookupAccumulator(); Node* new_target = environment()->LookupAccumulator();
Node* callee = environment()->LookupRegister(callee_reg); Node* callee = environment()->LookupRegister(callee_reg);
const Operator* op = const Operator* op =
javascript()->ConstructWithSpread(static_cast<uint32_t>(reg_count + 2)); javascript()->ConstructWithSpread(static_cast<int>(arg_count) + 2);
Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target, Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target,
receiver, reg_count); first_arg, arg_count + 2);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
void BytecodeGraphBuilder::VisitInvokeIntrinsic() { void BytecodeGraphBuilder::VisitInvokeIntrinsic() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0);
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
// Create node to perform the runtime call. Turbofan will take care of the // Create node to perform the runtime call. Turbofan will take care of the
// lowering. // lowering.
const Operator* call = javascript()->CallRuntime(functionId, reg_count); const Operator* call = javascript()->CallRuntime(functionId, arg_count);
Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); Node* value = ProcessCallRuntimeArguments(call, first_arg, arg_count);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }
Node* BytecodeGraphBuilder::ProcessConstructArguments( Node* BytecodeGraphBuilder::ProcessConstructArguments(
const Operator* call_new_op, Node* callee, Node* new_target, const Operator* call_new_op, Node* callee, Node* new_target,
interpreter::Register receiver, size_t reg_count) { interpreter::Register first_arg, size_t arity) {
int arg_count = static_cast<int>(reg_count); Node** all = local_zone()->NewArray<Node*>(arity);
// arity is args + callee and new target.
int arity = arg_count + 2;
Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity));
all[0] = callee; all[0] = callee;
int first_arg_index = receiver.index(); int first_arg_index = first_arg.index();
for (int i = 0; i < arg_count; ++i) { for (int i = 1; i < static_cast<int>(arity) - 1; ++i) {
all[1 + i] = environment()->LookupRegister( all[i] = environment()->LookupRegister(
interpreter::Register(first_arg_index + i)); interpreter::Register(first_arg_index + i - 1));
} }
all[arity - 1] = new_target; all[arity - 1] = new_target;
Node* value = MakeNode(call_new_op, arity, all, false); Node* value = MakeNode(call_new_op, static_cast<int>(arity), all, false);
return value; return value;
} }
void BytecodeGraphBuilder::VisitConstruct() { void BytecodeGraphBuilder::VisitConstruct() {
PrepareEagerCheckpoint(); PrepareEagerCheckpoint();
interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0);
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); interpreter::Register first_arg = bytecode_iterator().GetRegisterOperand(1);
size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
// Slot index of 0 is used indicate no feedback slot is available. Assert // 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. // the assumption that slot index 0 is never a valid feedback slot.
STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0);
@ -1682,9 +1629,9 @@ void BytecodeGraphBuilder::VisitConstruct() {
float const frequency = ComputeCallFrequency(slot_id); float const frequency = ComputeCallFrequency(slot_id);
const Operator* call = javascript()->Construct( const Operator* call = javascript()->Construct(
static_cast<uint32_t>(reg_count + 2), frequency, feedback); static_cast<int>(arg_count) + 2, frequency, feedback);
Node* value = Node* value = ProcessConstructArguments(call, callee, new_target, first_arg,
ProcessConstructArguments(call, callee, new_target, receiver, reg_count); arg_count + 2);
environment()->BindAccumulator(value, Environment::kAttachFrameState); environment()->BindAccumulator(value, Environment::kAttachFrameState);
} }

View File

@ -112,24 +112,24 @@ class BytecodeGraphBuilder {
Node** EnsureInputBufferSize(int size); Node** EnsureInputBufferSize(int size);
Node* const* GetCallArgumentsFromRegister(Node* callee, Node* receiver, Node* const* GetCallArgumentsFromRegister(Node* callee,
interpreter::Register first_arg, interpreter::Register first_arg,
int arg_count); size_t arity);
Node* ProcessCallArguments(const Operator* call_op, Node* const* args, Node* ProcessCallArguments(const Operator* call_op, Node* const* args,
int arg_count); size_t arg_count);
Node* ProcessCallArguments(const Operator* call_op, Node* callee, Node* ProcessCallArguments(const Operator* call_op, Node* callee,
interpreter::Register receiver, size_t reg_count); interpreter::Register receiver, size_t arity);
Node* ProcessConstructArguments(const Operator* call_new_op, Node* callee, Node* ProcessConstructArguments(const Operator* call_new_op, Node* callee,
Node* new_target, Node* new_target,
interpreter::Register receiver, interpreter::Register first_arg,
size_t reg_count); size_t arity);
Node* ProcessConstructWithSpreadArguments(const Operator* op, Node* callee, Node* ProcessConstructWithSpreadArguments(const Operator* op, Node* callee,
Node* new_target, Node* new_target,
interpreter::Register receiver, interpreter::Register first_arg,
size_t reg_count); size_t arity);
Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op, Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
interpreter::Register receiver, interpreter::Register first_arg,
size_t reg_count); size_t arity);
// Prepare information for eager deoptimization. This information is carried // Prepare information for eager deoptimization. This information is carried
// by dedicated {Checkpoint} nodes that are wired into the effect chain. // by dedicated {Checkpoint} nodes that are wired into the effect chain.
@ -159,12 +159,12 @@ class BytecodeGraphBuilder {
void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode); void BuildLdaLookupGlobalSlot(TypeofMode typeof_mode);
void BuildStaLookupSlot(LanguageMode language_mode); void BuildStaLookupSlot(LanguageMode language_mode);
void BuildCallVarArgs(TailCallMode tail_call_mode, void BuildCallVarArgs(TailCallMode tail_call_mode,
ConvertReceiverMode receiver_mode); ConvertReceiverMode receiver_hint);
void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_mode, void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_hint,
Node* const* args, size_t arg_count, int slot_id); Node* const* args, size_t arg_count, int slot_id);
void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_mode, void BuildCall(TailCallMode tail_call_mode, ConvertReceiverMode receiver_hint,
std::initializer_list<Node*> args, int slot_id) { std::initializer_list<Node*> args, int slot_id) {
BuildCall(tail_call_mode, receiver_mode, args.begin(), args.size(), BuildCall(tail_call_mode, receiver_hint, args.begin(), args.size(),
slot_id); slot_id);
} }
void BuildBinaryOp(const Operator* op); void BuildBinaryOp(const Operator* op);

View File

@ -318,7 +318,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
@ -328,7 +328,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
@ -340,8 +340,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
edx, // target to the call. It is checked to be Array function. edx, // target to the call. It is checked to be Array function.

View File

@ -607,7 +607,7 @@ void InterpreterDispatchDescriptor::InitializePlatformIndependent(
machine_types); machine_types);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformIndependent( void InterpreterPushArgsAndCallDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// kNumberOfArguments, kFirstArgument, kFunction // kNumberOfArguments, kFirstArgument, kFunction
MachineType machine_types[] = {MachineType::Int32(), MachineType::Pointer(), MachineType machine_types[] = {MachineType::Int32(), MachineType::Pointer(),
@ -616,7 +616,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformIndependent(
machine_types); machine_types);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformIndependent( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformIndependent(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
// kNumberOfArguments, kNewTarget, kConstructor, kFeedbackElement, // kNumberOfArguments, kNewTarget, kConstructor, kFeedbackElement,
// kFirstArgument // kFirstArgument
@ -627,7 +627,7 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformIndependent(
machine_types); machine_types);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::
InitializePlatformIndependent(CallInterfaceDescriptorData* data) { InitializePlatformIndependent(CallInterfaceDescriptorData* data) {
// kNumberOfArguments, kFunction, kFeedbackElement, kFirstArgument // kNumberOfArguments, kFunction, kFeedbackElement, kFirstArgument
MachineType machine_types[] = {MachineType::Int32(), MachineType::AnyTagged(), MachineType machine_types[] = {MachineType::Int32(), MachineType::AnyTagged(),

View File

@ -79,9 +79,9 @@ class PlatformInterfaceDescriptor;
V(GrowArrayElements) \ V(GrowArrayElements) \
V(NewArgumentsElements) \ V(NewArgumentsElements) \
V(InterpreterDispatch) \ V(InterpreterDispatch) \
V(InterpreterPushArgsThenCall) \ V(InterpreterPushArgsAndCall) \
V(InterpreterPushArgsThenConstruct) \ V(InterpreterPushArgsAndConstruct) \
V(InterpreterPushArgsThenConstructArray) \ V(InterpreterPushArgsAndConstructArray) \
V(InterpreterCEntry) \ V(InterpreterCEntry) \
V(ResumeGenerator) \ V(ResumeGenerator) \
V(FrameDropperTrampoline) \ V(FrameDropperTrampoline) \
@ -839,29 +839,30 @@ class V8_EXPORT_PRIVATE InterpreterDispatchDescriptor
CallInterfaceDescriptor) CallInterfaceDescriptor)
}; };
class InterpreterPushArgsThenCallDescriptor : public CallInterfaceDescriptor { class InterpreterPushArgsAndCallDescriptor : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kNumberOfArguments, kFirstArgument, kFunction) DEFINE_PARAMETERS(kNumberOfArguments, kFirstArgument, kFunction)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE( DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
InterpreterPushArgsThenCallDescriptor, CallInterfaceDescriptor) InterpreterPushArgsAndCallDescriptor, CallInterfaceDescriptor)
}; };
class InterpreterPushArgsThenConstructDescriptor
class InterpreterPushArgsAndConstructDescriptor
: public CallInterfaceDescriptor { : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kNumberOfArguments, kNewTarget, kConstructor, DEFINE_PARAMETERS(kNumberOfArguments, kNewTarget, kConstructor,
kFeedbackElement, kFirstArgument) kFeedbackElement, kFirstArgument)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE( DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
InterpreterPushArgsThenConstructDescriptor, CallInterfaceDescriptor) InterpreterPushArgsAndConstructDescriptor, CallInterfaceDescriptor)
}; };
class InterpreterPushArgsThenConstructArrayDescriptor class InterpreterPushArgsAndConstructArrayDescriptor
: public CallInterfaceDescriptor { : public CallInterfaceDescriptor {
public: public:
DEFINE_PARAMETERS(kNumberOfArguments, kFunction, kFeedbackElement, DEFINE_PARAMETERS(kNumberOfArguments, kFunction, kFeedbackElement,
kFirstArgument) kFirstArgument)
DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE( DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(
InterpreterPushArgsThenConstructArrayDescriptor, CallInterfaceDescriptor) InterpreterPushArgsAndConstructArrayDescriptor, CallInterfaceDescriptor)
}; };
class InterpreterCEntryDescriptor : public CallInterfaceDescriptor { class InterpreterCEntryDescriptor : public CallInterfaceDescriptor {

View File

@ -1252,50 +1252,42 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::MarkTryEnd(int handler_id) {
return *this; return *this;
} }
BytecodeArrayBuilder& BytecodeArrayBuilder::CallProperty(Register callable, BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
RegisterList args, RegisterList args,
int feedback_slot) { int feedback_slot,
if (args.register_count() == 1) { Call::CallType call_type,
OutputCallProperty0(callable, args[0], feedback_slot); TailCallMode tail_call_mode) {
} else if (args.register_count() == 2) { if (tail_call_mode == TailCallMode::kDisallow) {
OutputCallProperty1(callable, args[0], args[1], feedback_slot); if (call_type == Call::NAMED_PROPERTY_CALL ||
} else if (args.register_count() == 3) { call_type == Call::KEYED_PROPERTY_CALL) {
OutputCallProperty2(callable, args[0], args[1], args[2], 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 {
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);
}
}
} else { } else {
OutputCallProperty(callable, args, args.register_count(), feedback_slot); DCHECK(tail_call_mode == TailCallMode::kAllow);
OutputTailCall(callable, args, args.register_count(), feedback_slot);
} }
return *this; 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, BytecodeArrayBuilder& BytecodeArrayBuilder::CallWithSpread(Register callable,
RegisterList args) { RegisterList args) {
OutputCallWithSpread(callable, args, args.register_count()); OutputCallWithSpread(callable, args, args.register_count());

View File

@ -238,35 +238,14 @@ class V8_EXPORT_PRIVATE BytecodeArrayBuilder final
// Pop the current context and replace with |context|. // Pop the current context and replace with |context|.
BytecodeArrayBuilder& PopContext(Register context); BytecodeArrayBuilder& PopContext(Register context);
// Call a JS function which is known to be a property of a JS object. The // Call a JS function. The JSFunction or Callable to be called should be in
// JSFunction or Callable to be called should be in |callable|. The arguments // |callable|. The arguments should be in |args|, with the receiver in
// should be in |args|, with the receiver in |args[0]|. The call type of the // |args[0]|. The call type of the expression is in |call_type|. Type feedback
// expression is in |call_type|. Type feedback is recorded in the // is recorded in the |feedback_slot| in the type feedback vector.
// |feedback_slot| in the type feedback vector. BytecodeArrayBuilder& Call(
BytecodeArrayBuilder& CallProperty(Register callable, RegisterList args, Register callable, RegisterList args, int feedback_slot,
int feedback_slot); Call::CallType call_type,
TailCallMode tail_call_mode = TailCallMode::kDisallow);
// 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 // 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]| // |callable|, the receiver in |args[0]| and the arguments in |args[1]|

View File

@ -2597,12 +2597,6 @@ void BytecodeGenerator::VisitCall(Call* expr) {
Register callee = register_allocator()->NewRegister(); Register callee = register_allocator()->NewRegister();
RegisterList args = register_allocator()->NewGrowableRegisterList(); 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, // 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 // see if we can reduce the number by adding a separate argument which
// specifies the call type (e.g., property, spread, tailcall, etc.). // specifies the call type (e.g., property, spread, tailcall, etc.).
@ -2619,13 +2613,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
} }
case Call::GLOBAL_CALL: { case Call::GLOBAL_CALL: {
// Receiver is undefined for global calls. // Receiver is undefined for global calls.
if (!is_tail_call && !is_spread_call) { BuildPushUndefinedIntoRegisterList(&args);
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. // Load callee as a global variable.
VariableProxy* proxy = callee_expr->AsVariableProxy(); VariableProxy* proxy = callee_expr->AsVariableProxy();
BuildVariableLoadForAccumulatorValue(proxy->var(), BuildVariableLoadForAccumulatorValue(proxy->var(),
@ -2645,7 +2633,6 @@ void BytecodeGenerator::VisitCall(Call* expr) {
DCHECK(Register::AreContiguous(callee, receiver)); DCHECK(Register::AreContiguous(callee, receiver));
RegisterList result_pair(callee.index(), 2); RegisterList result_pair(callee.index(), 2);
USE(receiver); USE(receiver);
Variable* variable = callee_expr->AsVariableProxy()->var(); Variable* variable = callee_expr->AsVariableProxy()->var();
builder() builder()
->LoadLiteral(variable->raw_name()) ->LoadLiteral(variable->raw_name())
@ -2656,14 +2643,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
break; break;
} }
case Call::OTHER_CALL: { case Call::OTHER_CALL: {
// Receiver is undefined for other 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);
}
VisitForRegisterValue(callee_expr, callee); VisitForRegisterValue(callee_expr, callee);
break; break;
} }
@ -2689,9 +2669,7 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// Evaluate all arguments to the function call and store in sequential args // Evaluate all arguments to the function call and store in sequential args
// registers. // registers.
VisitArguments(expr->arguments(), &args); VisitArguments(expr->arguments(), &args);
int reciever_arg_count = implicit_undefined_receiver ? 0 : 1; CHECK_EQ(expr->arguments()->length() + 1, args.register_count());
CHECK_EQ(reciever_arg_count + expr->arguments()->length(),
args.register_count());
// Resolve callee for a potential direct eval call. This block will mutate the // Resolve callee for a potential direct eval call. This block will mutate the
// callee value. // callee value.
@ -2700,11 +2678,10 @@ void BytecodeGenerator::VisitCall(Call* expr) {
// Set up arguments for ResolvePossiblyDirectEval by copying callee, source // Set up arguments for ResolvePossiblyDirectEval by copying callee, source
// strings and function closure, and loading language and // strings and function closure, and loading language and
// position. // position.
Register first_arg = args[reciever_arg_count];
RegisterList runtime_call_args = register_allocator()->NewRegisterList(6); RegisterList runtime_call_args = register_allocator()->NewRegisterList(6);
builder() builder()
->MoveRegister(callee, runtime_call_args[0]) ->MoveRegister(callee, runtime_call_args[0])
.MoveRegister(first_arg, runtime_call_args[1]) .MoveRegister(args[1], runtime_call_args[1])
.MoveRegister(Register::function_closure(), runtime_call_args[2]) .MoveRegister(Register::function_closure(), runtime_call_args[2])
.LoadLiteral(Smi::FromInt(language_mode())) .LoadLiteral(Smi::FromInt(language_mode()))
.StoreAccumulatorInRegister(runtime_call_args[3]) .StoreAccumulatorInRegister(runtime_call_args[3])
@ -2721,23 +2698,15 @@ void BytecodeGenerator::VisitCall(Call* expr) {
builder()->SetExpressionPosition(expr); builder()->SetExpressionPosition(expr);
int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot()); // 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 (is_spread_call) { if (expr->only_last_arg_is_spread()) {
DCHECK(!is_tail_call); DCHECK_EQ(TailCallMode::kDisallow, expr->tail_call_mode());
DCHECK(!implicit_undefined_receiver);
builder()->CallWithSpread(callee, args); 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 { } else {
builder()->CallAnyReceiver(callee, args, feedback_slot_index); int const feedback_slot_index = feedback_index(expr->CallFeedbackICSlot());
builder()->Call(callee, args, feedback_slot_index, call_type,
expr->tail_call_mode());
} }
} }
@ -2799,8 +2768,6 @@ void BytecodeGenerator::VisitCallRuntime(CallRuntime* expr) {
if (expr->is_jsruntime()) { if (expr->is_jsruntime()) {
RegisterList args = register_allocator()->NewGrowableRegisterList(); RegisterList args = register_allocator()->NewGrowableRegisterList();
// Allocate a register for the receiver and load it with undefined. // 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); BuildPushUndefinedIntoRegisterList(&args);
VisitArguments(expr->arguments(), &args); VisitArguments(expr->arguments(), &args);
builder()->CallJSRuntime(expr->context_index(), args); builder()->CallJSRuntime(expr->context_index(), args);
@ -3186,8 +3153,9 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
builder()->JumpIfNull(&async_iterator_null); builder()->JumpIfNull(&async_iterator_null);
// Let iterator be Call(method, obj) // Let iterator be Call(method, obj)
builder()->StoreAccumulatorInRegister(method).CallProperty( builder()->StoreAccumulatorInRegister(method).Call(
method, args, feedback_index(async_call_slot)); method, args, feedback_index(async_call_slot),
Call::NAMED_PROPERTY_CALL);
// If Type(iterator) is not Object, throw a TypeError exception. // If Type(iterator) is not Object, throw a TypeError exception.
builder()->JumpIfJSReceiver(&done); builder()->JumpIfJSReceiver(&done);
@ -3202,7 +3170,8 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
.StoreAccumulatorInRegister(method); .StoreAccumulatorInRegister(method);
// Let syncIterator be Call(syncMethod, obj) // Let syncIterator be Call(syncMethod, obj)
builder()->CallProperty(method, args, feedback_index(call_slot)); builder()->Call(method, args, feedback_index(call_slot),
Call::NAMED_PROPERTY_CALL);
// Return CreateAsyncFromSyncIterator(syncIterator) // Return CreateAsyncFromSyncIterator(syncIterator)
// alias `method` register as it's no longer used // alias `method` register as it's no longer used
@ -3219,7 +3188,8 @@ void BytecodeGenerator::VisitGetIterator(GetIterator* expr) {
.StoreAccumulatorInRegister(method); .StoreAccumulatorInRegister(method);
// Let iterator be Call(method, obj). // Let iterator be Call(method, obj).
builder()->CallProperty(method, args, feedback_index(call_slot)); builder()->Call(method, args, feedback_index(call_slot),
Call::NAMED_PROPERTY_CALL);
// If Type(iterator) is not Object, throw a TypeError exception. // If Type(iterator) is not Object, throw a TypeError exception.
BytecodeLabel no_type_error; BytecodeLabel no_type_error;

View File

@ -238,15 +238,8 @@ bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) {
case Bytecode::kInc: case Bytecode::kInc:
case Bytecode::kDec: case Bytecode::kDec:
case Bytecode::kTypeOf: case Bytecode::kTypeOf:
case Bytecode::kCallAnyReceiver: case Bytecode::kCall:
case Bytecode::kCallProperty: 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::kConstruct:
case Bytecode::kConstructWithSpread: case Bytecode::kConstructWithSpread:
return true; return true;

View File

@ -158,8 +158,14 @@ namespace interpreter {
V(GetSuperConstructor, AccumulatorUse::kRead, OperandType::kRegOut) \ V(GetSuperConstructor, AccumulatorUse::kRead, OperandType::kRegOut) \
\ \
/* Call operations */ \ /* Call operations */ \
V(CallAnyReceiver, AccumulatorUse::kWrite, OperandType::kReg, \ V(Call, AccumulatorUse::kWrite, OperandType::kReg, OperandType::kRegList, \
OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \ 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(CallProperty, AccumulatorUse::kWrite, OperandType::kReg, \ V(CallProperty, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \ OperandType::kRegList, OperandType::kRegCount, OperandType::kIdx) \
V(CallProperty0, AccumulatorUse::kWrite, OperandType::kReg, \ V(CallProperty0, AccumulatorUse::kWrite, OperandType::kReg, \
@ -169,14 +175,6 @@ namespace interpreter {
V(CallProperty2, AccumulatorUse::kWrite, OperandType::kReg, \ V(CallProperty2, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kReg, OperandType::kReg, OperandType::kReg, \ OperandType::kReg, OperandType::kReg, OperandType::kReg, \
OperandType::kIdx) \ 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, \ V(CallWithSpread, AccumulatorUse::kWrite, OperandType::kReg, \
OperandType::kRegList, OperandType::kRegCount) \ OperandType::kRegList, OperandType::kRegCount) \
V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, \ V(TailCall, AccumulatorUse::kWrite, OperandType::kReg, \
@ -434,7 +432,7 @@ enum class Bytecode : uint8_t {
class V8_EXPORT_PRIVATE Bytecodes final { class V8_EXPORT_PRIVATE Bytecodes final {
public: public:
// The maximum number of operands a bytecode may have. // The maximum number of operands a bytecode may have.
static const int kMaxOperands = 5; static const int kMaxOperands = 5;
// Returns string representation of |bytecode|. // Returns string representation of |bytecode|.
@ -627,15 +625,13 @@ class V8_EXPORT_PRIVATE Bytecodes final {
// Returns true if the bytecode is a call or a constructor call. // Returns true if the bytecode is a call or a constructor call.
static constexpr bool IsCallOrConstruct(Bytecode bytecode) { static constexpr bool IsCallOrConstruct(Bytecode bytecode) {
return bytecode == Bytecode::kCallAnyReceiver || return bytecode == Bytecode::kCall || bytecode == Bytecode::kCallProperty ||
bytecode == Bytecode::kCallProperty || bytecode == Bytecode::kCall0 ||
bytecode == Bytecode::kCallProperty0 || bytecode == Bytecode::kCallProperty0 ||
bytecode == Bytecode::kCall1 ||
bytecode == Bytecode::kCallProperty1 || bytecode == Bytecode::kCallProperty1 ||
bytecode == Bytecode::kCall2 ||
bytecode == Bytecode::kCallProperty2 || bytecode == Bytecode::kCallProperty2 ||
bytecode == Bytecode::kCallUndefinedReceiver ||
bytecode == Bytecode::kCallUndefinedReceiver0 ||
bytecode == Bytecode::kCallUndefinedReceiver1 ||
bytecode == Bytecode::kCallUndefinedReceiver2 ||
bytecode == Bytecode::kTailCall || bytecode == Bytecode::kTailCall ||
bytecode == Bytecode::kConstruct || bytecode == Bytecode::kConstruct ||
bytecode == Bytecode::kCallWithSpread || bytecode == Bytecode::kCallWithSpread ||
@ -750,34 +746,6 @@ class V8_EXPORT_PRIVATE Bytecodes final {
// through the bytecode's handler. // through the bytecode's handler.
static bool MakesCallAlongCriticalPath(Bytecode bytecode); 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. // Returns true if the bytecode is a debug break.
static bool IsDebugBreak(Bytecode bytecode); static bool IsDebugBreak(Bytecode bytecode);

View File

@ -555,11 +555,11 @@ Node* InterpreterAssembler::IncrementCallCount(Node* feedback_vector,
SKIP_WRITE_BARRIER); SKIP_WRITE_BARRIER);
} }
Node* InterpreterAssembler::CallJSWithFeedback( Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
compiler::Node* function, compiler::Node* context, Node* first_arg, Node* arg_count,
compiler::Node* first_arg, compiler::Node* arg_count, Node* slot_id,
compiler::Node* slot_id, compiler::Node* feedback_vector, Node* feedback_vector,
ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode) { TailCallMode tail_call_mode) {
// Static checks to assert it is safe to examine the type feedback element. // 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 // 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. // or an AllocationSite, but the memory is safe to examine.
@ -572,8 +572,6 @@ Node* InterpreterAssembler::CallJSWithFeedback(
// to be a pointer. // to be a pointer.
DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
DCHECK(Bytecodes::IsCallOrConstruct(bytecode_)); DCHECK(Bytecodes::IsCallOrConstruct(bytecode_));
DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), receiver_mode);
STATIC_ASSERT(WeakCell::kSize >= kPointerSize); STATIC_ASSERT(WeakCell::kSize >= kPointerSize);
STATIC_ASSERT(AllocationSite::kTransitionInfoOffset == STATIC_ASSERT(AllocationSite::kTransitionInfoOffset ==
WeakCell::kValueOffset && WeakCell::kValueOffset &&
@ -600,9 +598,8 @@ Node* InterpreterAssembler::CallJSWithFeedback(
IncrementCallCount(feedback_vector, slot_id); IncrementCallCount(feedback_vector, slot_id);
// Call using call function builtin. // Call using call function builtin.
Callable callable = CodeFactory::InterpreterPushArgsThenCall( Callable callable = CodeFactory::InterpreterPushArgsAndCall(
isolate(), receiver_mode, tail_call_mode, isolate(), tail_call_mode, InterpreterPushArgsMode::kJSFunction);
InterpreterPushArgsMode::kJSFunction);
Node* code_target = HeapConstant(callable.code()); Node* code_target = HeapConstant(callable.code());
Node* ret_value = CallStub(callable.descriptor(), code_target, context, Node* ret_value = CallStub(callable.descriptor(), code_target, context,
arg_count, first_arg, function); arg_count, first_arg, function);
@ -626,33 +623,24 @@ Node* InterpreterAssembler::CallJSWithFeedback(
GotoIfNot(IsAllocationSiteMap(LoadMap(feedback_element)), GotoIfNot(IsAllocationSiteMap(LoadMap(feedback_element)),
&check_initialized); &check_initialized);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { // If it is not the Array() function, mark megamorphic.
// For undefined receivers (mostly global calls), do an additional check Node* context_slot = LoadContextElement(LoadNativeContext(context),
// for the monomorphic Array function, which would otherwise appear Context::ARRAY_FUNCTION_INDEX);
// megamorphic. Node* is_array_function = WordEqual(context_slot, function);
GotoIfNot(is_array_function, &mark_megamorphic);
// If it is not the Array() function, mark megamorphic. // It is a monomorphic Array function. Increment the call count.
Node* context_slot = LoadContextElement(LoadNativeContext(context), IncrementCallCount(feedback_vector, slot_id);
Context::ARRAY_FUNCTION_INDEX);
Node* is_array_function = WordEqual(context_slot, function);
GotoIfNot(is_array_function, &mark_megamorphic);
// It is a monomorphic Array function. Increment the call count. // Call ArrayConstructorStub.
IncrementCallCount(feedback_vector, slot_id); Callable callable_call =
CodeFactory::InterpreterPushArgsAndConstructArray(isolate());
// Call ArrayConstructorStub. Node* code_target_call = HeapConstant(callable_call.code());
Callable callable_call = Node* ret_value =
CodeFactory::InterpreterPushArgsThenConstructArray(isolate()); CallStub(callable_call.descriptor(), code_target_call, context,
Node* code_target_call = HeapConstant(callable_call.code()); arg_count, function, feedback_element, first_arg);
Node* ret_value = return_value.Bind(ret_value);
CallStub(callable_call.descriptor(), code_target_call, context, Goto(&end);
arg_count, function, feedback_element, first_arg);
return_value.Bind(ret_value);
Goto(&end);
} else {
Goto(&mark_megamorphic);
}
Bind(&check_initialized); Bind(&check_initialized);
{ {
@ -663,7 +651,7 @@ Node* InterpreterAssembler::CallJSWithFeedback(
HeapConstant(FeedbackVector::UninitializedSentinel(isolate()))); HeapConstant(FeedbackVector::UninitializedSentinel(isolate())));
GotoIfNot(is_uninitialized, &mark_megamorphic); GotoIfNot(is_uninitialized, &mark_megamorphic);
Comment("handle_uninitialized"); Comment("handle_unitinitialized");
// If it is not a JSFunction mark it as megamorphic. // If it is not a JSFunction mark it as megamorphic.
Node* is_smi = TaggedIsSmi(function); Node* is_smi = TaggedIsSmi(function);
GotoIf(is_smi, &mark_megamorphic); GotoIf(is_smi, &mark_megamorphic);
@ -725,9 +713,8 @@ Node* InterpreterAssembler::CallJSWithFeedback(
IncrementCallCount(feedback_vector, slot_id); IncrementCallCount(feedback_vector, slot_id);
// Call using call builtin. // Call using call builtin.
Callable callable_call = CodeFactory::InterpreterPushArgsThenCall( Callable callable_call = CodeFactory::InterpreterPushArgsAndCall(
isolate(), receiver_mode, tail_call_mode, isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
InterpreterPushArgsMode::kOther);
Node* code_target_call = HeapConstant(callable_call.code()); Node* code_target_call = HeapConstant(callable_call.code());
Node* ret_value = CallStub(callable_call.descriptor(), code_target_call, Node* ret_value = CallStub(callable_call.descriptor(), code_target_call,
context, arg_count, first_arg, function); context, arg_count, first_arg, function);
@ -741,14 +728,11 @@ Node* InterpreterAssembler::CallJSWithFeedback(
Node* InterpreterAssembler::CallJS(Node* function, Node* context, Node* InterpreterAssembler::CallJS(Node* function, Node* context,
Node* first_arg, Node* arg_count, Node* first_arg, Node* arg_count,
ConvertReceiverMode receiver_mode,
TailCallMode tail_call_mode) { TailCallMode tail_call_mode) {
DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
DCHECK(Bytecodes::IsCallOrConstruct(bytecode_)); DCHECK(Bytecodes::IsCallOrConstruct(bytecode_));
DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), receiver_mode); Callable callable = CodeFactory::InterpreterPushArgsAndCall(
Callable callable = CodeFactory::InterpreterPushArgsThenCall( isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
isolate(), receiver_mode, tail_call_mode,
InterpreterPushArgsMode::kOther);
Node* code_target = HeapConstant(callable.code()); Node* code_target = HeapConstant(callable.code());
return CallStub(callable.descriptor(), code_target, context, arg_count, return CallStub(callable.descriptor(), code_target, context, arg_count,
@ -758,9 +742,8 @@ Node* InterpreterAssembler::CallJS(Node* function, Node* context,
Node* InterpreterAssembler::CallJSWithSpread(Node* function, Node* context, Node* InterpreterAssembler::CallJSWithSpread(Node* function, Node* context,
Node* first_arg, Node* arg_count) { Node* first_arg, Node* arg_count) {
DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
DCHECK_EQ(Bytecodes::GetReceiverMode(bytecode_), ConvertReceiverMode::kAny); Callable callable = CodeFactory::InterpreterPushArgsAndCall(
Callable callable = CodeFactory::InterpreterPushArgsThenCall( isolate(), TailCallMode::kDisallow,
isolate(), ConvertReceiverMode::kAny, TailCallMode::kDisallow,
InterpreterPushArgsMode::kWithFinalSpread); InterpreterPushArgsMode::kWithFinalSpread);
Node* code_target = HeapConstant(callable.code()); Node* code_target = HeapConstant(callable.code());
@ -804,7 +787,7 @@ Node* InterpreterAssembler::Construct(Node* constructor, Node* context,
{ {
Comment("call using ConstructFunction"); Comment("call using ConstructFunction");
IncrementCallCount(feedback_vector, slot_id); IncrementCallCount(feedback_vector, slot_id);
Callable callable_function = CodeFactory::InterpreterPushArgsThenConstruct( Callable callable_function = CodeFactory::InterpreterPushArgsAndConstruct(
isolate(), InterpreterPushArgsMode::kJSFunction); isolate(), InterpreterPushArgsMode::kJSFunction);
return_value.Bind(CallStub(callable_function.descriptor(), return_value.Bind(CallStub(callable_function.descriptor(),
HeapConstant(callable_function.code()), context, HeapConstant(callable_function.code()), context,
@ -907,7 +890,7 @@ Node* InterpreterAssembler::Construct(Node* constructor, Node* context,
Bind(&call_construct); Bind(&call_construct);
{ {
Comment("call using Construct builtin"); Comment("call using Construct builtin");
Callable callable = CodeFactory::InterpreterPushArgsThenConstruct( Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
isolate(), InterpreterPushArgsMode::kOther); isolate(), InterpreterPushArgsMode::kOther);
Node* code_target = HeapConstant(callable.code()); Node* code_target = HeapConstant(callable.code());
return_value.Bind(CallStub(callable.descriptor(), code_target, context, return_value.Bind(CallStub(callable.descriptor(), code_target, context,
@ -927,7 +910,7 @@ Node* InterpreterAssembler::ConstructWithSpread(Node* constructor,
DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_)); DCHECK(Bytecodes::MakesCallAlongCriticalPath(bytecode_));
Variable return_value(this, MachineRepresentation::kTagged); Variable return_value(this, MachineRepresentation::kTagged);
Comment("call using ConstructWithSpread"); Comment("call using ConstructWithSpread");
Callable callable = CodeFactory::InterpreterPushArgsThenConstruct( Callable callable = CodeFactory::InterpreterPushArgsAndConstruct(
isolate(), InterpreterPushArgsMode::kWithFinalSpread); isolate(), InterpreterPushArgsMode::kWithFinalSpread);
Node* code_target = HeapConstant(callable.code()); Node* code_target = HeapConstant(callable.code());
return_value.Bind(CallStub(callable.descriptor(), code_target, context, return_value.Bind(CallStub(callable.descriptor(), code_target, context,

View File

@ -118,25 +118,23 @@ class V8_EXPORT_PRIVATE InterpreterAssembler : public CodeStubAssembler {
compiler::Node* IncrementCallCount(compiler::Node* feedback_vector, compiler::Node* IncrementCallCount(compiler::Node* feedback_vector,
compiler::Node* slot_id); compiler::Node* slot_id);
// Call JSFunction or Callable |function| with |arg_count| arguments (not // Call JSFunction or Callable |function| with |arg_count|
// including receiver) and the first argument located at |first_arg|. Type // arguments (not including receiver) and the first argument
// feedback is collected in the slot at index |slot_id|. // 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 compiler::Node* CallJSWithFeedback(compiler::Node* function,
// undefined and |first_arg| is the first parameter. Otherwise, |first_arg| is compiler::Node* context,
// the receiver and it is converted according to |receiver_mode|. compiler::Node* first_arg,
compiler::Node* CallJSWithFeedback( compiler::Node* arg_count,
compiler::Node* function, compiler::Node* context, compiler::Node* slot_id,
compiler::Node* first_arg, compiler::Node* arg_count, compiler::Node* feedback_vector,
compiler::Node* slot_id, compiler::Node* feedback_vector, TailCallMode tail_call_mode);
ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode);
// Call JSFunction or Callable |function| with |arg_count| arguments (not // Call JSFunction or Callable |function| with |arg_count|
// including receiver) and the first argument located at |first_arg|, possibly // arguments (not including receiver) and the first argument
// including the receiver depending on |receiver_mode|. // located at |first_arg|.
compiler::Node* CallJS(compiler::Node* function, compiler::Node* context, compiler::Node* CallJS(compiler::Node* function, compiler::Node* context,
compiler::Node* first_arg, compiler::Node* arg_count, compiler::Node* first_arg, compiler::Node* arg_count,
ConvertReceiverMode receiver_mode,
TailCallMode tail_call_mode); TailCallMode tail_call_mode);
// Call JSFunction or Callable |function| with |arg_count| // Call JSFunction or Callable |function| with |arg_count|

View File

@ -73,13 +73,11 @@ class InterpreterGenerator {
void DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler); void DoKeyedStoreIC(Callable ic, InterpreterAssembler* assembler);
// Generates code to perform a JS call that collects type feedback. // Generates code to perform a JS call that collects type feedback.
void DoJSCall(InterpreterAssembler* assembler, void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode);
ConvertReceiverMode receiver_mode, TailCallMode tail_call_mode);
// Generates code to perform a JS call with a known number of arguments that // Generates code to perform a JS call with a known number of arguments that
// collects type feedback. // 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. // Generates code to perform delete via function_id.
void DoDelete(Runtime::FunctionId function_id, void DoDelete(Runtime::FunctionId function_id,
@ -2324,78 +2322,50 @@ void InterpreterGenerator::DoGetSuperConstructor(
} }
void InterpreterGenerator::DoJSCall(InterpreterAssembler* assembler, void InterpreterGenerator::DoJSCall(InterpreterAssembler* assembler,
ConvertReceiverMode receiver_mode,
TailCallMode tail_call_mode) { TailCallMode tail_call_mode) {
Node* function_reg = __ BytecodeOperandReg(0); Node* function_reg = __ BytecodeOperandReg(0);
Node* function = __ LoadRegister(function_reg); Node* function = __ LoadRegister(function_reg);
Node* first_arg_reg = __ BytecodeOperandReg(1); Node* receiver_reg = __ BytecodeOperandReg(1);
Node* first_arg = __ RegisterLocation(first_arg_reg); Node* receiver_arg = __ RegisterLocation(receiver_reg);
Node* arg_list_count = __ BytecodeOperandCount(2); Node* receiver_args_count = __ BytecodeOperandCount(2);
Node* args_count; Node* receiver_count = __ Int32Constant(1);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
// 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* slot_id = __ BytecodeOperandIdx(3);
Node* feedback_vector = __ LoadFeedbackVector(); Node* feedback_vector = __ LoadFeedbackVector();
Node* context = __ GetContext(); Node* context = __ GetContext();
Node* result = Node* result =
__ CallJSWithFeedback(function, context, first_arg, args_count, slot_id, __ CallJSWithFeedback(function, context, receiver_arg, args_count,
feedback_vector, receiver_mode, tail_call_mode); slot_id, feedback_vector, tail_call_mode);
__ SetAccumulator(result); __ SetAccumulator(result);
__ Dispatch(); __ Dispatch();
} }
void InterpreterGenerator::DoJSCallN(InterpreterAssembler* assembler, void InterpreterGenerator::DoJSCallN(InterpreterAssembler* assembler,
int arg_count, int arg_count) {
ConvertReceiverMode receiver_mode) { const int kReceiverOperandIndex = 1;
// Indices and counts of operands on the bytecode. const int kReceiverOperandCount = 1;
const int kFirstArgumentOperandIndex = 1;
const int kReceiverOperandCount =
(receiver_mode == ConvertReceiverMode::kNullOrUndefined) ? 0 : 1;
const int kSlotOperandIndex = const int kSlotOperandIndex =
kFirstArgumentOperandIndex + kReceiverOperandCount + arg_count; kReceiverOperandIndex + kReceiverOperandCount + arg_count;
// Indices and counts of parameters to the call stub. const int kBoilerplatParameterCount = 7;
const int kBoilerplateParameterCount = 7;
const int kReceiverParameterIndex = 5; const int kReceiverParameterIndex = 5;
const int kReceiverParameterCount = 1;
// Only used in a DCHECK.
USE(kReceiverParameterCount);
Node* function_reg = __ BytecodeOperandReg(0); Node* function_reg = __ BytecodeOperandReg(0);
Node* function = __ LoadRegister(function_reg); Node* function = __ LoadRegister(function_reg);
std::array<Node*, Bytecodes::kMaxOperands + kBoilerplateParameterCount> temp; std::array<Node*, Bytecodes::kMaxOperands + kBoilerplatParameterCount> temp;
Callable call_ic = CodeFactory::CallIC(isolate_); Callable call_ic = CodeFactory::CallIC(isolate_);
temp[0] = __ HeapConstant(call_ic.code()); temp[0] = __ HeapConstant(call_ic.code());
temp[1] = function; temp[1] = function;
temp[2] = __ Int32Constant(arg_count); temp[2] = __ Int32Constant(arg_count);
temp[3] = __ BytecodeOperandIdxInt32(kSlotOperandIndex); temp[3] = __ BytecodeOperandIdxInt32(kSlotOperandIndex);
temp[4] = __ LoadFeedbackVector(); temp[4] = __ LoadFeedbackVector();
for (int i = 0; i < (arg_count + kReceiverOperandCount); ++i) {
int parameter_index = kReceiverParameterIndex; Node* reg = __ BytecodeOperandReg(i + kReceiverOperandIndex);
if (receiver_mode == ConvertReceiverMode::kNullOrUndefined) { temp[kReceiverParameterIndex + i] = __ LoadRegister(reg);
// The first argument parameter (the receiver) is implied to be undefined.
Node* undefined_value =
__ HeapConstant(isolate_->factory()->undefined_value());
temp[parameter_index++] = undefined_value;
} }
// The bytecode argument operands are copied into the remaining argument temp[kReceiverParameterIndex + arg_count + kReceiverOperandCount] =
// parameters. __ GetContext();
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, Node* result = __ CallStubN(call_ic.descriptor(), 1,
arg_count + kBoilerplateParameterCount, &temp[0]); arg_count + kBoilerplatParameterCount, &temp[0]);
__ SetAccumulator(result); __ SetAccumulator(result);
__ Dispatch(); __ Dispatch();
} }
@ -2405,46 +2375,40 @@ void InterpreterGenerator::DoJSCallN(InterpreterAssembler* assembler,
// Call a JSfunction or Callable in |callable| with the |receiver| and // Call a JSfunction or Callable in |callable| with the |receiver| and
// |arg_count| arguments in subsequent registers. Collect type feedback // |arg_count| arguments in subsequent registers. Collect type feedback
// into |feedback_slot_id| // into |feedback_slot_id|
void InterpreterGenerator::DoCallAnyReceiver(InterpreterAssembler* assembler) { void InterpreterGenerator::DoCall(InterpreterAssembler* assembler) {
DoJSCall(assembler, ConvertReceiverMode::kAny, TailCallMode::kDisallow); 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::DoCallProperty(InterpreterAssembler* assembler) { void InterpreterGenerator::DoCallProperty(InterpreterAssembler* assembler) {
DoJSCall(assembler, ConvertReceiverMode::kNotNullOrUndefined, // Same as Call
TailCallMode::kDisallow); UNREACHABLE();
} }
void InterpreterGenerator::DoCallProperty0(InterpreterAssembler* assembler) { void InterpreterGenerator::DoCallProperty0(InterpreterAssembler* assembler) {
DoJSCallN(assembler, 0, ConvertReceiverMode::kNotNullOrUndefined); // Same as Call0
UNREACHABLE();
} }
void InterpreterGenerator::DoCallProperty1(InterpreterAssembler* assembler) { void InterpreterGenerator::DoCallProperty1(InterpreterAssembler* assembler) {
DoJSCallN(assembler, 1, ConvertReceiverMode::kNotNullOrUndefined); // Same as Call1
UNREACHABLE();
} }
void InterpreterGenerator::DoCallProperty2(InterpreterAssembler* assembler) { void InterpreterGenerator::DoCallProperty2(InterpreterAssembler* assembler) {
DoJSCallN(assembler, 2, ConvertReceiverMode::kNotNullOrUndefined); // Same as Call2
} UNREACHABLE();
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 <callable> <receiver> <arg_count> <feedback_slot_id> // TailCall <callable> <receiver> <arg_count> <feedback_slot_id>
@ -2453,7 +2417,7 @@ void InterpreterGenerator::DoCallUndefinedReceiver2(
// |arg_count| arguments in subsequent registers. Collect type feedback // |arg_count| arguments in subsequent registers. Collect type feedback
// into |feedback_slot_id| // into |feedback_slot_id|
void InterpreterGenerator::DoTailCall(InterpreterAssembler* assembler) { void InterpreterGenerator::DoTailCall(InterpreterAssembler* assembler) {
DoJSCall(assembler, ConvertReceiverMode::kAny, TailCallMode::kAllow); DoJSCall(assembler, TailCallMode::kAllow);
} }
// CallRuntime <function_id> <first_arg> <arg_count> // CallRuntime <function_id> <first_arg> <arg_count>
@ -2533,7 +2497,7 @@ void InterpreterGenerator::DoCallJSRuntime(InterpreterAssembler* assembler) {
// Call the function. // Call the function.
Node* result = __ CallJS(function, context, first_arg, args_count, Node* result = __ CallJS(function, context, first_arg, args_count,
ConvertReceiverMode::kAny, TailCallMode::kDisallow); TailCallMode::kDisallow);
__ SetAccumulator(result); __ SetAccumulator(result);
__ Dispatch(); __ Dispatch();
} }

View File

@ -309,7 +309,7 @@ Node* IntrinsicsGenerator::Call(Node* args_reg, Node* arg_count,
} }
Node* result = __ CallJS(function, context, receiver_arg, target_args_count, Node* result = __ CallJS(function, context, receiver_arg, target_args_count,
ConvertReceiverMode::kAny, TailCallMode::kDisallow); TailCallMode::kDisallow);
return result; return result;
} }

View File

@ -52,8 +52,28 @@ void SetupInterpreter::InstallBytecodeHandlers(Interpreter* interpreter) {
bool SetupInterpreter::ReuseExistingHandler(Address* dispatch_table, bool SetupInterpreter::ReuseExistingHandler(Address* dispatch_table,
Bytecode bytecode, Bytecode bytecode,
OperandScale operand_scale) { OperandScale operand_scale) {
// TODO(leszeks): reuse Lda[Immutable][Current]ContextSlot size_t index = Interpreter::GetDispatchTableIndex(bytecode, operand_scale);
return false; switch (bytecode) {
case Bytecode::kCallProperty:
case Bytecode::kCallProperty0:
case Bytecode::kCallProperty1:
case Bytecode::kCallProperty2: {
const int offset = static_cast<int>(Bytecode::kCallProperty) -
static_cast<int>(Bytecode::kCall);
STATIC_ASSERT(offset == static_cast<int>(Bytecode::kCallProperty0) -
static_cast<int>(Bytecode::kCall0));
STATIC_ASSERT(offset == static_cast<int>(Bytecode::kCallProperty1) -
static_cast<int>(Bytecode::kCall1));
STATIC_ASSERT(offset == static_cast<int>(Bytecode::kCallProperty2) -
static_cast<int>(Bytecode::kCall2));
CHECK_LT(offset, index);
dispatch_table[index] = dispatch_table[index - offset];
return true;
break;
}
default:
return false;
}
} }
// static // static

View File

@ -314,7 +314,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
@ -324,7 +324,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
@ -336,8 +336,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
a1, // the target to call verified to be Array function a1, // the target to call verified to be Array function

View File

@ -313,7 +313,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
@ -323,7 +323,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
@ -335,8 +335,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
a0, // argument count (not including receiver) a0, // argument count (not including receiver)
a1, // the target to call verified to be Array function a1, // the target to call verified to be Array function

View File

@ -315,7 +315,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r3, // argument count (not including receiver) r3, // argument count (not including receiver)
@ -325,7 +325,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r3, // argument count (not including receiver) r3, // argument count (not including receiver)
@ -337,8 +337,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r3, // argument count (not including receiver) r3, // argument count (not including receiver)
r4, // target to call checked to be Array function r4, // target to call checked to be Array function

View File

@ -299,7 +299,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r2, // argument count (not including receiver) r2, // argument count (not including receiver)
@ -309,7 +309,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r2, // argument count (not including receiver) r2, // argument count (not including receiver)
@ -321,8 +321,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
r2, // argument count (not including receiver) r2, // argument count (not including receiver)
r3, // target to call checked to be Array function r3, // target to call checked to be Array function

View File

@ -316,7 +316,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
rax, // argument count (not including receiver) rax, // argument count (not including receiver)
@ -326,7 +326,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
rax, // argument count (not including receiver) rax, // argument count (not including receiver)
@ -338,8 +338,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
rax, // argument count (not including receiver) rax, // argument count (not including receiver)
rdx, // target to the call. It is checked to be Array function. rdx, // target to the call. It is checked to be Array function.

View File

@ -330,7 +330,7 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
@ -340,7 +340,7 @@ void InterpreterPushArgsThenCallDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific( void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
@ -352,8 +352,8 @@ void InterpreterPushArgsThenConstructDescriptor::InitializePlatformSpecific(
data->InitializePlatformSpecific(arraysize(registers), registers); data->InitializePlatformSpecific(arraysize(registers), registers);
} }
void InterpreterPushArgsThenConstructArrayDescriptor:: void InterpreterPushArgsAndConstructArrayDescriptor::InitializePlatformSpecific(
InitializePlatformSpecific(CallInterfaceDescriptorData* data) { CallInterfaceDescriptorData* data) {
Register registers[] = { Register registers[] = {
eax, // argument count (not including receiver) eax, // argument count (not including receiver)
edx, // target to the call. It is checked to be Array function. edx, // target to the call. It is checked to be Array function.

View File

@ -12,14 +12,16 @@ snippet: "
function f() { return t(); } function f() { return t(); }
f(); f();
" "
frame size: 1 frame size: 2
parameter count: 1 parameter count: 1
bytecode array length: 10 bytecode array length: 14
bytecodes: [ bytecodes: [
/* 27 E> */ B(StackCheck), /* 27 E> */ B(StackCheck),
/* 32 S> */ B(LdaGlobal), U8(0), U8(4), /* 32 S> */ B(LdaUndefined),
B(Star), R(1),
B(LdaGlobal), U8(0), U8(4),
B(Star), R(0), B(Star), R(0),
/* 39 E> */ B(CallUndefinedReceiver0), R(0), U8(2), /* 39 E> */ B(Call0), R(0), R(1), U8(2),
/* 44 S> */ B(Return), /* 44 S> */ B(Return),
] ]
constant pool: [ constant pool: [
@ -34,20 +36,22 @@ snippet: "
function f() { return t(1, 2, 3); } function f() { return t(1, 2, 3); }
f(); f();
" "
frame size: 4 frame size: 5
parameter count: 1 parameter count: 1
bytecode array length: 24 bytecode array length: 27
bytecodes: [ bytecodes: [
/* 34 E> */ B(StackCheck), /* 34 E> */ B(StackCheck),
/* 39 S> */ B(LdaGlobal), U8(0), U8(4), /* 39 S> */ B(LdaUndefined),
B(Star), R(1),
B(LdaGlobal), U8(0), U8(4),
B(Star), R(0), B(Star), R(0),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1),
B(LdaSmi), I8(2),
B(Star), R(2), B(Star), R(2),
B(LdaSmi), I8(3), B(LdaSmi), I8(2),
B(Star), R(3), B(Star), R(3),
/* 46 E> */ B(CallUndefinedReceiver), R(0), R(1), U8(3), U8(2), B(LdaSmi), I8(3),
B(Star), R(4),
/* 46 E> */ B(Call), R(0), R(1), U8(4), U8(2),
/* 58 S> */ B(Return), /* 58 S> */ B(Return),
] ]
constant pool: [ constant pool: [

View File

@ -9,9 +9,9 @@ wrap: yes
snippet: " snippet: "
g = function(){}; eval(''); return g(); g = function(){}; eval(''); return g();
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 73 bytecode array length: 81
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -24,25 +24,29 @@ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2), /* 34 S> */ B(CreateClosure), U8(0), U8(2), U8(2),
/* 36 E> */ B(StaLookupSlotSloppy), U8(1), /* 36 E> */ B(StaLookupSlotSloppy), U8(1),
/* 52 S> */ B(LdaLookupGlobalSlot), U8(2), U8(5), U8(1), /* 52 S> */ B(LdaUndefined),
B(Star), R(2),
/* 52 E> */ B(LdaLookupGlobalSlot), U8(2), U8(5), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(3), B(LdaConstant), U8(3),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(30),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(52), B(LdaSmi), I8(30),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(52),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 52 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(3), /* 52 E> */ B(Call1), R(1), R(2), R(3), U8(3),
/* 62 S> */ B(LdaLookupGlobalSlot), U8(1), U8(9), U8(1), /* 62 S> */ B(LdaUndefined),
B(Star), R(2),
/* 69 E> */ B(LdaLookupGlobalSlot), U8(1), U8(9), U8(1),
B(Star), R(1), B(Star), R(1),
/* 69 E> */ B(CallUndefinedReceiver0), R(1), U8(7), /* 69 E> */ B(Call0), R(1), R(2), U8(7),
/* 74 S> */ B(Return), /* 74 S> */ B(Return),
] ]
constant pool: [ constant pool: [

View File

@ -22,7 +22,7 @@ snippet: "
" "
frame size: 6 frame size: 6
parameter count: 1 parameter count: 1
bytecode array length: 34 bytecode array length: 33
bytecodes: [ bytecodes: [
B(Mov), R(closure), R(0), B(Mov), R(closure), R(0),
/* 99 E> */ B(StackCheck), /* 99 E> */ B(StackCheck),
@ -34,7 +34,7 @@ bytecodes: [
B(Mov), R(this), R(3), B(Mov), R(this), R(3),
B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3), B(CallRuntime), U16(Runtime::kLoadFromSuper), R(3), U8(3),
B(Star), R(1), B(Star), R(1),
/* 117 E> */ B(CallAnyReceiver), R(1), R(this), U8(1), U8(2), /* 117 E> */ B(Call0), R(1), R(this), U8(2),
/* 126 E> */ B(AddSmi), I8(1), U8(8), /* 126 E> */ B(AddSmi), I8(1), U8(8),
/* 131 S> */ B(Return), /* 131 S> */ B(Return),
] ]

View File

@ -75,16 +75,18 @@ handlers: [
snippet: " snippet: "
var a; (function() { a = 2; })(); return a; var a; (function() { a = 2; })(); return a;
" "
frame size: 2 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 17 bytecode array length: 21
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(1), B(CreateFunctionContext), U8(1),
B(PushContext), R(0), B(PushContext), R(0),
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 41 S> */ B(CreateClosure), U8(0), U8(4), U8(2), /* 41 S> */ B(LdaUndefined),
B(Star), R(2),
B(CreateClosure), U8(0), U8(4), U8(2),
B(Star), R(1), B(Star), R(1),
/* 64 E> */ B(CallUndefinedReceiver0), R(1), U8(2), /* 64 E> */ B(Call0), R(1), R(2), U8(2),
/* 68 S> */ B(LdaCurrentContextSlot), U8(4), /* 68 S> */ B(LdaCurrentContextSlot), U8(4),
/* 78 S> */ B(Return), /* 78 S> */ B(Return),
] ]
@ -386,9 +388,9 @@ snippet: "
var b = 100; var b = 100;
return b return b
" "
frame size: 2 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 787 bytecode array length: 791
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(254), B(CreateFunctionContext), U8(254),
B(PushContext), R(0), B(PushContext), R(0),
@ -899,9 +901,11 @@ bytecodes: [
/* 3421 E> */ B(StaCurrentContextSlot), U8(254), /* 3421 E> */ B(StaCurrentContextSlot), U8(254),
/* 3435 S> */ B(LdaZero), /* 3435 S> */ B(LdaZero),
/* 3435 E> */ B(StaCurrentContextSlot), U8(255), /* 3435 E> */ B(StaCurrentContextSlot), U8(255),
/* 3438 S> */ B(LdaGlobal), U8(0), U8(4), /* 3438 S> */ B(LdaUndefined),
B(Star), R(2),
B(LdaGlobal), U8(0), U8(4),
B(Star), R(1), B(Star), R(1),
/* 3438 E> */ B(CallUndefinedReceiver0), R(1), U8(2), /* 3438 E> */ B(Call0), R(1), R(2), U8(2),
/* 3454 S> */ B(LdaSmi), I8(100), /* 3454 S> */ B(LdaSmi), I8(100),
/* 3454 E> */ B(Wide), B(StaCurrentContextSlot), U16(256), /* 3454 E> */ B(Wide), B(StaCurrentContextSlot), U16(256),
/* 3459 S> */ B(Wide), B(LdaCurrentContextSlot), U16(256), /* 3459 S> */ B(Wide), B(LdaCurrentContextSlot), U16(256),

View File

@ -104,7 +104,7 @@ snippet: "
" "
frame size: 4 frame size: 4
parameter count: 1 parameter count: 1
bytecode array length: 27 bytecode array length: 31
bytecodes: [ bytecodes: [
B(LdaConstant), U8(0), B(LdaConstant), U8(0),
B(Star), R(1), B(Star), R(1),
@ -113,9 +113,11 @@ bytecodes: [
B(Mov), R(closure), R(3), B(Mov), R(closure), R(3),
B(CallRuntime), U16(Runtime::kDeclareGlobalsForInterpreter), R(1), U8(3), B(CallRuntime), U16(Runtime::kDeclareGlobalsForInterpreter), R(1), U8(3),
/* 0 E> */ B(StackCheck), /* 0 E> */ B(StackCheck),
/* 16 S> */ B(LdaGlobal), U8(1), U8(2), /* 16 S> */ B(LdaUndefined),
B(Star), R(2),
B(LdaGlobal), U8(1), U8(2),
B(Star), R(1), B(Star), R(1),
/* 16 E> */ B(CallUndefinedReceiver0), R(1), U8(5), /* 16 E> */ B(Call0), R(1), R(2), U8(5),
B(Star), R(0), B(Star), R(0),
/* 20 S> */ B(Return), /* 20 S> */ B(Return),
] ]

View File

@ -9,9 +9,9 @@ wrap: yes
snippet: " snippet: "
return eval('1;'); return eval('1;');
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 58 bytecode array length: 62
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -22,22 +22,24 @@ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), /* 34 S> */ B(LdaUndefined),
B(Star), R(2),
/* 41 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(30),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(41), B(LdaSmi), I8(30),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(41),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 41 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 41 E> */ B(Call1), R(1), R(2), R(3), U8(2),
/* 53 S> */ B(Return), /* 53 S> */ B(Return),
] ]
constant pool: [ constant pool: [

View File

@ -27,14 +27,16 @@ handlers: [
snippet: " snippet: "
return (function(){ })() return (function(){ })()
" "
frame size: 1 frame size: 2
parameter count: 1 parameter count: 1
bytecode array length: 11 bytecode array length: 15
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateClosure), U8(0), U8(4), U8(2), /* 34 S> */ B(LdaUndefined),
B(Star), R(1),
B(CreateClosure), U8(0), U8(4), U8(2),
B(Star), R(0), B(Star), R(0),
/* 56 E> */ B(CallUndefinedReceiver0), R(0), U8(2), /* 56 E> */ B(Call0), R(0), R(1), U8(2),
/* 59 S> */ B(Return), /* 59 S> */ B(Return),
] ]
constant pool: [ constant pool: [
@ -47,16 +49,18 @@ handlers: [
snippet: " snippet: "
return (function(x){ return x; })(1) return (function(x){ return x; })(1)
" "
frame size: 2 frame size: 3
parameter count: 1 parameter count: 1
bytecode array length: 16 bytecode array length: 20
bytecodes: [ bytecodes: [
/* 30 E> */ B(StackCheck), /* 30 E> */ B(StackCheck),
/* 34 S> */ B(CreateClosure), U8(0), U8(4), U8(2), /* 34 S> */ B(LdaUndefined),
B(Star), R(1),
B(CreateClosure), U8(0), U8(4), U8(2),
B(Star), R(0), B(Star), R(0),
B(LdaSmi), I8(1), B(LdaSmi), I8(1),
B(Star), R(1), B(Star), R(2),
/* 67 E> */ B(CallUndefinedReceiver1), R(0), R(1), U8(2), /* 67 E> */ B(Call1), R(0), R(1), R(2), U8(2),
/* 71 S> */ B(Return), /* 71 S> */ B(Return),
] ]
constant pool: [ constant pool: [

View File

@ -10,9 +10,9 @@ test function name: f
snippet: " snippet: "
eval('var x = 10;'); return x; eval('var x = 10;'); return x;
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 62 bytecode array length: 66
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -23,22 +23,24 @@ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 14 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), /* 14 S> */ B(LdaUndefined),
B(Star), R(2),
/* 14 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(10),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(14), B(LdaSmi), I8(10),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(14),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 14 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 14 E> */ B(Call1), R(1), R(2), R(3), U8(2),
/* 35 S> */ B(LdaLookupGlobalSlot), U8(2), U8(6), U8(1), /* 35 S> */ B(LdaLookupGlobalSlot), U8(2), U8(6), U8(1),
/* 45 S> */ B(Return), /* 45 S> */ B(Return),
] ]
@ -54,9 +56,9 @@ handlers: [
snippet: " snippet: "
eval('var x = 10;'); return typeof x; eval('var x = 10;'); return typeof x;
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 63 bytecode array length: 67
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -67,22 +69,24 @@ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 14 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), /* 14 S> */ B(LdaUndefined),
B(Star), R(2),
/* 14 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(10),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(14), B(LdaSmi), I8(10),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(14),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 14 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 14 E> */ B(Call1), R(1), R(2), R(3), U8(2),
/* 35 S> */ B(LdaLookupGlobalSlotInsideTypeof), U8(2), U8(6), U8(1), /* 35 S> */ B(LdaLookupGlobalSlotInsideTypeof), U8(2), U8(6), U8(1),
B(TypeOf), B(TypeOf),
/* 52 S> */ B(Return), /* 52 S> */ B(Return),
@ -99,9 +103,9 @@ handlers: [
snippet: " snippet: "
x = 20; return eval(''); x = 20; return eval('');
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 62 bytecode array length: 66
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -114,22 +118,24 @@ bytecodes: [
/* 10 E> */ B(StackCheck), /* 10 E> */ B(StackCheck),
/* 14 S> */ B(LdaSmi), I8(20), /* 14 S> */ B(LdaSmi), I8(20),
/* 16 E> */ B(StaLookupSlotSloppy), U8(0), /* 16 E> */ B(StaLookupSlotSloppy), U8(0),
/* 22 S> */ B(LdaLookupGlobalSlot), U8(1), U8(4), U8(1), /* 22 S> */ B(LdaUndefined),
B(Star), R(2),
/* 29 E> */ B(LdaLookupGlobalSlot), U8(1), U8(4), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(2), B(LdaConstant), U8(2),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(10),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(29), B(LdaSmi), I8(10),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(29),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 29 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 29 E> */ B(Call1), R(1), R(2), R(3), U8(2),
/* 39 S> */ B(Return), /* 39 S> */ B(Return),
] ]
constant pool: [ constant pool: [
@ -149,9 +155,9 @@ snippet: "
} }
f(); f();
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 62 bytecode array length: 66
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -162,22 +168,24 @@ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
/* 38 E> */ B(StackCheck), /* 38 E> */ B(StackCheck),
/* 44 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), /* 44 S> */ B(LdaUndefined),
B(Star), R(2),
/* 44 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(38),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(44), B(LdaSmi), I8(38),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(44),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 44 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 44 E> */ B(Call1), R(1), R(2), R(3), U8(2),
/* 66 S> */ B(LdaLookupContextSlot), U8(2), U8(6), U8(1), /* 66 S> */ B(LdaLookupContextSlot), U8(2), U8(6), U8(1),
/* 76 S> */ B(Return), /* 76 S> */ B(Return),
] ]
@ -198,9 +206,9 @@ snippet: "
} }
f(); f();
" "
frame size: 9 frame size: 10
parameter count: 1 parameter count: 1
bytecode array length: 62 bytecode array length: 66
bytecodes: [ bytecodes: [
B(CreateFunctionContext), U8(3), B(CreateFunctionContext), U8(3),
B(PushContext), R(0), B(PushContext), R(0),
@ -211,22 +219,24 @@ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(StaCurrentContextSlot), U8(5), B(StaCurrentContextSlot), U8(5),
/* 34 E> */ B(StackCheck), /* 34 E> */ B(StackCheck),
/* 40 S> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1), /* 40 S> */ B(LdaUndefined),
B(Star), R(2),
/* 40 E> */ B(LdaLookupGlobalSlot), U8(0), U8(4), U8(1),
B(Star), R(1), B(Star), R(1),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(2), B(Star), R(3),
B(LdaZero), B(LdaZero),
B(Star), R(6),
B(LdaSmi), I8(34),
B(Star), R(7), B(Star), R(7),
B(LdaSmi), I8(40), B(LdaSmi), I8(34),
B(Star), R(8), B(Star), R(8),
B(Mov), R(1), R(3), B(LdaSmi), I8(40),
B(Mov), R(2), R(4), B(Star), R(9),
B(Mov), R(closure), R(5), B(Mov), R(1), R(4),
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(3), U8(6), 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), B(Star), R(1),
/* 40 E> */ B(CallUndefinedReceiver1), R(1), R(2), U8(2), /* 40 E> */ B(Call1), R(1), R(2), R(3), U8(2),
/* 62 S> */ B(LdaLookupGlobalSlot), U8(2), U8(6), U8(1), /* 62 S> */ B(LdaLookupGlobalSlot), U8(2), U8(6), U8(1),
/* 72 S> */ B(Return), /* 72 S> */ B(Return),
] ]

View File

@ -171,7 +171,7 @@ snippet: "
" "
frame size: 10 frame size: 10
parameter count: 2 parameter count: 2
bytecode array length: 205 bytecode array length: 213
bytecodes: [ bytecodes: [
B(Ldar), R(new_target), B(Ldar), R(new_target),
B(JumpIfUndefined), U8(27), B(JumpIfUndefined), U8(27),
@ -228,15 +228,17 @@ bytecodes: [
/* 64 S> */ B(Return), /* 64 S> */ B(Return),
B(Ldar), R(6), B(Ldar), R(6),
/* 0 E> */ B(Throw), /* 0 E> */ B(Throw),
/* 32 S> */ B(LdaModuleVariable), I8(-1), U8(0), /* 32 S> */ B(LdaUndefined),
B(Star), R(5),
/* 32 E> */ B(LdaModuleVariable), I8(-1), U8(0),
B(JumpIfNotHole), U8(11), B(JumpIfNotHole), U8(11),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(5), B(Star), R(6),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
B(Star), R(4), B(Star), R(4),
B(LdaSmi), I8(42), B(LdaSmi), I8(42),
B(Star), R(5), B(Star), R(6),
/* 32 E> */ B(CallUndefinedReceiver1), R(4), R(5), U8(2), /* 32 E> */ B(Call1), R(4), R(5), R(6), U8(2),
B(Ldar), R(closure), B(Ldar), R(closure),
B(CreateBlockContext), U8(2), B(CreateBlockContext), U8(2),
B(PushContext), R(1), B(PushContext), R(1),
@ -244,15 +246,17 @@ bytecodes: [
B(StaCurrentContextSlot), U8(4), B(StaCurrentContextSlot), U8(4),
/* 47 S> */ B(LdaUndefined), /* 47 S> */ B(LdaUndefined),
/* 47 E> */ B(StaCurrentContextSlot), U8(4), /* 47 E> */ B(StaCurrentContextSlot), U8(4),
/* 52 S> */ B(LdaModuleVariable), I8(-1), U8(1), /* 52 S> */ B(LdaUndefined),
B(Star), R(5),
/* 52 E> */ B(LdaModuleVariable), I8(-1), U8(1),
B(JumpIfNotHole), U8(11), B(JumpIfNotHole), U8(11),
B(LdaConstant), U8(1), B(LdaConstant), U8(1),
B(Star), R(5), B(Star), R(6),
B(CallRuntime), U16(Runtime::kThrowReferenceError), R(5), U8(1), B(CallRuntime), U16(Runtime::kThrowReferenceError), R(6), U8(1),
B(Star), R(4), B(Star), R(4),
B(LdaSmi), I8(42), B(LdaSmi), I8(42),
B(Star), R(5), B(Star), R(6),
/* 52 E> */ B(CallUndefinedReceiver1), R(4), R(5), U8(4), /* 52 E> */ B(Call1), R(4), R(5), R(6), U8(4),
B(StaContextSlot), R(1), U8(6), U8(0), B(StaContextSlot), R(1), U8(6), U8(0),
B(PopContext), R(1), B(PopContext), R(1),
B(LdaCurrentContextSlot), U8(6), B(LdaCurrentContextSlot), U8(6),

View File

@ -1298,11 +1298,7 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) {
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
.MoveRegister(builder.Receiver(), args[0]); .MoveRegister(builder.Receiver(), args[0]);
if (tail_call_mode == TailCallMode::kAllow) { builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode);
builder.TailCall(reg, args, call_slot_index);
} else {
builder.CallProperty(reg, args, call_slot_index);
}
builder.Return(); builder.Return();
ast_factory.Internalize(isolate); ast_factory.Internalize(isolate);
@ -1325,11 +1321,7 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) {
builder.LoadNamedProperty(builder.Receiver(), name, slot_index) builder.LoadNamedProperty(builder.Receiver(), name, slot_index)
.StoreAccumulatorInRegister(reg) .StoreAccumulatorInRegister(reg)
.MoveRegister(builder.Receiver(), args[0]); .MoveRegister(builder.Receiver(), args[0]);
if (tail_call_mode == TailCallMode::kAllow) { builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode);
builder.TailCall(reg, args, call_slot_index);
} else {
builder.CallProperty(reg, args, call_slot_index);
}
builder.Return(); builder.Return();
ast_factory.Internalize(isolate); ast_factory.Internalize(isolate);
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate); Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray(isolate);
@ -1361,11 +1353,7 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) {
.LoadLiteral(Smi::FromInt(11)) .LoadLiteral(Smi::FromInt(11))
.StoreAccumulatorInRegister(args[2]); .StoreAccumulatorInRegister(args[2]);
if (tail_call_mode == TailCallMode::kAllow) { builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode);
builder.TailCall(reg, args, call_slot_index);
} else {
builder.CallProperty(reg, args, call_slot_index);
}
builder.Return(); builder.Return();
@ -1414,11 +1402,7 @@ static void TestInterpreterCall(TailCallMode tail_call_mode) {
.LoadLiteral(ast_factory.NewString(ast_factory.GetOneByteString("j"))) .LoadLiteral(ast_factory.NewString(ast_factory.GetOneByteString("j")))
.StoreAccumulatorInRegister(args[10]); .StoreAccumulatorInRegister(args[10]);
if (tail_call_mode == TailCallMode::kAllow) { builder.Call(reg, args, call_slot_index, Call::GLOBAL_CALL, tail_call_mode);
builder.TailCall(reg, args, call_slot_index);
} else {
builder.CallProperty(reg, args, call_slot_index);
}
builder.Return(); builder.Return();

View File

@ -39,8 +39,8 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
Register reg(0); Register reg(0);
Register other(reg.index() + 1); Register other(reg.index() + 1);
Register wide(128); Register wide(128);
RegisterList reg_list(0, 10); RegisterList reg_list;
RegisterList empty, single(0, 1), pair(0, 2), triple(0, 3); RegisterList single(0, 1), pair(0, 2), triple(0, 3);
// Emit argument creation operations. // Emit argument creation operations.
builder.CreateArguments(CreateArgumentsType::kMappedArguments) builder.CreateArguments(CreateArgumentsType::kMappedArguments)
@ -145,16 +145,16 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
builder.CreateObjectLiteral(0, 0, 0, reg); builder.CreateObjectLiteral(0, 0, 0, reg);
// Call operations. // Call operations.
builder.CallAnyReceiver(reg, reg_list, 1) builder.Call(reg, reg_list, 1, Call::GLOBAL_CALL)
.CallProperty(reg, reg_list, 1) .Call(reg, single, 1, Call::GLOBAL_CALL)
.CallProperty(reg, single, 1) .Call(reg, pair, 1, Call::GLOBAL_CALL)
.CallProperty(reg, pair, 1) .Call(reg, triple, 1, Call::GLOBAL_CALL)
.CallProperty(reg, triple, 1) .Call(reg, reg_list, 1, Call::NAMED_PROPERTY_CALL,
.CallUndefinedReceiver(reg, reg_list, 1) TailCallMode::kDisallow)
.CallUndefinedReceiver(reg, empty, 1) .Call(reg, single, 1, Call::NAMED_PROPERTY_CALL)
.CallUndefinedReceiver(reg, single, 1) .Call(reg, pair, 1, Call::NAMED_PROPERTY_CALL)
.CallUndefinedReceiver(reg, pair, 1) .Call(reg, triple, 1, Call::NAMED_PROPERTY_CALL)
.TailCall(reg, reg_list, 1) .Call(reg, reg_list, 1, Call::GLOBAL_CALL, TailCallMode::kAllow)
.CallRuntime(Runtime::kIsArray, reg) .CallRuntime(Runtime::kIsArray, reg)
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair) .CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg_list, pair)
.CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg_list) .CallJSRuntime(Context::SPREAD_ITERABLE_INDEX, reg_list)

View File

@ -38,10 +38,10 @@ TEST(BytecodeDecoder, DecodeBytecodeAndOperands) {
"LdaSmi.ExtraWide [-100000]"}, "LdaSmi.ExtraWide [-100000]"},
{{B(Star), R8(5)}, 2, 0, " Star r5"}, {{B(Star), R8(5)}, 2, 0, " Star r5"},
{{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"}, {{B(Wide), B(Star), R16(136)}, 4, 0, " Star.Wide r136"},
{{B(Wide), B(CallAnyReceiver), R16(134), R16(135), U16(10), U16(177)}, {{B(Wide), B(Call), R16(134), R16(135), U16(10), U16(177)},
10, 10,
0, 0,
"CallAnyReceiver.Wide r134, r135-r144, [177]"}, "Call.Wide r134, r135-r144, [177]"},
{{B(ForInPrepare), R8(10), R8(11)}, {{B(ForInPrepare), R8(10), R8(11)},
3, 3,
0, 0,

View File

@ -616,27 +616,25 @@ TARGET_TEST_F(InterpreterAssemblerTest, CallRuntime) {
} }
TARGET_TEST_F(InterpreterAssemblerTest, CallJS) { TARGET_TEST_F(InterpreterAssemblerTest, CallJS) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { TailCallMode tail_call_modes[] = {TailCallMode::kDisallow,
if (Bytecodes::IsCallOrConstruct(bytecode) && TailCallMode::kAllow};
bytecode != Bytecode::kCallWithSpread) { TRACED_FOREACH(TailCallMode, tail_call_mode, tail_call_modes) {
InterpreterAssemblerTestState state(this, bytecode); TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(&state, bytecode); if (Bytecodes::IsCallOrConstruct(bytecode)) {
ConvertReceiverMode receiver_mode = Bytecodes::GetReceiverMode(bytecode); InterpreterAssemblerTestState state(this, bytecode);
TailCallMode tail_call_mode = (bytecode == Bytecode::kTailCall) InterpreterAssemblerForTest m(&state, bytecode);
? TailCallMode::kAllow Callable builtin = CodeFactory::InterpreterPushArgsAndCall(
: TailCallMode::kDisallow; isolate(), tail_call_mode, InterpreterPushArgsMode::kOther);
Node* function = m.IntPtrConstant(0);
Callable builtin = CodeFactory::InterpreterPushArgsThenCall( Node* first_arg = m.IntPtrConstant(1);
isolate(), receiver_mode, tail_call_mode, Node* arg_count = m.Int32Constant(2);
InterpreterPushArgsMode::kOther); Node* context = m.IntPtrConstant(3);
Node* function = m.IntPtrConstant(0); Node* call_js =
Node* first_arg = m.IntPtrConstant(1); m.CallJS(function, context, first_arg, arg_count, tail_call_mode);
Node* arg_count = m.Int32Constant(2); EXPECT_THAT(call_js,
Node* context = m.IntPtrConstant(3); IsCall(_, IsHeapConstant(builtin.code()), arg_count,
Node* call_js = m.CallJS(function, context, first_arg, arg_count, first_arg, function, context, _, _));
receiver_mode, tail_call_mode); }
EXPECT_THAT(call_js, IsCall(_, IsHeapConstant(builtin.code()), arg_count,
first_arg, function, context, _, _));
} }
} }
} }