Revert of [Interpreter] Implements calls through CallICStub in the interpreter. (patchset #15 id:270001 of https://codereview.chromium.org/1688283003/ )
Reason for revert: It is not a good idea to call CallICStub from the builtin. It might be sensitive to the frame structure. Constructing a internal frame might cause problems. It is much better to inline the code related to the type feedback vector into the builtin. Original issue's description: > [Interpreter] Implements calls through CallICStub in the interpreter. > > Calls are implemented through CallICStub to collect type feedback. Adds > a new builtin called InterpreterPushArgsAndCallIC that pushes the > arguments onto stack and calls CallICStub. > > Also adds two new bytecodes CallIC and CallICWide to indicate calls have to > go through CallICStub. > > MIPS port contributed by balazs.kilvady. > > BUG=v8:4280, v8:4680 > LOG=N > > Committed: https://crrev.com/20362a2214c11a0f2ea5141b6a79e09458939cec > Cr-Commit-Position: refs/heads/master@{#34244} TBR=rmcilroy@chromium.org,mvstanton@chromium.org,mstarzinger@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:4280, v8:4680 Review URL: https://codereview.chromium.org/1731253003 Cr-Commit-Position: refs/heads/master@{#34252}
This commit is contained in:
parent
b38eabe845
commit
eb358178f8
@ -976,46 +976,6 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
||||
__ b(gt, &loop_header);
|
||||
}
|
||||
|
||||
static void Generate_InterpreterComputeLastArgumentAddress(
|
||||
MacroAssembler* masm, Register num_args, Register start_address,
|
||||
Register output_reg) {
|
||||
__ add(output_reg, num_args, Operand(1)); // Add one for receiver.
|
||||
__ mov(output_reg, Operand(output_reg, LSL, kPointerSizeLog2));
|
||||
__ sub(output_reg, start_address, output_reg);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- r0 : the number of arguments (not including the receiver)
|
||||
// -- r4 : the address of the first argument to be pushed. Subsequent
|
||||
// arguments should be consecutive above this, in the same order as
|
||||
// they are to be pushed onto the stack.
|
||||
// -- r1 : the target to call (can be any Object).
|
||||
// -- r3 : feedback vector slot id
|
||||
// -- r2 : type feedback vector
|
||||
// -----------------------------------
|
||||
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Find the address of the last argument.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, r0, r4, r5);
|
||||
|
||||
// Push the arguments.
|
||||
Generate_InterpreterPushArgs(masm, r4, r5, r6);
|
||||
|
||||
// Call via the CallIC stub.
|
||||
CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode,
|
||||
true);
|
||||
CallICStub stub(masm->isolate(), call_ic_state);
|
||||
// TODO(mythria): This should be replaced by a TailCallStub, when we
|
||||
// update the code to find the target IC from jump instructions.
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
@ -1029,7 +989,9 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
// -----------------------------------
|
||||
|
||||
// Find the address of the last argument.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, r0, r2, r3);
|
||||
__ add(r3, r0, Operand(1)); // Add one for receiver.
|
||||
__ mov(r3, Operand(r3, LSL, kPointerSizeLog2));
|
||||
__ sub(r3, r2, r3);
|
||||
|
||||
// Push the arguments.
|
||||
Generate_InterpreterPushArgs(masm, r2, r3, r4);
|
||||
@ -1980,17 +1942,6 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
|
||||
__ cmp(scratch1, Operand(0));
|
||||
__ b(ne, &done);
|
||||
|
||||
// Drop possible internal frame pushed for calling CallICStub.
|
||||
// TODO(mythria): when we tail call the CallICStub, remove this.
|
||||
{
|
||||
Label no_internal_callic_frame;
|
||||
__ ldr(scratch3, MemOperand(fp, StandardFrameConstants::kMarkerOffset));
|
||||
__ cmp(scratch3, Operand(Smi::FromInt(StackFrame::INTERNAL)));
|
||||
__ b(ne, &no_internal_callic_frame);
|
||||
__ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&no_internal_callic_frame);
|
||||
}
|
||||
|
||||
// Drop possible interpreter handler/stub frame.
|
||||
{
|
||||
Label no_interpreter_frame;
|
||||
|
@ -2067,6 +2067,8 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
__ cmp(r1, r5);
|
||||
__ b(ne, miss);
|
||||
|
||||
__ mov(r0, Operand(arg_count()));
|
||||
|
||||
// Increment the call count for monomorphic function calls.
|
||||
__ add(r2, r2, Operand::PointerOffsetFromSmiKey(r3));
|
||||
__ add(r2, r2, Operand(FixedArray::kHeaderSize + kPointerSize));
|
||||
@ -2076,30 +2078,18 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
|
||||
__ mov(r2, r4);
|
||||
__ mov(r3, r1);
|
||||
if (argc_in_register()) {
|
||||
// Pass a default ArgumentCountKey::Any since the argc is only available
|
||||
// in r0. We do not have the actual count here.
|
||||
ArrayConstructorStub stub(masm->isolate());
|
||||
__ TailCallStub(&stub);
|
||||
} else {
|
||||
// arg_count() is expected in r0 if the arg_count() >= 2
|
||||
// (ArgumentCountKey::MORE_THAN_ONE).
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
|
||||
|
||||
void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// r0 - number of arguments if argc_in_register() is true
|
||||
// r1 - function
|
||||
// r3 - slot id (Smi)
|
||||
// r2 - vector
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
if (!argc_in_register()) {
|
||||
int argc = arg_count();
|
||||
__ mov(r0, Operand(argc));
|
||||
}
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
|
||||
// The checks. First, does r1 match the recorded monomorphic target?
|
||||
__ add(r4, r2, Operand::PointerOffsetFromSmiKey(r3));
|
||||
@ -2135,6 +2125,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ str(r3, FieldMemOperand(r2, 0));
|
||||
|
||||
__ bind(&call_function);
|
||||
__ mov(r0, Operand(argc));
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
|
||||
tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
@ -2174,6 +2165,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ str(ip, FieldMemOperand(r4, FixedArray::kHeaderSize));
|
||||
|
||||
__ bind(&call);
|
||||
__ mov(r0, Operand(argc));
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
@ -2211,13 +2203,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
CreateWeakCellStub create_stub(masm->isolate());
|
||||
__ SmiTag(r0);
|
||||
__ Push(r0);
|
||||
__ Push(r1);
|
||||
__ CallStub(&create_stub);
|
||||
__ Pop(r1);
|
||||
__ Pop(r0);
|
||||
__ SmiUntag(r0);
|
||||
}
|
||||
|
||||
__ jmp(&call_function);
|
||||
@ -2234,10 +2222,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
FrameAndConstantPoolScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Store the number of arguments that is required later.
|
||||
__ SmiTag(r0);
|
||||
__ Push(r0);
|
||||
|
||||
// Push the receiver and the function and feedback info.
|
||||
__ Push(r1, r2, r3);
|
||||
|
||||
@ -2246,10 +2230,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Move result to edi and exit the internal frame.
|
||||
__ mov(r1, r0);
|
||||
|
||||
// Restore back the number of arguments to r0.
|
||||
__ Pop(r0);
|
||||
__ SmiUntag(r0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -443,18 +443,6 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallICDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
r0, // argument count (not including receiver)
|
||||
r4, // address of first argument
|
||||
r1, // the target callable to be call
|
||||
r3, // slot id
|
||||
r2 // type feedback vector
|
||||
};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -1981,17 +1981,6 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
|
||||
__ Cmp(scratch1, Operand(0));
|
||||
__ B(ne, &done);
|
||||
|
||||
// Drop possible internal frame pushed for calling CallICStub.
|
||||
// TODO(mythria): when we tail call the CallICStub, remove this.
|
||||
{
|
||||
Label no_internal_callic_frame;
|
||||
__ Ldr(scratch3, MemOperand(fp, StandardFrameConstants::kMarkerOffset));
|
||||
__ Cmp(scratch3, Operand(Smi::FromInt(StackFrame::INTERNAL)));
|
||||
__ B(ne, &no_internal_callic_frame);
|
||||
__ Ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&no_internal_callic_frame);
|
||||
}
|
||||
|
||||
// Drop possible interpreter handler/stub frame.
|
||||
{
|
||||
Label no_interpreter_frame;
|
||||
@ -2475,57 +2464,6 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
|
||||
RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
|
||||
Register num_args,
|
||||
Register start_addr) {
|
||||
// Find the address of the last argument.
|
||||
__ add(x5, num_args, Operand(1)); // Add one for receiver.
|
||||
__ lsl(x5, x5, kPointerSizeLog2);
|
||||
__ sub(x6, start_addr, x5);
|
||||
|
||||
// Push the arguments.
|
||||
Label loop_header, loop_check;
|
||||
__ Mov(x7, jssp);
|
||||
__ Claim(x5, 1);
|
||||
__ B(&loop_check);
|
||||
__ Bind(&loop_header);
|
||||
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
|
||||
__ Ldr(x5, MemOperand(start_addr, -kPointerSize, PostIndex));
|
||||
__ Str(x5, MemOperand(x7, -kPointerSize, PreIndex));
|
||||
__ Bind(&loop_check);
|
||||
__ Cmp(start_addr, x6);
|
||||
__ B(gt, &loop_header);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- x0 : the number of arguments (not including the receiver)
|
||||
// -- x4 : the address of the first argument to be pushed. Subsequent
|
||||
// arguments should be consecutive above this, in the same order as
|
||||
// they are to be pushed onto the stack.
|
||||
// -- x1 : the target to call (can be any Object).
|
||||
// -- x3 : feedback vector slot id
|
||||
// -- x2 : type feedback vector
|
||||
// -----------------------------------
|
||||
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Push arguments to stack. Clobbers x5-x7 registers.
|
||||
Generate_InterpreterPushArgs(masm, x0, x4);
|
||||
|
||||
// Call via the CallIC stub.
|
||||
CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode,
|
||||
true);
|
||||
CallICStub stub(masm->isolate(), call_ic_state);
|
||||
// TODO(mythria): This should be replaced by a TailCallStub, when we
|
||||
// update the code to find the target IC from jump instructions.
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
@ -2538,8 +2476,23 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
// -- x1 : the target to call (can be any Object).
|
||||
// -----------------------------------
|
||||
|
||||
// Push arguments to stack. Clobbers x5-x7 registers.
|
||||
Generate_InterpreterPushArgs(masm, x0, x2);
|
||||
// Find the address of the last argument.
|
||||
__ add(x3, x0, Operand(1)); // Add one for receiver.
|
||||
__ lsl(x3, x3, kPointerSizeLog2);
|
||||
__ sub(x4, x2, x3);
|
||||
|
||||
// Push the arguments.
|
||||
Label loop_header, loop_check;
|
||||
__ Mov(x5, jssp);
|
||||
__ Claim(x3, 1);
|
||||
__ B(&loop_check);
|
||||
__ Bind(&loop_header);
|
||||
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
|
||||
__ Ldr(x3, MemOperand(x2, -kPointerSize, PostIndex));
|
||||
__ Str(x3, MemOperand(x5, -kPointerSize, PreIndex));
|
||||
__ Bind(&loop_check);
|
||||
__ Cmp(x2, x4);
|
||||
__ B(gt, &loop_header);
|
||||
|
||||
// Call the target.
|
||||
__ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
|
||||
|
@ -2289,7 +2289,6 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
// x0 - number of arguments
|
||||
// x1 - function
|
||||
// x3 - slot id
|
||||
// x2 - vector
|
||||
@ -2304,6 +2303,8 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
__ Cmp(function, scratch);
|
||||
__ B(ne, miss);
|
||||
|
||||
__ Mov(x0, Operand(arg_count()));
|
||||
|
||||
// Increment the call count for monomorphic function calls.
|
||||
__ Add(feedback_vector, feedback_vector,
|
||||
Operand::UntagSmiAndScale(index, kPointerSizeLog2));
|
||||
@ -2318,31 +2319,20 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
Register new_target_arg = index;
|
||||
__ Mov(allocation_site_arg, allocation_site);
|
||||
__ Mov(new_target_arg, function);
|
||||
if (argc_in_register()) {
|
||||
// Pass a default ArgumentCountKey::Any since the argc is only available
|
||||
// in r0. We do not have the actual count here.
|
||||
ArrayConstructorStub stub(masm->isolate());
|
||||
__ TailCallStub(&stub);
|
||||
} else {
|
||||
// arg_count() is expected in r0 if the arg_count() >= 2
|
||||
// (ArgumentCountKey::MORE_THAN_ONE).
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
|
||||
|
||||
void CallICStub::Generate(MacroAssembler* masm) {
|
||||
ASM_LOCATION("CallICStub");
|
||||
|
||||
// x0 - number of arguments if argc_in_register() is true
|
||||
// x1 - function
|
||||
// x3 - slot id (Smi)
|
||||
// x2 - vector
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
if (!argc_in_register()) {
|
||||
__ Mov(x0, arg_count());
|
||||
}
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
|
||||
Register function = x1;
|
||||
Register feedback_vector = x2;
|
||||
@ -2385,6 +2375,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ Str(index, FieldMemOperand(feedback_vector, 0));
|
||||
|
||||
__ Bind(&call_function);
|
||||
__ Mov(x0, argc);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
|
||||
tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
@ -2419,6 +2410,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ Str(x5, FieldMemOperand(x4, FixedArray::kHeaderSize));
|
||||
|
||||
__ Bind(&call);
|
||||
__ Mov(x0, argc);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
@ -2456,13 +2448,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
CreateWeakCellStub create_stub(masm->isolate());
|
||||
__ SmiTag(x0);
|
||||
__ Push(x0);
|
||||
__ Push(function);
|
||||
__ CallStub(&create_stub);
|
||||
__ Pop(function);
|
||||
__ Pop(x0);
|
||||
__ SmiUntag(x0);
|
||||
}
|
||||
|
||||
__ B(&call_function);
|
||||
@ -2481,10 +2469,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Store number of arguments.
|
||||
__ SmiTag(x0);
|
||||
__ Push(x0);
|
||||
|
||||
// Push the receiver and the function and feedback info.
|
||||
__ Push(x1, x2, x3);
|
||||
|
||||
@ -2493,10 +2477,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Move result to edi and exit the internal frame.
|
||||
__ Mov(x1, x0);
|
||||
|
||||
// Restore number of arguments.
|
||||
__ Pop(x0);
|
||||
__ SmiUntag(x0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -478,18 +478,6 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallICDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
x0, // argument count (not including receiver)
|
||||
x4, // address of first argument
|
||||
x1, // the target callable to be call
|
||||
x3, // slot id
|
||||
x2 // type feedback vector
|
||||
};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -3999,18 +3999,6 @@ Handle<Code> Builtins::InterpreterPushArgsAndCall(TailCallMode tail_call_mode) {
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
Handle<Code> Builtins::InterpreterPushArgsAndCallIC(
|
||||
TailCallMode tail_call_mode) {
|
||||
switch (tail_call_mode) {
|
||||
case TailCallMode::kDisallow:
|
||||
return InterpreterPushArgsAndCallIC();
|
||||
case TailCallMode::kAllow:
|
||||
return InterpreterPushArgsAndTailCallIC();
|
||||
}
|
||||
UNREACHABLE();
|
||||
return Handle<Code>::null();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class RelocatableArguments
|
||||
|
@ -216,8 +216,6 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
|
||||
\
|
||||
V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(InterpreterPushArgsAndCallIC, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(InterpreterPushArgsAndTailCallIC, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(InterpreterPushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(InterpreterPushArgsAndTailCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
V(InterpreterPushArgsAndConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState) \
|
||||
@ -369,7 +367,6 @@ class Builtins {
|
||||
TailCallMode tail_call_mode = TailCallMode::kDisallow);
|
||||
Handle<Code> CallBoundFunction(TailCallMode tail_call_mode);
|
||||
Handle<Code> InterpreterPushArgsAndCall(TailCallMode tail_call_mode);
|
||||
Handle<Code> InterpreterPushArgsAndCallIC(TailCallMode tail_call_mode);
|
||||
|
||||
Code* builtin(Name name) {
|
||||
// Code::cast cannot be used here since we access builtins
|
||||
@ -585,16 +582,6 @@ class Builtins {
|
||||
|
||||
static void Generate_InterpreterEntryTrampoline(MacroAssembler* masm);
|
||||
static void Generate_InterpreterExitTrampoline(MacroAssembler* masm);
|
||||
static void Generate_InterpreterPushArgsAndCallIC(MacroAssembler* masm) {
|
||||
return Generate_InterpreterPushArgsAndCallICImpl(masm,
|
||||
TailCallMode::kDisallow);
|
||||
}
|
||||
static void Generate_InterpreterPushArgsAndTailCallIC(MacroAssembler* masm) {
|
||||
return Generate_InterpreterPushArgsAndCallICImpl(masm,
|
||||
TailCallMode::kAllow);
|
||||
}
|
||||
static void Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode);
|
||||
static void Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
|
||||
return Generate_InterpreterPushArgsAndCallImpl(masm,
|
||||
TailCallMode::kDisallow);
|
||||
|
@ -345,13 +345,6 @@ Callable CodeFactory::ConstructFunction(Isolate* isolate) {
|
||||
ConstructTrampolineDescriptor(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
Callable CodeFactory::InterpreterPushArgsAndCallIC(
|
||||
Isolate* isolate, TailCallMode tail_call_mode) {
|
||||
return Callable(
|
||||
isolate->builtins()->InterpreterPushArgsAndCallIC(tail_call_mode),
|
||||
InterpreterPushArgsAndCallICDescriptor(isolate));
|
||||
}
|
||||
|
||||
// static
|
||||
Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
|
||||
@ -361,6 +354,7 @@ Callable CodeFactory::InterpreterPushArgsAndCall(Isolate* isolate,
|
||||
InterpreterPushArgsAndCallDescriptor(isolate));
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
Callable CodeFactory::InterpreterPushArgsAndConstruct(Isolate* isolate) {
|
||||
return Callable(isolate->builtins()->InterpreterPushArgsAndConstruct(),
|
||||
|
@ -106,8 +106,6 @@ class CodeFactory final {
|
||||
static Callable Construct(Isolate* isolate);
|
||||
static Callable ConstructFunction(Isolate* isolate);
|
||||
|
||||
static Callable InterpreterPushArgsAndCallIC(Isolate* isolate,
|
||||
TailCallMode tail_call_mode);
|
||||
static Callable InterpreterPushArgsAndCall(Isolate* isolate,
|
||||
TailCallMode tail_call_mode);
|
||||
static Callable InterpreterPushArgsAndConstruct(Isolate* isolate);
|
||||
|
@ -973,13 +973,9 @@ class CallICStub: public PlatformCodeStub {
|
||||
}
|
||||
|
||||
protected:
|
||||
int arg_count() const {
|
||||
DCHECK(!argc_in_register());
|
||||
return state().argc();
|
||||
}
|
||||
int arg_count() const { return state().argc(); }
|
||||
ConvertReceiverMode convert_mode() const { return state().convert_mode(); }
|
||||
TailCallMode tail_call_mode() const { return state().tail_call_mode(); }
|
||||
bool argc_in_register() const { return state().argc_in_register(); }
|
||||
|
||||
CallICState state() const {
|
||||
return CallICState(static_cast<ExtraICState>(minor_key_));
|
||||
|
@ -501,7 +501,10 @@ Node* BytecodeGraphBuilder::BuildLoadNativeContextField(int index) {
|
||||
|
||||
|
||||
VectorSlotPair BytecodeGraphBuilder::CreateVectorSlotPair(int slot_id) {
|
||||
FeedbackVectorSlot slot = feedback_vector()->ToSlot(slot_id);
|
||||
FeedbackVectorSlot slot;
|
||||
if (slot_id >= TypeFeedbackVector::kReservedIndexCount) {
|
||||
slot = feedback_vector()->ToSlot(slot_id);
|
||||
}
|
||||
return VectorSlotPair(feedback_vector(), slot);
|
||||
}
|
||||
|
||||
@ -989,42 +992,6 @@ Node* BytecodeGraphBuilder::ProcessCallArguments(const Operator* call_op,
|
||||
return value;
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::BuildCallWithFeedbackSlot(
|
||||
TailCallMode tail_call_mode) {
|
||||
FrameStateBeforeAndAfter states(this);
|
||||
// TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver
|
||||
// register has been loaded with null / undefined explicitly or we are sure it
|
||||
// is not null / undefined.
|
||||
ConvertReceiverMode receiver_hint = ConvertReceiverMode::kAny;
|
||||
Node* callee =
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
|
||||
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
|
||||
int slot_id = bytecode_iterator().GetIndexOperand(3);
|
||||
VectorSlotPair feedback = CreateVectorSlotPair(slot_id);
|
||||
|
||||
const Operator* call = javascript()->CallFunction(
|
||||
arg_count + 1, feedback, receiver_hint, tail_call_mode);
|
||||
Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
|
||||
environment()->BindAccumulator(value, &states);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCallIC() {
|
||||
BuildCallWithFeedbackSlot(TailCallMode::kDisallow);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitCallICWide() {
|
||||
BuildCallWithFeedbackSlot(TailCallMode::kDisallow);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitTailCallIC() {
|
||||
BuildCallWithFeedbackSlot(TailCallMode::kAllow);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::VisitTailCallICWide() {
|
||||
BuildCallWithFeedbackSlot(TailCallMode::kAllow);
|
||||
}
|
||||
|
||||
void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode) {
|
||||
FrameStateBeforeAndAfter states(this);
|
||||
// TODO(rmcilroy): Set receiver_hint correctly based on whether the receiver
|
||||
@ -1035,9 +1002,11 @@ void BytecodeGraphBuilder::BuildCall(TailCallMode tail_call_mode) {
|
||||
environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
|
||||
interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1);
|
||||
size_t arg_count = bytecode_iterator().GetRegisterCountOperand(2);
|
||||
VectorSlotPair feedback =
|
||||
CreateVectorSlotPair(bytecode_iterator().GetIndexOperand(3));
|
||||
|
||||
const Operator* call = javascript()->CallFunction(
|
||||
arg_count + 1, VectorSlotPair(), receiver_hint, tail_call_mode);
|
||||
arg_count + 1, feedback, receiver_hint, tail_call_mode);
|
||||
Node* value = ProcessCallArguments(call, callee, receiver, arg_count + 1);
|
||||
environment()->BindAccumulator(value, &states);
|
||||
}
|
||||
|
@ -124,7 +124,6 @@ class BytecodeGraphBuilder {
|
||||
void BuildLdaLookupSlot(TypeofMode typeof_mode);
|
||||
void BuildStaLookupSlot(LanguageMode language_mode);
|
||||
void BuildCall(TailCallMode tail_call_mode);
|
||||
void BuildCallWithFeedbackSlot(TailCallMode tail_call_mode);
|
||||
void BuildCallJSRuntime();
|
||||
void BuildCallRuntime();
|
||||
void BuildCallRuntimeForPair();
|
||||
|
@ -559,58 +559,6 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
|
||||
__ j(greater, &loop_header, Label::kNear);
|
||||
}
|
||||
|
||||
static void Generate_InterpreterComputeLastArgumentAddress(MacroAssembler* masm,
|
||||
Register r) {
|
||||
// Find the address of the last argument.
|
||||
// ----------- S t a t e -------------
|
||||
// input: eax : Number of arguments.
|
||||
// input: ebx : Address of the first argument.
|
||||
// output: Register |r|: Address of the last argument.
|
||||
// -----------------------------------
|
||||
__ mov(r, eax);
|
||||
__ add(r, Immediate(1)); // Add one for receiver.
|
||||
__ shl(r, kPointerSizeLog2);
|
||||
__ neg(r);
|
||||
__ add(r, ebx);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_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
|
||||
// arguments should be consecutive above this, in the same order as
|
||||
// they are to be pushed onto the stack.
|
||||
// -- edi : the target to call (can be any Object).
|
||||
// -- edx : feedback slot id.
|
||||
// -- ecx : type feedback vector.
|
||||
// -----------------------------------
|
||||
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
// Store type feedback vector on the stack since we ran out of registers.
|
||||
__ Push(ecx);
|
||||
|
||||
// computes the address of last argument in ecx.
|
||||
// ecx = ebx - (eax + 1) * kPointerSize.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, ecx);
|
||||
Generate_InterpreterPushArgs(masm, ecx);
|
||||
|
||||
// Restore feedback vector to ebx from the stack. It was pushed
|
||||
// before the arguments were pushed, so compute the correct offset.
|
||||
__ mov(ebx, Operand(esp, eax, times_pointer_size, 1 * kPointerSize));
|
||||
|
||||
// Call via the CallIC stub.
|
||||
CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode,
|
||||
true);
|
||||
CallICStub stub(masm->isolate(), call_ic_state);
|
||||
// TODO(mythria): This should be replaced by a TailCallStub, when we
|
||||
// update the code to find the target IC from jump instructions.
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
@ -626,9 +574,13 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
// Pop return address to allow tail-call after pushing arguments.
|
||||
__ Pop(edx);
|
||||
|
||||
// computes the address of last argument in ecx.
|
||||
// ecx = ebx - (eax + 1) * kPointerSize.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, ecx);
|
||||
// Find the address of the last argument.
|
||||
__ mov(ecx, eax);
|
||||
__ add(ecx, Immediate(1)); // Add one for receiver.
|
||||
__ shl(ecx, kPointerSizeLog2);
|
||||
__ neg(ecx);
|
||||
__ add(ecx, ebx);
|
||||
|
||||
Generate_InterpreterPushArgs(masm, ecx);
|
||||
|
||||
// Call the target.
|
||||
@ -638,6 +590,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
@ -649,24 +602,27 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
// they are to be pushed onto the stack.
|
||||
// -----------------------------------
|
||||
|
||||
// Save number of arguments on the stack below where arguments are going
|
||||
// to be pushed.
|
||||
__ mov(ecx, eax);
|
||||
__ neg(ecx);
|
||||
__ mov(Operand(esp, ecx, times_pointer_size, -kPointerSize), eax);
|
||||
__ mov(eax, ecx);
|
||||
|
||||
// Pop return address to allow tail-call after pushing arguments.
|
||||
__ Pop(ecx);
|
||||
|
||||
// Push edi in the slot meant for receiver. We need an extra register so
|
||||
// store edi temporarily on the stack.
|
||||
__ Push(edi);
|
||||
|
||||
// Find the address of the last argument.
|
||||
__ mov(edi, eax);
|
||||
__ neg(edi);
|
||||
__ shl(edi, kPointerSizeLog2);
|
||||
__ add(edi, ebx);
|
||||
__ shl(eax, kPointerSizeLog2);
|
||||
__ add(eax, ebx);
|
||||
|
||||
Generate_InterpreterPushArgs(masm, edi);
|
||||
// Push padding for receiver.
|
||||
__ Push(Immediate(0));
|
||||
|
||||
// Restore number of arguments from slot on stack. edi was pushed at
|
||||
// the slot meant for receiver.
|
||||
__ mov(edi, Operand(esp, eax, times_pointer_size, 0));
|
||||
Generate_InterpreterPushArgs(masm, eax);
|
||||
|
||||
// Restore number of arguments from slot on stack.
|
||||
__ mov(eax, Operand(esp, -kPointerSize));
|
||||
|
||||
// Re-push return address.
|
||||
__ Push(ecx);
|
||||
@ -1917,17 +1873,6 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
|
||||
__ cmp(scratch1, Immediate(0));
|
||||
__ j(not_equal, &done, Label::kNear);
|
||||
|
||||
// Drop possible internal frame pushed for calling CallICStub.
|
||||
// TODO(mythria): when we tail call the CallICStub, remove this.
|
||||
{
|
||||
Label no_internal_callic_frame;
|
||||
__ cmp(Operand(ebp, StandardFrameConstants::kMarkerOffset),
|
||||
Immediate(Smi::FromInt(StackFrame::INTERNAL)));
|
||||
__ j(not_equal, &no_internal_callic_frame, Label::kNear);
|
||||
__ mov(ebp, Operand(ebp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&no_internal_callic_frame);
|
||||
}
|
||||
|
||||
// Drop possible interpreter handler/stub frame.
|
||||
{
|
||||
Label no_interpreter_frame;
|
||||
|
@ -1624,11 +1624,11 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
// edi - function
|
||||
// edx - slot id
|
||||
// ebx - vector
|
||||
// eax - number of arguments - if argc_in_register() is true.
|
||||
__ LoadGlobalFunction(Context::ARRAY_FUNCTION_INDEX, ecx);
|
||||
__ cmp(edi, ecx);
|
||||
__ j(not_equal, miss);
|
||||
|
||||
__ mov(eax, arg_count());
|
||||
// Reload ecx.
|
||||
__ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
|
||||
FixedArray::kHeaderSize));
|
||||
@ -1640,17 +1640,9 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
|
||||
__ mov(ebx, ecx);
|
||||
__ mov(edx, edi);
|
||||
if (argc_in_register()) {
|
||||
// Pass a default ArgumentCountKey::Any since the argc is only available
|
||||
// in eax. We do not have the actual count here.
|
||||
ArrayConstructorStub stub(masm->isolate());
|
||||
__ TailCallStub(&stub);
|
||||
} else {
|
||||
// arg_count() is expected in rax if the arg_count() >= 2
|
||||
// (ArgumentCountKey::MORE_THAN_ONE).
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
|
||||
// Unreachable.
|
||||
}
|
||||
|
||||
@ -1659,13 +1651,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// edi - function
|
||||
// edx - slot id
|
||||
// ebx - vector
|
||||
// eax - number of arguments - if argc_in_register() is true.
|
||||
Isolate* isolate = masm->isolate();
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
if (!argc_in_register()) {
|
||||
int argc = arg_count();
|
||||
__ Set(eax, argc);
|
||||
}
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
|
||||
// The checks. First, does edi match the recorded monomorphic target?
|
||||
__ mov(ecx, FieldOperand(ebx, edx, times_half_pointer_size,
|
||||
@ -1698,6 +1687,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
Immediate(Smi::FromInt(CallICNexus::kCallCountIncrement)));
|
||||
|
||||
__ bind(&call_function);
|
||||
__ Set(eax, argc);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
|
||||
tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
@ -1737,6 +1727,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
Immediate(TypeFeedbackVector::MegamorphicSentinel(isolate)));
|
||||
|
||||
__ bind(&call);
|
||||
__ Set(eax, argc);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
@ -1773,15 +1764,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
CreateWeakCellStub create_stub(isolate);
|
||||
__ SmiTag(eax);
|
||||
__ push(eax);
|
||||
__ push(edi);
|
||||
|
||||
__ CallStub(&create_stub);
|
||||
|
||||
__ pop(edi);
|
||||
__ pop(eax);
|
||||
__ SmiUntag(eax);
|
||||
}
|
||||
|
||||
__ jmp(&call_function);
|
||||
@ -1801,9 +1786,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Store eax since we need it later.
|
||||
__ SmiTag(eax);
|
||||
__ push(eax);
|
||||
// Push the function and feedback info.
|
||||
__ push(edi);
|
||||
__ push(ebx);
|
||||
@ -1814,10 +1796,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Move result to edi and exit the internal frame.
|
||||
__ mov(edi, eax);
|
||||
|
||||
// Restore eax.
|
||||
__ pop(eax);
|
||||
__ SmiUntag(eax);
|
||||
}
|
||||
|
||||
|
||||
|
@ -433,18 +433,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallICDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
eax, // argument count (not including receiver)
|
||||
ebx, // address of first argument
|
||||
edi, // the target callable to be call
|
||||
edx, // feedback vector slot id
|
||||
ecx // type feedback vector
|
||||
};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -26,11 +26,10 @@ class CallICState final BASE_EMBEDDED {
|
||||
explicit CallICState(ExtraICState extra_ic_state)
|
||||
: bit_field_(extra_ic_state) {}
|
||||
CallICState(int argc, ConvertReceiverMode convert_mode,
|
||||
TailCallMode tail_call_mode, bool is_argc_in_reg = false)
|
||||
TailCallMode tail_call_mode)
|
||||
: bit_field_(ArgcBits::encode(argc) |
|
||||
ConvertModeBits::encode(convert_mode) |
|
||||
TailCallModeBits::encode(tail_call_mode) |
|
||||
ArgcInRegBits::encode(is_argc_in_reg)) {}
|
||||
TailCallModeBits::encode(tail_call_mode)) {}
|
||||
|
||||
ExtraICState GetExtraICState() const { return bit_field_; }
|
||||
|
||||
@ -45,13 +44,11 @@ class CallICState final BASE_EMBEDDED {
|
||||
TailCallMode tail_call_mode() const {
|
||||
return TailCallModeBits::decode(bit_field_);
|
||||
}
|
||||
bool argc_in_register() { return ArgcInRegBits::decode(bit_field_); }
|
||||
|
||||
private:
|
||||
typedef BitField<int, 0, Code::kArgumentsBits> ArgcBits;
|
||||
typedef BitField<ConvertReceiverMode, ArgcBits::kNext, 2> ConvertModeBits;
|
||||
typedef BitField<TailCallMode, ConvertModeBits::kNext, 1> TailCallModeBits;
|
||||
typedef BitField<bool, TailCallModeBits::kNext, 1> ArgcInRegBits;
|
||||
|
||||
int const bit_field_;
|
||||
};
|
||||
|
@ -78,7 +78,6 @@ class PlatformInterfaceDescriptor;
|
||||
V(GrowArrayElements) \
|
||||
V(InterpreterDispatch) \
|
||||
V(InterpreterPushArgsAndCall) \
|
||||
V(InterpreterPushArgsAndCallIC) \
|
||||
V(InterpreterPushArgsAndConstruct) \
|
||||
V(InterpreterCEntry)
|
||||
|
||||
@ -758,18 +757,13 @@ class InterpreterDispatchDescriptor : public CallInterfaceDescriptor {
|
||||
static const int kContextParameter = 5;
|
||||
};
|
||||
|
||||
class InterpreterPushArgsAndCallICDescriptor : public CallInterfaceDescriptor {
|
||||
public:
|
||||
DECLARE_DESCRIPTOR(InterpreterPushArgsAndCallICDescriptor,
|
||||
CallInterfaceDescriptor)
|
||||
};
|
||||
|
||||
class InterpreterPushArgsAndCallDescriptor : public CallInterfaceDescriptor {
|
||||
public:
|
||||
DECLARE_DESCRIPTOR(InterpreterPushArgsAndCallDescriptor,
|
||||
CallInterfaceDescriptor)
|
||||
};
|
||||
|
||||
|
||||
class InterpreterPushArgsAndConstructDescriptor
|
||||
: public CallInterfaceDescriptor {
|
||||
public:
|
||||
|
@ -1059,10 +1059,12 @@ void BytecodeArrayBuilder::EnsureReturn(FunctionLiteral* literal) {
|
||||
}
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::CallIC(
|
||||
Register callable, Register receiver_args, size_t receiver_args_count,
|
||||
int feedback_slot, TailCallMode tail_call_mode) {
|
||||
Bytecode bytecode = BytecodeForCallIC(tail_call_mode);
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
|
||||
Register receiver_args,
|
||||
size_t receiver_args_count,
|
||||
int feedback_slot,
|
||||
TailCallMode tail_call_mode) {
|
||||
Bytecode bytecode = BytecodeForCall(tail_call_mode);
|
||||
if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver_args) &&
|
||||
FitsInIdx8Operand(receiver_args_count) &&
|
||||
FitsInIdx8Operand(feedback_slot)) {
|
||||
@ -1083,26 +1085,6 @@ BytecodeArrayBuilder& BytecodeArrayBuilder::CallIC(
|
||||
return *this;
|
||||
}
|
||||
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::Call(Register callable,
|
||||
Register receiver_args,
|
||||
size_t receiver_args_count,
|
||||
TailCallMode tail_call_mode) {
|
||||
Bytecode bytecode = BytecodeForCall(tail_call_mode);
|
||||
if (FitsInReg8Operand(callable) && FitsInReg8Operand(receiver_args) &&
|
||||
FitsInIdx8Operand(receiver_args_count)) {
|
||||
Output(bytecode, callable.ToRawOperand(), receiver_args.ToRawOperand(),
|
||||
static_cast<uint8_t>(receiver_args_count));
|
||||
} else if (FitsInReg16Operand(callable) &&
|
||||
FitsInReg16Operand(receiver_args) &&
|
||||
FitsInIdx16Operand(receiver_args_count)) {
|
||||
bytecode = BytecodeForWideOperands(bytecode);
|
||||
Output(bytecode, callable.ToRawOperand(), receiver_args.ToRawOperand(),
|
||||
static_cast<uint16_t>(receiver_args_count));
|
||||
} else {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
BytecodeArrayBuilder& BytecodeArrayBuilder::New(Register constructor,
|
||||
Register first_arg,
|
||||
size_t arg_count) {
|
||||
@ -1444,10 +1426,6 @@ Bytecode BytecodeArrayBuilder::BytecodeForCompareOperation(Token::Value op) {
|
||||
// static
|
||||
Bytecode BytecodeArrayBuilder::BytecodeForWideOperands(Bytecode bytecode) {
|
||||
switch (bytecode) {
|
||||
case Bytecode::kCallIC:
|
||||
return Bytecode::kCallICWide;
|
||||
case Bytecode::kTailCallIC:
|
||||
return Bytecode::kTailCallICWide;
|
||||
case Bytecode::kCall:
|
||||
return Bytecode::kCallWide;
|
||||
case Bytecode::kTailCall:
|
||||
@ -1591,19 +1569,6 @@ Bytecode BytecodeArrayBuilder::BytecodeForDelete(LanguageMode language_mode) {
|
||||
return static_cast<Bytecode>(-1);
|
||||
}
|
||||
|
||||
// static
|
||||
Bytecode BytecodeArrayBuilder::BytecodeForCallIC(TailCallMode tail_call_mode) {
|
||||
switch (tail_call_mode) {
|
||||
case TailCallMode::kDisallow:
|
||||
return Bytecode::kCallIC;
|
||||
case TailCallMode::kAllow:
|
||||
return Bytecode::kTailCallIC;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return static_cast<Bytecode>(-1);
|
||||
}
|
||||
|
||||
// static
|
||||
Bytecode BytecodeArrayBuilder::BytecodeForCall(TailCallMode tail_call_mode) {
|
||||
switch (tail_call_mode) {
|
||||
|
@ -163,28 +163,18 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
|
||||
// <receiver_args + receiver_arg_count - 1>.
|
||||
BytecodeArrayBuilder& Call(
|
||||
Register callable, Register receiver_args, size_t receiver_arg_count,
|
||||
TailCallMode tail_call_mode = TailCallMode::kDisallow);
|
||||
int feedback_slot, TailCallMode tail_call_mode = TailCallMode::kDisallow);
|
||||
|
||||
BytecodeArrayBuilder& TailCall(Register callable, Register receiver_args,
|
||||
size_t receiver_arg_count) {
|
||||
return Call(callable, receiver_args, receiver_arg_count,
|
||||
size_t receiver_arg_count, int feedback_slot) {
|
||||
return Call(callable, receiver_args, receiver_arg_count, feedback_slot,
|
||||
TailCallMode::kAllow);
|
||||
}
|
||||
|
||||
// Call a JS function. The JSFunction or Callable to be called should be in
|
||||
// |callable|, the receiver should be in |receiver_args| and all subsequent
|
||||
// arguments should be in registers <receiver_args + 1> to
|
||||
// <receiver_args + receiver_arg_count - 1>.
|
||||
// Call through CallICStub to get Typefeedback.
|
||||
BytecodeArrayBuilder& CallIC(Register callable, Register receiver_args,
|
||||
size_t receiver_arg_count, int feedback_slot,
|
||||
TailCallMode tail_call_mode);
|
||||
|
||||
// Call the new operator. The accumulator holds the |new_target|.
|
||||
// The |constructor| is in a register followed by |arg_count|
|
||||
// consecutive arguments starting at |first_arg| for the constuctor
|
||||
// invocation.
|
||||
|
||||
BytecodeArrayBuilder& New(Register constructor, Register first_arg,
|
||||
size_t arg_count);
|
||||
|
||||
@ -297,7 +287,6 @@ class BytecodeArrayBuilder final : public ZoneObject, private RegisterMover {
|
||||
static Bytecode BytecodeForCreateArguments(CreateArgumentsType type);
|
||||
static Bytecode BytecodeForDelete(LanguageMode language_mode);
|
||||
static Bytecode BytecodeForCall(TailCallMode tail_call_mode);
|
||||
static Bytecode BytecodeForCallIC(TailCallMode tail_call_mode);
|
||||
|
||||
static bool FitsInIdx8Operand(int value);
|
||||
static bool FitsInIdx8Operand(size_t value);
|
||||
|
@ -2457,15 +2457,9 @@ void BytecodeGenerator::VisitCall(Call* expr) {
|
||||
}
|
||||
|
||||
builder()->SetExpressionPosition(expr);
|
||||
if (expr->CallFeedbackICSlot().IsInvalid()) {
|
||||
builder()->Call(callee, receiver, 1 + args->length(),
|
||||
expr->tail_call_mode());
|
||||
} else {
|
||||
DCHECK(call_type != Call::POSSIBLY_EVAL_CALL);
|
||||
builder()->CallIC(callee, receiver, 1 + args->length(),
|
||||
feedback_index(expr->CallFeedbackICSlot()),
|
||||
expr->tail_call_mode());
|
||||
}
|
||||
builder()->Call(callee, receiver, 1 + args->length(),
|
||||
feedback_index(expr->CallFeedbackICSlot()),
|
||||
expr->tail_call_mode());
|
||||
execution_result()->SetResultInAccumulator();
|
||||
}
|
||||
|
||||
|
@ -278,10 +278,8 @@ bool Bytecodes::IsJump(Bytecode bytecode) {
|
||||
// static
|
||||
bool Bytecodes::IsCallOrNew(Bytecode bytecode) {
|
||||
return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall ||
|
||||
bytecode == Bytecode::kNew || bytecode == Bytecode::kCallIC ||
|
||||
bytecode == Bytecode::kCallWide ||
|
||||
bytecode == Bytecode::kTailCallWide ||
|
||||
bytecode == Bytecode::kNewWide || bytecode == Bytecode::kCallICWide;
|
||||
bytecode == Bytecode::kNew || bytecode == Bytecode::kCallWide ||
|
||||
bytecode == Bytecode::kTailCallWide || bytecode == Bytecode::kNewWide;
|
||||
}
|
||||
|
||||
// static
|
||||
|
@ -169,20 +169,14 @@ namespace interpreter {
|
||||
V(DeletePropertySloppy, OperandType::kReg8) \
|
||||
\
|
||||
/* Call operations */ \
|
||||
V(CallIC, OperandType::kReg8, OperandType::kReg8, OperandType::kRegCount8, \
|
||||
V(Call, OperandType::kReg8, OperandType::kReg8, OperandType::kRegCount8, \
|
||||
OperandType::kIdx8) \
|
||||
V(CallICWide, OperandType::kReg16, OperandType::kReg16, \
|
||||
OperandType::kRegCount16, OperandType::kIdx16) \
|
||||
V(TailCallIC, OperandType::kReg8, OperandType::kReg8, \
|
||||
OperandType::kRegCount8, OperandType::kIdx8) \
|
||||
V(TailCallICWide, OperandType::kReg16, OperandType::kReg16, \
|
||||
OperandType::kRegCount16, OperandType::kIdx16) \
|
||||
V(Call, OperandType::kReg8, OperandType::kReg8, OperandType::kRegCount8) \
|
||||
V(CallWide, OperandType::kReg16, OperandType::kReg16, \
|
||||
OperandType::kRegCount16) \
|
||||
V(TailCall, OperandType::kReg8, OperandType::kReg8, OperandType::kRegCount8) \
|
||||
OperandType::kRegCount16, OperandType::kIdx16) \
|
||||
V(TailCall, OperandType::kReg8, OperandType::kReg8, OperandType::kRegCount8, \
|
||||
OperandType::kIdx8) \
|
||||
V(TailCallWide, OperandType::kReg16, OperandType::kReg16, \
|
||||
OperandType::kRegCount16) \
|
||||
OperandType::kRegCount16, OperandType::kIdx16) \
|
||||
V(CallRuntime, OperandType::kIdx16, OperandType::kMaybeReg8, \
|
||||
OperandType::kRegCount8) \
|
||||
V(CallRuntimeWide, OperandType::kIdx16, OperandType::kMaybeReg16, \
|
||||
|
@ -345,19 +345,6 @@ Node* InterpreterAssembler::CallJS(Node* function, Node* context,
|
||||
first_arg, function);
|
||||
}
|
||||
|
||||
Node* InterpreterAssembler::CallJSWithFeedback(Node* function, Node* context,
|
||||
Node* first_arg, Node* arg_count,
|
||||
Node* slot_id,
|
||||
Node* type_feedback_vector,
|
||||
TailCallMode tail_call_mode) {
|
||||
Callable callable =
|
||||
CodeFactory::InterpreterPushArgsAndCallIC(isolate(), tail_call_mode);
|
||||
Node* code_target = HeapConstant(callable.code());
|
||||
|
||||
return CallStub(callable.descriptor(), code_target, context, arg_count,
|
||||
first_arg, function, slot_id, type_feedback_vector);
|
||||
}
|
||||
|
||||
Node* InterpreterAssembler::CallConstruct(Node* constructor, Node* context,
|
||||
Node* new_target, Node* first_arg,
|
||||
Node* arg_count) {
|
||||
|
@ -87,18 +87,6 @@ class InterpreterAssembler : public compiler::CodeStubAssembler {
|
||||
compiler::Node* first_arg, compiler::Node* arg_count,
|
||||
TailCallMode tail_call_mode);
|
||||
|
||||
// Call JSFunction or Callable |function| with |arg_count|
|
||||
// arguments (not including receiver) and the first argument
|
||||
// located at |first_arg| with feedback slot id |slot_id| and
|
||||
// type feedback vector |type_feedback_vector|.
|
||||
compiler::Node* CallJSWithFeedback(compiler::Node* function,
|
||||
compiler::Node* context,
|
||||
compiler::Node* first_arg,
|
||||
compiler::Node* arg_count,
|
||||
compiler::Node* slot_id,
|
||||
compiler::Node* type_feedback_vector,
|
||||
TailCallMode tail_call_mode);
|
||||
|
||||
// Call constructor |constructor| with |arg_count| arguments (not
|
||||
// including receiver) and the first argument located at
|
||||
// |first_arg|. The |new_target| is the same as the
|
||||
|
@ -934,58 +934,6 @@ void Interpreter::DoDeletePropertySloppy(InterpreterAssembler* assembler) {
|
||||
DoDelete(Runtime::kDeleteProperty_Sloppy, assembler);
|
||||
}
|
||||
|
||||
void Interpreter::DoJSCallWithFeedback(InterpreterAssembler* assembler,
|
||||
TailCallMode tail_call_mode) {
|
||||
Node* function_reg = __ BytecodeOperandReg(0);
|
||||
Node* function = __ LoadRegister(function_reg);
|
||||
Node* receiver_reg = __ BytecodeOperandReg(1);
|
||||
Node* receiver_arg = __ RegisterLocation(receiver_reg);
|
||||
Node* receiver_args_count = __ BytecodeOperandCount(2);
|
||||
Node* receiver_count = __ Int32Constant(1);
|
||||
Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
|
||||
Node* slot_id_raw = __ BytecodeOperandIdx(3);
|
||||
Node* slot_id = __ SmiTag(slot_id_raw);
|
||||
Node* type_feedback_vector = __ LoadTypeFeedbackVector();
|
||||
Node* context = __ GetContext();
|
||||
Node* result =
|
||||
__ CallJSWithFeedback(function, context, receiver_arg, args_count,
|
||||
slot_id, type_feedback_vector, tail_call_mode);
|
||||
__ SetAccumulator(result);
|
||||
__ Dispatch();
|
||||
}
|
||||
|
||||
// Call <callable> <receiver> <arg_count>
|
||||
//
|
||||
// Call a JSfunction or Callable in |callable| with the |receiver| and
|
||||
// |arg_count| arguments in subsequent registers.
|
||||
void Interpreter::DoCallIC(InterpreterAssembler* assembler) {
|
||||
DoJSCallWithFeedback(assembler, TailCallMode::kDisallow);
|
||||
}
|
||||
|
||||
// CallWide <callable> <receiver> <arg_count>
|
||||
//
|
||||
// Call a JSfunction or Callable in |callable| with the |receiver| and
|
||||
// |arg_count| arguments in subsequent registers.
|
||||
void Interpreter::DoCallICWide(InterpreterAssembler* assembler) {
|
||||
DoJSCallWithFeedback(assembler, TailCallMode::kDisallow);
|
||||
}
|
||||
|
||||
// Call <callable> <receiver> <arg_count>
|
||||
//
|
||||
// Call a JSfunction or Callable in |callable| with the |receiver| and
|
||||
// |arg_count| arguments in subsequent registers.
|
||||
void Interpreter::DoTailCallIC(InterpreterAssembler* assembler) {
|
||||
DoJSCallWithFeedback(assembler, TailCallMode::kAllow);
|
||||
}
|
||||
|
||||
// CallWide <callable> <receiver> <arg_count>
|
||||
//
|
||||
// Call a JSfunction or Callable in |callable| with the |receiver| and
|
||||
// |arg_count| arguments in subsequent registers.
|
||||
void Interpreter::DoTailCallICWide(InterpreterAssembler* assembler) {
|
||||
DoJSCallWithFeedback(assembler, TailCallMode::kAllow);
|
||||
}
|
||||
|
||||
void Interpreter::DoJSCall(InterpreterAssembler* assembler,
|
||||
TailCallMode tail_call_mode) {
|
||||
Node* function_reg = __ BytecodeOperandReg(0);
|
||||
@ -996,6 +944,7 @@ void Interpreter::DoJSCall(InterpreterAssembler* assembler,
|
||||
Node* receiver_count = __ Int32Constant(1);
|
||||
Node* args_count = __ Int32Sub(receiver_args_count, receiver_count);
|
||||
Node* context = __ GetContext();
|
||||
// TODO(rmcilroy): Use the call type feedback slot to call via CallStub.
|
||||
Node* result =
|
||||
__ CallJS(function, context, receiver_arg, args_count, tail_call_mode);
|
||||
__ SetAccumulator(result);
|
||||
|
@ -94,10 +94,6 @@ class Interpreter {
|
||||
// Generates code to perform a JS call.
|
||||
void DoJSCall(InterpreterAssembler* assembler, TailCallMode tail_call_mode);
|
||||
|
||||
// Generates code to perform a JS call with feedback.
|
||||
void DoJSCallWithFeedback(InterpreterAssembler* assembler,
|
||||
TailCallMode tail_call_mode);
|
||||
|
||||
// Generates code to perform a runtime call.
|
||||
void DoCallRuntimeCommon(InterpreterAssembler* assembler);
|
||||
|
||||
|
@ -961,58 +961,6 @@ void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
||||
__ Jump(ra);
|
||||
}
|
||||
|
||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
||||
Register limit, Register scratch) {
|
||||
Label loop_header, loop_check;
|
||||
__ Branch(&loop_check);
|
||||
__ bind(&loop_header);
|
||||
__ lw(scratch, MemOperand(index));
|
||||
__ Addu(index, index, Operand(-kPointerSize));
|
||||
__ push(scratch);
|
||||
__ bind(&loop_check);
|
||||
__ Branch(&loop_header, gt, index, Operand(limit));
|
||||
}
|
||||
|
||||
static void Generate_InterpreterComputeLastArgumentAddress(
|
||||
MacroAssembler* masm, Register num_args, Register start_address,
|
||||
Register output_reg) {
|
||||
__ Addu(output_reg, num_args, Operand(1)); // Add one for receiver.
|
||||
__ sll(output_reg, output_reg, kPointerSizeLog2);
|
||||
__ Subu(output_reg, start_address, output_reg);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : the number of arguments (not including the receiver)
|
||||
// -- t0 : the address of the first argument to be pushed. Subsequent
|
||||
// arguments should be consecutive above this, in the same order as
|
||||
// they are to be pushed onto the stack.
|
||||
// -- a1 : the target to call (can be any Object).
|
||||
// -- a3 : feedback vector slot id
|
||||
// -- a2 : type feedback vector
|
||||
// -----------------------------------
|
||||
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Computes the address of last argument in t1.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, a0, t0, t1);
|
||||
|
||||
// Push the arguments.
|
||||
Generate_InterpreterPushArgs(masm, t0, t1, at);
|
||||
|
||||
// Call via the CallIC stub.
|
||||
CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode,
|
||||
true);
|
||||
CallICStub stub(masm->isolate(), call_ic_state);
|
||||
// TODO(mythria): This should be replaced by a TailCallStub, when we
|
||||
// update the code to find the target IC from jump instructions.
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
@ -1025,11 +973,20 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
// -- a1 : the target to call (can be any Object).
|
||||
// -----------------------------------
|
||||
|
||||
// Computes the address of last argument in a3.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, a0, a2, a3);
|
||||
// Find the address of the last argument.
|
||||
__ Addu(a3, a0, Operand(1)); // Add one for receiver.
|
||||
__ sll(a3, a3, kPointerSizeLog2);
|
||||
__ Subu(a3, a2, Operand(a3));
|
||||
|
||||
// Push the arguments.
|
||||
Generate_InterpreterPushArgs(masm, a2, a3, at);
|
||||
Label loop_header, loop_check;
|
||||
__ Branch(&loop_check);
|
||||
__ bind(&loop_header);
|
||||
__ lw(t0, MemOperand(a2));
|
||||
__ Addu(a2, a2, Operand(-kPointerSize));
|
||||
__ push(t0);
|
||||
__ bind(&loop_check);
|
||||
__ Branch(&loop_header, gt, a2, Operand(a3));
|
||||
|
||||
// Call the target.
|
||||
__ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
|
||||
@ -1037,6 +994,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
@ -2011,17 +1969,6 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
|
||||
__ lb(scratch1, MemOperand(at));
|
||||
__ Branch(&done, ne, scratch1, Operand(zero_reg));
|
||||
|
||||
// Drop possible internal frame pushed for calling CallICStub.
|
||||
// TODO(mythria): when we tail call the CallICStub, remove this.
|
||||
{
|
||||
Label no_internal_callic_frame;
|
||||
__ lw(scratch3, MemOperand(fp, StandardFrameConstants::kMarkerOffset));
|
||||
__ Branch(&no_internal_callic_frame, ne, scratch3,
|
||||
Operand(Smi::FromInt(StackFrame::INTERNAL)));
|
||||
__ lw(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&no_internal_callic_frame);
|
||||
}
|
||||
|
||||
// Drop possible interpreter handler/stub frame.
|
||||
{
|
||||
Label no_interpreter_frame;
|
||||
|
@ -2181,7 +2181,6 @@ void CallConstructStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
// a0 - number of arguments - if argc_in_register() is true.
|
||||
// a1 - function
|
||||
// a3 - slot id
|
||||
// a2 - vector
|
||||
@ -2189,6 +2188,8 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
__ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, at);
|
||||
__ Branch(miss, ne, a1, Operand(at));
|
||||
|
||||
__ li(a0, Operand(arg_count()));
|
||||
|
||||
// Increment the call count for monomorphic function calls.
|
||||
__ Lsa(at, a2, a3, kPointerSizeLog2 - kSmiTagSize);
|
||||
__ lw(a3, FieldMemOperand(at, FixedArray::kHeaderSize + kPointerSize));
|
||||
@ -2197,32 +2198,20 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
|
||||
__ mov(a2, t0);
|
||||
__ mov(a3, a1);
|
||||
if (argc_in_register()) {
|
||||
// Pass a default ArgumentCountKey::Any since the argc is only available
|
||||
// in a0. We do not have the actual count here.
|
||||
ArrayConstructorStub stub(masm->isolate());
|
||||
__ TailCallStub(&stub);
|
||||
} else {
|
||||
// arg_count() is expected in a0 if the arg_count() >= 2
|
||||
// (ArgumentCountKey::MORE_THAN_ONE).
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
|
||||
|
||||
void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// a0 - number of arguments - if argc_in_register() is true.
|
||||
// a1 - function
|
||||
// a3 - slot id (Smi)
|
||||
// a2 - vector
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
if (!argc_in_register()) {
|
||||
int argc = arg_count();
|
||||
__ li(a0, argc);
|
||||
}
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
|
||||
// The checks. First, does a1 match the recorded monomorphic target?
|
||||
// The checks. First, does r1 match the recorded monomorphic target?
|
||||
__ Lsa(t0, a2, a3, kPointerSizeLog2 - kSmiTagSize);
|
||||
__ lw(t0, FieldMemOperand(t0, FixedArray::kHeaderSize));
|
||||
|
||||
@ -2256,7 +2245,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ bind(&call_function);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
|
||||
tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg));
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
|
||||
USE_DELAY_SLOT);
|
||||
__ li(a0, Operand(argc)); // In delay slot.
|
||||
|
||||
__ bind(&extra_checks_or_miss);
|
||||
Label uninitialized, miss, not_allocation_site;
|
||||
@ -2293,7 +2284,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
__ bind(&call);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg));
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
|
||||
USE_DELAY_SLOT);
|
||||
__ li(a0, Operand(argc)); // In delay slot.
|
||||
|
||||
__ bind(&uninitialized);
|
||||
|
||||
@ -2327,11 +2320,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
CreateWeakCellStub create_stub(masm->isolate());
|
||||
__ SmiTag(a0);
|
||||
__ Push(a0, a1);
|
||||
__ Push(a1);
|
||||
__ CallStub(&create_stub);
|
||||
__ Pop(a0, a1);
|
||||
__ SmiUntag(a0);
|
||||
__ Pop(a1);
|
||||
}
|
||||
|
||||
__ Branch(&call_function);
|
||||
@ -2348,19 +2339,14 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
__ SmiTag(a0);
|
||||
// Push number of arguments, receiver, function and feedback info.
|
||||
__ Push(a0, a1, a2, a3);
|
||||
// Push the receiver and the function and feedback info.
|
||||
__ Push(a1, a2, a3);
|
||||
|
||||
// Call the entry.
|
||||
__ CallRuntime(Runtime::kCallIC_Miss);
|
||||
|
||||
// Move result to a1 and exit the internal frame.
|
||||
__ mov(a1, v0);
|
||||
|
||||
// Restore a0.
|
||||
__ Pop(a0);
|
||||
__ SmiUntag(a0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -428,18 +428,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallICDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
a0, // argument count (not including receiver)
|
||||
t0, // address of first argument
|
||||
a1, // the target callable to be call
|
||||
a3, // feedback vector slot id
|
||||
a2 // type feedback vector
|
||||
};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -1077,58 +1077,6 @@ void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
|
||||
__ Jump(ra);
|
||||
}
|
||||
|
||||
static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
|
||||
Register limit, Register scratch) {
|
||||
Label loop_header, loop_check;
|
||||
__ Branch(&loop_check);
|
||||
__ bind(&loop_header);
|
||||
__ ld(scratch, MemOperand(index));
|
||||
__ Daddu(index, index, Operand(-kPointerSize));
|
||||
__ push(scratch);
|
||||
__ bind(&loop_check);
|
||||
__ Branch(&loop_header, gt, index, Operand(limit));
|
||||
}
|
||||
|
||||
static void Generate_InterpreterComputeLastArgumentAddress(
|
||||
MacroAssembler* masm, Register num_args, Register start_address,
|
||||
Register output_reg) {
|
||||
__ Daddu(output_reg, num_args, Operand(1)); // Add one for receiver.
|
||||
__ dsll(output_reg, output_reg, kPointerSizeLog2);
|
||||
__ Dsubu(output_reg, start_address, output_reg);
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode) {
|
||||
// ----------- S t a t e -------------
|
||||
// -- a0 : the number of arguments (not including the receiver)
|
||||
// -- a4 : the address of the first argument to be pushed. Subsequent
|
||||
// arguments should be consecutive above this, in the same order as
|
||||
// they are to be pushed onto the stack.
|
||||
// -- a1 : the target to call (can be any Object).
|
||||
// -- a3 : feedback vector slot id
|
||||
// -- a2 : type feedback vector
|
||||
// -----------------------------------
|
||||
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Computes the address of last argument in a5.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, a0, a4, a5);
|
||||
|
||||
// Push the arguments.
|
||||
Generate_InterpreterPushArgs(masm, a4, a5, at);
|
||||
|
||||
// Call via the CallIC stub.
|
||||
CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode,
|
||||
true);
|
||||
CallICStub stub(masm->isolate(), call_ic_state);
|
||||
// TODO(mythria): This should be replaced by a TailCallStub, when we
|
||||
// update the code to find the target IC from jump instructions.
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
@ -1141,11 +1089,20 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
// -- a1 : the target to call (can be any Object).
|
||||
// -----------------------------------
|
||||
|
||||
// Computes the address of last argument in a3.
|
||||
Generate_InterpreterComputeLastArgumentAddress(masm, a0, a2, a3);
|
||||
// Find the address of the last argument.
|
||||
__ Daddu(a3, a0, Operand(1)); // Add one for receiver.
|
||||
__ dsll(a3, a3, kPointerSizeLog2);
|
||||
__ Dsubu(a3, a2, Operand(a3));
|
||||
|
||||
// Push the arguments.
|
||||
Generate_InterpreterPushArgs(masm, a2, a3, at);
|
||||
Label loop_header, loop_check;
|
||||
__ Branch(&loop_check);
|
||||
__ bind(&loop_header);
|
||||
__ ld(t0, MemOperand(a2));
|
||||
__ Daddu(a2, a2, Operand(-kPointerSize));
|
||||
__ push(t0);
|
||||
__ bind(&loop_check);
|
||||
__ Branch(&loop_header, gt, a2, Operand(a3));
|
||||
|
||||
// Call the target.
|
||||
__ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
|
||||
@ -2131,17 +2088,6 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
|
||||
__ lb(scratch1, MemOperand(at));
|
||||
__ Branch(&done, ne, scratch1, Operand(zero_reg));
|
||||
|
||||
// Drop possible internal frame pushed for calling CallICStub.
|
||||
// TODO(mythria): when we tail call the CallICStub, remove this.
|
||||
{
|
||||
Label no_internal_callic_frame;
|
||||
__ ld(scratch3, MemOperand(fp, StandardFrameConstants::kMarkerOffset));
|
||||
__ Branch(&no_internal_callic_frame, ne, scratch3,
|
||||
Operand(Smi::FromInt(StackFrame::INTERNAL)));
|
||||
__ ld(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&no_internal_callic_frame);
|
||||
}
|
||||
|
||||
// Drop possible interpreter handler/stub frame.
|
||||
{
|
||||
Label no_interpreter_frame;
|
||||
|
@ -2224,7 +2224,6 @@ void StringCharCodeAtGenerator::GenerateFast(MacroAssembler* masm) {
|
||||
|
||||
|
||||
void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
// a0 - number of arguments - if argc_in_register() is true.
|
||||
// a1 - function
|
||||
// a3 - slot id
|
||||
// a2 - vector
|
||||
@ -2232,42 +2231,32 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
__ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, at);
|
||||
__ Branch(miss, ne, a1, Operand(at));
|
||||
|
||||
__ li(a0, Operand(arg_count()));
|
||||
|
||||
// Increment the call count for monomorphic function calls.
|
||||
__ dsrl(a5, a3, kSmiShiftSize + 1 - kPointerSizeLog2);
|
||||
__ Daddu(a3, a2, Operand(a5));
|
||||
__ ld(a5, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
|
||||
__ Daddu(a5, a5, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
|
||||
__ sd(a5, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
|
||||
__ dsrl(t0, a3, 32 - kPointerSizeLog2);
|
||||
__ Daddu(a3, a2, Operand(t0));
|
||||
__ ld(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
|
||||
__ Daddu(t0, t0, Operand(Smi::FromInt(CallICNexus::kCallCountIncrement)));
|
||||
__ sd(t0, FieldMemOperand(a3, FixedArray::kHeaderSize + kPointerSize));
|
||||
|
||||
__ mov(a2, a4);
|
||||
__ mov(a3, a1);
|
||||
if (argc_in_register()) {
|
||||
// Pass a default ArgumentCountKey::Any since the argc is only available
|
||||
// in a0. We do not have the actual count here.
|
||||
ArrayConstructorStub stub(masm->isolate());
|
||||
__ TailCallStub(&stub);
|
||||
} else {
|
||||
// arg_count() is expected in a0 if the arg_count() >= 2
|
||||
// (ArgumentCountKey::MORE_THAN_ONE).
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
|
||||
|
||||
void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// a0 - number of arguments - if argc_in_register() is true.
|
||||
// a1 - function
|
||||
// a3 - slot id (Smi)
|
||||
// a2 - vector
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
if (!argc_in_register()) {
|
||||
int argc = arg_count();
|
||||
__ li(a0, argc);
|
||||
}
|
||||
int argc = arg_count();
|
||||
ParameterCount actual(argc);
|
||||
|
||||
// The checks. First, does a1 match the recorded monomorphic target?
|
||||
__ dsrl(a4, a3, kSmiShiftSize + 1 - kPointerSizeLog2);
|
||||
// The checks. First, does r1 match the recorded monomorphic target?
|
||||
__ dsrl(a4, a3, 32 - kPointerSizeLog2);
|
||||
__ Daddu(a4, a2, Operand(a4));
|
||||
__ ld(a4, FieldMemOperand(a4, FixedArray::kHeaderSize));
|
||||
|
||||
@ -2302,7 +2291,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
__ bind(&call_function);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
|
||||
tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg));
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
|
||||
USE_DELAY_SLOT);
|
||||
__ li(a0, Operand(argc)); // In delay slot.
|
||||
|
||||
__ bind(&extra_checks_or_miss);
|
||||
Label uninitialized, miss, not_allocation_site;
|
||||
@ -2340,7 +2331,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
|
||||
__ bind(&call);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg));
|
||||
RelocInfo::CODE_TARGET, al, zero_reg, Operand(zero_reg),
|
||||
USE_DELAY_SLOT);
|
||||
__ li(a0, Operand(argc)); // In delay slot.
|
||||
|
||||
__ bind(&uninitialized);
|
||||
|
||||
@ -2375,11 +2368,9 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
CreateWeakCellStub create_stub(masm->isolate());
|
||||
__ SmiTag(a0);
|
||||
__ Push(a0, a1);
|
||||
__ Push(a1);
|
||||
__ CallStub(&create_stub);
|
||||
__ Pop(a0, a1);
|
||||
__ SmiUntag(a0);
|
||||
__ Pop(a1);
|
||||
}
|
||||
|
||||
__ Branch(&call_function);
|
||||
@ -2396,19 +2387,14 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
__ SmiTag(a0);
|
||||
// Push number of arguments, receiver, function and feedback info.
|
||||
__ Push(a0, a1, a2, a3);
|
||||
// Push the receiver and the function and feedback info.
|
||||
__ Push(a1, a2, a3);
|
||||
|
||||
// Call the entry.
|
||||
__ CallRuntime(Runtime::kCallIC_Miss);
|
||||
|
||||
// Move result to a1 and exit the internal frame.
|
||||
__ mov(a1, v0);
|
||||
|
||||
// Restore a0.
|
||||
__ Pop(a0);
|
||||
__ SmiUntag(a0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -428,18 +428,6 @@ void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallICDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
a0, // argument count (not including receiver)
|
||||
a4, // address of first argument
|
||||
a1, // the target callable to be call
|
||||
a3, // feedback vector slot id
|
||||
a2 // type feedback vector
|
||||
};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndConstructDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -639,38 +639,6 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallICImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_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
|
||||
// arguments should be consecutive above this, in the same order as
|
||||
// they are to be pushed onto the stack.
|
||||
// -- rdi : the target to call (can be any Object).
|
||||
// -- rdx : Feedback vector slot-id.
|
||||
// -- r9 : type feedback vector. // TODO(mythria): move to rbx to match
|
||||
// CallICStub expectation.
|
||||
// -----------------------------------
|
||||
|
||||
{
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
Generate_InterpreterPushArgs(masm, true);
|
||||
|
||||
__ Move(rbx, r9);
|
||||
|
||||
// Call via the CallIC stub.
|
||||
CallICState call_ic_state(0, ConvertReceiverMode::kAny, tail_call_mode,
|
||||
true);
|
||||
CallICStub stub(masm->isolate(), call_ic_state);
|
||||
// TODO(mythria): This should be replaced by a TailCallStub, when we
|
||||
// update the code to find the target IC from jump instructions.
|
||||
__ CallStub(&stub);
|
||||
}
|
||||
__ Ret();
|
||||
}
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
MacroAssembler* masm, TailCallMode tail_call_mode) {
|
||||
@ -694,6 +662,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
|
||||
RelocInfo::CODE_TARGET);
|
||||
}
|
||||
|
||||
|
||||
// static
|
||||
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
|
||||
// ----------- S t a t e -------------
|
||||
@ -2104,17 +2073,6 @@ void PrepareForTailCall(MacroAssembler* masm, Register args_reg,
|
||||
__ cmpb(Operand(kScratchRegister, 0), Immediate(0));
|
||||
__ j(not_equal, &done);
|
||||
|
||||
// Drop possible internal frame pushed for calling CallICStub.
|
||||
// TODO(mythria): when we tail call the CallICStub, remove this.
|
||||
{
|
||||
Label no_internal_callic_frame;
|
||||
__ Cmp(Operand(rbp, StandardFrameConstants::kMarkerOffset),
|
||||
Smi::FromInt(StackFrame::INTERNAL));
|
||||
__ j(not_equal, &no_internal_callic_frame, Label::kNear);
|
||||
__ movp(rbp, Operand(rbp, StandardFrameConstants::kCallerFPOffset));
|
||||
__ bind(&no_internal_callic_frame);
|
||||
}
|
||||
|
||||
// Drop possible interpreter handler/stub frame.
|
||||
{
|
||||
Label no_interpreter_frame;
|
||||
|
@ -1500,12 +1500,13 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
// rdi - function
|
||||
// rdx - slot id
|
||||
// rbx - vector
|
||||
// rax - number of arguments if argc_in_register() is true.
|
||||
// rcx - allocation site (loaded from vector[slot]).
|
||||
__ LoadNativeContextSlot(Context::ARRAY_FUNCTION_INDEX, r8);
|
||||
__ cmpp(rdi, r8);
|
||||
__ j(not_equal, miss);
|
||||
|
||||
__ movp(rax, Immediate(arg_count()));
|
||||
|
||||
// Increment the call count for monomorphic function calls.
|
||||
__ SmiAddConstant(FieldOperand(rbx, rdx, times_pointer_size,
|
||||
FixedArray::kHeaderSize + kPointerSize),
|
||||
@ -1513,17 +1514,8 @@ void CallICStub::HandleArrayCase(MacroAssembler* masm, Label* miss) {
|
||||
|
||||
__ movp(rbx, rcx);
|
||||
__ movp(rdx, rdi);
|
||||
if (argc_in_register()) {
|
||||
// Pass a default ArgumentCountKey::Any since the argc is only available
|
||||
// in rax. We do not have the actual count here.
|
||||
ArrayConstructorStub stub(masm->isolate());
|
||||
__ TailCallStub(&stub);
|
||||
} else {
|
||||
// arg_count() is expected in rax if the arg_count() >= 2
|
||||
// (ArgumentCountKey::MORE_THAN_ONE).
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
ArrayConstructorStub stub(masm->isolate(), arg_count());
|
||||
__ TailCallStub(&stub);
|
||||
}
|
||||
|
||||
|
||||
@ -1532,14 +1524,12 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
// -- rdi - function
|
||||
// -- rdx - slot id
|
||||
// -- rbx - vector
|
||||
// -- rax - number of arguments if argc_in_register() is true.
|
||||
// -----------------------------------
|
||||
Isolate* isolate = masm->isolate();
|
||||
Label extra_checks_or_miss, call, call_function;
|
||||
if (!argc_in_register()) {
|
||||
int argc = arg_count();
|
||||
__ Set(rax, argc);
|
||||
}
|
||||
int argc = arg_count();
|
||||
StackArgumentsAccessor args(rsp, argc);
|
||||
ParameterCount actual(argc);
|
||||
|
||||
// The checks. First, does rdi match the recorded monomorphic target?
|
||||
__ SmiToInteger32(rdx, rdx);
|
||||
@ -1573,6 +1563,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
Smi::FromInt(CallICNexus::kCallCountIncrement));
|
||||
|
||||
__ bind(&call_function);
|
||||
__ Set(rax, argc);
|
||||
__ Jump(masm->isolate()->builtins()->CallFunction(convert_mode(),
|
||||
tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
@ -1611,6 +1602,7 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
TypeFeedbackVector::MegamorphicSentinel(isolate));
|
||||
|
||||
__ bind(&call);
|
||||
__ Set(rax, argc);
|
||||
__ Jump(masm->isolate()->builtins()->Call(convert_mode(), tail_call_mode()),
|
||||
RelocInfo::CODE_TARGET);
|
||||
|
||||
@ -1648,16 +1640,10 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
CreateWeakCellStub create_stub(isolate);
|
||||
|
||||
__ Integer32ToSmi(rax, rax);
|
||||
__ Push(rax);
|
||||
__ Integer32ToSmi(rdx, rdx);
|
||||
__ Push(rdi);
|
||||
|
||||
__ CallStub(&create_stub);
|
||||
|
||||
__ Pop(rdi);
|
||||
__ Pop(rax);
|
||||
__ SmiToInteger32(rax, rax);
|
||||
}
|
||||
|
||||
__ jmp(&call_function);
|
||||
@ -1677,10 +1663,6 @@ void CallICStub::Generate(MacroAssembler* masm) {
|
||||
void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
FrameScope scope(masm, StackFrame::INTERNAL);
|
||||
|
||||
// Store the number of arguments to be used later.
|
||||
__ Integer32ToSmi(rax, rax);
|
||||
__ Push(rax);
|
||||
|
||||
// Push the receiver and the function and feedback info.
|
||||
__ Push(rdi);
|
||||
__ Push(rbx);
|
||||
@ -1692,10 +1674,6 @@ void CallICStub::GenerateMiss(MacroAssembler* masm) {
|
||||
|
||||
// Move result to edi and exit the internal frame.
|
||||
__ movp(rdi, rax);
|
||||
// rdi, rbx, rdx are arguments to CallIC_Miss. They will be popped by
|
||||
// Runtime_CallIC_Miss.
|
||||
__ Pop(rax);
|
||||
__ SmiToInteger32(rax, rax);
|
||||
}
|
||||
|
||||
|
||||
|
@ -415,19 +415,6 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallICDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
rax, // argument count (not including receiver)
|
||||
rbx, // address of first argument
|
||||
rdi, // the target callable to be call
|
||||
rdx, // slot id
|
||||
r9, // type feedback vector // TODO(mythria): move to rbx to match
|
||||
// CallICStub.
|
||||
};
|
||||
data->InitializePlatformSpecific(arraysize(registers), registers);
|
||||
}
|
||||
|
||||
void InterpreterPushArgsAndCallDescriptor::InitializePlatformSpecific(
|
||||
CallInterfaceDescriptorData* data) {
|
||||
Register registers[] = {
|
||||
|
@ -563,18 +563,6 @@
|
||||
'test-run-jsexceptions/ThrowMessagePosition': [FAIL],
|
||||
'test-api/TryCatchMixedNesting': [FAIL],
|
||||
|
||||
# TODO(4680): Related to lack of code-ageing in interpreter.
|
||||
'test-heap/Regress169209': [FAIL],
|
||||
|
||||
# TODO(4680): Related to lack of code-ageing and/or lack of compilation cache
|
||||
# in interpreter.
|
||||
'test-heap/CompilationCacheCachingBehavior': [FAIL],
|
||||
|
||||
# TODO(4680): Use CallConstructStub for new operator.
|
||||
'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [FAIL],
|
||||
'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [FAIL],
|
||||
'test-heap/WeakFunctionInConstructor': [FAIL],
|
||||
|
||||
# TODO(rmcilroy,4680): Test assert errors.
|
||||
'test-cpu-profiler/CodeEvents': [FAIL],
|
||||
'test-cpu-profiler/TickEvents': [FAIL],
|
||||
@ -599,8 +587,17 @@
|
||||
'test-profile-generator/LineNumber': [FAIL],
|
||||
'test-profile-generator/ProfileNodeScriptId': [FAIL],
|
||||
'test-profile-generator/RecordStackTraceAtStartProfiling': [FAIL],
|
||||
'test-feedback-vector/VectorCallICStates': [FAIL],
|
||||
'test-compiler/FeedbackVectorPreservedAcrossRecompiles': [FAIL],
|
||||
'test-api/PromiseRejectCallback': [FAIL],
|
||||
'test-api/SetJitCodeEventHandler': [FAIL],
|
||||
'test-heap/WeakFunctionInConstructor': [FAIL],
|
||||
'test-heap/Regress169209': [FAIL],
|
||||
'test-heap/IncrementalMarkingClearsMonomorphicConstructor': [FAIL],
|
||||
'test-heap/IncrementalMarkingPreservesMonomorphicConstructor': [FAIL],
|
||||
'test-heap/IncrementalMarkingPreservesMonomorphicCallIC': [FAIL],
|
||||
'test-heap/CompilationCacheCachingBehavior': [FAIL],
|
||||
'test-heap/CellsInOptimizedCodeAreWeak': [FAIL],
|
||||
'test-run-inlining/InlineTwice': [FAIL],
|
||||
'test-serialize/SerializeInternalReference': [FAIL, ['arch == arm or arch == arm64', PASS]],
|
||||
}], # ignition == True
|
||||
|
@ -136,9 +136,6 @@ class BytecodeGraphTester {
|
||||
compilation_info.MarkAsDeoptimizationEnabled();
|
||||
compiler::Pipeline pipeline(&compilation_info);
|
||||
Handle<Code> code = pipeline.GenerateCode();
|
||||
// We do not actually record weak dependencies between objects and
|
||||
// code objects. We just clear the dependencies for now.
|
||||
compilation_info.dependencies()->Commit(compilation_info.code());
|
||||
function->ReplaceCode(*code);
|
||||
|
||||
return function;
|
||||
|
@ -1512,7 +1512,7 @@ TEST(PropertyCall) {
|
||||
B(Star), R(1), //
|
||||
B(LoadIC), R(1), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(0), //
|
||||
B(CallIC), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
@ -1531,7 +1531,7 @@ TEST(PropertyCall) {
|
||||
B(Star), R(2), //
|
||||
B(Ldar), A(3, 4), //
|
||||
B(Star), R(3), //
|
||||
B(CallIC), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
|
||||
B(Return) //
|
||||
},
|
||||
1,
|
||||
@ -1553,7 +1553,7 @@ TEST(PropertyCall) {
|
||||
B(Star), R(2), //
|
||||
B(Ldar), A(2, 3), //
|
||||
B(Star), R(3), //
|
||||
B(CallIC), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(0), R(1), U8(3), U8(vector->GetIndex(slot1)), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
@ -1577,7 +1577,7 @@ TEST(PropertyCall) {
|
||||
B(Star), R(1), //
|
||||
B(LoadICWide), R(1), U16(0), U16(wide_idx + 4), //
|
||||
B(Star), R(0), //
|
||||
B(CallICWide), R16(0), R16(1), U16(1), U16(wide_idx + 2), //
|
||||
B(CallWide), R16(0), R16(1), U16(1), U16(wide_idx + 2), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
@ -1826,13 +1826,13 @@ TEST(CallGlobal) {
|
||||
1,
|
||||
15,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(0), //
|
||||
B(CallIC), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Return) //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(0), //
|
||||
B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Return) //
|
||||
},
|
||||
1,
|
||||
{"t"}},
|
||||
@ -1841,19 +1841,19 @@ TEST(CallGlobal) {
|
||||
1,
|
||||
27,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(0), //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(Star), R(2), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(Star), R(3), //
|
||||
B(LdaSmi8), U8(3), //
|
||||
B(Star), R(4), //
|
||||
B(CallIC), R(0), R(1), U8(4), U8(vector->GetIndex(slot1)), //
|
||||
B(Return) //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(LdaGlobal), U8(0), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(0), //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(Star), R(2), //
|
||||
B(LdaSmi8), U8(2), //
|
||||
B(Star), R(3), //
|
||||
B(LdaSmi8), U8(3), //
|
||||
B(Star), R(4), //
|
||||
B(Call), R(0), R(1), U8(4), U8(vector->GetIndex(slot1)), //
|
||||
B(Return) //
|
||||
},
|
||||
1,
|
||||
{"t"}},
|
||||
@ -2300,7 +2300,7 @@ TEST(DeclareGlobals) {
|
||||
B(Star), R(2), //
|
||||
B(LdaGlobal), U8(1), U8(load_vector->GetIndex(load_slot_1)), //
|
||||
B(Star), R(1), //
|
||||
B(CallIC), R(1), R(2), U8(1), //
|
||||
B(Call), R(1), R(2), U8(1), //
|
||||
/* */ U8(load_vector->GetIndex(call_slot_1)), //
|
||||
B(Star), R(0), //
|
||||
B(Return) //
|
||||
@ -3774,13 +3774,13 @@ TEST(FunctionLiterals) {
|
||||
1,
|
||||
15,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(CreateClosure), U8(0), U8(0), //
|
||||
B(Star), R(0), //
|
||||
B(CallIC), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
|
||||
B(Return) //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(CreateClosure), U8(0), U8(0), //
|
||||
B(Star), R(0), //
|
||||
B(Call), R(0), R(1), U8(1), U8(vector->GetIndex(slot)), //
|
||||
B(Return) //
|
||||
},
|
||||
1,
|
||||
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
|
||||
@ -3789,15 +3789,15 @@ TEST(FunctionLiterals) {
|
||||
1,
|
||||
19,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(CreateClosure), U8(0), U8(0), //
|
||||
B(Star), R(0), //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(Star), R(2), //
|
||||
B(CallIC), R(0), R(1), U8(2), U8(vector->GetIndex(slot)), //
|
||||
B(Return) //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(CreateClosure), U8(0), U8(0), //
|
||||
B(Star), R(0), //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(Star), R(2), //
|
||||
B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot)), //
|
||||
B(Return) //
|
||||
},
|
||||
1,
|
||||
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
|
||||
@ -3861,7 +3861,7 @@ TEST(RegExpLiterals) {
|
||||
B(Star), R(0), //
|
||||
B(LdaConstant), U8(2), //
|
||||
B(Star), R(2), //
|
||||
B(CallIC), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(0), R(1), U8(2), U8(vector->GetIndex(slot1)), //
|
||||
B(Return), //
|
||||
},
|
||||
3,
|
||||
@ -5036,17 +5036,17 @@ TEST(ContextVariables) {
|
||||
1,
|
||||
25,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
|
||||
/* */ R(closure), U8(1), //
|
||||
B(PushContext), R(0), //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(2), //
|
||||
B(CreateClosure), U8(0), U8(0), //
|
||||
B(Star), R(1), //
|
||||
B(CallIC), R(1), R(2), U8(1), U8(vector->GetIndex(slot)), //
|
||||
B(LdaContextSlot), R(context), U8(first_context_slot), //
|
||||
B(Return), //
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), //
|
||||
/* */ R(closure), U8(1), //
|
||||
B(PushContext), R(0), //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(2), //
|
||||
B(CreateClosure), U8(0), U8(0), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot)), //
|
||||
B(LdaContextSlot), R(context), U8(first_context_slot), //
|
||||
B(Return), //
|
||||
},
|
||||
1,
|
||||
{InstanceType::SHARED_FUNCTION_INFO_TYPE}},
|
||||
@ -5087,7 +5087,7 @@ TEST(ContextVariables) {
|
||||
"return b",
|
||||
3 * kPointerSize,
|
||||
1,
|
||||
1041,
|
||||
1042,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
/* */ U8(1), //
|
||||
@ -5104,9 +5104,9 @@ TEST(ContextVariables) {
|
||||
B(StaContextSlot), R(context), U8(wide_slot++)), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(2), //
|
||||
B(LdaGlobal), U8(0), U8(1), //
|
||||
B(LdaGlobal), U8(0), U8(1), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(1), //
|
||||
B(Call), R(1), R(2), U8(1), U8(0), //
|
||||
B(LdaSmi8), U8(100), //
|
||||
B(StaContextSlotWide), R(context), U16(256), //
|
||||
B(LdaContextSlotWide), R(context), U16(256), //
|
||||
@ -6324,13 +6324,13 @@ DISABLED_TEST(ForOf) {
|
||||
B(LdaConstant), U8(1), //
|
||||
B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(4), //
|
||||
B(CallIC), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Star), R(1), //
|
||||
B(Ldar), R(1), //
|
||||
B(Star), R(6), //
|
||||
B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)), //
|
||||
B(Star), R(5), //
|
||||
B(CallIC), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Star), R(2), //
|
||||
B(Star), R(4), //
|
||||
B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1), //
|
||||
@ -6373,13 +6373,13 @@ DISABLED_TEST(ForOf) {
|
||||
B(LdaConstant), U8(1), //
|
||||
B(KeyedLoadIC), R(6), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(5), //
|
||||
B(CallIC), R(5), R(6), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Star), R(1), //
|
||||
B(Ldar), R(1), //
|
||||
B(Star), R(7), //
|
||||
B(LoadIC), R(7), U8(2), U8(vector->GetIndex(slot4)), //
|
||||
B(Star), R(6), //
|
||||
B(CallIC), R(6), R(7), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Call), R(6), R(7), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Star), R(2), //
|
||||
B(Star), R(5), //
|
||||
B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(5), U8(1), //
|
||||
@ -6424,13 +6424,13 @@ DISABLED_TEST(ForOf) {
|
||||
B(LdaConstant), U8(1), //
|
||||
B(KeyedLoadIC), R(5), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(4), //
|
||||
B(CallIC), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Star), R(1), //
|
||||
B(Ldar), R(1), //
|
||||
B(Star), R(6), //
|
||||
B(LoadIC), R(6), U8(2), U8(vector->GetIndex(slot4)), //
|
||||
B(Star), R(5), //
|
||||
B(CallIC), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Call), R(5), R(6), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Star), R(2), //
|
||||
B(Star), R(4), //
|
||||
B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(4), U8(1), //
|
||||
@ -6486,13 +6486,13 @@ DISABLED_TEST(ForOf) {
|
||||
B(LdaConstant), U8(2), //
|
||||
B(KeyedLoadIC), R(4), U8(vector->GetIndex(slot2)), //
|
||||
B(Star), R(3), //
|
||||
B(CallIC), R(3), R(4), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Call), R(3), R(4), U8(1), U8(vector->GetIndex(slot1)), //
|
||||
B(Star), R(0), //
|
||||
B(Ldar), R(0), //
|
||||
B(Star), R(5), //
|
||||
B(LoadIC), R(5), U8(3), U8(vector->GetIndex(slot4)), //
|
||||
B(Star), R(4), //
|
||||
B(CallIC), R(4), R(5), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Call), R(4), R(5), U8(1), U8(vector->GetIndex(slot3)), //
|
||||
B(Star), R(1), //
|
||||
B(Star), R(3), //
|
||||
B(CallRuntime), U16(Runtime::kInlineIsJSReceiver), R(3), U8(1), //
|
||||
@ -7440,7 +7440,7 @@ TEST(Eval) {
|
||||
{"return eval('1;');",
|
||||
9 * kPointerSize,
|
||||
1,
|
||||
64,
|
||||
65,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
/* */ U8(1), //
|
||||
@ -7468,7 +7468,7 @@ TEST(Eval) {
|
||||
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
|
||||
/* */ U8(5), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(2), //
|
||||
B(Call), R(1), R(2), U8(2), U8(0), //
|
||||
B(Return), //
|
||||
},
|
||||
2,
|
||||
@ -7498,7 +7498,7 @@ TEST(LookupSlot) {
|
||||
{"eval('var x = 10;'); return x;",
|
||||
9 * kPointerSize,
|
||||
1,
|
||||
66,
|
||||
67,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
/* */ U8(1), //
|
||||
@ -7526,7 +7526,7 @@ TEST(LookupSlot) {
|
||||
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
|
||||
U8(5), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(2), //
|
||||
B(Call), R(1), R(2), U8(2), U8(0), //
|
||||
B(LdaLookupSlot), U8(2), //
|
||||
B(Return), //
|
||||
},
|
||||
@ -7535,7 +7535,7 @@ TEST(LookupSlot) {
|
||||
{"eval('var x = 10;'); return typeof x;",
|
||||
9 * kPointerSize,
|
||||
1,
|
||||
67,
|
||||
68,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
/* */ U8(1), //
|
||||
@ -7563,7 +7563,7 @@ TEST(LookupSlot) {
|
||||
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
|
||||
/* */ U8(5), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(2), //
|
||||
B(Call), R(1), R(2), U8(2), U8(0), //
|
||||
B(LdaLookupSlotInsideTypeof), U8(2), //
|
||||
B(TypeOf), //
|
||||
B(Return), //
|
||||
@ -7573,7 +7573,7 @@ TEST(LookupSlot) {
|
||||
{"x = 20; return eval('');",
|
||||
9 * kPointerSize,
|
||||
1,
|
||||
68,
|
||||
69,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
U8(1), //
|
||||
@ -7603,7 +7603,7 @@ TEST(LookupSlot) {
|
||||
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
|
||||
/* */ U8(5), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(2), //
|
||||
B(Call), R(1), R(2), U8(2), U8(0), //
|
||||
B(Return), //
|
||||
},
|
||||
3,
|
||||
@ -7641,7 +7641,7 @@ TEST(CallLookupSlot) {
|
||||
{"g = function(){}; eval(''); return g();",
|
||||
9 * kPointerSize,
|
||||
1,
|
||||
84,
|
||||
85,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
/* */ U8(1), //
|
||||
@ -7671,12 +7671,12 @@ TEST(CallLookupSlot) {
|
||||
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
|
||||
U8(5), //
|
||||
B(Star), R(1), //
|
||||
B(Call), R(1), R(2), U8(2), //
|
||||
B(Call), R(1), R(2), U8(2), U8(0), //
|
||||
B(LdaConstant), U8(1), //
|
||||
B(Star), R(3), //
|
||||
B(CallRuntimeForPair), U16(Runtime::kLoadLookupSlotForCall), //
|
||||
R(3), U8(1), R(1), //
|
||||
B(CallIC), R(1), R(2), U8(1), U8(vector->GetIndex(slot2)), //
|
||||
B(Call), R(1), R(2), U8(1), U8(vector->GetIndex(slot2)), //
|
||||
B(Return), //
|
||||
},
|
||||
4,
|
||||
@ -9069,7 +9069,7 @@ TEST(ClassDeclarations) {
|
||||
B(Star), R(6), //
|
||||
B(CallRuntime), U16(Runtime::kDefineClass), R(3), U8(4), //
|
||||
B(Star), R(3), //
|
||||
B(LoadIC), R(3), U8(1), U8(1), //
|
||||
B(LoadIC), R(3), U8(1), U8(1), //
|
||||
B(Star), R(4), //
|
||||
B(CallRuntime), U16(Runtime::kFinalizeClassDefinition), R(3), U8(2), //
|
||||
B(Star), R(0), //
|
||||
@ -9096,113 +9096,6 @@ TEST(ClassDeclarations) {
|
||||
}
|
||||
}
|
||||
|
||||
TEST(TailCall) {
|
||||
bool old_tailcall_flag = FLAG_harmony_tailcalls;
|
||||
FLAG_harmony_tailcalls = true;
|
||||
|
||||
InitializedHandleScope handle_scope;
|
||||
BytecodeGeneratorHelper helper;
|
||||
|
||||
int closure = Register::function_closure().index();
|
||||
int context = Register::current_context().index();
|
||||
int new_target = Register::new_target().index();
|
||||
|
||||
// clang-format off
|
||||
ExpectedSnippet<const char*> snippets[] = {
|
||||
{"function g() { throw new Error('foo'); };"
|
||||
"var eval = g;"
|
||||
"function f() {"
|
||||
" 'use strict';"
|
||||
" return eval('g()');"
|
||||
"}",
|
||||
9 * kPointerSize,
|
||||
1,
|
||||
63,
|
||||
{
|
||||
B(CallRuntime), U16(Runtime::kNewFunctionContext), R(closure), //
|
||||
U8(1), //
|
||||
B(PushContext), R(0), //
|
||||
B(Ldar), THIS(1), //
|
||||
B(StaContextSlot), R(context), U8(4), //
|
||||
B(CreateUnmappedArguments), //
|
||||
B(StaContextSlot), R(context), U8(5), //
|
||||
B(Ldar), R(new_target), //
|
||||
B(StaContextSlot), R(context), U8(6), //
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(2), //
|
||||
B(LdaGlobal), U8(0), U8(1), //
|
||||
B(Star), R(1), //
|
||||
B(LdaConstant), U8(1), //
|
||||
B(Star), R(3), //
|
||||
B(Mov), R(1), R(4), //
|
||||
B(Mov), R(3), R(5), //
|
||||
B(Mov), R(closure), R(6), //
|
||||
B(LdaSmi8), U8(1), //
|
||||
B(Star), R(7), //
|
||||
B(LdaSmi8), U8(64), //
|
||||
B(Star), R(8), //
|
||||
B(CallRuntime), U16(Runtime::kResolvePossiblyDirectEval), R(4), //
|
||||
U8(5), //
|
||||
B(Star), R(1), //
|
||||
B(TailCall), R(1), R(2), U8(2), //
|
||||
B(Return), //
|
||||
},
|
||||
2,
|
||||
{"eval",
|
||||
"g()"}}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
||||
Handle<BytecodeArray> bytecode_array =
|
||||
helper.MakeBytecodeForFunction(snippets[i].code_snippet);
|
||||
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
|
||||
}
|
||||
|
||||
FLAG_harmony_tailcalls = old_tailcall_flag;
|
||||
}
|
||||
|
||||
TEST(TailCallIC) {
|
||||
bool old_tailcall_flag = FLAG_harmony_tailcalls;
|
||||
FLAG_harmony_tailcalls = true;
|
||||
|
||||
InitializedHandleScope handle_scope;
|
||||
BytecodeGeneratorHelper helper;
|
||||
|
||||
// clang-format off
|
||||
ExpectedSnippet<const char*> snippets[] = {
|
||||
{"function g() { return 0; };"
|
||||
"function f() {"
|
||||
" 'use strict';"
|
||||
" return g();"
|
||||
"}",
|
||||
2 * kPointerSize,
|
||||
1,
|
||||
15,
|
||||
{
|
||||
B(StackCheck), //
|
||||
B(LdaUndefined), //
|
||||
B(Star), R(1), //
|
||||
B(LdaGlobal), U8(0), U8(3), //
|
||||
B(Star), R(0), //
|
||||
B(TailCallIC), R(0), R(1), U8(1), U8(1), //
|
||||
B(Return),
|
||||
},
|
||||
1,
|
||||
{"g"}}
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
for (size_t i = 0; i < arraysize(snippets); i++) {
|
||||
Handle<BytecodeArray> bytecode_array =
|
||||
helper.MakeBytecodeForFunction(snippets[i].code_snippet);
|
||||
CheckBytecodeArrayEqual(snippets[i], bytecode_array);
|
||||
}
|
||||
|
||||
FLAG_harmony_tailcalls = old_tailcall_flag;
|
||||
}
|
||||
|
||||
// TODO(oth): Add tests for super keyword.
|
||||
|
||||
} // namespace interpreter
|
||||
|
@ -928,8 +928,7 @@ TEST(InterpreterStoreKeyedProperty) {
|
||||
CHECK_EQ(Smi::cast(*result), Smi::FromInt(999));
|
||||
}
|
||||
|
||||
static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
bool has_feedback_slot) {
|
||||
static void TestInterpreterCall(TailCallMode tail_call_mode) {
|
||||
HandleAndZoneScope handles;
|
||||
i::Isolate* isolate = handles.main_isolate();
|
||||
i::Factory* factory = isolate->factory();
|
||||
@ -937,15 +936,10 @@ static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
|
||||
i::FeedbackVectorSpec feedback_spec(&zone);
|
||||
i::FeedbackVectorSlot slot = feedback_spec.AddLoadICSlot();
|
||||
i::FeedbackVectorSlot call_slot = feedback_spec.AddCallICSlot();
|
||||
|
||||
Handle<i::TypeFeedbackVector> vector =
|
||||
i::NewTypeFeedbackVector(isolate, &feedback_spec);
|
||||
int slot_index = vector->GetIndex(slot);
|
||||
int call_slot_index = -1;
|
||||
if (has_feedback_slot) {
|
||||
call_slot_index = vector->GetIndex(call_slot);
|
||||
}
|
||||
|
||||
Handle<i::String> name = factory->NewStringFromAsciiChecked("func");
|
||||
name = factory->string_table()->LookupString(isolate, name);
|
||||
@ -955,16 +949,9 @@ static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
|
||||
0, 1);
|
||||
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
|
||||
.StoreAccumulatorInRegister(Register(0));
|
||||
|
||||
if (has_feedback_slot) {
|
||||
builder.CallIC(Register(0), builder.Parameter(0), 1, call_slot_index,
|
||||
tail_call_mode);
|
||||
} else {
|
||||
builder.Call(Register(0), builder.Parameter(0), 1, tail_call_mode);
|
||||
}
|
||||
|
||||
builder.Return();
|
||||
.StoreAccumulatorInRegister(Register(0))
|
||||
.Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
|
||||
.Return();
|
||||
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
|
||||
|
||||
InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
|
||||
@ -981,14 +968,9 @@ static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
BytecodeArrayBuilder builder(handles.main_isolate(), handles.main_zone(), 1,
|
||||
0, 1);
|
||||
builder.LoadNamedProperty(builder.Parameter(0), name, slot_index)
|
||||
.StoreAccumulatorInRegister(Register(0));
|
||||
if (has_feedback_slot) {
|
||||
builder.CallIC(Register(0), builder.Parameter(0), 1, call_slot_index,
|
||||
tail_call_mode);
|
||||
} else {
|
||||
builder.Call(Register(0), builder.Parameter(0), 1, tail_call_mode);
|
||||
}
|
||||
builder.Return();
|
||||
.StoreAccumulatorInRegister(Register(0))
|
||||
.Call(Register(0), builder.Parameter(0), 1, 0, tail_call_mode)
|
||||
.Return();
|
||||
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
|
||||
|
||||
InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
|
||||
@ -1014,17 +996,9 @@ static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
.LoadLiteral(Smi::FromInt(51))
|
||||
.StoreAccumulatorInRegister(Register(2))
|
||||
.LoadLiteral(Smi::FromInt(11))
|
||||
.StoreAccumulatorInRegister(Register(3));
|
||||
|
||||
if (has_feedback_slot) {
|
||||
builder.CallIC(Register(0), Register(1), 3, call_slot_index,
|
||||
tail_call_mode);
|
||||
} else {
|
||||
builder.Call(Register(0), Register(1), 3, tail_call_mode);
|
||||
}
|
||||
|
||||
builder.Return();
|
||||
|
||||
.StoreAccumulatorInRegister(Register(3))
|
||||
.Call(Register(0), Register(1), 3, 0, tail_call_mode)
|
||||
.Return();
|
||||
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
|
||||
|
||||
InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
|
||||
@ -1065,17 +1039,9 @@ static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
.LoadLiteral(factory->NewStringFromAsciiChecked("i"))
|
||||
.StoreAccumulatorInRegister(Register(10))
|
||||
.LoadLiteral(factory->NewStringFromAsciiChecked("j"))
|
||||
.StoreAccumulatorInRegister(Register(11));
|
||||
|
||||
if (has_feedback_slot) {
|
||||
builder.CallIC(Register(0), Register(1), 11, call_slot_index,
|
||||
tail_call_mode);
|
||||
} else {
|
||||
builder.Call(Register(0), Register(1), 11, tail_call_mode);
|
||||
}
|
||||
|
||||
builder.Return();
|
||||
|
||||
.StoreAccumulatorInRegister(Register(11))
|
||||
.Call(Register(0), Register(1), 11, 0, tail_call_mode)
|
||||
.Return();
|
||||
Handle<BytecodeArray> bytecode_array = builder.ToBytecodeArray();
|
||||
|
||||
InterpreterTester tester(handles.main_isolate(), bytecode_array, vector);
|
||||
@ -1095,13 +1061,9 @@ static void TestInterpreterCall(TailCallMode tail_call_mode,
|
||||
}
|
||||
}
|
||||
|
||||
TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow, false); }
|
||||
TEST(InterpreterCall) { TestInterpreterCall(TailCallMode::kDisallow); }
|
||||
|
||||
TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow, false); }
|
||||
|
||||
TEST(InterpreterCallIC) { TestInterpreterCall(TailCallMode::kDisallow, true); }
|
||||
|
||||
TEST(InterpreterTailCallIC) { TestInterpreterCall(TailCallMode::kAllow, true); }
|
||||
TEST(InterpreterTailCall) { TestInterpreterCall(TailCallMode::kAllow); }
|
||||
|
||||
static BytecodeArrayBuilder& SetRegister(BytecodeArrayBuilder& builder,
|
||||
Register reg, int value,
|
||||
|
@ -918,12 +918,6 @@
|
||||
'unicodelctest-no-optimization': [SKIP],
|
||||
}], # ignition == True and (arch == arm or arch == arm64)
|
||||
|
||||
['ignition == True and arch == x64', {
|
||||
# TODO(mythria,4680): Stack call size exceeds limit.
|
||||
# Try to tail call CallICStub from PushArgsAndCallIC builtin.
|
||||
'regress/regress-353551': [FAIL],
|
||||
}], # ignition == True and arch == x64
|
||||
|
||||
##############################################################################
|
||||
['gcov_coverage', {
|
||||
# Tests taking too long.
|
||||
|
@ -94,14 +94,10 @@ TEST_F(BytecodeArrayBuilderTest, AllBytecodesGenerated) {
|
||||
.CreateObjectLiteral(factory->NewFixedArray(1), 0, 0);
|
||||
|
||||
// Call operations.
|
||||
builder.Call(reg, other, 1)
|
||||
.Call(reg, wide, 1)
|
||||
.TailCall(reg, other, 1)
|
||||
.TailCall(reg, wide, 1)
|
||||
.CallIC(reg, other, 1, 0, TailCallMode::kDisallow)
|
||||
.CallIC(reg, other, 1, 0, TailCallMode::kAllow)
|
||||
.CallIC(reg, wide, 1, 0, TailCallMode::kDisallow)
|
||||
.CallIC(reg, wide, 1, 0, TailCallMode::kAllow)
|
||||
builder.Call(reg, other, 1, 0)
|
||||
.Call(reg, wide, 1, 0)
|
||||
.TailCall(reg, other, 1, 0)
|
||||
.TailCall(reg, wide, 1, 0)
|
||||
.CallRuntime(Runtime::kIsArray, reg, 1)
|
||||
.CallRuntime(Runtime::kIsArray, wide, 1)
|
||||
.CallRuntimeForPair(Runtime::kLoadLookupSlotForCall, reg, 1, other)
|
||||
|
Loading…
Reference in New Issue
Block a user