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:
parent
0151651603
commit
c473f2931d
@ -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();
|
||||
|
@ -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");
|
||||
|
@ -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") \
|
||||
|
@ -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( \
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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_;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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, ¬_no_registers, Label::kNear);
|
||||
__ ret(1 * kPointerSize); // Remove state.
|
||||
|
||||
__ bind(¬_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, ¬_tos_eax, Label::kNear);
|
||||
__ ret(2 * kPointerSize); // Remove state, eax.
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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, ¬_no_registers, Label::kNear);
|
||||
__ ret(1 * kPointerSize); // Remove state.
|
||||
|
||||
__ bind(¬_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, ¬_tos_rax, Label::kNear);
|
||||
__ ret(2 * kPointerSize); // Remove state, rax.
|
||||
|
||||
|
@ -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};
|
||||
|
Loading…
Reference in New Issue
Block a user