Revert of [Interpreter] Remove InterpreterExitTrampoline and replace with returning to the entry trampoline. (patchset #6 id:170001 of https://codereview.chromium.org/1969423002/ )

Reason for revert:
Breaks
https://build.chromium.org/p/client.v8.ports/builders/V8%20Linux%20-%20arm%20-%20sim/builds/619

Might only affect pure release builds?

Original issue's description:
> [Interpreter] Remove InterpreterExitTrampoline and replace with returning to the entry trampoline.
>
> In order to support compiling to baseline on return we need to be able to
> return to the actual return address. With this change this is what the
> Return bytecode now does, removing the need for the
> InterpreterExitTrampoline.
>
> This change also removes the InterpreterNotifyDeoptXXX builtins and
> unifies FCG and Igntion to both use NotifyDeoptXXX. As part of this
> change, FullCodegenerator::State is moved to Deoptimize::BailoutState.
>
> BUG=v8:4280
> LOG=N
>
> Committed: https://crrev.com/34c9626e2ee56fe805de549697ca5323aed7cb66
> Cr-Commit-Position: refs/heads/master@{#36288}

TBR=mstarzinger@chromium.org,oth@chromium.org,rmcilroy@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=v8:4280

Review-Url: https://codereview.chromium.org/1986353002
Cr-Commit-Position: refs/heads/master@{#36294}
This commit is contained in:
machenbach 2016-05-17 12:44:12 -07:00 committed by Commit bot
parent 0151651603
commit c473f2931d
27 changed files with 992 additions and 800 deletions

View File

@ -959,6 +959,7 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
Generate_JSEntryTrampolineHelper(masm, true);
}
// Generate code for entering a JS function with the interpreter.
// On entry to the function the receiver and arguments have been pushed on the
// stack left to right. The actual argument count matches the formal parameter
@ -1059,19 +1060,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ ldr(ip, MemOperand(kInterpreterDispatchTableRegister, r1, LSL,
kPointerSizeLog2));
__ Call(ip);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in r0.
// Get the arguments + reciever count.
__ ldr(r2, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
__ ldr(r2, FieldMemOperand(r2, BytecodeArray::kParameterSizeOffset));
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
__ add(sp, sp, r2, LeaveCC);
__ Jump(lr);
// Even though the first bytecode handler was called, we will never return.
__ Abort(kUnexpectedReturnFromBytecodeHandler);
// If the bytecode array is no longer present, then the underlying function
// has been switched to a different kind of code and we heal the closure by
@ -1086,6 +1077,21 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Jump(r4);
}
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
// The return value is in accumulator, which is already in r0.
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Drop receiver + arguments and return.
__ ldr(ip, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kParameterSizeOffset));
__ add(sp, sp, ip, LeaveCC);
__ Jump(lr);
}
static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
Register limit, Register scratch) {
Label loop_header, loop_check;
@ -1098,6 +1104,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm, Register index,
__ b(gt, &loop_header);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
@ -1123,6 +1130,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -1147,16 +1155,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
__ Move(r2, masm->isolate()->builtins()->InterpreterEntryTrampoline());
__ add(lr, r2, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize the dispatch table register.
__ mov(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
@ -1188,6 +1188,55 @@ void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
__ mov(pc, ip);
}
static void Generate_InterpreterNotifyDeoptimizedHelper(
MacroAssembler* masm, Deoptimizer::BailoutType type) {
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
__ mov(r1, Operand(Smi::FromInt(static_cast<int>(type))));
__ push(r1);
__ CallRuntime(Runtime::kNotifyDeoptimized);
// Tear down internal frame.
}
// Drop state (we don't use these for interpreter deopts) and and pop the
// accumulator value into the accumulator register.
__ Drop(1);
__ Pop(kInterpreterAccumulatorRegister);
// Enter the bytecode dispatch.
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
}
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
}
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the address of the interpreter entry trampoline as a return address.
// This simulates the initial call to bytecode handlers in interpreter entry
// trampoline. The return will never actually be taken, but our stack walker
// uses this address to determine whether a frame is interpreted.
__ Move(lr, masm->isolate()->builtins()->InterpreterEntryTrampoline());
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- r0 : argument count (preserved for callee)
@ -1477,17 +1526,14 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
__ SmiUntag(r6);
// Switch on the state.
Label with_tos_register, unknown_state;
__ cmp(r6,
Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
__ cmp(r6, Operand(FullCodeGenerator::NO_REGISTERS));
__ b(ne, &with_tos_register);
__ add(sp, sp, Operand(1 * kPointerSize)); // Remove state.
__ Ret();
__ bind(&with_tos_register);
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), r0.code());
__ ldr(r0, MemOperand(sp, 1 * kPointerSize));
__ cmp(r6,
Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
__ cmp(r6, Operand(FullCodeGenerator::TOS_REG));
__ b(ne, &unknown_state);
__ add(sp, sp, Operand(2 * kPointerSize)); // Remove state.
__ Ret();

View File

@ -963,6 +963,7 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
Generate_JSEntryTrampolineHelper(masm, true);
}
// Generate code for entering a JS function with the interpreter.
// On entry to the function the receiver and arguments have been pushed on the
// stack left to right. The actual argument count matches the formal parameter
@ -1061,20 +1062,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Mov(x1, Operand(x1, LSL, kPointerSizeLog2));
__ Ldr(ip0, MemOperand(kInterpreterDispatchTableRegister, x1));
__ Call(ip0);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in x0.
// Get the arguments + reciever count.
__ ldr(x1, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
__ Ldr(w1, FieldMemOperand(x1, BytecodeArray::kParameterSizeOffset));
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Drop receiver + arguments and return.
__ Drop(x1, 1);
__ Ret();
// Even though the first bytecode handler was called, we will never return.
__ Abort(kUnexpectedReturnFromBytecodeHandler);
// Load debug copy of the bytecode array.
__ Bind(&load_debug_bytecode_array);
@ -1095,87 +1085,22 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Jump(x7);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
// ----------- S t a t e -------------
// -- x0 : the number of arguments (not including the receiver)
// -- x2 : the address of the first argument to be pushed. Subsequent
// 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).
// -----------------------------------
// Find the address of the last argument.
__ add(x3, x0, Operand(1)); // Add one for receiver.
__ lsl(x3, x3, kPointerSizeLog2);
__ sub(x4, x2, x3);
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
// The return value is in accumulator, which is already in x0.
// 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);
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Call the target.
__ Jump(masm->isolate()->builtins()->Call(ConvertReceiverMode::kAny,
tail_call_mode),
RelocInfo::CODE_TARGET);
// Drop receiver + arguments and return.
__ Ldr(w1, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kParameterSizeOffset));
__ Drop(x1, 1);
__ Ret();
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argument count (not including receiver)
// -- x3 : new target
// -- x1 : constructor to call
// -- x2 : address of the first argument
// -----------------------------------
// Find the address of the last argument.
__ add(x5, x0, Operand(1)); // Add one for receiver (to be constructed).
__ lsl(x5, x5, kPointerSizeLog2);
// Set stack pointer and where to stop.
__ Mov(x6, jssp);
__ Claim(x5, 1);
__ sub(x4, x6, x5);
// Push a slot for the receiver.
__ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex));
Label loop_header, loop_check;
// Push the arguments.
__ B(&loop_check);
__ Bind(&loop_header);
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
__ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
__ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
__ Bind(&loop_check);
__ Cmp(x6, x4);
__ B(gt, &loop_header);
// Call the constructor with x0, x1, and x3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
__ LoadObject(x1, masm->isolate()->builtins()->InterpreterEntryTrampoline());
__ Add(lr, x1, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize the dispatch table register.
__ Mov(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
@ -1207,6 +1132,55 @@ void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
__ Jump(ip0);
}
static void Generate_InterpreterNotifyDeoptimizedHelper(
MacroAssembler* masm, Deoptimizer::BailoutType type) {
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
__ Mov(x1, Operand(Smi::FromInt(static_cast<int>(type))));
__ Push(x1);
__ CallRuntime(Runtime::kNotifyDeoptimized);
// Tear down internal frame.
}
// Drop state (we don't use these for interpreter deopts) and and pop the
// accumulator value into the accumulator register.
__ Drop(1);
__ Pop(kInterpreterAccumulatorRegister);
// Enter the bytecode dispatch.
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
}
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
}
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the address of the interpreter entry trampoline as a return address.
// This simulates the initial call to bytecode handlers in interpreter entry
// trampoline. The return will never actually be taken, but our stack walker
// uses this address to determine whether a frame is interpreted.
__ LoadObject(lr, masm->isolate()->builtins()->InterpreterEntryTrampoline());
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argument count (preserved for callee)
@ -1495,19 +1469,15 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
// Switch on the state.
Label with_tos_register, unknown_state;
__ CompareAndBranch(state,
static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS),
ne, &with_tos_register);
__ CompareAndBranch(
state, FullCodeGenerator::NO_REGISTERS, ne, &with_tos_register);
__ Drop(1); // Remove state.
__ Ret();
__ Bind(&with_tos_register);
// Reload TOS register.
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), x0.code());
__ Peek(x0, kPointerSize);
__ CompareAndBranch(state,
static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER),
ne, &unknown_state);
__ CompareAndBranch(state, FullCodeGenerator::TOS_REG, ne, &unknown_state);
__ Drop(2); // Remove state and TOS.
__ Ret();
@ -2684,6 +2654,79 @@ void Builtins::Generate_Construct(MacroAssembler* masm) {
RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
// ----------- S t a t e -------------
// -- x0 : the number of arguments (not including the receiver)
// -- x2 : the address of the first argument to be pushed. Subsequent
// 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).
// -----------------------------------
// 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,
tail_call_mode),
RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- x0 : argument count (not including receiver)
// -- x3 : new target
// -- x1 : constructor to call
// -- x2 : address of the first argument
// -----------------------------------
// Find the address of the last argument.
__ add(x5, x0, Operand(1)); // Add one for receiver (to be constructed).
__ lsl(x5, x5, kPointerSizeLog2);
// Set stack pointer and where to stop.
__ Mov(x6, jssp);
__ Claim(x5, 1);
__ sub(x4, x6, x5);
// Push a slot for the receiver.
__ Str(xzr, MemOperand(x6, -kPointerSize, PreIndex));
Label loop_header, loop_check;
// Push the arguments.
__ B(&loop_check);
__ Bind(&loop_header);
// TODO(rmcilroy): Push two at a time once we ensure we keep stack aligned.
__ Ldr(x5, MemOperand(x2, -kPointerSize, PostIndex));
__ Str(x5, MemOperand(x6, -kPointerSize, PreIndex));
__ Bind(&loop_check);
__ Cmp(x6, x4);
__ B(gt, &loop_header);
// Call the constructor with x0, x1, and x3 unmodified.
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_AllocateInNewSpace(MacroAssembler* masm) {
ASM_LOCATION("Builtins::Generate_AllocateInNewSpace");

View File

@ -253,6 +253,8 @@ namespace internal {
V(kUnsupportedPhiUseOfArguments, "Unsupported phi use of arguments") \
V(kUnsupportedPhiUseOfConstVariable, \
"Unsupported phi use of const or let variable") \
V(kUnexpectedReturnFromBytecodeHandler, \
"Unexpectedly returned from a bytecode handler") \
V(kUnexpectedReturnFromThrow, "Unexpectedly returned from a throw") \
V(kUnsupportedSwitchStatement, "Unsupported switch statement") \
V(kUnsupportedTaggedImmediate, "Unsupported tagged immediate") \

View File

@ -237,9 +237,13 @@ inline bool operator&(BuiltinExtraArguments lhs, BuiltinExtraArguments rhs) {
V(NotifyStubFailureSaveDoubles, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
V(InterpreterEntryTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterExitTrampoline, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterPushArgsAndCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterPushArgsAndTailCall, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterPushArgsAndConstruct, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterNotifyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterNotifySoftDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterNotifyLazyDeoptimized, BUILTIN, UNINITIALIZED, kNoExtraICState) \
V(InterpreterEnterBytecodeDispatch, BUILTIN, UNINITIALIZED, kNoExtraICState) \
\
V(LoadIC_Miss, BUILTIN, UNINITIALIZED, kNoExtraICState) \
@ -656,7 +660,7 @@ class Builtins {
static void Generate_StackCheck(MacroAssembler* masm);
static void Generate_InterpreterEntryTrampoline(MacroAssembler* masm);
static void Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm);
static void Generate_InterpreterExitTrampoline(MacroAssembler* masm);
static void Generate_InterpreterPushArgsAndCall(MacroAssembler* masm) {
return Generate_InterpreterPushArgsAndCallImpl(masm,
TailCallMode::kDisallow);
@ -667,6 +671,10 @@ class Builtins {
static void Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode);
static void Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm);
static void Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm);
static void Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm);
static void Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm);
static void Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm);
#define DECLARE_CODE_AGE_BUILTIN_GENERATOR(C) \
static void Generate_Make##C##CodeYoungAgainEvenMarking( \

View File

