Index: test/unittests/compiler/interpreter-assembler-unittest.cc |
diff --git a/test/unittests/compiler/interpreter-assembler-unittest.cc b/test/unittests/compiler/interpreter-assembler-unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..dcde9a9cb5cefe36f14978d5f52d013487801ac1 |
--- /dev/null |
+++ b/test/unittests/compiler/interpreter-assembler-unittest.cc |
@@ -0,0 +1,176 @@ |
+// Copyright 2015 the V8 project authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "test/unittests/compiler/interpreter-assembler-unittest.h" |
+ |
+#include "src/compiler/graph.h" |
+#include "src/compiler/node.h" |
+#include "test/unittests/compiler/compiler-test-utils.h" |
+#include "test/unittests/compiler/node-test-utils.h" |
+ |
+namespace v8 { |
+namespace internal { |
+namespace compiler { |
+ |
+const interpreter::Bytecode kBytecodes[] = { |
+#define DEFINE_BYTECODE(Name, _) interpreter::Bytecode::k##Name, |
+ BYTECODE_LIST(DEFINE_BYTECODE) |
+#undef DEFINE_BYTECODE |
+}; |
+ |
+ |
+Graph* |
+InterpreterAssemblerTest::InterpreterAssemblerForTest::GetCompletedGraph() { |
+ End(); |
+ return graph(); |
+} |
+ |
+ |
+Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsLoad( |
+ const Matcher<LoadRepresentation>& rep_matcher, |
+ const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher) { |
+ return ::i::compiler::IsLoad(rep_matcher, base_matcher, index_matcher, |
+ graph()->start(), graph()->start()); |
+} |
+ |
+ |
+Matcher<Node*> InterpreterAssemblerTest::InterpreterAssemblerForTest::IsStore( |
+ const Matcher<StoreRepresentation>& rep_matcher, |
+ const Matcher<Node*>& base_matcher, const Matcher<Node*>& index_matcher, |
+ const Matcher<Node*>& value_matcher) { |
+ return ::i::compiler::IsStore(rep_matcher, base_matcher, index_matcher, |
+ value_matcher, graph()->start(), |
+ graph()->start()); |
+} |
+ |
+ |
+Matcher<Node*> IsIntPtrAdd(const Matcher<Node*>& lhs_matcher, |
+ const Matcher<Node*>& rhs_matcher) { |
+ return kPointerSize == 8 ? IsInt64Add(lhs_matcher, rhs_matcher) |
+ : IsInt32Add(lhs_matcher, rhs_matcher); |
+} |
+ |
+ |
+Matcher<Node*> IsIntPtrConstant(intptr_t value) { |
+#ifdef V8_TARGET_ARCH_64_BIT |
+ return IsInt64Constant(value); |
+#else |
+ return IsInt32Constant(value); |
+#endif |
+} |
+ |
+ |
+TARGET_TEST_F(InterpreterAssemblerTest, Dispatch) { |
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
+ InterpreterAssemblerForTest m(this, bytecode); |
+ m.Dispatch(); |
+ Graph* graph = m.GetCompletedGraph(); |
+ |
+ Node* end = graph->end(); |
+ EXPECT_EQ(1, end->InputCount()); |
+ Node* tail_call_node = end->InputAt(0); |
+ |
+ Matcher<Node*> next_bytecode_matcher = |
+ IsIntPtrAdd(IsParameter(Linkage::kInterpreterBytecodeParameter), |
+ IsInt32Constant(interpreter::Bytecodes::Size(bytecode))); |
+ Matcher<Node*> target_bytecode_matcher = |
+ m.IsLoad(kMachUint8, next_bytecode_matcher, IsIntPtrConstant(0)); |
+ Matcher<Node*> code_target_matcher = m.IsLoad( |
+ kMachPtr, IsParameter(Linkage::kInterpreterDispatchTableParameter), |
+ IsWord32Shl(target_bytecode_matcher, |
+ IsInt32Constant(kPointerSizeLog2))); |
+ |
+ EXPECT_EQ(CallDescriptor::kInterpreterDispatch, |
+ m.call_descriptor()->kind()); |
+ EXPECT_THAT( |
+ tail_call_node, |
+ IsTailCall(m.call_descriptor(), code_target_matcher, |
+ next_bytecode_matcher, |
+ IsParameter(Linkage::kInterpreterDispatchTableParameter), |
+ graph->start(), graph->start())); |
+ } |
+} |
+ |
+ |
+TARGET_TEST_F(InterpreterAssemblerTest, BytecodeArg) { |
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
+ InterpreterAssemblerForTest m(this, bytecode); |
+ int number_of_args = interpreter::Bytecodes::NumberOfArguments(bytecode); |
+ for (int i = 0; i < number_of_args; i++) { |
+ Node* load_arg_node = m.BytecodeArg(i); |
+ EXPECT_THAT(load_arg_node, |
+ m.IsLoad(kMachUint8, |
+ IsParameter(Linkage::kInterpreterBytecodeParameter), |
+ IsInt32Constant(1 + i))); |
+ } |
+ } |
+} |
+ |
+ |
+TARGET_TEST_F(InterpreterAssemblerTest, LoadRegisterFixed) { |
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
+ InterpreterAssemblerForTest m(this, bytecode); |
+ for (int i = 0; i < m.kMaxRegisterIndex; i++) { |
+ Node* load_reg_node = m.LoadRegister(i); |
+ EXPECT_THAT(load_reg_node, |
+ m.IsLoad(kMachPtr, IsLoadFramePointer(), |
+ IsInt32Constant(m.kFirstRegisterOffsetFromFp - |
+ (i << kPointerSizeLog2)))); |
+ } |
+ } |
+} |
+ |
+ |
+TARGET_TEST_F(InterpreterAssemblerTest, LoadRegister) { |
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
+ InterpreterAssemblerForTest m(this, bytecode); |
+ Node* reg_index_node = m.Int32Constant(44); |
+ Node* load_reg_node = m.LoadRegister(reg_index_node); |
+ EXPECT_THAT( |
+ load_reg_node, |
+ m.IsLoad(kMachPtr, IsLoadFramePointer(), |
+ IsInt32Sub(IsInt32Constant(m.kFirstRegisterOffsetFromFp), |
+ IsWord32Shl(reg_index_node, |
+ IsInt32Constant(kPointerSizeLog2))))); |
+ } |
+} |
+ |
+ |
+TARGET_TEST_F(InterpreterAssemblerTest, StoreRegisterFixed) { |
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
+ InterpreterAssemblerForTest m(this, bytecode); |
+ Node* store_value = m.Int32Constant(0xdeadbeef); |
+ for (int i = 0; i < m.kMaxRegisterIndex; i++) { |
+ Node* store_reg_node = m.StoreRegister(store_value, i); |
+ EXPECT_THAT(store_reg_node, |
+ m.IsStore(StoreRepresentation(kMachPtr, kNoWriteBarrier), |
+ IsLoadFramePointer(), |
+ IsInt32Constant(m.kFirstRegisterOffsetFromFp - |
+ (i << kPointerSizeLog2)), |
+ store_value)); |
+ } |
+ } |
+} |
+ |
+ |
+TARGET_TEST_F(InterpreterAssemblerTest, StoreRegister) { |
+ TRACED_FOREACH(interpreter::Bytecode, bytecode, kBytecodes) { |
+ InterpreterAssemblerForTest m(this, bytecode); |
+ Node* store_value = m.Int32Constant(0xdeadbeef); |
+ Node* reg_index_node = m.Int32Constant(44); |
+ Node* store_reg_node = m.StoreRegister(store_value, reg_index_node); |
+ EXPECT_THAT( |
+ store_reg_node, |
+ m.IsStore(StoreRepresentation(kMachPtr, kNoWriteBarrier), |
+ IsLoadFramePointer(), |
+ IsInt32Sub(IsInt32Constant(m.kFirstRegisterOffsetFromFp), |
+ IsWord32Shl(reg_index_node, |
+ IsInt32Constant(kPointerSizeLog2))), |
+ store_value)); |
+ } |
+} |
+ |
+} // namespace compiler |
+} // namespace internal |
+} // namespace v8 |