Commit 025d476c authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Save bytecode offset in interpreter stack frames.

Adds a slot for the bytecode offset to interpreter stack frames and
saves it on calls, and restores after calls.

Also fixes RawMachineAssembler::Return() to call MergeControlToEnd.

BUG=v8:4280
LOG=N

Review URL: https://codereview.chromium.org/1512543002

Cr-Commit-Position: refs/heads/master@{#32906}
parent c6e7d658
......@@ -775,6 +775,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ push(r3);
// Push zero for bytecode array offset.
__ mov(r0, Operand(0));
__ push(r0);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
__ ldr(r0, FieldMemOperand(r1, JSFunction::kSharedFunctionInfoOffset));
......@@ -841,9 +845,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Load accumulator, register file, bytecode offset, dispatch table into
// registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ sub(kInterpreterRegisterFileRegister, fp,
Operand(2 * kPointerSize +
StandardFrameConstants::kFixedFrameSizeFromFp));
__ add(kInterpreterRegisterFileRegister, fp,
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ LoadRoot(kInterpreterDispatchTableRegister,
......
......@@ -797,6 +797,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);
__ Push(x3);
// Push zero for bytecode array offset.
__ Mov(x0, Operand(0));
__ Push(x0);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
__ Ldr(x0, FieldMemOperand(x1, JSFunction::kSharedFunctionInfoOffset));
......@@ -860,9 +864,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Load accumulator, register file, bytecode offset, dispatch table into
// registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ Sub(kInterpreterRegisterFileRegister, fp,
Operand(2 * kPointerSize +
StandardFrameConstants::kFixedFrameSizeFromFp));
__ Add(kInterpreterRegisterFileRegister, fp,
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ Mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ LoadRoot(kInterpreterDispatchTableRegister,
......
......@@ -35,6 +35,8 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
InstructionSelector::SupportedMachineOperatorFlags())),
accumulator_(
raw_assembler_->Parameter(Linkage::kInterpreterAccumulatorParameter)),
bytecode_offset_(raw_assembler_->Parameter(
Linkage::kInterpreterBytecodeOffsetParameter)),
context_(
raw_assembler_->Parameter(Linkage::kInterpreterContextParameter)),
code_generated_(false) {}
......@@ -80,6 +82,9 @@ Node* InterpreterAssembler::GetContext() { return context_; }
void InterpreterAssembler::SetContext(Node* value) { context_ = value; }
Node* InterpreterAssembler::BytecodeOffset() { return bytecode_offset_; }
Node* InterpreterAssembler::RegisterFileRawPointer() {
return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
}
......@@ -90,31 +95,29 @@ Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
}
Node* InterpreterAssembler::BytecodeOffset() {
return raw_assembler_->Parameter(
Linkage::kInterpreterBytecodeOffsetParameter);
}
Node* InterpreterAssembler::DispatchTableRawPointer() {
return raw_assembler_->Parameter(Linkage::kInterpreterDispatchTableParameter);
}
Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
return WordShl(index, kPointerSizeLog2);
Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
}
Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
return IntPtrAdd(RegisterFileRawPointer(), RegisterFrameOffset(reg_index));
Node* InterpreterAssembler::LoadRegister(int offset) {
return raw_assembler_->Load(MachineType::AnyTagged(),
RegisterFileRawPointer(), Int32Constant(offset));
}
Node* InterpreterAssembler::LoadRegister(interpreter::Register reg) {
return raw_assembler_->Load(
MachineType::AnyTagged(), RegisterFileRawPointer(),
RegisterFrameOffset(Int32Constant(reg.ToOperand())));
return LoadRegister(reg.ToOperand() << kPointerSizeLog2);
}
Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
return WordShl(index, kPointerSizeLog2);
}
......@@ -125,6 +128,19 @@ Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
}
Node* InterpreterAssembler::StoreRegister(Node* value, int offset) {
return raw_assembler_->Store(MachineRepresentation::kTagged,
RegisterFileRawPointer(), Int32Constant(offset),
value, kNoWriteBarrier);
}
Node* InterpreterAssembler::StoreRegister(Node* value,
interpreter::Register reg) {
return StoreRegister(value, reg.ToOperand() << kPointerSizeLog2);
}
Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
return raw_assembler_->Store(
MachineRepresentation::kTagged, RegisterFileRawPointer(),
......@@ -386,8 +402,23 @@ Node* InterpreterAssembler::CallConstruct(Node* new_target, Node* constructor,
}
void InterpreterAssembler::CallPrologue() {
StoreRegister(SmiTag(bytecode_offset_),
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
}
void InterpreterAssembler::CallEpilogue() {
// Restore the bytecode offset from the stack frame.
bytecode_offset_ = SmiUntag(LoadRegister(
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
}
Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
Node** args) {
CallPrologue();
Node* stack_pointer_before_call = nullptr;
if (FLAG_debug_code) {
stack_pointer_before_call = raw_assembler_->LoadStackPointer();
......@@ -398,6 +429,8 @@ Node* InterpreterAssembler::CallN(CallDescriptor* descriptor, Node* code_target,
AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
kUnexpectedStackPointer);
}
CallEpilogue();
return return_val;
}
......@@ -497,21 +530,32 @@ Node* InterpreterAssembler::CallRuntime(Node* function_id, Node* first_arg,
Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* arg1) {
return raw_assembler_->CallRuntime1(function_id, arg1, GetContext());
CallPrologue();
Node* return_val =
raw_assembler_->CallRuntime1(function_id, arg1, GetContext());
CallEpilogue();
return return_val;
}
Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* arg1, Node* arg2) {
return raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext());
CallPrologue();
Node* return_val =
raw_assembler_->CallRuntime2(function_id, arg1, arg2, GetContext());
CallEpilogue();
return return_val;
}
Node* InterpreterAssembler::CallRuntime(Runtime::FunctionId function_id,
Node* arg1, Node* arg2, Node* arg3,
Node* arg4) {
return raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3, arg4,
GetContext());
CallPrologue();
Node* return_val = raw_assembler_->CallRuntime4(function_id, arg1, arg2, arg3,
arg4, GetContext());
CallEpilogue();
return return_val;
}
......@@ -595,8 +639,9 @@ void InterpreterAssembler::DispatchTo(Node* new_bytecode_offset) {
void InterpreterAssembler::Abort(BailoutReason bailout_reason) {
Node* abort_id = SmiTag(Int32Constant(bailout_reason));
CallRuntime(Runtime::kAbort, abort_id);
Return();
Node* ret_value = CallRuntime(Runtime::kAbort, abort_id);
// Unreached, but keeps turbofan happy.
raw_assembler_->Return(ret_value);
}
......
......@@ -60,8 +60,11 @@ class InterpreterAssembler {
void SetContext(Node* value);
// Loads from and stores to the interpreter register file.
Node* LoadRegister(int offset);
Node* LoadRegister(interpreter::Register reg);
Node* LoadRegister(Node* reg_index);
Node* StoreRegister(Node* value, int offset);
Node* StoreRegister(Node* value, interpreter::Register reg);
Node* StoreRegister(Node* value, Node* reg_index);
// Returns the location in memory of the register |reg_index| in the
......@@ -163,6 +166,11 @@ class InterpreterAssembler {
// Returns a raw pointer to first entry in the interpreter dispatch table.
Node* DispatchTableRawPointer();
// Saves and restores interpreter bytecode offset to the interpreter stack
// frame when performing a call.
void CallPrologue();
void CallEpilogue();
// Returns the offset of register |index| relative to RegisterFilePointer().
Node* RegisterFrameOffset(Node* index);
......@@ -173,8 +181,6 @@ class InterpreterAssembler {
Node* CallN(CallDescriptor* descriptor, Node* code_target, Node** args);
Node* CallIC(CallInterfaceDescriptor descriptor, Node* target, Node** args);
Node* CallJSBuiltin(int context_index, Node* receiver, Node** js_args,
int js_arg_count);
// Returns BytecodeOffset() advanced by delta bytecodes. Note: this does not
// update BytecodeOffset() itself.
......@@ -193,8 +199,11 @@ class InterpreterAssembler {
interpreter::Bytecode bytecode_;
base::SmartPointer<RawMachineAssembler> raw_assembler_;
Node* accumulator_;
Node* bytecode_offset_;
Node* context_;
bool code_generated_;
DISALLOW_COPY_AND_ASSIGN(InterpreterAssembler);
......
......@@ -96,6 +96,7 @@ void RawMachineAssembler::Switch(Node* index, RawMachineLabel* default_label,
void RawMachineAssembler::Return(Node* value) {
Node* ret = MakeNode(common()->Return(), 1, &value);
NodeProperties::MergeControlToEnd(graph(), common(), ret);
schedule()->AddReturn(CurrentBlock(), ret);
current_block_ = nullptr;
}
......@@ -104,6 +105,7 @@ void RawMachineAssembler::Return(Node* value) {
void RawMachineAssembler::Return(Node* v1, Node* v2) {
Node* values[] = {v1, v2};
Node* ret = MakeNode(common()->Return(2), 2, values);
NodeProperties::MergeControlToEnd(graph(), common(), ret);
schedule()->AddReturn(CurrentBlock(), ret);
current_block_ = nullptr;
}
......@@ -112,6 +114,7 @@ void RawMachineAssembler::Return(Node* v1, Node* v2) {
void RawMachineAssembler::Return(Node* v1, Node* v2, Node* v3) {
Node* values[] = {v1, v2, v3};
Node* ret = MakeNode(common()->Return(3), 3, values);
NodeProperties::MergeControlToEnd(graph(), common(), ret);
schedule()->AddReturn(CurrentBlock(), ret);
current_block_ = nullptr;
}
......
......@@ -176,12 +176,18 @@ class ConstructFrameConstants : public AllStatic {
class InterpreterFrameConstants : public AllStatic {
public:
// FP-relative.
static const int kRegisterFilePointerFromFp =
-StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
// Register file pointer relative.
static const int kLastParamFromRegisterPointer =
StandardFrameConstants::kFixedFrameSize + 2 * kPointerSize;
static const int kNewTargetFromRegisterPointer = kPointerSize;
static const int kFunctionFromRegisterPointer = 2 * kPointerSize;
static const int kContextFromRegisterPointer = 3 * kPointerSize;
StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
static const int kBytecodeOffsetFromRegisterPointer = 1 * kPointerSize;
static const int kNewTargetFromRegisterPointer = 2 * kPointerSize;
static const int kFunctionFromRegisterPointer = 3 * kPointerSize;
static const int kContextFromRegisterPointer = 4 * kPointerSize;
};
......
......@@ -522,6 +522,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ push(edi); // Callee's JS function.
__ push(edx); // Callee's new target.
// Push zero for bytecode array offset.
__ push(Immediate(0));
// Get the bytecode array from the function object and load the pointer to the
// first entry into edi (InterpreterBytecodeRegister).
__ mov(eax, FieldOperand(edi, JSFunction::kSharedFunctionInfoOffset));
......@@ -591,9 +594,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ mov(kInterpreterRegisterFileRegister, ebp);
__ sub(kInterpreterRegisterFileRegister,
Immediate(2 * kPointerSize +
StandardFrameConstants::kFixedFrameSizeFromFp));
__ add(kInterpreterRegisterFileRegister,
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterBytecodeOffsetRegister,
Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
// Since the dispatch table root might be set after builtins are generated,
......@@ -617,6 +619,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// and header removal.
__ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
__ call(ebx);
__ nop(); // Ensure that return address still counts as interpreter entry
// trampoline.
}
......
......@@ -17,6 +17,7 @@ namespace internal {
namespace interpreter {
using compiler::Node;
#define __ assembler->
......@@ -1188,9 +1189,9 @@ void Interpreter::DoJumpIfFalseConstant(
void Interpreter::DoJumpIfToBooleanTrue(
compiler::InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* relative_jump = __ BytecodeOperandImm(0);
Node* to_boolean_value =
__ CallRuntime(Runtime::kInterpreterToBoolean, accumulator);
Node* relative_jump = __ BytecodeOperandImm(0);
Node* true_value = __ BooleanConstant(true);
__ JumpIfWordEqual(to_boolean_value, true_value, relative_jump);
}
......@@ -1221,9 +1222,9 @@ void Interpreter::DoJumpIfToBooleanTrueConstant(
void Interpreter::DoJumpIfToBooleanFalse(
compiler::InterpreterAssembler* assembler) {
Node* accumulator = __ GetAccumulator();
Node* relative_jump = __ BytecodeOperandImm(0);
Node* to_boolean_value =
__ CallRuntime(Runtime::kInterpreterToBoolean, accumulator);
Node* relative_jump = __ BytecodeOperandImm(0);
Node* false_value = __ BooleanConstant(false);
__ JumpIfWordEqual(to_boolean_value, false_value, relative_jump);
}
......
......@@ -771,6 +771,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ Push(a3);
// Push zero for bytecode array offset.
__ Push(zero_reg);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
__ lw(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
......@@ -835,9 +838,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Load bytecode offset and dispatch table into registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ Subu(kInterpreterRegisterFileRegister, fp,
Operand(2 * kPointerSize +
StandardFrameConstants::kFixedFrameSizeFromFp));
__ Addu(kInterpreterRegisterFileRegister, fp,
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ li(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ LoadRoot(kInterpreterDispatchTableRegister,
......
......@@ -762,6 +762,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ Push(a3);
// Push zero for bytecode array offset.
__ Push(zero_reg);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
__ ld(a0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset));
......@@ -826,9 +829,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// Load bytecode offset and dispatch table into registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ Dsubu(kInterpreterRegisterFileRegister, fp,
Operand(2 * kPointerSize +
StandardFrameConstants::kFixedFrameSizeFromFp));
__ Daddu(kInterpreterRegisterFileRegister, fp,
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ li(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ LoadRoot(kInterpreterDispatchTableRegister,
......
......@@ -593,6 +593,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Push(rdi); // Callee's JS function.
__ Push(rdx); // Callee's new target.
// Push zero for bytecode array offset.
__ Push(Immediate(0));
// Get the bytecode array from the function object and load the pointer to the
// first entry into edi (InterpreterBytecodeRegister).
__ movp(rax, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset));
......@@ -658,9 +661,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
// registers.
__ LoadRoot(kInterpreterAccumulatorRegister, Heap::kUndefinedValueRootIndex);
__ movp(kInterpreterRegisterFileRegister, rbp);
__ subp(kInterpreterRegisterFileRegister,
Immediate(2 * kPointerSize +
StandardFrameConstants::kFixedFrameSizeFromFp));
__ addp(kInterpreterRegisterFileRegister,
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ movp(kInterpreterBytecodeOffsetRegister,
Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ LoadRoot(kInterpreterDispatchTableRegister,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment