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

[Interpreter] Pass context to interpreter bytecode handlers and add LoadConstextSlot

Passes the current context to bytecode interpreter handlers. This is held in the
context register on all architectures except for ia32 where there are too few
registers and it is instead spilled to the stack.

Also changes Load/StoreRegister to use kMachAnyTagged representation since they
should only ever hold tagged values.

BUG=v8:4280
LOG=N

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

Cr-Commit-Position: refs/heads/master@{#30325}
parent 53ac9fe8
......@@ -72,6 +72,11 @@ void InterpreterAssembler::SetAccumulator(Node* value) {
}
Node* InterpreterAssembler::ContextTaggedPointer() {
return raw_assembler_->Parameter(Linkage::kInterpreterContextParameter);
}
Node* InterpreterAssembler::RegisterFileRawPointer() {
return raw_assembler_->Parameter(Linkage::kInterpreterRegisterFileParameter);
}
......@@ -99,13 +104,13 @@ Node* InterpreterAssembler::RegisterFrameOffset(Node* index) {
Node* InterpreterAssembler::LoadRegister(Node* reg_index) {
return raw_assembler_->Load(kMachPtr, RegisterFileRawPointer(),
return raw_assembler_->Load(kMachAnyTagged, RegisterFileRawPointer(),
RegisterFrameOffset(reg_index));
}
Node* InterpreterAssembler::StoreRegister(Node* value, Node* reg_index) {
return raw_assembler_->Store(kMachPtr, RegisterFileRawPointer(),
return raw_assembler_->Store(kMachAnyTagged, RegisterFileRawPointer(),
RegisterFrameOffset(reg_index), value);
}
......@@ -152,6 +157,11 @@ Node* InterpreterAssembler::Int32Constant(int value) {
}
Node* InterpreterAssembler::IntPtrConstant(intptr_t value) {
return raw_assembler_->IntPtrConstant(value);
}
Node* InterpreterAssembler::NumberConstant(double value) {
return raw_assembler_->NumberConstant(value);
}
......@@ -177,6 +187,12 @@ Node* InterpreterAssembler::SmiUntag(Node* value) {
}
Node* InterpreterAssembler::LoadContextSlot(int slot_index) {
return raw_assembler_->Load(kMachAnyTagged, ContextTaggedPointer(),
IntPtrConstant(Context::SlotOffset(slot_index)));
}
void InterpreterAssembler::Return() {
Node* exit_trampoline_code_object =
HeapConstant(Unique<HeapObject>::CreateImmovable(
......@@ -187,10 +203,11 @@ void InterpreterAssembler::Return() {
STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
Node* tail_call = raw_assembler_->TailCallInterpreterDispatch(
call_descriptor(), exit_trampoline_code_object, GetAccumulator(),
RegisterFileRawPointer(), BytecodeOffset(), BytecodeArrayTaggedPointer(),
DispatchTableRawPointer());
DispatchTableRawPointer(), ContextTaggedPointer());
// This should always be the end node.
SetEndInput(tail_call);
}
......@@ -219,10 +236,12 @@ void InterpreterAssembler::Dispatch() {
STATIC_ASSERT(2 == Linkage::kInterpreterBytecodeOffsetParameter);
STATIC_ASSERT(3 == Linkage::kInterpreterBytecodeArrayParameter);
STATIC_ASSERT(4 == Linkage::kInterpreterDispatchTableParameter);
STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
Node* tail_call = raw_assembler_->TailCallInterpreterDispatch(
call_descriptor(), target_code_object, GetAccumulator(),
RegisterFileRawPointer(), new_bytecode_offset,
BytecodeArrayTaggedPointer(), DispatchTableRawPointer());
BytecodeArrayTaggedPointer(), DispatchTableRawPointer(),
ContextTaggedPointer());
// This should always be the end node.
SetEndInput(tail_call);
}
......
......@@ -53,6 +53,7 @@ class InterpreterAssembler {
// Constants.
Node* Int32Constant(int value);
Node* IntPtrConstant(intptr_t value);
Node* NumberConstant(double value);
Node* HeapConstant(Unique<HeapObject> object);
......@@ -60,6 +61,9 @@ class InterpreterAssembler {
Node* SmiTag(Node* value);
Node* SmiUntag(Node* value);
// Load |slot_index| from the current context.
Node* LoadContextSlot(int slot_index);
// Returns from the function.
void Return();
......@@ -81,8 +85,10 @@ class InterpreterAssembler {
Node* BytecodeArrayTaggedPointer();
// Returns the offset from the BytecodeArrayPointer of the current bytecode.
Node* BytecodeOffset();
// Returns a pointer to first entry in the interpreter dispatch table.
// Returns a raw pointer to first entry in the interpreter dispatch table.
Node* DispatchTableRawPointer();
// Returns a tagged pointer to the current context.
Node* ContextTaggedPointer();
// Returns the offset of register |index| relative to RegisterFilePointer().
Node* RegisterFrameOffset(Node* index);
......
......@@ -387,8 +387,8 @@ CallDescriptor* Linkage::GetJSCallDescriptor(Zone* zone, bool is_osr,
CallDescriptor* Linkage::GetInterpreterDispatchDescriptor(Zone* zone) {
MachineSignature::Builder types(zone, 0, 5);
LocationSignature::Builder locations(zone, 0, 5);
MachineSignature::Builder types(zone, 0, 6);
LocationSignature::Builder locations(zone, 0, 6);
// Add registers for fixed parameters passed via interpreter dispatch.
STATIC_ASSERT(0 == Linkage::kInterpreterAccumulatorParameter);
......@@ -411,6 +411,15 @@ CallDescriptor* Linkage::GetInterpreterDispatchDescriptor(Zone* zone) {
types.AddParam(kMachPtr);
locations.AddParam(regloc(kInterpreterDispatchTableRegister));
STATIC_ASSERT(5 == Linkage::kInterpreterContextParameter);
types.AddParam(kMachAnyTagged);
#if defined(V8_TARGET_ARCH_IA32)
locations.AddParam(
LinkageLocation::ForCallerFrameSlot(kInterpreterContextSpillSlot));
#else
locations.AddParam(regloc(kContextRegister));
#endif
LinkageLocation target_loc = LinkageLocation::ForAnyRegister();
return new (zone) CallDescriptor( // --
CallDescriptor::kCallCodeObject, // kind
......
......@@ -335,6 +335,7 @@ class Linkage : public ZoneObject {
static const int kInterpreterBytecodeOffsetParameter = 2;
static const int kInterpreterBytecodeArrayParameter = 3;
static const int kInterpreterDispatchTableParameter = 4;
static const int kInterpreterContextParameter = 5;
private:
CallDescriptor* const incoming_;
......
......@@ -251,10 +251,10 @@ Node* RawMachineAssembler::CallCFunction8(
Node* RawMachineAssembler::TailCallInterpreterDispatch(
const CallDescriptor* call_descriptor, Node* target, Node* arg1, Node* arg2,
Node* arg3, Node* arg4, Node* arg5) {
Node* tail_call =
graph()->NewNode(common()->TailCall(call_descriptor), target, arg1, arg2,
arg3, arg4, arg5, graph()->start(), graph()->start());
Node* arg3, Node* arg4, Node* arg5, Node* arg6) {
Node* tail_call = graph()->NewNode(common()->TailCall(call_descriptor),
target, arg1, arg2, arg3, arg4, arg5, arg6,
graph()->start(), graph()->start());
schedule()->AddTailCall(CurrentBlock(), tail_call);
return tail_call;
}
......
......@@ -510,7 +510,8 @@ class RawMachineAssembler {
Node* arg5, Node* arg6, Node* arg7);
Node* TailCallInterpreterDispatch(const CallDescriptor* call_descriptor,
Node* target, Node* arg1, Node* arg2,
Node* arg3, Node* arg4, Node* arg5);
Node* arg3, Node* arg4, Node* arg5,
Node* arg6);
// ===========================================================================
// The following utility methods deal with control flow, hence might switch
......
......@@ -725,8 +725,9 @@ void Builtins::Generate_InterpreterEntryTrampoline(MacroAssembler* masm) {
__ add(kInterpreterDispatchTableRegister,
Immediate(FixedArray::kHeaderSize - kHeapObjectTag));
// TODO(rmcilroy) Push our context as a stack located parameter of the
// bytecode handler.
// Push context as a stack located parameter to the bytecode handler.
DCHECK_EQ(-1, kInterpreterContextSpillSlot);
__ push(esi);
// Dispatch to the first bytecode handler for the function.
__ movzx_b(esi, Operand(kInterpreterBytecodeArrayRegister,
......
......@@ -26,6 +26,9 @@ const Register kInterpreterDispatchTableRegister = {kRegister_ebx_Code};
const Register kRuntimeCallFunctionRegister = {kRegister_ebx_Code};
const Register kRuntimeCallArgCountRegister = {kRegister_eax_Code};
// Spill slots used by interpreter dispatch calling convention.
const int kInterpreterContextSpillSlot = -1;
// Convenience for platform-independent signatures. We do not normally
// distinguish memory operands from other operands on ia32.
typedef Operand MemOperand;
......
......@@ -23,6 +23,12 @@ const interpreter::Bytecode kBytecodes[] = {
};
Matcher<Node*> IsIntPtrConstant(const intptr_t value) {
return kPointerSize == 8 ? IsInt64Constant(static_cast<int64_t>(value))
: IsInt32Constant(static_cast<int32_t>(value));
}
Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher)
......@@ -130,6 +136,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) {
next_bytecode_offset_matcher,
IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
IsParameter(Linkage::kInterpreterDispatchTableParameter),
IsParameter(Linkage::kInterpreterContextParameter),
graph->start(), graph->start()));
}
}
......@@ -158,6 +165,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, Return) {
IsParameter(Linkage::kInterpreterBytecodeOffsetParameter),
IsParameter(Linkage::kInterpreterBytecodeArrayParameter),
IsParameter(Linkage::kInterpreterDispatchTableParameter),
IsParameter(Linkage::kInterpreterContextParameter),
graph->start(), graph->start()));
}
}
......@@ -223,7 +231,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) {
Node* load_reg_node = m.LoadRegister(reg_index_node);
EXPECT_THAT(
load_reg_node,
m.IsLoad(kMachPtr,
m.IsLoad(kMachAnyTagged,
IsParameter(Linkage::kInterpreterRegisterFileParameter),
IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2))));
}
......@@ -238,7 +246,7 @@ TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) {
Node* store_reg_node = m.StoreRegister(store_value, reg_index_node);
EXPECT_THAT(
store_reg_node,
m.IsStore(StoreRepresentation(kMachPtr, kNoWriteBarrier),
m.IsStore(StoreRepresentation(kMachAnyTagged, kNoWriteBarrier),
IsParameter(Linkage::kInterpreterRegisterFileParameter),
IsWordShl(reg_index_node, IsInt32Constant(kPointerSizeLog2)),
store_value));
......@@ -257,6 +265,18 @@ TARGET_TEST_F(InterpreterAssemblerTest, SmiTag) {
}
}
TARGET_TEST_F(InterpreterAssemblerTest, LoadContextSlot) {
TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) {
InterpreterAssemblerForTest m(this, bytecode);
Node* load_context = m.LoadContextSlot(22);
EXPECT_THAT(load_context,
m.IsLoad(kMachAnyTagged,
IsParameter(Linkage::kInterpreterContextParameter),
IsIntPtrConstant(Context::SlotOffset(22))));
}
}
} // namespace compiler
} // namespace internal
} // namespace v8
......@@ -1766,6 +1766,48 @@ Matcher<Node*> IsTailCall(
}
Matcher<Node*> IsTailCall(
const Matcher<CallDescriptor const*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher, const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& value2_matcher, const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& value4_matcher, const Matcher<Node*>& value5_matcher,
const Matcher<Node*>& value6_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
std::vector<Matcher<Node*>> value_matchers;
value_matchers.push_back(value0_matcher);
value_matchers.push_back(value1_matcher);
value_matchers.push_back(value2_matcher);
value_matchers.push_back(value3_matcher);
value_matchers.push_back(value4_matcher);
value_matchers.push_back(value5_matcher);
value_matchers.push_back(value6_matcher);
return MakeMatcher(new IsTailCallMatcher(descriptor_matcher, value_matchers,
effect_matcher, control_matcher));
}
Matcher<Node*> IsTailCall(
const Matcher<CallDescriptor const*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher, const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& value2_matcher, const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& value4_matcher, const Matcher<Node*>& value5_matcher,
const Matcher<Node*>& value6_matcher, const Matcher<Node*>& value7_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher) {
std::vector<Matcher<Node*>> value_matchers;
value_matchers.push_back(value0_matcher);
value_matchers.push_back(value1_matcher);
value_matchers.push_back(value2_matcher);
value_matchers.push_back(value3_matcher);
value_matchers.push_back(value4_matcher);
value_matchers.push_back(value5_matcher);
value_matchers.push_back(value6_matcher);
value_matchers.push_back(value7_matcher);
return MakeMatcher(new IsTailCallMatcher(descriptor_matcher, value_matchers,
effect_matcher, control_matcher));
}
Matcher<Node*> IsReferenceEqual(const Matcher<Type*>& type_matcher,
const Matcher<Node*>& lhs_matcher,
const Matcher<Node*>& rhs_matcher) {
......
......@@ -158,6 +158,21 @@ Matcher<Node*> IsTailCall(
const Matcher<Node*>& value4_matcher, const Matcher<Node*>& value5_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsTailCall(
const Matcher<CallDescriptor const*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher, const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& value2_matcher, const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& value4_matcher, const Matcher<Node*>& value5_matcher,
const Matcher<Node*>& value6_matcher, const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsTailCall(
const Matcher<CallDescriptor const*>& descriptor_matcher,
const Matcher<Node*>& value0_matcher, const Matcher<Node*>& value1_matcher,
const Matcher<Node*>& value2_matcher, const Matcher<Node*>& value3_matcher,
const Matcher<Node*>& value4_matcher, const Matcher<Node*>& value5_matcher,
const Matcher<Node*>& value6_matcher, const Matcher<Node*>& value7_matcher,
const Matcher<Node*>& effect_matcher,
const Matcher<Node*>& control_matcher);
Matcher<Node*> IsBooleanNot(const Matcher<Node*>& value_matcher);
......
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