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