[Interpreter] Pass context to interpreter bytecode handlers and add LoadConstextSlot
authorrmcilroy <rmcilroy@chromium.org>
Mon, 24 Aug 2015 10:25:34 +0000 (03:25 -0700)
committerCommit bot <commit-bot@chromium.org>
Mon, 24 Aug 2015 10:25:50 +0000 (10:25 +0000)
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}

src/compiler/interpreter-assembler.cc
src/compiler/interpreter-assembler.h
src/compiler/linkage.cc
src/compiler/linkage.h
src/compiler/raw-machine-assembler.cc
src/compiler/raw-machine-assembler.h
src/ia32/builtins-ia32.cc
src/ia32/macro-assembler-ia32.h
test/unittests/compiler/interpreter-assembler-unittest.cc
test/unittests/compiler/node-test-utils.cc
test/unittests/compiler/node-test-utils.h

index 47e014ba3992b3aa2e1b1ce4b191b0f76b15930c..f981a4f6751442c2573887b82cf098c05f05939e 100644 (file)
@@ -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);
 }
index 4662fc8042519c6ce81a9d50b0489042a1c866d9..b15311bbedf02d0a6cdef9905dec05b049c90f4c 100644 (file)
@@ -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);
index 2bbedaceb26b075b7ddc60b8c65081e4be29bce5..1b342ee472a6aff7a5aaf44eea8be3b1a4f8001f 100644 (file)
@@ -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
index f5507a0594ea56fdfe2c3dd37300f4857e234cbb..57203627887647cbaa1736d45292054d121adbbe 100644 (file)
@@ -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_;
index f437922fa6aa3363b1b908d2ada508624c5ae002..81faa7d840b82d963ffb93f05a84bdd024c46bd3 100644 (file)
@@ -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;
 }
index 05f4ebab026de5f815a273519e8c4681185ca67a..b76a2589e03ceeda22ae9da2b986b256754938be 100644 (file)
@@ -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
index 15f3ace14ec28edffe5ab5a09f0ddb26bff301dc..392ed430e8a8a3ef5a65510fb96789cc7c530fcf 100644 (file)
@@ -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,
index b228ef9a2850e272487fbe4355941dbf4c769d57..82d5003032e57c94c360fa33466be9efedb17bf5 100644 (file)
@@ -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;
index a869f7ebb1121450022f63395029c5567b55bbce..bc5be263fff4d615741e78189144a08f6ce975e5 100644 (file)
@@ -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
index d097ee4b66ac170f47e759f0ad7a3410a4df67a2..4112e224a4b0fa56195196e2a7291cc745d8aea0 100644 (file)
@@ -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) {
index 149dcfc43924e0511b99db475ffac7771128646e..0c6f3ab837803f011dc2c5bfb574c12b36041d2d 100644 (file)
@@ -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);