Commit a2935d63 authored by rmcilroy's avatar rmcilroy Committed by Commit bot

[Interpreter] Save and restore dispatch table pointer during calls.

Saves and restores the dispatch pointer during calls to enable the debugger to
switch the dispatch table used by a function during it's execution.

Also moves the accumulator and context nodes to be Variables so that they will
be properly merged across branches.

BUG=v8:4280,v8:4690
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#33894}
parent e3555421
......@@ -988,11 +988,12 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ PushFixedFrame(r1);
__ add(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ push(r3);
// Push zero for bytecode array offset.
// Push new.target, dispatch table pointer and zero for bytecode array offset.
__ mov(r0, Operand(0));
__ push(r0);
__ mov(r2, Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ Push(r3, r2, r0);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
......@@ -1051,9 +1052,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ mov(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ ldr(kInterpreterDispatchTableRegister,
MemOperand(fp, InterpreterFrameConstants::kDispatchTableFromFp));
// Dispatch to the first bytecode handler for the function.
__ ldrb(r1, MemOperand(kInterpreterBytecodeArrayRegister,
......
......@@ -996,11 +996,12 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
FrameScope frame_scope(masm, StackFrame::MANUAL);
__ Push(lr, fp, cp, x1);
__ Add(fp, jssp, StandardFrameConstants::kFixedFrameSizeFromFp);
__ Push(x3);
// Push zero for bytecode array offset.
// Push dispatch table pointer.
__ Mov(x0, Operand(0));
__ Push(x0);
__ Mov(x2, Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ Push(x3, x2, x0);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
......@@ -1057,9 +1058,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ Mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ Mov(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ Ldr(kInterpreterDispatchTableRegister,
MemOperand(fp, InterpreterFrameConstants::kDispatchTableFromFp));
// Dispatch to the first bytecode handler for the function.
__ Ldrb(x1, MemOperand(kInterpreterBytecodeArrayRegister,
......
......@@ -11,6 +11,7 @@
#include "src/frames-inl.h"
#include "src/full-codegen/full-codegen.h"
#include "src/global-handles.h"
#include "src/interpreter/interpreter.h"
#include "src/macro-assembler.h"
#include "src/profiler/cpu-profiler.h"
#include "src/v8.h"
......@@ -1183,13 +1184,21 @@ void Deoptimizer::DoComputeInterpretedFrame(int frame_index) {
DCHECK(!is_bottommost || input_->GetFrameSlot(input_offset) == value);
WriteValueToOutput(function, 0, frame_index, output_offset, "function ");
// TODO(rmcilroy): Deal with new.target correctly - currently just set it to
// The new.target slot is only used during function activiation which is
// before the first deopt point, so should never be needed. Just set it to
// undefined.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
Object* new_target = isolate_->heap()->undefined_value();
WriteValueToOutput(new_target, 0, frame_index, output_offset, "new_target ");
// Set the dispatch table pointer.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
Address dispatch_table = isolate()->interpreter()->dispatch_table_address();
WriteValueToOutput(reinterpret_cast<Object*>(dispatch_table), 0, frame_index,
output_offset, "dispatch_table ");
// The bytecode offset was mentioned explicitly in the BEGIN_FRAME.
output_offset -= kPointerSize;
input_offset -= kPointerSize;
......
......@@ -1136,7 +1136,6 @@ int InterpretedFrame::LookupExceptionHandlerInTable(
return table->LookupRange(pc_offset, context_register, prediction);
}
int InterpretedFrame::GetBytecodeOffset() const {
const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp,
......@@ -1145,7 +1144,6 @@ int InterpretedFrame::GetBytecodeOffset() const {
return raw_offset - BytecodeArray::kHeaderSize + kHeapObjectTag;
}
void InterpretedFrame::PatchBytecodeOffset(int new_offset) {
const int index = InterpreterFrameConstants::kBytecodeOffsetExpressionIndex;
DCHECK_EQ(InterpreterFrameConstants::kBytecodeOffsetFromFp,
......@@ -1161,6 +1159,17 @@ Object* InterpretedFrame::GetInterpreterRegister(int register_index) const {
return GetExpression(index + register_index);
}
Address InterpretedFrame::GetDispatchTable() const {
return Memory::Address_at(
fp() + InterpreterFrameConstants::kDispatchTableFromFp);
}
void InterpretedFrame::PatchDispatchTable(Address dispatch_table) {
Address* dispatch_table_address = reinterpret_cast<Address*>(
fp() + InterpreterFrameConstants::kDispatchTableFromFp);
*dispatch_table_address = dispatch_table;
}
void InterpretedFrame::Summarize(List<FrameSummary>* functions) {
DCHECK(functions->length() == 0);
AbstractCode* abstract_code =
......@@ -1412,6 +1421,22 @@ void JavaScriptFrame::Iterate(ObjectVisitor* v) const {
IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
}
void InterpretedFrame::Iterate(ObjectVisitor* v) const {
// Visit tagged pointers in the fixed frame.
Object** fixed_frame_base =
&Memory::Object_at(fp() + InterpreterFrameConstants::kNewTargetFromFp);
Object** fixed_frame_limit =
&Memory::Object_at(fp() + StandardFrameConstants::kLastObjectOffset) + 1;
v->VisitPointers(fixed_frame_base, fixed_frame_limit);
// Visit the expressions.
Object** expression_base = &Memory::Object_at(sp());
Object** expression_limit = &Memory::Object_at(
fp() + InterpreterFrameConstants::kBytecodeOffsetFromFp) + 1;
v->VisitPointers(expression_base, expression_limit);
IteratePc(v, pc_address(), constant_pool_address(), LookupCode());
}
void InternalFrame::Iterate(ObjectVisitor* v) const {
// Internal frames only have object pointers on the expression stack
......
......@@ -178,28 +178,33 @@ class InterpreterFrameConstants : public AllStatic {
public:
// Fixed frame includes new.target and bytecode offset.
static const int kFixedFrameSize =
StandardFrameConstants::kFixedFrameSize + 2 * kPointerSize;
StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
static const int kFixedFrameSizeFromFp =
StandardFrameConstants::kFixedFrameSizeFromFp + 2 * kPointerSize;
StandardFrameConstants::kFixedFrameSizeFromFp + 3 * kPointerSize;
// FP-relative.
static const int kBytecodeOffsetFromFp =
static const int kNewTargetFromFp =
-StandardFrameConstants::kFixedFrameSizeFromFp - 1 * kPointerSize;
static const int kDispatchTableFromFp =
-StandardFrameConstants::kFixedFrameSizeFromFp - 2 * kPointerSize;
static const int kRegisterFilePointerFromFp =
static const int kBytecodeOffsetFromFp =
-StandardFrameConstants::kFixedFrameSizeFromFp - 3 * kPointerSize;
static const int kRegisterFilePointerFromFp =
-StandardFrameConstants::kFixedFrameSizeFromFp - 4 * kPointerSize;
// Expression index for {StandardFrame::GetExpressionAddress}.
static const int kBytecodeOffsetExpressionIndex = 1;
static const int kRegisterFileExpressionIndex = 2;
static const int kBytecodeOffsetExpressionIndex = 2;
static const int kRegisterFileExpressionIndex = 3;
// Register file pointer relative.
static const int kLastParamFromRegisterPointer =
StandardFrameConstants::kFixedFrameSize + 3 * kPointerSize;
StandardFrameConstants::kFixedFrameSize + 4 * 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;
static const int kDispatchTableFromRegisterPointer = 2 * kPointerSize;
static const int kNewTargetFromRegisterPointer = 3 * kPointerSize;
static const int kFunctionFromRegisterPointer = 4 * kPointerSize;
static const int kContextFromRegisterPointer = 5 * kPointerSize;
};
......@@ -723,6 +728,9 @@ class InterpretedFrame : public JavaScriptFrame {
public:
Type type() const override { return INTERPRETED; }
// GC support.
void Iterate(ObjectVisitor* v) const override;
// Lookup exception handler for current {pc}, returns -1 if none found.
int LookupExceptionHandlerInTable(
int* data, HandlerTable::CatchPrediction* prediction) override;
......@@ -734,6 +742,13 @@ class InterpretedFrame : public JavaScriptFrame {
// unwinding to continue execution at a different bytecode offset.
void PatchBytecodeOffset(int new_offset);
// Returns the current dispatch table pointer.
Address GetDispatchTable() const;
// Updates the current dispatch table pointer with |dispatch_table|. Used by
// the debugger to swap execution onto the debugger dispatch table.
void PatchDispatchTable(Address dispatch_table);
// Access to the interpreter register file for this frame.
Object* GetInterpreterRegister(int register_index) const;
......
......@@ -546,6 +546,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ push(edi); // Callee's JS function.
__ push(edx); // Callee's new target.
// Push dispatch table pointer.
__ mov(eax, Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ push(eax);
// Push zero for bytecode array offset.
__ push(Immediate(0));
......@@ -608,8 +612,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterBytecodeOffsetRegister,
Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ mov(ebx, Operand(ebp, InterpreterFrameConstants::kDispatchTableFromFp));
// Push dispatch table as a stack located parameter to the bytecode handler.
DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
......
......@@ -26,11 +26,16 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
isolate, zone, InterpreterDispatchDescriptor(isolate),
Code::ComputeFlags(Code::STUB), Bytecodes::ToString(bytecode), 0),
bytecode_(bytecode),
accumulator_(
Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter)),
context_(Parameter(InterpreterDispatchDescriptor::kContextParameter)),
accumulator_(this, MachineRepresentation::kTagged),
context_(this, MachineRepresentation::kTagged),
dispatch_table_(this, MachineType::PointerRepresentation()),
disable_stack_check_across_call_(false),
stack_pointer_before_call_(nullptr) {
accumulator_.Bind(
Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
context_.Bind(Parameter(InterpreterDispatchDescriptor::kContextParameter));
dispatch_table_.Bind(
Parameter(InterpreterDispatchDescriptor::kDispatchTableParameter));
if (FLAG_trace_ignition) {
TraceBytecode(Runtime::kInterpreterTraceBytecodeEntry);
}
......@@ -38,15 +43,17 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
InterpreterAssembler::~InterpreterAssembler() {}
Node* InterpreterAssembler::GetAccumulator() { return accumulator_; }
Node* InterpreterAssembler::GetAccumulator() { return accumulator_.value(); }
void InterpreterAssembler::SetAccumulator(Node* value) { accumulator_ = value; }
void InterpreterAssembler::SetAccumulator(Node* value) {
accumulator_.Bind(value);
}
Node* InterpreterAssembler::GetContext() { return context_; }
Node* InterpreterAssembler::GetContext() { return context_.value(); }
void InterpreterAssembler::SetContext(Node* value) {
StoreRegister(value, Register::current_context());
context_ = value;
context_.Bind(value);
}
Node* InterpreterAssembler::BytecodeOffset() {
......@@ -62,7 +69,7 @@ Node* InterpreterAssembler::BytecodeArrayTaggedPointer() {
}
Node* InterpreterAssembler::DispatchTableRawPointer() {
return Parameter(InterpreterDispatchDescriptor::kDispatchTableParameter);
return dispatch_table_.value();
}
Node* InterpreterAssembler::RegisterLocation(Node* reg_index) {
......@@ -303,6 +310,8 @@ Node* InterpreterAssembler::LoadTypeFeedbackVector() {
void InterpreterAssembler::CallPrologue() {
StoreRegister(SmiTag(BytecodeOffset()),
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer);
StoreRegister(DispatchTableRawPointer(),
InterpreterFrameConstants::kDispatchTableFromRegisterPointer);
if (FLAG_debug_code && !disable_stack_check_across_call_) {
DCHECK(stack_pointer_before_call_ == nullptr);
......@@ -318,6 +327,11 @@ void InterpreterAssembler::CallEpilogue() {
AbortIfWordNotEqual(stack_pointer_before_call, stack_pointer_after_call,
kUnexpectedStackPointer);
}
// Restore dispatch table from stack frame in case the debugger has swapped us
// to the debugger dispatch table.
dispatch_table_.Bind(LoadRegister(
InterpreterFrameConstants::kDispatchTableFromRegisterPointer));
}
Node* InterpreterAssembler::CallJS(Node* function, Node* context,
......
......@@ -176,8 +176,9 @@ class InterpreterAssembler : public compiler::CodeStubAssembler {
BailoutReason bailout_reason);
Bytecode bytecode_;
compiler::Node* accumulator_;
compiler::Node* context_;
CodeStubAssembler::Variable accumulator_;
CodeStubAssembler::Variable context_;
CodeStubAssembler::Variable dispatch_table_;
bool disable_stack_check_across_call_;
compiler::Node* stack_pointer_before_call_;
......
......@@ -974,10 +974,11 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Push(ra, fp, cp, a1);
__ Addu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ Push(a3);
// Push zero for bytecode array offset.
__ Push(zero_reg);
// Push new.target, dispatch table pointer and zero for bytecode array offset.
__ li(a0, Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ Push(a3, a0, zero_reg);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
......@@ -1035,9 +1036,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ li(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ li(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ lw(kInterpreterDispatchTableRegister,
MemOperand(fp, InterpreterFrameConstants::kDispatchTableFromFp));
// Dispatch to the first bytecode handler for the function.
__ Addu(a0, kInterpreterBytecodeArrayRegister,
......
......@@ -966,10 +966,11 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Push(ra, fp, cp, a1);
__ Daddu(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ Push(a3);
// Push zero for bytecode array offset.
__ Push(zero_reg);
// Push new.target, dispatch table pointer and zero for bytecode array offset.
__ li(a0, Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ Push(a3, a0, zero_reg);
// Get the bytecode array from the function object and load the pointer to the
// first entry into kInterpreterBytecodeRegister.
......@@ -1027,9 +1028,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ li(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ li(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ lw(kInterpreterDispatchTableRegister,
MemOperand(fp, InterpreterFrameConstants::kDispatchTableFromFp));
// Dispatch to the first bytecode handler for the function.
__ Daddu(a0, kInterpreterBytecodeArrayRegister,
......
......@@ -979,6 +979,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ addi(fp, sp, Operand(StandardFrameConstants::kFixedFrameSizeFromFp));
__ push(r6);
// Push dispatch table pointer.
__ mov(r3, Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ push(r3);
// Push zero for bytecode array offset.
__ li(r3, Operand::Zero());
__ push(r3);
......@@ -1039,9 +1043,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Operand(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterBytecodeOffsetRegister,
Operand(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ mov(kInterpreterDispatchTableRegister,
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ lwz(kInterpreterDispatchTableRegister,
MemOperand(fp, InterpreterFrameConstants::kDispatchTableFromFp));
// Dispatch to the first bytecode handler for the function.
__ lbzx(r4, MemOperand(kInterpreterBytecodeArrayRegister,
......
......@@ -620,6 +620,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ Push(rdi); // Callee's JS function.
__ Push(rdx); // Callee's new target.
// Push dispatch table pointer.
__ Move(rax, ExternalReference::interpreter_dispatch_table_address(
masm->isolate()));
__ Push(rax);
// Push zero for bytecode array offset.
__ Push(Immediate(0));
......@@ -680,9 +684,8 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ movp(kInterpreterBytecodeOffsetRegister,
Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ Move(
kInterpreterDispatchTableRegister,
ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
__ movp(kInterpreterDispatchTableRegister,
Operand(rbp, InterpreterFrameConstants::kDispatchTableFromFp));
// Dispatch to the first bytecode handler for the function.
__ movzxbp(rbx, Operand(kInterpreterBytecodeArrayRegister,
......
......@@ -546,6 +546,10 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ push(edi); // Callee's JS function.
__ push(edx); // Callee's new target.
// Push dispatch table pointer.
__ mov(eax, Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ push(eax);
// Push zero for bytecode array offset.
__ push(Immediate(0));
......@@ -608,8 +612,7 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterBytecodeOffsetRegister,
Immediate(BytecodeArray::kHeaderSize - kHeapObjectTag));
__ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
__ mov(ebx, Operand(ebp, InterpreterFrameConstants::kDispatchTableFromFp));
// Push dispatch table as a stack located parameter to the bytecode handler.
DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
......
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