[Interpreter] No longer require context machine register in bytecode handlers

The current context is stored as a stack slot on the interpreter frame
and therefore we don't need to also maintain a machine register for the
context. Removes this register from bytecode handlers.

In the process modifies this frees up a register on ia32 to keep the
dispatch table pointer in a register rather than on a stack slot on
ia32.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#35511}
This commit is contained in:
rmcilroy 2016-04-15 02:33:21 -07:00 committed by Commit bot
parent 0e8d220e8b
commit 6dca319395
18 changed files with 53 additions and 125 deletions

View File

@ -1139,11 +1139,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the context from the frame.
__ ldr(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ ldr(
kInterpreterBytecodeArrayRegister,

View File

@ -1088,11 +1088,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the context from the frame.
__ Ldr(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ Ldr(
kInterpreterBytecodeArrayRegister,

View File

@ -409,12 +409,9 @@ CallDescriptor* Linkage::GetBytecodeDispatchCallDescriptor(
int stack_parameter_count) {
const int register_parameter_count = descriptor.GetRegisterParameterCount();
const int parameter_count = register_parameter_count + stack_parameter_count;
const int context_count = 1;
const size_t parameter_and_context_count =
static_cast<size_t>(parameter_count + context_count);
LocationSignature::Builder locations(zone, 0, parameter_and_context_count);
MachineSignature::Builder types(zone, 0, parameter_and_context_count);
LocationSignature::Builder locations(zone, 0, parameter_count);
MachineSignature::Builder types(zone, 0, parameter_count);
// Add parameters in registers and on the stack.
for (int i = 0; i < parameter_count; i++) {
@ -432,9 +429,6 @@ CallDescriptor* Linkage::GetBytecodeDispatchCallDescriptor(
types.AddParam(MachineType::AnyTagged());
}
}
// Add context.
locations.AddParam(regloc(kContextRegister));
types.AddParam(MachineType::AnyTagged());
// The target for interpreter dispatches is a code entry address.
MachineType target_type = MachineType::Pointer();

View File

@ -308,7 +308,7 @@ std::ostream& operator<<(std::ostream& os, const CallDescriptor::Kind& k);
// Call[CodeStub] code, arg 1, arg 2, [...], context
// Call[JSFunction] function, rcvr, arg 1, [...], new, #arg, context
// Call[Runtime] CEntryStub, arg 1, arg 2, [...], fun, #arg, context
// Call[BytecodeDispatch] address, arg 1, arg 2, [...], context
// Call[BytecodeDispatch] address, arg 1, arg 2, [...]
class Linkage : public ZoneObject {
public:
explicit Linkage(CallDescriptor* incoming) : incoming_(incoming) {}

View File

@ -597,21 +597,15 @@ 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())));
// Push dispatch table as a stack located parameter to the bytecode handler.
DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
__ push(ebx);
__ mov(kInterpreterDispatchTableRegister,
Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Dispatch to the first bytecode handler for the function.
__ movzx_b(eax, Operand(kInterpreterBytecodeArrayRegister,
__ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister, times_1, 0));
__ mov(ebx, Operand(ebx, eax, times_pointer_size, 0));
// Restore undefined_value in accumulator (eax)
// TODO(rmcilroy): Remove this once we move the dispatch table back into a
// register.
__ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
__ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
times_pointer_size, 0));
__ call(ebx);
// Even though the first bytecode handler was called, we will never return.
@ -737,10 +731,13 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize register file register.
// Initialize register file register and dispatch table register.
__ mov(kInterpreterRegisterFileRegister, ebp);
__ add(kInterpreterRegisterFileRegister,
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterDispatchTableRegister,
Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the bytecode array pointer from the frame.
__ mov(kInterpreterBytecodeArrayRegister,
@ -762,23 +759,11 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
__ SmiUntag(kInterpreterBytecodeOffsetRegister);
// Push dispatch table as a stack located parameter to the bytecode handler.
__ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
__ Pop(esi);
__ Push(ebx);
__ Push(esi);
// Dispatch to the target bytecode.
__ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
__ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister, times_1, 0));
__ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
// Get the context from the frame.
__ mov(kContextRegister,
Operand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
__ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
times_pointer_size, 0));
__ jmp(ebx);
}

View File

@ -383,7 +383,8 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister };
kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -23,14 +23,12 @@ const Register kInterpreterAccumulatorRegister = {Register::kCode_eax};
const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
const Register kInterpreterDispatchTableRegister = {Register::kCode_esi};
const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_edx};
const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};
const Register kRuntimeCallArgCountRegister = {Register::kCode_eax};
// Spill slots used by interpreter dispatch calling convention.
const int kInterpreterDispatchTableSpillSlot = -1;
// Convenience for platform-independent signatures. We do not normally
// distinguish memory operands from other operands on ia32.
typedef Operand MemOperand;