@ -848,8 +848,9 @@ void Deoptimizer::DoComputeOutputFrames() {
" @%d => node=%d, pc=0x%08" V8PRIxPTR ", caller sp=0x%08" V8PRIxPTR
", state=%s, took %0.3f ms]\n",
bailout_id_, node_id.ToInt(), output_[index]->GetPc(),
caller_frame_top_, BailoutStateToString(static_cast<BailoutState>(
output_[index]->GetState()->value())),
caller_frame_top_, FullCodeGenerator::State2String(
static_cast<FullCodeGenerator::State>(
output_[index]->GetState()->value())),
ms);
}
}
@ -1061,11 +1062,10 @@ void Deoptimizer::DoComputeJSFrame(TranslatedFrame* translated_frame,
// If we are going to the catch handler, then the exception lives in
// the accumulator.
BailoutState state =
goto_catch_handler
? BailoutState::TOS_REGISTER
: FullCodeGenerator::BailoutStateField::decode(pc_and_state);
output_frame->SetState(Smi::FromInt(static_cast<int>(state)));
FullCodeGenerator::State state =
goto_catch_handler ? FullCodeGenerator::TOS_REG
: FullCodeGenerator::StateField::decode(pc_and_state);
output_frame->SetState(Smi::FromInt(state));
// Set the continuation for the topmost frame.
if (is_topmost) {
@ -1281,9 +1281,7 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
Code* dispatch_builtin =
builtins->builtin(Builtins::kInterpreterEnterBytecodeDispatch);
output_frame->SetPc(reinterpret_cast<intptr_t>(dispatch_builtin->entry()));
// Restore accumulator (TOS) register.
output_frame->SetState(
Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
output_frame->SetState(0);
// Update constant pool.
if (FLAG_enable_embedded_constant_pool) {
@ -1299,11 +1297,14 @@ void Deoptimizer::DoComputeInterpretedFrame(TranslatedFrame* translated_frame,
// Set the continuation for the topmost frame.
if (is_topmost) {
Code* continuation = builtins->builtin(Builtins::kNotifyDeoptimized);
Code* continuation =
builtins->builtin(Builtins::kInterpreterNotifyDeoptimized);
if (bailout_type_ == LAZY) {
continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized);
continuation =
builtins->builtin(Builtins::kInterpreterNotifyLazyDeoptimized);
} else if (bailout_type_ == SOFT) {
continuation = builtins->builtin(Builtins::kNotifySoftDeoptimized);
continuation =
builtins->builtin(Builtins::kInterpreterNotifySoftDeoptimized);
} else {
CHECK_EQ(bailout_type_, EAGER);
}
@ -1517,7 +1518,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
// value of result register is preserved during continuation execution.
// We do this here by "pushing" the result of the constructor function to the
// top of the reconstructed stack and then using the
// BailoutState::TOS_REGISTER machinery.
// FullCodeGenerator::TOS_REG machinery.
if (is_topmost) {
height_in_bytes += kPointerSize;
}
@ -1638,8 +1639,7 @@ void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame,
DebugPrintOutputSlot(value, frame_index, output_offset,
"constructor result\n");
output_frame->SetState(
Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
}
CHECK_EQ(0u, output_offset);
@ -1693,7 +1693,7 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
// value of result register is preserved during continuation execution.
// We do this here by "pushing" the result of the accessor function to the
// top of the reconstructed stack and then using the
// BailoutState::TOS_REGISTER machinery.
// FullCodeGenerator::TOS_REG machinery.
// We don't need to restore the result in case of a setter call because we
// have to return the stored value but not the result of the setter function.
bool should_preserve_result = is_topmost && !is_setter_stub_frame;
@ -1812,11 +1812,9 @@ void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame,
DebugPrintOutputSlot(value, frame_index, output_offset,
"accessor result\n");
output_frame->SetState(
Smi::FromInt(static_cast<int>(BailoutState::TOS_REGISTER)));
output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG));
} else {
output_frame->SetState(
Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
}
CHECK_EQ(0u, output_offset);
@ -2071,8 +2069,7 @@ void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame,
output_frame->SetConstantPool(constant_pool_value);
output_frame->SetRegister(constant_pool_reg.code(), constant_pool_value);
}
output_frame->SetState(
Smi::FromInt(static_cast<int>(BailoutState::NO_REGISTERS)));
output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS));
Code* notify_failure =
isolate_->builtins()->builtin(Builtins::kNotifyStubFailureSaveDoubles);
output_frame->SetContinuation(

View File

@ -402,22 +402,6 @@ class Deoptimizer : public Malloced {
public:
enum BailoutType { EAGER, LAZY, SOFT, kLastBailoutType = SOFT };
enum class BailoutState {
NO_REGISTERS,
TOS_REGISTER,
};
static const char* BailoutStateToString(BailoutState state) {
switch (state) {
case BailoutState::NO_REGISTERS:
return "NO_REGISTERS";
case BailoutState::TOS_REGISTER:
return "TOS_REGISTER";
}
UNREACHABLE();
return nullptr;
}
#define DEOPT_MESSAGES_CONSTANTS(C, T) C,
enum DeoptReason {
DEOPT_MESSAGES_LIST(DEOPT_MESSAGES_CONSTANTS) kLastDeoptReason

View File

@ -176,8 +176,7 @@ void FullCodeGenerator::Generate() {
__ push(r1);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
// The new target value is not used, clobbering is safe.
DCHECK_NULL(info->scope()->new_target_var());
} else {
@ -233,8 +232,7 @@ void FullCodeGenerator::Generate() {
// Register holding this function and new target are both trashed in case we
// bailout here. But since that can happen only when new target is not used
// and we allocate a context, the value of |function_in_register| is correct.
PrepareForBailoutForId(BailoutId::FunctionContext(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
@ -296,8 +294,7 @@ void FullCodeGenerator::Generate() {
}
// Visit the declarations and body.
PrepareForBailoutForId(BailoutId::FunctionEntry(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{
Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(scope()->declarations());
@ -310,8 +307,7 @@ void FullCodeGenerator::Generate() {
{
Comment cmnt(masm_, "[ Stack check");
PrepareForBailoutForId(BailoutId::Declarations(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
Label ok;
__ LoadRoot(ip, Heap::kStackLimitRootIndex);
__ cmp(sp, Operand(ip));
@ -409,11 +405,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
EmitProfilingCounterReset();
__ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@ -735,7 +731,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
Label skip;
if (should_normalize) __ b(&skip);
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
if (should_normalize) {
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r0, ip);
@ -793,7 +789,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ LoadRoot(r0, Heap::kTheHoleValueRootIndex);
__ str(r0, ContextMemOperand(cp, variable->index()));
// No write barrier since the_hole_value is in old space.
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@ -814,7 +810,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ Push(r2, r0);
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
__ CallRuntime(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -860,7 +856,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
@ -872,7 +868,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VisitForStackValue(declaration->fun());
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -904,7 +900,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Keep the switch value on the stack until a case matches.
VisitForStackValue(stmt->tag());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@ -953,7 +949,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ b(&skip);
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
PrepareForBailout(clause, TOS_REG);
__ LoadRoot(ip, Heap::kTrueValueRootIndex);
__ cmp(r0, ip);
__ b(ne, &next_test);
@ -982,12 +978,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case body");
CaseClause* clause = clauses->at(i);
__ bind(clause->body_target());
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@ -1020,7 +1016,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(r0);
// Check cache validity in generated code. If we cannot guarantee cache
@ -1040,7 +1036,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&call_runtime);
__ push(r0); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kForInEnumerate);
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
// If we got a map from the runtime call, we can do a fast
// modification check. Otherwise, we got a fixed array, and we have
@ -1081,7 +1077,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Push(r1, r0); // Smi and array
__ ldr(r1, FieldMemOperand(r0, FixedArray::kLengthOffset));
__ Push(r1); // Fixed array length (as smi).
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
__ mov(r0, Operand(Smi::FromInt(0)));
__ Push(r0); // Initial index.
@ -1123,7 +1119,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(r1); // Enumerable.
__ push(r3); // Current entry.
__ CallRuntime(Runtime::kForInFilter);
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
__ mov(r3, Operand(r0));
__ LoadRoot(ip, Heap::kUndefinedValueRootIndex);
__ cmp(r0, ip);
@ -1136,11 +1132,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@ -1159,7 +1155,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
decrement_loop_depth();
}
@ -1318,7 +1314,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
// Record position before possible IC call.
SetExpressionPosition(proxy);
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
@ -1425,7 +1421,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallStub(&stub);
RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in r0.
@ -1461,7 +1457,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ ldr(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1495,7 +1491,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
break;
case ObjectLiteral::Property::GETTER:
@ -1553,7 +1549,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
} else {
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
VisitForStackValue(value);
@ -1626,7 +1622,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
bool result_saved = false; // Is the result saved to the stack?
ZoneList<Expression*>* subexprs = expr->values();
@ -1656,8 +1652,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
// In case the array literal contains spread expressions it has two parts. The
@ -1677,8 +1672,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForStackValue(subexpr);
CallRuntimeWithOperands(Runtime::kAppendElement);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
@ -1761,27 +1755,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->target(), TOS_REG);
break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
}
}
@ -1801,7 +1791,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
// Deoptimization point in case the binary operation may have side effects.
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->binary_operation(), TOS_REG);
} else {
VisitForAccumulatorValue(expr->value());
}
@ -1813,7 +1803,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
break;
case NAMED_PROPERTY:
@ -2281,7 +2271,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
}
@ -2326,7 +2316,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
}
@ -2350,7 +2340,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
@ -2363,8 +2353,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
DCHECK(!callee->AsProperty()->IsSuperAccess());
__ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
__ ldr(ip, MemOperand(sp, 0));
PushOperand(ip);
@ -2403,7 +2392,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ str(r0, MemOperand(sp, kPointerSize));
@ -2428,8 +2417,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ ldr(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
__ Move(LoadDescriptor::NameRegister(), r0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
__ ldr(ip, MemOperand(sp, 0));
@ -2465,7 +2453,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ str(r0, MemOperand(sp, kPointerSize));
@ -2485,7 +2473,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
if (FLAG_trace) {
@ -2553,7 +2541,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
__ Push(callee->name());
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
PushOperands(r0, r1); // Function, receiver.
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this
@ -2602,7 +2590,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Touch up the stack with the resolved function.
__ str(r0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr);
@ -2652,7 +2640,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate());
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
RestoreContext();
context()->Plug(r0);
}
@ -3085,7 +3073,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to r1.
int const argc = args->length() - 2;
__ ldr(r1, MemOperand(sp, (argc + 1) * kPointerSize));
@ -3289,14 +3277,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
&materialize_true);
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
__ LoadRoot(r0, Heap::kTrueValueRootIndex);
if (context()->IsStackValue()) __ push(r0);
__ jmp(&done);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
__ LoadRoot(r0, Heap::kFalseValueRootIndex);
if (context()->IsStackValue()) __ push(r0);
__ bind(&done);
@ -3398,9 +3384,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// We need a second deoptimization point after loading the value
// in case evaluating the property load my have a side effect.
if (assign_type == VARIABLE) {
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->expression(), TOS_REG);
} else {
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
}
// Inline smi case if we are in a loop.
@ -3449,7 +3435,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@ -3496,8 +3482,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(r0);
}
// For all contexts except EffectConstant We have the result on
@ -3508,8 +3493,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(r0);
}
break;
@ -3519,7 +3503,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
@ -3558,7 +3542,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();

View File

@ -179,8 +179,7 @@ void FullCodeGenerator::Generate() {
__ Mov(x10, Operand(info->scope()->GetScopeInfo(info->isolate())));
__ Push(x1, x10);
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
// The new target value is not used, clobbering is safe.
DCHECK_NULL(info->scope()->new_target_var());
} else {
@ -236,8 +235,7 @@ void FullCodeGenerator::Generate() {
// Register holding this function and new target are both trashed in case we
// bailout here. But since that can happen only when new target is not used
// and we allocate a context, the value of |function_in_register| is correct.
PrepareForBailoutForId(BailoutId::FunctionContext(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
@ -299,8 +297,7 @@ void FullCodeGenerator::Generate() {
}
// Visit the declarations and body.
PrepareForBailoutForId(BailoutId::FunctionEntry(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{
Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(scope()->declarations());
@ -313,8 +310,7 @@ void FullCodeGenerator::Generate() {
{
Comment cmnt(masm_, "[ Stack check");
PrepareForBailoutForId(BailoutId::Declarations(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
Label ok;
DCHECK(jssp.Is(__ StackPointer()));
__ CompareRoot(jssp, Heap::kStackLimitRootIndex);
@ -397,11 +393,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
EmitProfilingCounterReset();
__ Bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@ -732,7 +728,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
if (should_normalize) {
__ B(&skip);
}
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
if (should_normalize) {
__ CompareRoot(x0, Heap::kTrueValueRootIndex);
Split(eq, if_true, if_false, NULL);
@ -790,7 +786,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ LoadRoot(x10, Heap::kTheHoleValueRootIndex);
__ Str(x10, ContextMemOperand(cp, variable->index()));
// No write barrier since the_hole_value is in old space.
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@ -812,7 +808,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
__ CallRuntime(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -858,7 +854,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
@ -870,7 +866,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VisitForStackValue(declaration->fun());
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -907,7 +903,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Keep the switch value on the stack until a case matches.
VisitForStackValue(stmt->tag());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@ -954,7 +950,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ B(&skip);
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
PrepareForBailout(clause, TOS_REG);
__ JumpIfNotRoot(x0, Heap::kTrueValueRootIndex, &next_test);
__ Drop(1);
__ B(clause->body_target());
@ -980,12 +976,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case body");
CaseClause* clause = clauses->at(i);
__ Bind(clause->body_target());
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
VisitStatements(clause->statements());
}
__ Bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@ -1018,7 +1014,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ Bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ Push(x0);
// Check cache validity in generated code. If we cannot guarantee cache
@ -1038,7 +1034,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Bind(&call_runtime);
__ Push(x0); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kForInEnumerate);
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
// If we got a map from the runtime call, we can do a fast
// modification check. Otherwise, we got a fixed array, and we have
@ -1074,7 +1070,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Mov(x1, Smi::FromInt(1)); // Smi(1) indicates slow check.
__ Ldr(x2, FieldMemOperand(x0, FixedArray::kLengthOffset));
__ Push(x1, x0, x2); // Smi and array, fixed array length (as smi).
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
__ Push(xzr); // Initial index.
// Generate code for doing the condition check.
@ -1114,7 +1110,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// just skip it.
__ Push(x1, x3);
__ CallRuntime(Runtime::kForInFilter);
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
__ Mov(x3, x0);
__ JumpIfRoot(x0, Heap::kUndefinedValueRootIndex,
loop_statement.continue_label());
@ -1126,11 +1122,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@ -1150,7 +1146,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ Bind(&exit);
decrement_loop_depth();
}
@ -1303,7 +1299,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
// Record position before possible IC call.
SetExpressionPosition(proxy);
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
@ -1411,7 +1407,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallStub(&stub);
RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in x0.
@ -1447,7 +1443,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ Peek(StoreDescriptor::ReceiverRegister(), 0);
EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1480,7 +1476,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
VisitForStackValue(value);
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
@ -1537,7 +1533,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
} else {
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
VisitForStackValue(value);
@ -1608,7 +1604,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
bool result_saved = false; // Is the result saved to the stack?
ZoneList<Expression*>* subexprs = expr->values();
@ -1638,8 +1634,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
// In case the array literal contains spread expressions it has two parts. The
@ -1659,8 +1654,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForStackValue(subexpr);
CallRuntimeWithOperands(Runtime::kAppendElement);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
@ -1740,27 +1734,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->target(), TOS_REG);
break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
}
}
@ -1780,7 +1770,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
// Deoptimization point in case the binary operation may have side effects.
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->binary_operation(), TOS_REG);
} else {
VisitForAccumulatorValue(expr->value());
}
@ -1792,7 +1782,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
break;
case NAMED_PROPERTY:
@ -2172,7 +2162,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
}
@ -2220,7 +2210,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
}
@ -2244,7 +2234,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
@ -2261,8 +2251,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
DCHECK(!callee->AsProperty()->IsSuperAccess());
__ Peek(LoadDescriptor::ReceiverRegister(), 0);
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
PopOperand(x10);
PushOperands(x0, x10);
@ -2302,7 +2291,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ Poke(x0, kPointerSize);
@ -2328,8 +2317,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ Peek(LoadDescriptor::ReceiverRegister(), 0);
__ Move(LoadDescriptor::NameRegister(), x0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
PopOperand(x10);
@ -2365,7 +2353,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ Poke(x0, kPointerSize);
@ -2386,7 +2374,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
if (FLAG_trace) {
@ -2455,7 +2443,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
__ Push(callee->name());
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
PushOperands(x0, x1); // Receiver, function.
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this
@ -2504,7 +2492,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Touch up the stack with the resolved function.
__ Poke(x0, (arg_count + 1) * kPointerSize);
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr);
@ -2556,7 +2544,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate());
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
RestoreContext();
context()->Plug(x0);
}
@ -2990,7 +2978,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to x1.
int const argc = args->length() - 2;
__ Peek(x1, (argc + 1) * kXRegSize);
@ -3203,14 +3191,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
__ Bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
__ LoadRoot(result_register(), Heap::kTrueValueRootIndex);
__ B(&done);
__ Bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
__ LoadRoot(result_register(), Heap::kFalseValueRootIndex);
__ B(&done);
@ -3310,9 +3296,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// We need a second deoptimization point after loading the value
// in case evaluating the property load my have a side effect.
if (assign_type == VARIABLE) {
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->expression(), TOS_REG);
} else {
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
}
// Inline smi case if we are in a loop.
@ -3361,7 +3347,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@ -3410,8 +3396,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(x0);
}
// For all contexts except EffectConstant We have the result on
@ -3422,8 +3407,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(x0);
}
break;
@ -3433,7 +3417,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
@ -3472,7 +3456,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();

View File

@ -164,8 +164,8 @@ void FullCodeGenerator::Initialize() {
masm_->set_predictable_code_size(true);
}
void FullCodeGenerator::PrepareForBailout(Expression* node,
BailoutState state) {
void FullCodeGenerator::PrepareForBailout(Expression* node, State state) {
PrepareForBailoutForId(node->id(), state);
}
@ -188,9 +188,9 @@ void FullCodeGenerator::RecordJSReturnSite(Call* call) {
// if the function was inlined, i.e., this is the return address in the
// inlined function's frame.
//
// The bailout state is ignored. We defensively set it to TOS_REGISTER, which
// is the real state of the unoptimized code at the return site.
PrepareForBailoutForId(call->ReturnId(), BailoutState::TOS_REGISTER);
// The state is ignored. We defensively set it to TOS_REG, which is the
// real state of the unoptimized code at the return site.
PrepareForBailoutForId(call->ReturnId(), TOS_REG);
#ifdef DEBUG
// In debug builds, mark the return so we can verify that this function
// was called.
@ -199,13 +199,13 @@ void FullCodeGenerator::RecordJSReturnSite(Call* call) {
#endif
}
void FullCodeGenerator::PrepareForBailoutForId(BailoutId id,
BailoutState state) {
void FullCodeGenerator::PrepareForBailoutForId(BailoutId id, State state) {
// There's no need to prepare this code for bailouts from already optimized
// code or code that can't be optimized.
if (!info_->HasDeoptimizationSupport()) return;
unsigned pc_and_state =
BailoutStateField::encode(state) | PcField::encode(masm_->pc_offset());
StateField::encode(state) | PcField::encode(masm_->pc_offset());
DCHECK(Smi::IsValid(pc_and_state));
#ifdef DEBUG
for (int i = 0; i < bailout_entries_.length(); ++i) {
@ -752,7 +752,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
} else {
VisitForControl(left, test->true_label(), &eval_right, &eval_right);
}
PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
PrepareForBailoutForId(right_id, NO_REGISTERS);
__ bind(&eval_right);
} else if (context()->IsAccumulatorValue()) {
@ -771,7 +771,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
__ jmp(&done);
__ bind(&discard);
__ Drop(1);
PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
PrepareForBailoutForId(right_id, NO_REGISTERS);
} else if (context()->IsStackValue()) {
VisitForAccumulatorValue(left);
@ -786,7 +786,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
}
__ bind(&discard);
__ Drop(1);
PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
PrepareForBailoutForId(right_id, NO_REGISTERS);
} else {
DCHECK(context()->IsEffect());
@ -796,7 +796,7 @@ void FullCodeGenerator::VisitLogicalExpression(BinaryOperation* expr) {
} else {
VisitForControl(left, &done, &eval_right, &eval_right);
}
PrepareForBailoutForId(right_id, BailoutState::NO_REGISTERS);
PrepareForBailoutForId(right_id, NO_REGISTERS);
__ bind(&eval_right);
}
@ -854,7 +854,7 @@ void FullCodeGenerator::VisitProperty(Property* expr) {
EmitKeyedSuperPropertyLoad(expr);
}
}
PrepareForBailoutForId(expr->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->LoadId(), TOS_REG);
context()->Plug(result_register());
}
@ -866,7 +866,7 @@ void FullCodeGenerator::VisitForTypeofValue(Expression* expr) {
if (proxy != NULL && (proxy->var()->IsUnallocatedOrGlobalSlot() ||
proxy->var()->IsLookupSlot())) {
EmitVariableLoad(proxy, INSIDE_TYPEOF);
PrepareForBailout(proxy, BailoutState::TOS_REGISTER);
PrepareForBailout(proxy, TOS_REG);
} else {
// This expression cannot throw a reference error at the top level.
VisitInDuplicateContext(expr);
@ -914,24 +914,24 @@ void FullCodeGenerator::VisitIfStatement(IfStatement* stmt) {
if (stmt->HasElseStatement()) {
VisitForControl(stmt->condition(), &then_part, &else_part, &then_part);
PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
__ bind(&then_part);
Visit(stmt->then_statement());
__ jmp(&done);
PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
__ bind(&else_part);
Visit(stmt->else_statement());
} else {
VisitForControl(stmt->condition(), &then_part, &done, &then_part);
PrepareForBailoutForId(stmt->ThenId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ThenId(), NO_REGISTERS);
__ bind(&then_part);
Visit(stmt->then_statement());
PrepareForBailoutForId(stmt->ElseId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ElseId(), NO_REGISTERS);
}
__ bind(&done);
PrepareForBailoutForId(stmt->IfId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->IfId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitContinue(Statement* target) {
@ -1095,7 +1095,7 @@ void FullCodeGenerator::EmitPropertyKey(ObjectLiteralProperty* property,
BailoutId bailout_id) {
VisitForStackValue(property->key());
CallRuntimeWithOperands(Runtime::kToName);
PrepareForBailoutForId(bailout_id, BailoutState::NO_REGISTERS);
PrepareForBailoutForId(bailout_id, NO_REGISTERS);
PushOperand(result_register());
}
@ -1121,12 +1121,12 @@ void FullCodeGenerator::VisitWithStatement(WithStatement* stmt) {
Callable callable = CodeFactory::ToObject(isolate());
__ Move(callable.descriptor().GetRegisterParameter(0), result_register());
__ Call(callable.code(), RelocInfo::CODE_TARGET);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ToObjectId(), NO_REGISTERS);
PushOperand(result_register());
PushFunctionArgumentForContextAllocation();
CallRuntimeWithOperands(Runtime::kPushWithContext);
StoreToFrameField(StandardFrameConstants::kContextOffset, context_register());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
Scope* saved_scope = scope();
scope_ = stmt->scope();
@ -1158,7 +1158,7 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
// Record the position of the do while condition and make sure it is
// possible to break on the condition.
__ bind(loop_statement.continue_label());
PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
// Here is the actual 'while' keyword.
SetExpressionAsStatementPosition(stmt->cond());
@ -1168,12 +1168,12 @@ void FullCodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
&book_keeping);
// Check stack before looping.
PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
__ bind(&book_keeping);
EmitBackEdgeBookkeeping(stmt, &body);
__ jmp(&body);
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
@ -1194,7 +1194,7 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
loop_statement.break_label(),
&body);
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&body);
Visit(stmt->body());
@ -1204,7 +1204,7 @@ void FullCodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
EmitBackEdgeBookkeeping(stmt, &loop);
__ jmp(&loop);
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
@ -1227,11 +1227,11 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
// Emit the test at the bottom of the loop (even if empty).
__ jmp(&test);
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
__ bind(&body);
Visit(stmt->body());
PrepareForBailoutForId(stmt->ContinueId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ContinueId(), NO_REGISTERS);
__ bind(loop_statement.continue_label());
if (stmt->next() != NULL) {
SetStatementPosition(stmt->next());
@ -1252,7 +1252,7 @@ void FullCodeGenerator::VisitForStatement(ForStatement* stmt) {
__ jmp(&body);
}
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
@ -1288,12 +1288,12 @@ void FullCodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
Visit(stmt->body());
// Check stack before looping.
PrepareForBailoutForId(stmt->BackEdgeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BackEdgeId(), NO_REGISTERS);
EmitBackEdgeBookkeeping(stmt, loop_statement.continue_label());
__ jmp(loop_statement.continue_label());
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(loop_statement.break_label());
decrement_loop_depth();
}
@ -1437,7 +1437,7 @@ void FullCodeGenerator::VisitDebuggerStatement(DebuggerStatement* stmt) {
__ DebugBreak();
// Ignore the return value.
PrepareForBailoutForId(stmt->DebugBreakId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->DebugBreakId(), NO_REGISTERS);
}
@ -1452,7 +1452,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
VisitForControl(expr->condition(), &true_case, &false_case, &true_case);
int original_stack_depth = operand_stack_depth_;
PrepareForBailoutForId(expr->ThenId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->ThenId(), NO_REGISTERS);
__ bind(&true_case);
SetExpressionPosition(expr->then_expression());
if (context()->IsTest()) {
@ -1467,7 +1467,7 @@ void FullCodeGenerator::VisitConditional(Conditional* expr) {
}
operand_stack_depth_ = original_stack_depth;
PrepareForBailoutForId(expr->ElseId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->ElseId(), NO_REGISTERS);
__ bind(&false_case);
SetExpressionPosition(expr->else_expression());
VisitInDuplicateContext(expr->else_expression());
@ -1518,7 +1518,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
PushOperand(Smi::FromInt(lit->end_position()));
CallRuntimeWithOperands(Runtime::kDefineClass);
PrepareForBailoutForId(lit->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(lit->CreateLiteralId(), TOS_REG);
PushOperand(result_register());
// Load the "prototype" from the constructor.
@ -1527,7 +1527,7 @@ void FullCodeGenerator::VisitClassLiteral(ClassLiteral* lit) {
Heap::kprototype_stringRootIndex);
__ Move(LoadDescriptor::SlotRegister(), SmiFromSlot(lit->PrototypeSlot()));
CallLoadIC(NOT_INSIDE_TYPEOF);
PrepareForBailoutForId(lit->PrototypeId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(lit->PrototypeId(), TOS_REG);
PushOperand(result_register());
EmitClassDefineProperties(lit);
@ -1668,7 +1668,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
EmitCallJSRuntimeFunction(expr);
context()->DropAndPlug(1, result_register());
@ -1690,7 +1690,7 @@ void FullCodeGenerator::VisitCallRuntime(CallRuntime* expr) {
}
// Call the C runtime function.
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
__ CallRuntime(expr->function(), arg_count);
OperandStackDepthDecrement(arg_count);
context()->Plug(result_register());
@ -1879,7 +1879,7 @@ FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
saved_scope_ = codegen_->scope();
if (scope == NULL) {
codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
needs_block_context_ = false;
} else {
needs_block_context_ = scope->NeedsContext();
@ -1896,13 +1896,12 @@ FullCodeGenerator::EnterBlockScopeIfNeeded::EnterBlockScopeIfNeeded(
codegen_->context_register());
}
CHECK_EQ(0, scope->num_stack_slots());
codegen_->PrepareForBailoutForId(entry_id, BailoutState::NO_REGISTERS);
codegen_->PrepareForBailoutForId(entry_id, NO_REGISTERS);
}
{
Comment cmnt(masm(), "[ Declarations");
codegen_->VisitDeclarations(scope->declarations());
codegen_->PrepareForBailoutForId(declarations_id,
BailoutState::NO_REGISTERS);
codegen_->PrepareForBailoutForId(declarations_id, NO_REGISTERS);
}
}
}
@ -1916,7 +1915,7 @@ FullCodeGenerator::EnterBlockScopeIfNeeded::~EnterBlockScopeIfNeeded() {
codegen_->StoreToFrameField(StandardFrameConstants::kContextOffset,
codegen_->context_register());
}
codegen_->PrepareForBailoutForId(exit_id_, BailoutState::NO_REGISTERS);
codegen_->PrepareForBailoutForId(exit_id_, NO_REGISTERS);
codegen_->scope_ = saved_scope_;
}

View File

@ -14,7 +14,6 @@
#include "src/code-stubs.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/deoptimizer.h"
#include "src/globals.h"
#include "src/objects.h"
@ -29,6 +28,11 @@ class JumpPatchSite;
class FullCodeGenerator: public AstVisitor {
public:
enum State {
NO_REGISTERS,
TOS_REG
};
FullCodeGenerator(MacroAssembler* masm, CompilationInfo* info)
: masm_(masm),
info_(info),
@ -56,10 +60,19 @@ class FullCodeGenerator: public AstVisitor {
static bool MakeCode(CompilationInfo* info);
// Encode bailout state and pc-offset as a BitField<type, start, size>.
// Encode state and pc-offset as a BitField<type, start, size>.
// Only use 30 bits because we encode the result as a smi.
class BailoutStateField : public BitField<Deoptimizer::BailoutState, 0, 1> {};
class PcField : public BitField<unsigned, 1, 30 - 1> {};
class StateField : public BitField<State, 0, 1> { };
class PcField : public BitField<unsigned, 1, 30-1> { };
static const char* State2String(State state) {
switch (state) {
case NO_REGISTERS: return "NO_REGISTERS";
case TOS_REG: return "TOS_REG";
}
UNREACHABLE();
return NULL;
}
static const int kMaxBackEdgeWeight = 127;
@ -93,8 +106,6 @@ class FullCodeGenerator: public AstVisitor {
static Register result_register();
private:
typedef Deoptimizer::BailoutState BailoutState;
class Breakable;
class Iteration;
class TryFinally;
@ -355,21 +366,21 @@ class FullCodeGenerator: public AstVisitor {
if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
EffectContext context(this);
Visit(expr);
PrepareForBailout(expr, BailoutState::NO_REGISTERS);
PrepareForBailout(expr, NO_REGISTERS);
}
void VisitForAccumulatorValue(Expression* expr) {
if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
AccumulatorValueContext context(this);
Visit(expr);
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
}
void VisitForStackValue(Expression* expr) {
if (FLAG_verify_operand_stack_depth) EmitOperandStackDepthCheck();
StackValueContext context(this);
Visit(expr);
PrepareForBailout(expr, BailoutState::NO_REGISTERS);
PrepareForBailout(expr, NO_REGISTERS);
}
void VisitForControl(Expression* expr,
@ -441,8 +452,8 @@ class FullCodeGenerator: public AstVisitor {
NilValue nil);
// Bailout support.
void PrepareForBailout(Expression* node, Deoptimizer::BailoutState state);
void PrepareForBailoutForId(BailoutId id, Deoptimizer::BailoutState state);
void PrepareForBailout(Expression* node, State state);
void PrepareForBailoutForId(BailoutId id, State state);
// Returns a smi for the index into the FixedArray that backs the feedback
// vector

View File

@ -168,8 +168,7 @@ void FullCodeGenerator::Generate() {
__ push(edi);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
// The new target value is not used, clobbering is safe.
DCHECK_NULL(info->scope()->new_target_var());
} else {
@ -228,8 +227,7 @@ void FullCodeGenerator::Generate() {
// Register holding this function and new target are both trashed in case we
// bailout here. But since that can happen only when new target is not used
// and we allocate a context, the value of |function_in_register| is correct.
PrepareForBailoutForId(BailoutId::FunctionContext(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
@ -291,8 +289,7 @@ void FullCodeGenerator::Generate() {
}
// Visit the declarations and body.
PrepareForBailoutForId(BailoutId::FunctionEntry(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{
Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(scope()->declarations());
@ -305,8 +302,7 @@ void FullCodeGenerator::Generate() {
{
Comment cmnt(masm_, "[ Stack check");
PrepareForBailoutForId(BailoutId::Declarations(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
Label ok;
ExternalReference stack_limit =
ExternalReference::address_of_stack_limit(isolate());
@ -373,11 +369,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
EmitProfilingCounterReset();
__ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@ -684,7 +680,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
Label skip;
if (should_normalize) __ jmp(&skip, Label::kNear);
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
if (should_normalize) {
__ cmp(eax, isolate()->factory()->true_value());
Split(equal, if_true, if_false, NULL);
@ -740,7 +736,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ mov(ContextOperand(esi, variable->index()),
Immediate(isolate()->factory()->the_hole_value()));
// No write barrier since the hole value is in old space.
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@ -761,7 +757,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ push(
Immediate(Smi::FromInt(variable->DeclarationPropertyAttributes())));
__ CallRuntime(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -805,7 +801,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
@ -815,7 +811,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VisitForStackValue(declaration->fun());
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -846,7 +842,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Keep the switch value on the stack until a case matches.
VisitForStackValue(stmt->tag());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@ -895,7 +891,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ jmp(&skip, Label::kNear);
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
PrepareForBailout(clause, TOS_REG);
__ cmp(eax, isolate()->factory()->true_value());
__ j(not_equal, &next_test);
__ Drop(1);
@ -923,12 +919,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case body");
CaseClause* clause = clauses->at(i);
__ bind(clause->body_target());
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@ -961,7 +957,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(eax);
// Check cache validity in generated code. If we cannot guarantee cache
@ -978,7 +974,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&call_runtime);
__ push(eax);
__ CallRuntime(Runtime::kForInEnumerate);
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
__ cmp(FieldOperand(eax, HeapObject::kMapOffset),
isolate()->factory()->meta_map());
__ j(not_equal, &fixed_array);
@ -1014,7 +1010,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(eax); // Array
__ mov(eax, FieldOperand(eax, FixedArray::kLengthOffset));
__ push(eax); // Fixed array length (as smi).
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
__ push(Immediate(Smi::FromInt(0))); // Initial index.
// Generate code for doing the condition check.
@ -1052,7 +1048,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ push(ecx); // Enumerable.
__ push(ebx); // Current entry.
__ CallRuntime(Runtime::kForInFilter);
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
__ cmp(eax, isolate()->factory()->undefined_value());
__ j(equal, loop_statement.continue_label());
__ mov(ebx, eax);
@ -1064,11 +1060,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@ -1085,7 +1081,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
decrement_loop_depth();
}
@ -1243,7 +1239,7 @@ void FullCodeGenerator::EmitGlobalVariableLoad(VariableProxy* proxy,
void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
SetExpressionPosition(proxy);
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
@ -1355,7 +1351,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallStub(&stub);
RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in eax.
@ -1391,7 +1387,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ mov(StoreDescriptor::ReceiverRegister(), Operand(esp, 0));
EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
}
@ -1419,7 +1415,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
@ -1475,7 +1471,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
} else {
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
VisitForStackValue(value);
@ -1548,7 +1544,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
bool result_saved = false; // Is the result saved to the stack?
ZoneList<Expression*>* subexprs = expr->values();
@ -1578,8 +1574,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
Handle<Code> ic =
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
// In case the array literal contains spread expressions it has two parts. The
@ -1599,8 +1594,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForStackValue(subexpr);
CallRuntimeWithOperands(Runtime::kAppendElement);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
@ -1679,27 +1673,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->target(), TOS_REG);
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
}
}
@ -1718,7 +1708,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
// Deoptimization point in case the binary operation may have side effects.
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->binary_operation(), TOS_REG);
} else {
VisitForAccumulatorValue(expr->value());
}
@ -1730,7 +1720,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
break;
case NAMED_PROPERTY:
@ -2189,7 +2179,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
}
@ -2235,7 +2225,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
}
@ -2256,7 +2246,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
@ -2268,8 +2258,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
DCHECK(!callee->AsProperty()->IsSuperAccess());
__ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
PushOperand(Operand(esp, 0));
__ mov(Operand(esp, kPointerSize), eax);
@ -2304,7 +2293,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ mov(Operand(esp, kPointerSize), eax);
@ -2329,8 +2318,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ mov(LoadDescriptor::ReceiverRegister(), Operand(esp, 0));
__ mov(LoadDescriptor::NameRegister(), eax);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
PushOperand(Operand(esp, 0));
@ -2362,7 +2350,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ mov(Operand(esp, kPointerSize), eax);
@ -2382,7 +2370,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
if (FLAG_trace) {
@ -2450,7 +2438,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
PushOperand(eax); // Function.
PushOperand(edx); // Receiver.
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the function
// and receiver and have the slow path jump around this code.
@ -2495,7 +2483,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Touch up the stack with the resolved function.
__ mov(Operand(esp, (arg_count + 1) * kPointerSize), eax);
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr);
__ mov(edi, Operand(esp, (arg_count + 1) * kPointerSize));
@ -2544,7 +2532,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate());
__ call(stub.GetCode(), RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
RestoreContext();
context()->Plug(eax);
}
@ -2980,7 +2968,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to edi.
int const argc = args->length() - 2;
__ mov(edi, Operand(esp, (argc + 1) * kPointerSize));
@ -3187,8 +3175,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
&materialize_true);
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ mov(eax, isolate()->factory()->true_value());
} else {
@ -3196,8 +3183,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
}
__ jmp(&done, Label::kNear);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ mov(eax, isolate()->factory()->false_value());
} else {
@ -3296,9 +3282,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// We need a second deoptimization point after loading the value
// in case evaluating the property load my have a side effect.
if (assign_type == VARIABLE) {
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->expression(), TOS_REG);
} else {
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
}
// Inline smi case if we are in a loop.
@ -3353,7 +3339,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@ -3401,8 +3387,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(eax);
}
// For all contexts except EffectContext We have the result on
@ -3414,8 +3399,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Perform the assignment as if via '='.
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(eax);
}
break;
@ -3425,7 +3409,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
@ -3464,7 +3448,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
// Result is on the stack
if (!context()->IsEffect()) {

View File

@ -186,8 +186,7 @@ void FullCodeGenerator::Generate() {
__ push(a1);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
// The new target value is not used, clobbering is safe.
DCHECK_NULL(info->scope()->new_target_var());
} else {
@ -243,8 +242,7 @@ void FullCodeGenerator::Generate() {
// Register holding this function and new target are both trashed in case we
// bailout here. But since that can happen only when new target is not used
// and we allocate a context, the value of |function_in_register| is correct.
PrepareForBailoutForId(BailoutId::FunctionContext(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
@ -307,8 +305,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal
// redeclaration.
PrepareForBailoutForId(BailoutId::FunctionEntry(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{
Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(scope()->declarations());
@ -321,8 +318,7 @@ void FullCodeGenerator::Generate() {
{
Comment cmnt(masm_, "[ Stack check");
PrepareForBailoutForId(BailoutId::Declarations(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
Label ok;
__ LoadRoot(at, Heap::kStackLimitRootIndex);
__ Branch(&ok, hs, sp, Operand(at));
@ -401,11 +397,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
EmitProfilingCounterReset();
__ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@ -731,7 +727,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
Label skip;
if (should_normalize) __ Branch(&skip);
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
if (should_normalize) {
__ LoadRoot(t0, Heap::kTrueValueRootIndex);
Split(eq, a0, Operand(t0), if_true, if_false, NULL);
@ -790,7 +786,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ sw(at, ContextMemOperand(cp, variable->index()));
// No write barrier since the_hole_value is in old space.
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@ -812,7 +808,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ Push(a2, a0);
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
__ CallRuntime(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -858,7 +854,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
@ -870,7 +866,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VisitForStackValue(declaration->fun());
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -902,7 +898,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Keep the switch value on the stack until a case matches.
VisitForStackValue(stmt->tag());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@ -952,7 +948,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ Branch(&skip);
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
PrepareForBailout(clause, TOS_REG);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(&next_test, ne, v0, Operand(at));
__ Drop(1);
@ -979,12 +975,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case body");
CaseClause* clause = clauses->at(i);
__ bind(clause->body_target());
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@ -1020,7 +1016,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CallStub(&stub);
__ mov(a0, v0);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(a0);
// Check cache validity in generated code. If we cannot guarantee cache
@ -1040,7 +1036,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&call_runtime);
__ push(a0); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kForInEnumerate);
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
// If we got a map from the runtime call, we can do a fast
// modification check. Otherwise, we got a fixed array, and we have
@ -1078,7 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Push(a1, v0); // Smi and array
__ lw(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
__ Push(a1); // Fixed array length (as smi).
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
__ li(a0, Operand(Smi::FromInt(0)));
__ Push(a0); // Initial index.
@ -1119,7 +1115,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// just skip it.
__ Push(a1, a3); // Enumerable and current entry.
__ CallRuntime(Runtime::kForInFilter);
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
__ mov(a3, result_register());
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(loop_statement.continue_label(), eq, a3, Operand(at));
@ -1131,11 +1127,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@ -1154,7 +1150,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
decrement_loop_depth();
}
@ -1313,7 +1309,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
// Record position before possible IC call.
SetExpressionPosition(proxy);
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
@ -1420,7 +1416,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallStub(&stub);
RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in v0.
@ -1457,7 +1453,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ lw(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1491,7 +1487,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
@ -1548,7 +1544,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
} else {
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
VisitForStackValue(value);
@ -1620,7 +1616,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
bool result_saved = false; // Is the result saved to the stack?
ZoneList<Expression*>* subexprs = expr->values();
@ -1652,8 +1648,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
// In case the array literal contains spread expressions it has two parts. The
@ -1673,8 +1668,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForStackValue(subexpr);
CallRuntimeWithOperands(Runtime::kAppendElement);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
@ -1757,27 +1751,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->target(), TOS_REG);
break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
}
}
@ -1797,7 +1787,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
// Deoptimization point in case the binary operation may have side effects.
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->binary_operation(), TOS_REG);
} else {
VisitForAccumulatorValue(expr->value());
}
@ -1809,7 +1799,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
break;
case NAMED_PROPERTY:
@ -2286,7 +2276,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
@ -2337,7 +2327,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
@ -2358,7 +2348,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
@ -2371,8 +2361,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
DCHECK(!callee->AsProperty()->IsSuperAccess());
__ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
__ lw(at, MemOperand(sp, 0));
PushOperand(at);
@ -2409,7 +2398,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ sw(v0, MemOperand(sp, kPointerSize));
@ -2434,8 +2423,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ lw(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
__ Move(LoadDescriptor::NameRegister(), v0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
__ lw(at, MemOperand(sp, 0));
@ -2469,7 +2457,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ sw(v0, MemOperand(sp, kPointerSize));
@ -2489,7 +2477,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Record source position of the IC call.
SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
@ -2559,7 +2547,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
__ Push(callee->name());
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
PushOperands(v0, v1); // Function, receiver.
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this
@ -2607,7 +2595,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Touch up the stack with the resolved function.
__ sw(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr);
__ lw(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@ -2656,7 +2644,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate());
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
RestoreContext();
context()->Plug(v0);
}
@ -3104,7 +3092,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to a1.
int const argc = args->length() - 2;
__ lw(a1, MemOperand(sp, (argc + 1) * kPointerSize));
@ -3308,14 +3296,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
&materialize_true);
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
__ LoadRoot(v0, Heap::kTrueValueRootIndex);
if (context()->IsStackValue()) __ push(v0);
__ jmp(&done);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
__ LoadRoot(v0, Heap::kFalseValueRootIndex);
if (context()->IsStackValue()) __ push(v0);
__ bind(&done);
@ -3415,9 +3401,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// We need a second deoptimization point after loading the value
// in case evaluating the property load my have a side effect.
if (assign_type == VARIABLE) {
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->expression(), TOS_REG);
} else {
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
}
// Inline smi case if we are in a loop.
@ -3468,7 +3454,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@ -3514,8 +3500,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(v0);
}
// For all contexts except EffectConstant we have the result on
@ -3526,8 +3511,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
break;
@ -3538,7 +3522,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
@ -3578,7 +3562,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();

View File

@ -185,8 +185,7 @@ void FullCodeGenerator::Generate() {
__ push(a1);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
// The new target value is not used, clobbering is safe.
DCHECK_NULL(info->scope()->new_target_var());
} else {
@ -242,8 +241,7 @@ void FullCodeGenerator::Generate() {
// Register holding this function and new target are both trashed in case we
// bailout here. But since that can happen only when new target is not used
// and we allocate a context, the value of |function_in_register| is correct.
PrepareForBailoutForId(BailoutId::FunctionContext(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
@ -304,8 +302,7 @@ void FullCodeGenerator::Generate() {
}
// Visit the declarations and body.
PrepareForBailoutForId(BailoutId::FunctionEntry(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{
Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(scope()->declarations());
@ -318,8 +315,7 @@ void FullCodeGenerator::Generate() {
{
Comment cmnt(masm_, "[ Stack check");
PrepareForBailoutForId(BailoutId::Declarations(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
Label ok;
__ LoadRoot(at, Heap::kStackLimitRootIndex);
__ Branch(&ok, hs, sp, Operand(at));
@ -400,11 +396,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
EmitProfilingCounterReset();
__ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@ -730,7 +726,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
Label skip;
if (should_normalize) __ Branch(&skip);
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
if (should_normalize) {
__ LoadRoot(a4, Heap::kTrueValueRootIndex);
Split(eq, a0, Operand(a4), if_true, if_false, NULL);
@ -789,7 +785,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ LoadRoot(at, Heap::kTheHoleValueRootIndex);
__ sd(at, ContextMemOperand(cp, variable->index()));
// No write barrier since the_hole_value is in old space.
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@ -811,7 +807,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ Push(a2, a0);
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
__ CallRuntime(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -857,7 +853,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
@ -869,7 +865,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VisitForStackValue(declaration->fun());
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -901,7 +897,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Keep the switch value on the stack until a case matches.
VisitForStackValue(stmt->tag());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@ -951,7 +947,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ Branch(&skip);
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
PrepareForBailout(clause, TOS_REG);
__ LoadRoot(at, Heap::kTrueValueRootIndex);
__ Branch(&next_test, ne, v0, Operand(at));
__ Drop(1);
@ -978,12 +974,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case body");
CaseClause* clause = clauses->at(i);
__ bind(clause->body_target());
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@ -1020,7 +1016,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ CallStub(&stub);
__ mov(a0, v0);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ push(a0);
// Check cache validity in generated code. If we cannot guarantee cache
@ -1040,7 +1036,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&call_runtime);
__ push(a0); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kForInEnumerate);
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
// If we got a map from the runtime call, we can do a fast
// modification check. Otherwise, we got a fixed array, and we have
@ -1078,7 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Push(a1, v0); // Smi and array
__ ld(a1, FieldMemOperand(v0, FixedArray::kLengthOffset));
__ Push(a1); // Fixed array length (as smi).
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
__ li(a0, Operand(Smi::FromInt(0)));
__ Push(a0); // Initial index.
@ -1120,7 +1116,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// just skip it.
__ Push(a1, a3); // Enumerable and current entry.
__ CallRuntime(Runtime::kForInFilter);
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
__ mov(a3, result_register());
__ LoadRoot(at, Heap::kUndefinedValueRootIndex);
__ Branch(loop_statement.continue_label(), eq, a3, Operand(at));
@ -1132,11 +1128,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@ -1155,7 +1151,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
decrement_loop_depth();
}
@ -1314,7 +1310,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
// Record position before possible IC call.
SetExpressionPosition(proxy);
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
@ -1421,7 +1417,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallStub(&stub);
RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in v0.
@ -1458,7 +1454,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ ld(StoreDescriptor::ReceiverRegister(), MemOperand(sp));
EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1492,7 +1488,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
@ -1549,7 +1545,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
} else {
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
VisitForStackValue(value);
@ -1621,7 +1617,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
bool result_saved = false; // Is the result saved to the stack?
ZoneList<Expression*>* subexprs = expr->values();
@ -1653,8 +1649,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
// In case the array literal contains spread expressions it has two parts. The
@ -1674,8 +1669,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForStackValue(subexpr);
CallRuntimeWithOperands(Runtime::kAppendElement);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
@ -1758,27 +1752,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->target(), TOS_REG);
break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
}
}
@ -1798,7 +1788,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
}
// Deoptimization point in case the binary operation may have side effects.
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->binary_operation(), TOS_REG);
} else {
VisitForAccumulatorValue(expr->value());
}
@ -1810,7 +1800,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
break;
case NAMED_PROPERTY:
@ -2285,7 +2275,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
@ -2336,7 +2326,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
@ -2357,7 +2347,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the method prologue if it
// is a sloppy mode method.
@ -2370,8 +2360,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
DCHECK(!callee->AsProperty()->IsSuperAccess());
__ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
__ ld(at, MemOperand(sp, 0));
PushOperand(at);
@ -2408,7 +2397,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ sd(v0, MemOperand(sp, kPointerSize));
@ -2433,8 +2422,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ ld(LoadDescriptor::ReceiverRegister(), MemOperand(sp, 0));
__ Move(LoadDescriptor::NameRegister(), v0);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
__ ld(at, MemOperand(sp, 0));
@ -2468,7 +2456,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ sd(v0, MemOperand(sp, kPointerSize));
@ -2488,7 +2476,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Record source position of the IC call.
SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
@ -2558,7 +2546,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
__ Push(callee->name());
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
PushOperands(v0, v1); // Function, receiver.
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the
// function and receiver and have the slow path jump around this
@ -2606,7 +2594,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Touch up the stack with the resolved function.
__ sd(v0, MemOperand(sp, (arg_count + 1) * kPointerSize));
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
// Record source position for debugger.
SetCallPosition(expr);
__ ld(a1, MemOperand(sp, (arg_count + 1) * kPointerSize));
@ -2655,7 +2643,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate());
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
RestoreContext();
context()->Plug(v0);
}
@ -3104,7 +3092,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to a1.
int const argc = args->length() - 2;
__ ld(a1, MemOperand(sp, (argc + 1) * kPointerSize));
@ -3309,14 +3297,12 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
&materialize_true);
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
__ LoadRoot(v0, Heap::kTrueValueRootIndex);
if (context()->IsStackValue()) __ push(v0);
__ jmp(&done);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
__ LoadRoot(v0, Heap::kFalseValueRootIndex);
if (context()->IsStackValue()) __ push(v0);
__ bind(&done);
@ -3416,9 +3402,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// We need a second deoptimization point after loading the value
// in case evaluating the property load my have a side effect.
if (assign_type == VARIABLE) {
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->expression(), TOS_REG);
} else {
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
}
// Inline smi case if we are in a loop.
@ -3469,7 +3455,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@ -3515,8 +3501,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(v0);
}
// For all contexts except EffectConstant we have the result on
@ -3527,8 +3512,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
} else {
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(v0);
}
break;
@ -3539,7 +3523,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
@ -3579,7 +3563,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();

View File

@ -166,8 +166,7 @@ void FullCodeGenerator::Generate() {
__ Push(rdi);
__ Push(info->scope()->GetScopeInfo(info->isolate()));
__ CallRuntime(Runtime::kNewScriptContext);
PrepareForBailoutForId(BailoutId::ScriptContext(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(BailoutId::ScriptContext(), TOS_REG);
// The new target value is not used, clobbering is safe.
DCHECK_NULL(info->scope()->new_target_var());
} else {
@ -223,8 +222,7 @@ void FullCodeGenerator::Generate() {
// Register holding this function and new target are both trashed in case we
// bailout here. But since that can happen only when new target is not used
// and we allocate a context, the value of |function_in_register| is correct.
PrepareForBailoutForId(BailoutId::FunctionContext(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionContext(), NO_REGISTERS);
// Possibly set up a local binding to the this function which is used in
// derived constructors with super calls.
@ -288,8 +286,7 @@ void FullCodeGenerator::Generate() {
// Visit the declarations and body unless there is an illegal
// redeclaration.
PrepareForBailoutForId(BailoutId::FunctionEntry(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::FunctionEntry(), NO_REGISTERS);
{
Comment cmnt(masm_, "[ Declarations");
VisitDeclarations(scope()->declarations());
@ -302,8 +299,7 @@ void FullCodeGenerator::Generate() {
{
Comment cmnt(masm_, "[ Stack check");
PrepareForBailoutForId(BailoutId::Declarations(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(BailoutId::Declarations(), NO_REGISTERS);
Label ok;
__ CompareRoot(rsp, Heap::kStackLimitRootIndex);
__ j(above_equal, &ok, Label::kNear);
@ -376,11 +372,11 @@ void FullCodeGenerator::EmitBackEdgeBookkeeping(IterationStatement* stmt,
}
__ bind(&ok);
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
// Record a mapping of the OSR id to this PC. This is used if the OSR
// entry becomes the target of a bailout. We don't expect it to be, but
// we want it to work if it is.
PrepareForBailoutForId(stmt->OsrEntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->OsrEntryId(), NO_REGISTERS);
}
void FullCodeGenerator::EmitProfilingCounterHandlingForReturnSequence(
@ -696,7 +692,7 @@ void FullCodeGenerator::PrepareForBailoutBeforeSplit(Expression* expr,
Label skip;
if (should_normalize) __ jmp(&skip, Label::kNear);
PrepareForBailout(expr, BailoutState::TOS_REGISTER);
PrepareForBailout(expr, TOS_REG);
if (should_normalize) {
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
Split(equal, if_true, if_false, NULL);
@ -752,7 +748,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
__ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex);
__ movp(ContextOperand(rsi, variable->index()), kScratchRegister);
// No write barrier since the hole value is in old space.
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
}
break;
@ -772,7 +768,7 @@ void FullCodeGenerator::VisitVariableDeclaration(
}
__ Push(Smi::FromInt(variable->DeclarationPropertyAttributes()));
__ CallRuntime(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -817,7 +813,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
kDontSaveFPRegs,
EMIT_REMEMBERED_SET,
OMIT_SMI_CHECK);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
@ -827,7 +823,7 @@ void FullCodeGenerator::VisitFunctionDeclaration(
VisitForStackValue(declaration->fun());
PushOperand(Smi::FromInt(variable->DeclarationPropertyAttributes()));
CallRuntimeWithOperands(Runtime::kDeclareLookupSlot);
PrepareForBailoutForId(proxy->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->id(), NO_REGISTERS);
break;
}
}
@ -858,7 +854,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
// Keep the switch value on the stack until a case matches.
VisitForStackValue(stmt->tag());
PrepareForBailoutForId(stmt->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->EntryId(), NO_REGISTERS);
ZoneList<CaseClause*>* clauses = stmt->cases();
CaseClause* default_clause = NULL; // Can occur anywhere in the list.
@ -908,7 +904,7 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Label skip;
__ jmp(&skip, Label::kNear);
PrepareForBailout(clause, BailoutState::TOS_REGISTER);
PrepareForBailout(clause, TOS_REG);
__ CompareRoot(rax, Heap::kTrueValueRootIndex);
__ j(not_equal, &next_test);
__ Drop(1);
@ -936,12 +932,12 @@ void FullCodeGenerator::VisitSwitchStatement(SwitchStatement* stmt) {
Comment cmnt(masm_, "[ Case body");
CaseClause* clause = clauses->at(i);
__ bind(clause->body_target());
PrepareForBailoutForId(clause->EntryId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(clause->EntryId(), NO_REGISTERS);
VisitStatements(clause->statements());
}
__ bind(nested_statement.break_label());
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
}
@ -974,7 +970,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
ToObjectStub stub(isolate());
__ CallStub(&stub);
__ bind(&done_convert);
PrepareForBailoutForId(stmt->ToObjectId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->ToObjectId(), TOS_REG);
__ Push(rax);
// Check cache validity in generated code. If we cannot guarantee cache
@ -994,7 +990,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ bind(&call_runtime);
__ Push(rax); // Duplicate the enumerable object on the stack.
__ CallRuntime(Runtime::kForInEnumerate);
PrepareForBailoutForId(stmt->EnumId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->EnumId(), TOS_REG);
// If we got a map from the runtime call, we can do a fast
// modification check. Otherwise, we got a fixed array, and we have
@ -1036,7 +1032,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Push(rax); // Array
__ movp(rax, FieldOperand(rax, FixedArray::kLengthOffset));
__ Push(rax); // Fixed array length (as smi).
PrepareForBailoutForId(stmt->PrepareId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->PrepareId(), NO_REGISTERS);
__ Push(Smi::FromInt(0)); // Initial index.
// Generate code for doing the condition check.
@ -1078,7 +1074,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
__ Push(rcx); // Enumerable.
__ Push(rbx); // Current entry.
__ CallRuntime(Runtime::kForInFilter);
PrepareForBailoutForId(stmt->FilterId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(stmt->FilterId(), TOS_REG);
__ CompareRoot(rax, Heap::kUndefinedValueRootIndex);
__ j(equal, loop_statement.continue_label());
__ movp(rbx, rax);
@ -1090,11 +1086,11 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// Perform the assignment as if via '='.
{ EffectContext context(this);
EmitAssignment(stmt->each(), stmt->EachFeedbackSlot());
PrepareForBailoutForId(stmt->AssignmentId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->AssignmentId(), NO_REGISTERS);
}
// Both Crankshaft and Turbofan expect BodyId to be right before stmt->body().
PrepareForBailoutForId(stmt->BodyId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->BodyId(), NO_REGISTERS);
// Generate code for the body of the loop.
Visit(stmt->body());
@ -1111,7 +1107,7 @@ void FullCodeGenerator::VisitForInStatement(ForInStatement* stmt) {
DropOperands(5);
// Exit and decrement the loop depth.
PrepareForBailoutForId(stmt->ExitId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(stmt->ExitId(), NO_REGISTERS);
__ bind(&exit);
decrement_loop_depth();
}
@ -1270,7 +1266,7 @@ void FullCodeGenerator::EmitVariableLoad(VariableProxy* proxy,
TypeofMode typeof_mode) {
// Record position before possible IC call.
SetExpressionPosition(proxy);
PrepareForBailoutForId(proxy->BeforeId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(proxy->BeforeId(), NO_REGISTERS);
Variable* var = proxy->var();
// Three cases: global variables, lookup variables, and all other types of
@ -1380,7 +1376,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ CallStub(&stub);
RestoreContext();
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
// If result_saved is true the result is on top of the stack. If
// result_saved is false the result is in rax.
@ -1416,7 +1412,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
__ movp(StoreDescriptor::ReceiverRegister(), Operand(rsp, 0));
EmitLoadStoreICSlot(property->GetSlot(0));
CallStoreIC();
PrepareForBailoutForId(key->id(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(key->id(), NO_REGISTERS);
if (NeedsHomeObject(value)) {
EmitSetHomeObjectAccumulator(value, 0, property->GetSlot(1));
@ -1445,7 +1441,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
break;
case ObjectLiteral::Property::GETTER:
if (property->emit_store()) {
@ -1499,7 +1495,7 @@ void FullCodeGenerator::VisitObjectLiteral(ObjectLiteral* expr) {
DCHECK(property->emit_store());
CallRuntimeWithOperands(Runtime::kInternalSetPrototype);
PrepareForBailoutForId(expr->GetIdForPropertySet(property_index),
BailoutState::NO_REGISTERS);
NO_REGISTERS);
} else {
EmitPropertyKey(property, expr->GetIdForPropertyName(property_index));
VisitForStackValue(value);
@ -1572,7 +1568,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
FastCloneShallowArrayStub stub(isolate(), allocation_site_mode);
__ CallStub(&stub);
}
PrepareForBailoutForId(expr->CreateLiteralId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->CreateLiteralId(), TOS_REG);
bool result_saved = false; // Is the result saved to the stack?
ZoneList<Expression*>* subexprs = expr->values();
@ -1602,8 +1598,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
CallIC(ic);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
// In case the array literal contains spread expressions it has two parts. The
@ -1623,8 +1618,7 @@ void FullCodeGenerator::VisitArrayLiteral(ArrayLiteral* expr) {
VisitForStackValue(subexpr);
CallRuntimeWithOperands(Runtime::kAppendElement);
PrepareForBailoutForId(expr->GetIdForElement(array_index),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->GetIdForElement(array_index), NO_REGISTERS);
}
if (result_saved) {
@ -1702,27 +1696,23 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
switch (assign_type) {
case VARIABLE:
EmitVariableLoad(expr->target()->AsVariableProxy());
PrepareForBailout(expr->target(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->target(), TOS_REG);
break;
case NAMED_PROPERTY:
EmitNamedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case NAMED_SUPER_PROPERTY:
EmitNamedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_SUPER_PROPERTY:
EmitKeyedSuperPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
case KEYED_PROPERTY:
EmitKeyedPropertyLoad(property);
PrepareForBailoutForId(property->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(property->LoadId(), TOS_REG);
break;
}
}
@ -1741,7 +1731,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
EmitBinaryOp(expr->binary_operation(), op);
}
// Deoptimization point in case the binary operation may have side effects.
PrepareForBailout(expr->binary_operation(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->binary_operation(), TOS_REG);
} else {
VisitForAccumulatorValue(expr->value());
}
@ -1753,7 +1743,7 @@ void FullCodeGenerator::VisitAssignment(Assignment* expr) {
case VARIABLE:
EmitVariableAssignment(expr->target()->AsVariableProxy()->var(),
expr->op(), expr->AssignmentSlot());
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
break;
case NAMED_PROPERTY:
@ -2176,7 +2166,7 @@ void FullCodeGenerator::EmitNamedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
}
@ -2220,7 +2210,7 @@ void FullCodeGenerator::EmitKeyedPropertyAssignment(Assignment* expr) {
EmitLoadStoreICSlot(expr->AssignmentSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
}
@ -2241,7 +2231,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
if (callee->IsVariableProxy()) {
{ StackValueContext context(this);
EmitVariableLoad(callee->AsVariableProxy());
PrepareForBailout(callee, BailoutState::NO_REGISTERS);
PrepareForBailout(callee, NO_REGISTERS);
}
// Push undefined as receiver. This is patched in the Call builtin if it
// is a sloppy mode method.
@ -2253,8 +2243,7 @@ void FullCodeGenerator::EmitCallWithLoadIC(Call* expr) {
DCHECK(!callee->AsProperty()->IsSuperAccess());
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
EmitNamedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
PushOperand(Operand(rsp, 0));
__ movp(Operand(rsp, kPointerSize), rax);
@ -2290,7 +2279,7 @@ void FullCodeGenerator::EmitSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ movp(Operand(rsp, kPointerSize), rax);
@ -2315,8 +2304,7 @@ void FullCodeGenerator::EmitKeyedCallWithLoadIC(Call* expr,
__ movp(LoadDescriptor::ReceiverRegister(), Operand(rsp, 0));
__ Move(LoadDescriptor::NameRegister(), rax);
EmitKeyedPropertyLoad(callee->AsProperty());
PrepareForBailoutForId(callee->AsProperty()->LoadId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(callee->AsProperty()->LoadId(), TOS_REG);
// Push the target function under the receiver.
PushOperand(Operand(rsp, 0));
@ -2349,7 +2337,7 @@ void FullCodeGenerator::EmitKeyedSuperCallWithLoadIC(Call* expr) {
// - home_object
// - key
CallRuntimeWithOperands(Runtime::kLoadKeyedFromSuper);
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
// Replace home_object with target function.
__ movp(Operand(rsp, kPointerSize), rax);
@ -2369,7 +2357,7 @@ void FullCodeGenerator::EmitCall(Call* expr, ConvertReceiverMode mode) {
VisitForStackValue(args->at(i));
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
SetCallPosition(expr, expr->tail_call_mode());
if (expr->tail_call_mode() == TailCallMode::kAllow) {
if (FLAG_trace) {
@ -2437,7 +2425,7 @@ void FullCodeGenerator::PushCalleeAndWithBaseObject(Call* expr) {
__ CallRuntime(Runtime::kLoadLookupSlotForCall);
PushOperand(rax); // Function.
PushOperand(rdx); // Receiver.
PrepareForBailoutForId(expr->LookupId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->LookupId(), NO_REGISTERS);
// If fast case code has been generated, emit code to push the function
// and receiver and have the slow path jump around this code.
@ -2483,7 +2471,7 @@ void FullCodeGenerator::EmitPossiblyEvalCall(Call* expr) {
// Touch up the callee.
__ movp(Operand(rsp, (arg_count + 1) * kPointerSize), rax);
PrepareForBailoutForId(expr->EvalId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->EvalId(), NO_REGISTERS);
SetCallPosition(expr);
__ movp(rdi, Operand(rsp, (arg_count + 1) * kPointerSize));
@ -2532,7 +2520,7 @@ void FullCodeGenerator::VisitCallNew(CallNew* expr) {
CallConstructStub stub(isolate());
__ Call(stub.GetCode(), RelocInfo::CODE_TARGET);
OperandStackDepthDecrement(arg_count + 1);
PrepareForBailoutForId(expr->ReturnId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ReturnId(), TOS_REG);
RestoreContext();
context()->Plug(rax);
}
@ -2966,7 +2954,7 @@ void FullCodeGenerator::EmitCall(CallRuntime* expr) {
for (Expression* const arg : *args) {
VisitForStackValue(arg);
}
PrepareForBailoutForId(expr->CallId(), BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->CallId(), NO_REGISTERS);
// Move target to rdi.
int const argc = args->length() - 2;
__ movp(rdi, Operand(rsp, (argc + 1) * kPointerSize));
@ -3173,8 +3161,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
&materialize_true);
if (!context()->IsAccumulatorValue()) OperandStackDepthIncrement(1);
__ bind(&materialize_true);
PrepareForBailoutForId(expr->MaterializeTrueId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeTrueId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ LoadRoot(rax, Heap::kTrueValueRootIndex);
} else {
@ -3182,8 +3169,7 @@ void FullCodeGenerator::VisitUnaryOperation(UnaryOperation* expr) {
}
__ jmp(&done, Label::kNear);
__ bind(&materialize_false);
PrepareForBailoutForId(expr->MaterializeFalseId(),
BailoutState::NO_REGISTERS);
PrepareForBailoutForId(expr->MaterializeFalseId(), NO_REGISTERS);
if (context()->IsAccumulatorValue()) {
__ LoadRoot(rax, Heap::kFalseValueRootIndex);
} else {
@ -3282,9 +3268,9 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// We need a second deoptimization point after loading the value
// in case evaluating the property load my have a side effect.
if (assign_type == VARIABLE) {
PrepareForBailout(expr->expression(), BailoutState::TOS_REGISTER);
PrepareForBailout(expr->expression(), TOS_REG);
} else {
PrepareForBailoutForId(prop->LoadId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(prop->LoadId(), TOS_REG);
}
// Inline smi case if we are in a loop.
@ -3337,7 +3323,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Convert old value into a number.
ToNumberStub convert_stub(isolate());
__ CallStub(&convert_stub);
PrepareForBailoutForId(expr->ToNumberId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->ToNumberId(), TOS_REG);
// Save result for postfix expressions.
if (expr->is_postfix()) {
@ -3385,8 +3371,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
{ EffectContext context(this);
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context.Plug(rax);
}
// For all contexts except kEffect: We have the result on
@ -3398,8 +3383,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
// Perform the assignment as if via '='.
EmitVariableAssignment(expr->expression()->AsVariableProxy()->var(),
Token::ASSIGN, expr->CountSlot());
PrepareForBailoutForId(expr->AssignmentId(),
BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
context()->Plug(rax);
}
break;
@ -3409,7 +3393,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
PopOperand(StoreDescriptor::ReceiverRegister());
EmitLoadStoreICSlot(expr->CountSlot());
CallStoreIC();
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();
@ -3448,7 +3432,7 @@ void FullCodeGenerator::VisitCountOperation(CountOperation* expr) {
CodeFactory::KeyedStoreIC(isolate(), language_mode()).code();
EmitLoadStoreICSlot(expr->CountSlot());
CallIC(ic);
PrepareForBailoutForId(expr->AssignmentId(), BailoutState::TOS_REGISTER);
PrepareForBailoutForId(expr->AssignmentId(), TOS_REG);
if (expr->is_postfix()) {
if (!context()->IsEffect()) {
context()->PlugTOS();

View File

@ -685,30 +685,30 @@ int Heap::NextScriptId() {
return last_id;
}
void Heap::SetArgumentsAdaptorDeoptPCOffset(int pc_offset) {
DCHECK(arguments_adaptor_deopt_pc_offset() == Smi::FromInt(0));
set_arguments_adaptor_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetConstructStubDeoptPCOffset(int pc_offset) {
DCHECK(construct_stub_deopt_pc_offset() == Smi::FromInt(0));
set_construct_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetGetterStubDeoptPCOffset(int pc_offset) {
DCHECK(getter_stub_deopt_pc_offset() == Smi::FromInt(0));
set_getter_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetSetterStubDeoptPCOffset(int pc_offset) {
DCHECK(setter_stub_deopt_pc_offset() == Smi::FromInt(0));
set_setter_stub_deopt_pc_offset(Smi::FromInt(pc_offset));
}
void Heap::SetInterpreterEntryReturnPCOffset(int pc_offset) {
DCHECK(interpreter_entry_return_pc_offset() == Smi::FromInt(0));
set_interpreter_entry_return_pc_offset(Smi::FromInt(pc_offset));
}
AlwaysAllocateScope::AlwaysAllocateScope(Isolate* isolate)
: heap_(isolate->heap()) {

View File

@ -205,8 +205,8 @@ using v8::MemoryPressureLevel;
V(Smi, arguments_adaptor_deopt_pc_offset, ArgumentsAdaptorDeoptPCOffset) \
V(Smi, construct_stub_deopt_pc_offset, ConstructStubDeoptPCOffset) \
V(Smi, getter_stub_deopt_pc_offset, GetterStubDeoptPCOffset) \
V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset) \
V(Smi, interpreter_entry_return_pc_offset, InterpreterEntryReturnPCOffset)
V(Smi, setter_stub_deopt_pc_offset, SetterStubDeoptPCOffset)
#define ROOT_LIST(V) \
STRONG_ROOT_LIST(V) \
@ -794,7 +794,6 @@ class Heap {
inline void SetConstructStubDeoptPCOffset(int pc_offset);
inline void SetGetterStubDeoptPCOffset(int pc_offset);
inline void SetSetterStubDeoptPCOffset(int pc_offset);
inline void SetInterpreterEntryReturnPCOffset(int pc_offset);
// For post mortem debugging.
void RememberUnmappedPage(Address page, bool compacted);

View File

@ -620,22 +620,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
times_pointer_size, 0));
__ call(ebx);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in eax.
// Get the arguments + reciever count.
__ mov(ebx, Operand(ebp, InterpreterFrameConstants::kBytecodeArrayFromFp));
__ mov(ebx, FieldOperand(ebx, BytecodeArray::kParameterSizeOffset));
// Leave the frame (also dropping the register file).
__ leave();
// Drop receiver + arguments and return.
__ pop(ecx);
__ add(esp, ebx);
__ push(ecx);
__ ret(0);
// Even though the first bytecode handler was called, we will never return.
__ Abort(kUnexpectedReturnFromBytecodeHandler);
// Load debug copy of the bytecode array.
__ bind(&load_debug_bytecode_array);
@ -661,6 +648,23 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ jmp(ecx);
}
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
// The return value is in accumulator, which is already in eax.
// Leave the frame (also dropping the register file).
__ leave();
// Drop receiver + arguments and return.
__ mov(ebx, FieldOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kParameterSizeOffset));
__ pop(ecx);
__ add(esp, ebx);
__ push(ecx);
__ ret(0);
}
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
Register array_limit) {
// ----------- S t a t e -------------
@ -678,6 +682,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
__ j(greater, &loop_header, Label::kNear);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
@ -746,18 +751,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
__ LoadHeapObject(ebx,
masm->isolate()->builtins()->InterpreterEntryTrampoline());
__ add(ebx, Immediate(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
__ push(ebx);
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize the dispatch table register.
__ mov(kInterpreterDispatchTableRegister,
Immediate(ExternalReference::interpreter_dispatch_table_address(
@ -788,6 +783,58 @@ void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
__ jmp(ebx);
}
static void Generate_InterpreterNotifyDeoptimizedHelper(
MacroAssembler* masm, Deoptimizer::BailoutType type) {
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
__ Push(Smi::FromInt(static_cast<int>(type)));
__ CallRuntime(Runtime::kNotifyDeoptimized);
// Tear down internal frame.
}
// Drop state (we don't use these for interpreter deopts) and and pop the
// accumulator value into the accumulator register and push PC at top
// of stack (to simulate initial call to bytecode handler in interpreter entry
// trampoline).
__ Pop(ebx);
__ Drop(1);
__ Pop(kInterpreterAccumulatorRegister);
__ Push(ebx);
// Enter the bytecode dispatch.
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
}
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
}
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the address of the interpreter entry trampoline as a return address.
// This simulates the initial call to bytecode handlers in interpreter entry
// trampoline. The return will never actually be taken, but our stack walker
// uses this address to determine whether a frame is interpreted.
__ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline());
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- eax : argument count (preserved for callee)
@ -1084,14 +1131,13 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
// Switch on the state.
Label not_no_registers, not_tos_eax;
__ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS));
__ cmp(ecx, FullCodeGenerator::NO_REGISTERS);
__ j(not_equal, &not_no_registers, Label::kNear);
__ ret(1 * kPointerSize); // Remove state.
__ bind(&not_no_registers);
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), eax.code());
__ mov(eax, Operand(esp, 2 * kPointerSize));
__ cmp(ecx, static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER));
__ cmp(ecx, FullCodeGenerator::TOS_REG);
__ j(not_equal, &not_tos_eax, Label::kNear);
__ ret(2 * kPointerSize); // Remove state, eax.

View File

@ -149,11 +149,6 @@ int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) {
}
// static
size_t Bytecodes::ReturnCount(Bytecode bytecode) {
return bytecode == Bytecode::kReturn ? 1 : 0;
}
// static
int Bytecodes::NumberOfOperands(Bytecode bytecode) {
DCHECK(bytecode <= Bytecode::kLast);

View File

@ -239,7 +239,7 @@ namespace interpreter {
/* Non-local flow control */ \
V(Throw, AccumulatorUse::kRead) \
V(ReThrow, AccumulatorUse::kRead) \
V(Return, AccumulatorUse::kRead) \
V(Return, AccumulatorUse::kNone) \
\
/* Generators */ \
V(SuspendGenerator, AccumulatorUse::kRead, OperandType::kReg) \
@ -509,9 +509,6 @@ class Bytecodes {
// Returns the size of |operand|.
static OperandSize SizeOfOperand(OperandType operand, OperandScale scale);
// Returns the number of values which |bytecode| returns.
static size_t ReturnCount(Bytecode bytecode);
// Returns true if the bytecode is a conditional jump taking
// an immediate byte operand (OperandType::kImm).
static bool IsConditionalJumpImmediate(Bytecode bytecode);

View File

@ -27,8 +27,7 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
OperandScale operand_scale)
: CodeStubAssembler(isolate, zone, InterpreterDispatchDescriptor(isolate),
Code::ComputeFlags(Code::BYTECODE_HANDLER),
Bytecodes::ToString(bytecode),
Bytecodes::ReturnCount(bytecode)),
Bytecodes::ToString(bytecode), 0),
bytecode_(bytecode),
operand_scale_(operand_scale),
accumulator_(this, MachineRepresentation::kTagged),
@ -601,7 +600,7 @@ void InterpreterAssembler::DispatchWide(OperandScale operand_scale) {
DispatchToBytecodeHandlerEntry(target_code_entry, next_bytecode_offset);
}
void InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
compiler::Node* InterpreterAssembler::InterpreterReturn() {
// TODO(rmcilroy): Investigate whether it is worth supporting self
// optimization of primitive functions like FullCodegen.
@ -611,6 +610,10 @@ void InterpreterAssembler::UpdateInterruptBudgetOnReturn() {
Int32Sub(Int32Constant(kHeapObjectTag + BytecodeArray::kHeaderSize),
BytecodeOffset());
UpdateInterruptBudget(profiling_weight);
Node* exit_trampoline_code_object =
HeapConstant(isolate()->builtins()->InterpreterExitTrampoline());
return DispatchToBytecodeHandler(exit_trampoline_code_object);
}
Node* InterpreterAssembler::StackCheckTriggeredInterrupt() {

View File

@ -127,8 +127,8 @@ class InterpreterAssembler : public CodeStubAssembler {
// Returns true if the stack guard check triggers an interrupt.
compiler::Node* StackCheckTriggeredInterrupt();
// Updates the profiler interrupt budget for a return.
void UpdateInterruptBudgetOnReturn();
// Returns from the function.
compiler::Node* InterpreterReturn();
// Dispatch to the bytecode.
compiler::Node* Dispatch();

View File

@ -1642,9 +1642,7 @@ void Interpreter::DoReThrow(InterpreterAssembler* assembler) {
//
// Return the value in the accumulator.
void Interpreter::DoReturn(InterpreterAssembler* assembler) {
__ UpdateInterruptBudgetOnReturn();
Node* accumulator = __ GetAccumulator();
__ Return(accumulator);
__ InterpreterReturn();
}
// Debugger

View File

@ -1051,20 +1051,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Lsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2);
__ lw(at, MemOperand(at));
__ Call(at);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in v0.
// Get the arguments + reciever count.
__ lw(t0, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
__ lw(t0, FieldMemOperand(t0, BytecodeArray::kParameterSizeOffset));
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Drop receiver + arguments and return.
__ Addu(sp, sp, t0);
__ Jump(ra);
// Even though the first bytecode handler was called, we will never return.
__ Abort(kUnexpectedReturnFromBytecodeHandler);
// Load debug copy of the bytecode array.
__ bind(&load_debug_bytecode_array);
@ -1085,6 +1074,21 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Jump(t0);
}
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
// The return value is in accumulator, which is already in v0.
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Drop receiver + arguments and return.
__ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kParameterSizeOffset));
__ Addu(sp, sp, at);
__ Jump(ra);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
@ -1117,6 +1121,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -1147,16 +1152,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
__ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
__ Addu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize the dispatch table register.
__ li(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
@ -1190,6 +1187,55 @@ void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
__ Jump(a1);
}
static void Generate_InterpreterNotifyDeoptimizedHelper(
MacroAssembler* masm, Deoptimizer::BailoutType type) {
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
__ li(a1, Operand(Smi::FromInt(static_cast<int>(type))));
__ push(a1);
__ CallRuntime(Runtime::kNotifyDeoptimized);
// Tear down internal frame.
}
// Drop state (we don't use these for interpreter deopts) and and pop the
// accumulator value into the accumulator register.
__ Drop(1);
__ Pop(kInterpreterAccumulatorRegister);
// Enter the bytecode dispatch.
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
}
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
}
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the address of the interpreter entry trampoline as a return address.
// This simulates the initial call to bytecode handlers in interpreter entry
// trampoline. The return will never actually be taken, but our stack walker
// uses this address to determine whether a frame is interpreted.
__ li(ra, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argument count (preserved for callee)
@ -1487,17 +1533,15 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
__ SmiUntag(t2);
// Switch on the state.
Label with_tos_register, unknown_state;
__ Branch(&with_tos_register, ne, t2,
Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
__ Branch(&with_tos_register,
ne, t2, Operand(FullCodeGenerator::NO_REGISTERS));
__ Ret(USE_DELAY_SLOT);
// Safe to fill delay slot Addu will emit one instruction.
__ Addu(sp, sp, Operand(1 * kPointerSize)); // Remove state.
__ bind(&with_tos_register);
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code());
__ lw(v0, MemOperand(sp, 1 * kPointerSize));
__ Branch(&unknown_state, ne, t2,
Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
__ Branch(&unknown_state, ne, t2, Operand(FullCodeGenerator::TOS_REG));
__ Ret(USE_DELAY_SLOT);
// Safe to fill delay slot Addu will emit one instruction.

View File

@ -940,6 +940,7 @@ void Builtins::Generate_JSConstructEntryTrampoline(MacroAssembler* masm) {
Generate_JSEntryTrampolineHelper(masm, true);
}
// Generate code for entering a JS function with the interpreter.
// On entry to the function the receiver and arguments have been pushed on the
// stack left to right. The actual argument count matches the formal parameter
@ -1039,20 +1040,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Dlsa(at, kInterpreterDispatchTableRegister, a0, kPointerSizeLog2);
__ ld(at, MemOperand(at));
__ Call(at);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in v0.
// Get the arguments + reciever count.
__ ld(t0, MemOperand(fp, InterpreterFrameConstants::kBytecodeArrayFromFp));
__ lw(t0, FieldMemOperand(t0, BytecodeArray::kParameterSizeOffset));
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Drop receiver + arguments and return.
__ Daddu(sp, sp, t0);
__ Jump(ra);
// Even though the first bytecode handler was called, we will never return.
__ Abort(kUnexpectedReturnFromBytecodeHandler);
// Load debug copy of the bytecode array.
__ bind(&load_debug_bytecode_array);
@ -1073,6 +1063,21 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Jump(a4);
}
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
// The return value is in accumulator, which is already in v0.
// Leave the frame (also dropping the register file).
__ LeaveFrame(StackFrame::JAVA_SCRIPT);
// Drop receiver + arguments and return.
__ lw(at, FieldMemOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kParameterSizeOffset));
__ Daddu(sp, sp, at);
__ Jump(ra);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
@ -1105,6 +1110,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -1135,16 +1141,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
__ li(t0, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
__ Daddu(ra, t0, Operand(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize the dispatch table register.
__ li(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
@ -1178,6 +1176,55 @@ void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
__ Jump(a1);
}
static void Generate_InterpreterNotifyDeoptimizedHelper(
MacroAssembler* masm, Deoptimizer::BailoutType type) {
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
__ li(a1, Operand(Smi::FromInt(static_cast<int>(type))));
__ push(a1);
__ CallRuntime(Runtime::kNotifyDeoptimized);
// Tear down internal frame.
}
// Drop state (we don't use these for interpreter deopts) and and pop the
// accumulator value into the accumulator register.
__ Drop(1);
__ Pop(kInterpreterAccumulatorRegister);
// Enter the bytecode dispatch.
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
}
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
}
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the address of the interpreter entry trampoline as a return address.
// This simulates the initial call to bytecode handlers in interpreter entry
// trampoline. The return will never actually be taken, but our stack walker
// uses this address to determine whether a frame is interpreted.
__ li(ra, Operand(masm->isolate()->builtins()->InterpreterEntryTrampoline()));
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- a0 : argument count (preserved for callee)
@ -1474,17 +1521,15 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
__ SmiUntag(a6);
// Switch on the state.
Label with_tos_register, unknown_state;
__ Branch(&with_tos_register, ne, a6,
Operand(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
__ Branch(&with_tos_register,
ne, a6, Operand(FullCodeGenerator::NO_REGISTERS));
__ Ret(USE_DELAY_SLOT);
// Safe to fill delay slot Addu will emit one instruction.
__ Daddu(sp, sp, Operand(1 * kPointerSize)); // Remove state.
__ bind(&with_tos_register);
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), v0.code());
__ ld(v0, MemOperand(sp, 1 * kPointerSize));
__ Branch(&unknown_state, ne, t2,
Operand(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
__ Branch(&unknown_state, ne, a6, Operand(FullCodeGenerator::TOS_REG));
__ Ret(USE_DELAY_SLOT);
// Safe to fill delay slot Addu will emit one instruction.

View File

@ -13738,9 +13738,8 @@ void DeoptimizationOutputData::DeoptimizationOutputDataPrint(
int pc_and_state = this->PcAndState(i)->value();
os << std::setw(6) << this->AstId(i).ToInt() << " " << std::setw(8)
<< FullCodeGenerator::PcField::decode(pc_and_state) << " "
<< Deoptimizer::BailoutStateToString(
FullCodeGenerator::BailoutStateField::decode(pc_and_state))
<< "\n";
<< FullCodeGenerator::State2String(
FullCodeGenerator::StateField::decode(pc_and_state)) << "\n";
}
}

View File

@ -699,22 +699,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ movp(rbx, Operand(kInterpreterDispatchTableRegister, rbx,
times_pointer_size, 0));
__ call(rbx);
masm->isolate()->heap()->SetInterpreterEntryReturnPCOffset(masm->pc_offset());
// The return value is in rax.
// Get the arguments + reciever count.
__ movp(rbx, Operand(rbp, InterpreterFrameConstants::kBytecodeArrayFromFp));
__ movl(rbx, FieldOperand(rbx, BytecodeArray::kParameterSizeOffset));
// Leave the frame (also dropping the register file).
__ leave();
// Drop receiver + arguments and return.
__ PopReturnAddressTo(rcx);
__ addp(rsp, rbx);
__ PushReturnAddressFrom(rcx);
__ ret(0);
// Even though the first bytecode handler was called, we will never return.
__ Abort(kUnexpectedReturnFromBytecodeHandler);
// Load debug copy of the bytecode array.
__ bind(&load_debug_bytecode_array);
@ -737,6 +724,23 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ jmp(rcx);
}
void Builtins::Generate_InterpreterExitTrampoline(MacroAssembler* masm) {
// The return value is in accumulator, which is already in rax.
// Leave the frame (also dropping the register file).
__ leave();
// Drop receiver + arguments and return.
__ movl(rbx, FieldOperand(kInterpreterBytecodeArrayRegister,
BytecodeArray::kParameterSizeOffset));
__ PopReturnAddressTo(rcx);
__ addp(rsp, rbx);
__ PushReturnAddressFrom(rcx);
__ ret(0);
}
static void Generate_InterpreterPushArgs(MacroAssembler* masm,
bool push_receiver) {
// ----------- S t a t e -------------
@ -767,6 +771,7 @@ static void Generate_InterpreterPushArgs(MacroAssembler* masm,
__ j(greater, &loop_header, Label::kNear);
}
// static
void Builtins::Generate_InterpreterPushArgsAndCallImpl(
MacroAssembler* masm, TailCallMode tail_call_mode) {
@ -790,6 +795,7 @@ void Builtins::Generate_InterpreterPushArgsAndCallImpl(
RelocInfo::CODE_TARGET);
}
// static
void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
// ----------- S t a t e -------------
@ -817,17 +823,8 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
__ Jump(masm->isolate()->builtins()->Construct(), RelocInfo::CODE_TARGET);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the return address to the correct point in the interpreter entry
// trampoline.
Smi* interpreter_entry_return_pc_offset(
masm->isolate()->heap()->interpreter_entry_return_pc_offset());
DCHECK_NE(interpreter_entry_return_pc_offset, Smi::FromInt(0));
__ Move(rbx, masm->isolate()->builtins()->InterpreterEntryTrampoline());
__ addp(rbx, Immediate(interpreter_entry_return_pc_offset->value() +
Code::kHeaderSize - kHeapObjectTag));
__ Push(rbx);
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize dispatch table register.
__ Move(
kInterpreterDispatchTableRegister,
@ -859,6 +856,58 @@ void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
__ jmp(rbx);
}
static void Generate_InterpreterNotifyDeoptimizedHelper(
MacroAssembler* masm, Deoptimizer::BailoutType type) {
// Enter an internal frame.
{
FrameScope scope(masm, StackFrame::INTERNAL);
// Pass the deoptimization type to the runtime system.
__ Push(Smi::FromInt(static_cast<int>(type)));
__ CallRuntime(Runtime::kNotifyDeoptimized);
// Tear down internal frame.
}
// Drop state (we don't use these for interpreter deopts) and and pop the
// accumulator value into the accumulator register and push PC at top
// of stack (to simulate initial call to bytecode handler in interpreter entry
// trampoline).
__ Pop(rbx);
__ Drop(1);
__ Pop(kInterpreterAccumulatorRegister);
__ Push(rbx);
// Enter the bytecode dispatch.
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_InterpreterNotifyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::EAGER);
}
void Builtins::Generate_InterpreterNotifySoftDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::SOFT);
}
void Builtins::Generate_InterpreterNotifyLazyDeoptimized(MacroAssembler* masm) {
Generate_InterpreterNotifyDeoptimizedHelper(masm, Deoptimizer::LAZY);
}
void Builtins::Generate_InterpreterEnterBytecodeDispatch(MacroAssembler* masm) {
// Set the address of the interpreter entry trampoline as a return address.
// This simulates the initial call to bytecode handlers in interpreter entry
// trampoline. The return will never actually be taken, but our stack walker
// uses this address to determine whether a frame is interpreted.
__ Push(masm->isolate()->builtins()->InterpreterEntryTrampoline());
Generate_EnterBytecodeDispatch(masm);
}
void Builtins::Generate_CompileLazy(MacroAssembler* masm) {
// ----------- S t a t e -------------
// -- rax : argument count (preserved for callee)
@ -1132,16 +1181,13 @@ static void Generate_NotifyDeoptimizedHelper(MacroAssembler* masm,
// Switch on the state.
Label not_no_registers, not_tos_rax;
__ cmpp(kScratchRegister,
Immediate(static_cast<int>(Deoptimizer::BailoutState::NO_REGISTERS)));
__ cmpp(kScratchRegister, Immediate(FullCodeGenerator::NO_REGISTERS));
__ j(not_equal, &not_no_registers, Label::kNear);
__ ret(1 * kPointerSize); // Remove state.
__ bind(&not_no_registers);
DCHECK_EQ(kInterpreterAccumulatorRegister.code(), rax.code());
__ movp(rax, Operand(rsp, kPCOnStackSize + kPointerSize));
__ cmpp(kScratchRegister,
Immediate(static_cast<int>(Deoptimizer::BailoutState::TOS_REGISTER)));
__ cmpp(kScratchRegister, Immediate(FullCodeGenerator::TOS_REG));
__ j(not_equal, &not_tos_rax, Label::kNear);
__ ret(2 * kPointerSize); // Remove state, rax.

View File

@ -382,6 +382,32 @@ TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
}
}
TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) {
// If debug code is enabled we emit extra code in InterpreterReturn.
if (FLAG_debug_code) return;
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* tail_call_node = m.InterpreterReturn();
Handle<HeapObject> exit_trampoline =
isolate()->builtins()->InterpreterExitTrampoline();
Matcher<Node*> exit_trampoline_entry_matcher =
IsIntPtrAdd(IsHeapConstant(exit_trampoline),
IsIntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
EXPECT_THAT(
tail_call_node,
IsTailCall(
_, exit_trampoline_entry_matcher,
IsParameter(InterpreterDispatchDescriptor::kAccumulatorParameter),
IsParameter(
InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
_,
IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
_, _));
}
}
TARGET_TEST_F(InterpreterAssemblerTest, BytecodeOperand) {
static const OperandScale kOperandScales[] = {
OperandScale::kSingle, OperandScale::kDouble, OperandScale::kQuadruple};