View File

@ -33,13 +33,11 @@ InterpreterAssembler::InterpreterAssembler(Isolate* isolate, Zone* zone,
operand_scale_(operand_scale),
accumulator_(this, MachineRepresentation::kTagged),
accumulator_use_(AccumulatorUse::kNone),
context_(this, MachineRepresentation::kTagged),
bytecode_array_(this, MachineRepresentation::kTagged),
disable_stack_check_across_call_(false),
stack_pointer_before_call_(nullptr) {
accumulator_.Bind(
Parameter(InterpreterDispatchDescriptor::kAccumulatorParameter));
context_.Bind(Parameter(InterpreterDispatchDescriptor::kContextParameter));
bytecode_array_.Bind(
Parameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter));
if (FLAG_trace_ignition) {
@ -70,11 +68,12 @@ void InterpreterAssembler::SetAccumulator(Node* value) {
accumulator_.Bind(value);
}
Node* InterpreterAssembler::GetContext() { return context_.value(); }
Node* InterpreterAssembler::GetContext() {
return LoadRegister(Register::current_context());
}
void InterpreterAssembler::SetContext(Node* value) {
StoreRegister(value, Register::current_context());
context_.Bind(value);
}
Node* InterpreterAssembler::BytecodeOffset() {
@ -103,7 +102,7 @@ Node* InterpreterAssembler::LoadRegister(int offset) {
}
Node* InterpreterAssembler::LoadRegister(Register reg) {
return LoadRegister(IntPtrConstant(-reg.index()));
return LoadRegister(-reg.index() << kPointerSizeLog2);
}
Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
@ -581,8 +580,8 @@ void InterpreterAssembler::DispatchToBytecodeHandlerEntry(
InterpreterDispatchDescriptor descriptor(isolate());
Node* args[] = {GetAccumulatorUnchecked(), RegisterFileRawPointer(),
bytecode_offset, BytecodeArrayTaggedPointer(),
DispatchTableRawPointer(), GetContext()};
bytecode_offset, BytecodeArrayTaggedPointer(),
DispatchTableRawPointer()};
TailCallBytecodeDispatch(descriptor, handler_entry, args);
}

View File

@ -233,7 +233,6 @@ class InterpreterAssembler : public compiler::CodeStubAssembler {
OperandScale operand_scale_;
CodeStubAssembler::Variable accumulator_;
AccumulatorUse accumulator_use_;
CodeStubAssembler::Variable context_;
CodeStubAssembler::Variable bytecode_array_;
bool disable_stack_check_across_call_;

View File

@ -1135,11 +1135,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the context from the frame.
__ lw(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ lw(
kInterpreterBytecodeArrayRegister,

View File

@ -1124,11 +1124,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the context from the frame.
__ ld(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ ld(
kInterpreterBytecodeArrayRegister,

View File

@ -1150,11 +1150,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the context from the frame.
__ LoadP(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ LoadP(
kInterpreterBytecodeArrayRegister,

View File

@ -1141,11 +1141,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
Operand(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the context from the frame.
__ LoadP(kContextRegister,
MemOperand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ LoadP(
kInterpreterBytecodeArrayRegister,

View File

@ -812,11 +812,6 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
kInterpreterDispatchTableRegister,
ExternalReference::interpreter_dispatch_table_address(masm->isolate()));
// Get the context from the frame.
__ movp(kContextRegister,
Operand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
// Get the bytecode array pointer from the frame.
__ movp(
kInterpreterBytecodeArrayRegister,

View File

@ -600,21 +600,15 @@ 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())));
// Push dispatch table as a stack located parameter to the bytecode handler.
DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
__ push(ebx);
__ mov(kInterpreterDispatchTableRegister,
Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Dispatch to the first bytecode handler for the function.
__ movzx_b(eax, Operand(kInterpreterBytecodeArrayRegister,
__ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister, times_1, 0));
__ mov(ebx, Operand(ebx, eax, times_pointer_size, 0));
// Restore undefined_value in accumulator (eax)
// TODO(rmcilroy): Remove this once we move the dispatch table back into a
// register.
__ mov(eax, Immediate(masm->isolate()->factory()->undefined_value()));
__ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
times_pointer_size, 0));
// TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
// and header removal.
__ add(ebx, Immediate(Code::kHeaderSize - kHeapObjectTag));
@ -743,10 +737,13 @@ void Builtins::Generate_InterpreterPushArgsAndConstruct(MacroAssembler* masm) {
static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
// Initialize register file register.
// Initialize register file register and dispatch table register.
__ mov(kInterpreterRegisterFileRegister, ebp);
__ add(kInterpreterRegisterFileRegister,
Immediate(InterpreterFrameConstants::kRegisterFilePointerFromFp));
__ mov(kInterpreterDispatchTableRegister,
Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
// Get the bytecode array pointer from the frame.
__ mov(kInterpreterBytecodeArrayRegister,
@ -768,23 +765,11 @@ static void Generate_EnterBytecodeDispatch(MacroAssembler* masm) {
InterpreterFrameConstants::kBytecodeOffsetFromRegisterPointer));
__ SmiUntag(kInterpreterBytecodeOffsetRegister);
// Push dispatch table as a stack located parameter to the bytecode handler.
__ mov(ebx, Immediate(ExternalReference::interpreter_dispatch_table_address(
masm->isolate())));
DCHECK_EQ(-1, kInterpreterDispatchTableSpillSlot);
__ Pop(esi);
__ Push(ebx);
__ Push(esi);
// Dispatch to the target bytecode.
__ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
__ movzx_b(ebx, Operand(kInterpreterBytecodeArrayRegister,
kInterpreterBytecodeOffsetRegister, times_1, 0));
__ mov(ebx, Operand(ebx, esi, times_pointer_size, 0));
// Get the context from the frame.
__ mov(kContextRegister,
Operand(kInterpreterRegisterFileRegister,
InterpreterFrameConstants::kContextFromRegisterPointer));
__ mov(ebx, Operand(kInterpreterDispatchTableRegister, ebx,
times_pointer_size, 0));
// TODO(rmcilroy): Make dispatch table point to code entrys to avoid untagging
// and header removal.

View File

@ -381,7 +381,8 @@ void InterpreterDispatchDescriptor::InitializePlatformSpecific(
CallInterfaceDescriptorData* data) {
Register registers[] = {
kInterpreterAccumulatorRegister, kInterpreterRegisterFileRegister,
kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister};
kInterpreterBytecodeOffsetRegister, kInterpreterBytecodeArrayRegister,
kInterpreterDispatchTableRegister};
data->InitializePlatformSpecific(arraysize(registers), registers);
}

View File

@ -23,6 +23,7 @@ const Register kInterpreterAccumulatorRegister = {Register::kCode_eax};
const Register kInterpreterRegisterFileRegister = {Register::kCode_edx};
const Register kInterpreterBytecodeOffsetRegister = {Register::kCode_ecx};
const Register kInterpreterBytecodeArrayRegister = {Register::kCode_edi};
const Register kInterpreterDispatchTableRegister = {Register::kCode_esi};
const Register kJavaScriptCallArgCountRegister = {Register::kCode_eax};
const Register kJavaScriptCallNewTargetRegister = {Register::kCode_edx};
const Register kRuntimeCallFunctionRegister = {Register::kCode_ebx};

View File

@ -346,8 +346,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
next_bytecode_offset_matcher,
IsParameter(InterpreterDispatchDescriptor::kBytecodeArrayParameter),
IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
_));
_, _));
}
}
@ -390,8 +389,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, Jump) {
next_bytecode_offset_matcher, _,
IsParameter(
InterpreterDispatchDescriptor::kDispatchTableParameter),
IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
_));
_, _));
}
}
}
@ -441,8 +439,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, JumpIfWordEqual) {
next_bytecode_offset_matcher, _,
IsParameter(
InterpreterDispatchDescriptor::kDispatchTableParameter),
IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
_));
_, _));
}
// TODO(oth): test control flow paths.
@ -477,8 +474,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, InterpreterReturn) {
InterpreterDispatchDescriptor::kBytecodeOffsetParameter),
_,
IsParameter(InterpreterDispatchDescriptor::kDispatchTableParameter),
IsParameter(InterpreterDispatchDescriptor::kContextParameter), _,
_));
_, _));
}
}
@ -570,12 +566,16 @@ TARGET_TEST_F(InterpreterAssemblerTest, GetSetAccumulator) {
}
}
TARGET_TEST_F(InterpreterAssemblerTest, GetSetContext) {
TARGET_TEST_F(InterpreterAssemblerTest, GetContext) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* context_node = m.Int32Constant(100);
m.SetContext(context_node);
EXPECT_THAT(m.GetContext(), context_node);
EXPECT_THAT(
m.GetContext(),
m.IsLoad(
MachineType::AnyTagged(),
IsParameter(InterpreterDispatchDescriptor::kRegisterFileParameter),
IsIntPtrConstant(-Register::current_context().index()
<< kPointerSizeLog2)));
}
}