'../src/d8.gyp:d8',
'../test/base-unittests/base-unittests.gyp:*',
'../test/cctest/cctest.gyp:*',
+ '../test/compiler-unittests/compiler-unittests.gyp:*',
],
'conditions': [
['component!="shared_library"', {
}
BasicBlock* InputBlock(int index) {
- NodeId block_id = static_cast<NodeId>(instr_->InputAt(index)->index());
+ NodeId block_id = static_cast<NodeId>(InputInt32(index));
// operand should be a block id.
DCHECK(block_id >= 0);
DCHECK(block_id < gen_->schedule()->BasicBlockCount());
InstructionOperand* Label(BasicBlock* block) {
// TODO(bmeurer): We misuse ImmediateOperand here.
- return ImmediateOperand::Create(block->id(), zone());
+ return TempImmediate(block->id());
}
protected:
"+include/v8stdint.h",
"-src",
"+src/base",
- "+testing",
+ "+testing/gtest",
]
--- /dev/null
+include_rules = [
+ "+src",
+ "+testing/gmock",
+ "+testing/gtest",
+]
--- /dev/null
+// Copyright 2014 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/compiler-unittests/instruction-selector-unittest.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class InstructionSelectorARMTest : public InstructionSelectorTest {};
+
+
+COMPILER_TEST_F(InstructionSelectorARMTest, Int32AddP) {
+ StreamBuilder m(this, kMachineWord32, kMachineWord32, kMachineWord32);
+ m.Return(m.Int32Add(m.Parameter(0), m.Parameter(1)));
+ Stream s = m.Build();
+ ASSERT_EQ(1U, s.size());
+ EXPECT_EQ(kArmAdd, s[0]->arch_opcode());
+ EXPECT_EQ(kMode_Operand2_R, s[0]->addressing_mode());
+ EXPECT_EQ(2U, s[0]->InputCount());
+ EXPECT_EQ(1U, s[0]->OutputCount());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
--- /dev/null
+// Copyright 2014 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 "include/libplatform/libplatform.h"
+#include "test/compiler-unittests/compiler-unittests.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+using testing::IsNull;
+using testing::NotNull;
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// static
+v8::Isolate* CompilerTest::isolate_ = NULL;
+
+
+CompilerTest::CompilerTest()
+ : isolate_scope_(isolate_),
+ handle_scope_(isolate_),
+ context_scope_(v8::Context::New(isolate_)),
+ zone_(isolate()) {}
+
+
+CompilerTest::~CompilerTest() {}
+
+
+// static
+void CompilerTest::SetUpTestCase() {
+ Test::SetUpTestCase();
+ EXPECT_THAT(isolate_, IsNull());
+ isolate_ = v8::Isolate::New();
+ ASSERT_THAT(isolate_, NotNull());
+}
+
+
+// static
+void CompilerTest::TearDownTestCase() {
+ ASSERT_THAT(isolate_, NotNull());
+ isolate_->Dispose();
+ isolate_ = NULL;
+ Test::TearDownTestCase();
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+
+namespace {
+
+class CompilerTestEnvironment V8_FINAL : public ::testing::Environment {
+ public:
+ CompilerTestEnvironment() : platform_(NULL) {}
+ ~CompilerTestEnvironment() {}
+
+ virtual void SetUp() V8_OVERRIDE {
+ EXPECT_THAT(platform_, IsNull());
+ platform_ = v8::platform::CreateDefaultPlatform();
+ v8::V8::InitializePlatform(platform_);
+ ASSERT_TRUE(v8::V8::Initialize());
+ }
+
+ virtual void TearDown() V8_OVERRIDE {
+ ASSERT_THAT(platform_, NotNull());
+ v8::V8::Dispose();
+ v8::V8::ShutdownPlatform();
+ delete platform_;
+ platform_ = NULL;
+ }
+
+ private:
+ v8::Platform* platform_;
+};
+
+}
+
+
+int main(int argc, char** argv) {
+ testing::InitGoogleMock(&argc, argv);
+ testing::AddGlobalTestEnvironment(new CompilerTestEnvironment);
+ v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
+ return RUN_ALL_TESTS();
+}
--- /dev/null
+# Copyright 2014 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.
+
+{
+ 'variables': {
+ 'v8_code': 1,
+ },
+ 'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
+ 'targets': [
+ {
+ 'target_name': 'compiler-unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ '../../testing/gmock.gyp:gmock',
+ '../../testing/gtest.gyp:gtest',
+ '../../tools/gyp/v8.gyp:v8_libplatform',
+ ],
+ 'include_dirs': [
+ '../..',
+ ],
+ 'sources': [ ### gcmole(all) ###
+ 'compiler-unittests.cc',
+ 'instruction-selector-unittest.cc',
+ ],
+ 'conditions': [
+ ['v8_target_arch=="arm"', {
+ 'sources': [ ### gcmole(arch:arm) ###
+ 'arm/instruction-selector-arm-unittest.cc',
+ ],
+ }],
+ ['component=="shared_library"', {
+ # compiler-unittests can't be built against a shared library, so we
+ # need to depend on the underlying static target in that case.
+ 'conditions': [
+ ['v8_use_snapshot=="true"', {
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8_snapshot'],
+ },
+ {
+ 'dependencies': [
+ '../../tools/gyp/v8.gyp:v8_nosnapshot',
+ ],
+ }],
+ ],
+ }, {
+ 'dependencies': ['../../tools/gyp/v8.gyp:v8'],
+ }],
+ ['os_posix == 1', {
+ # TODO(svenpanne): This is a temporary work-around to fix the warnings
+ # that show up because we use -std=gnu++0x instead of -std=c++11.
+ 'cflags!': [
+ '-pedantic',
+ ],
+ }],
+ ],
+ },
+ ],
+}
--- /dev/null
+// Copyright 2014 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.
+
+#ifndef V8_COMPILER_UNITTESTS_COMPILER_UNITTESTS_H_
+#define V8_COMPILER_UNITTESTS_COMPILER_UNITTESTS_H_
+
+#include "include/v8.h"
+#include "src/zone.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+// The COMPILER_TEST(Case, Name) macro works just like
+// TEST(Case, Name), except that the test is disabled
+// if the platform is not a supported TurboFan target.
+#if V8_TURBOFAN_TARGET
+#define COMPILER_TEST(Case, Name) TEST(Case, Name)
+#else
+#define COMPILER_TEST(Case, Name) TEST(Case, DISABLED_##Name)
+#endif
+
+
+// The COMPILER_TEST_F(Case, Name) macro works just like
+// TEST_F(Case, Name), except that the test is disabled
+// if the platform is not a supported TurboFan target.
+#if V8_TURBOFAN_TARGET
+#define COMPILER_TEST_F(Case, Name) TEST_F(Case, Name)
+#else
+#define COMPILER_TEST_F(Case, Name) TEST_F(Case, DISABLED_##Name)
+#endif
+
+
+class CompilerTest : public ::testing::Test {
+ public:
+ CompilerTest();
+ virtual ~CompilerTest();
+
+ Isolate* isolate() const { return reinterpret_cast<Isolate*>(isolate_); }
+ Zone* zone() { return &zone_; }
+
+ protected:
+ static void SetUpTestCase();
+ static void TearDownTestCase();
+
+ private:
+ static v8::Isolate* isolate_;
+ v8::Isolate::Scope isolate_scope_;
+ v8::HandleScope handle_scope_;
+ v8::Context::Scope context_scope_;
+ Zone zone_;
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_UNITTESTS_COMPILER_UNITTESTS_H_
--- /dev/null
+# Copyright 2014 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.
+
+[
+]
--- /dev/null
+// Copyright 2014 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/compiler-unittests/instruction-selector-unittest.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+InstructionSelectorTest::Stream InstructionSelectorTest::StreamBuilder::Build(
+ InstructionSelector::Features features,
+ InstructionSelectorTest::StreamBuilderMode mode) {
+ Schedule* schedule = Export();
+ EXPECT_NE(0, graph()->NodeCount());
+ CompilationInfo info(test_->isolate(), test_->zone());
+ Linkage linkage(&info, call_descriptor());
+ InstructionSequence sequence(&linkage, graph(), schedule);
+ SourcePositionTable source_position_table(graph());
+ InstructionSelector selector(&sequence, &source_position_table, features);
+ selector.SelectInstructions();
+ if (FLAG_trace_turbo) {
+ OFStream out(stdout);
+ out << "--- Code sequence after instruction selection ---" << endl
+ << sequence;
+ }
+ Stream s;
+ for (InstructionSequence::const_iterator i = sequence.begin();
+ i != sequence.end(); ++i) {
+ Instruction* instr = *i;
+ if (instr->opcode() < 0) continue;
+ if (mode == kTargetInstructions) {
+ switch (instr->arch_opcode()) {
+#define CASE(Name) \
+ case k##Name: \
+ break;
+ TARGET_ARCH_OPCODE_LIST(CASE)
+#undef CASE
+ default:
+ continue;
+ }
+ }
+ for (size_t i = 0; i < instr->OutputCount(); ++i) {
+ InstructionOperand* output = instr->OutputAt(i);
+ EXPECT_NE(InstructionOperand::IMMEDIATE, output->kind());
+ if (output->IsConstant()) {
+ s.constants_.insert(std::make_pair(
+ output->index(), sequence.GetConstant(output->index())));
+ }
+ }
+ for (size_t i = 0; i < instr->InputCount(); ++i) {
+ InstructionOperand* input = instr->InputAt(i);
+ EXPECT_NE(InstructionOperand::CONSTANT, input->kind());
+ if (input->IsImmediate()) {
+ s.immediates_.insert(std::make_pair(
+ input->index(), sequence.GetImmediate(input->index())));
+ }
+ }
+ s.instructions_.push_back(instr);
+ }
+ return s;
+}
+
+
+COMPILER_TEST_F(InstructionSelectorTest, ReturnP) {
+ StreamBuilder m(this, kMachineWord32, kMachineWord32);
+ m.Return(m.Parameter(0));
+ Stream s = m.Build(kAllInstructions);
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArchNop, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(kArchRet, s[1]->arch_opcode());
+ EXPECT_EQ(1U, s[1]->InputCount());
+}
+
+
+COMPILER_TEST_F(InstructionSelectorTest, ReturnImm) {
+ StreamBuilder m(this, kMachineWord32);
+ m.Return(m.Int32Constant(0));
+ Stream s = m.Build(kAllInstructions);
+ ASSERT_EQ(2U, s.size());
+ EXPECT_EQ(kArchNop, s[0]->arch_opcode());
+ ASSERT_EQ(1U, s[0]->OutputCount());
+ EXPECT_EQ(InstructionOperand::CONSTANT, s[0]->OutputAt(0)->kind());
+ EXPECT_EQ(0, s.ToInt32(s[0]->OutputAt(0)));
+ EXPECT_EQ(kArchRet, s[1]->arch_opcode());
+ EXPECT_EQ(1U, s[1]->InputCount());
+}
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
--- /dev/null
+// Copyright 2014 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.
+
+#ifndef V8_COMPILER_UNITTESTS_INSTRUCTION_SELECTOR_UNITTEST_H_
+#define V8_COMPILER_UNITTESTS_INSTRUCTION_SELECTOR_UNITTEST_H_
+
+#include <deque>
+
+#include "src/compiler/instruction-selector.h"
+#include "src/compiler/raw-machine-assembler.h"
+#include "test/compiler-unittests/compiler-unittests.h"
+
+namespace v8 {
+namespace internal {
+namespace compiler {
+
+class InstructionSelectorTest : public CompilerTest {
+ public:
+ InstructionSelectorTest() {}
+ virtual ~InstructionSelectorTest() {}
+
+ protected:
+ class Stream;
+
+ enum StreamBuilderMode { kAllInstructions, kTargetInstructions };
+
+ class StreamBuilder V8_FINAL : public RawMachineAssembler {
+ public:
+ StreamBuilder(InstructionSelectorTest* test,
+ MachineRepresentation return_type)
+ : RawMachineAssembler(new (test->zone()) Graph(test->zone()),
+ CallDescriptorBuilder(test->zone(), return_type)),
+ test_(test) {}
+ StreamBuilder(InstructionSelectorTest* test,
+ MachineRepresentation return_type,
+ MachineRepresentation parameter0_type)
+ : RawMachineAssembler(new (test->zone()) Graph(test->zone()),
+ CallDescriptorBuilder(test->zone(), return_type,
+ parameter0_type)),
+ test_(test) {}
+ StreamBuilder(InstructionSelectorTest* test,
+ MachineRepresentation return_type,
+ MachineRepresentation parameter0_type,
+ MachineRepresentation parameter1_type)
+ : RawMachineAssembler(
+ new (test->zone()) Graph(test->zone()),
+ CallDescriptorBuilder(test->zone(), return_type, parameter0_type,
+ parameter1_type)),
+ test_(test) {}
+
+ Stream Build(CpuFeature feature) {
+ return Build(InstructionSelector::Features(feature));
+ }
+ Stream Build(CpuFeature feature1, CpuFeature feature2) {
+ return Build(InstructionSelector::Features(feature1, feature2));
+ }
+ Stream Build(StreamBuilderMode mode = kTargetInstructions) {
+ return Build(InstructionSelector::Features(), mode);
+ }
+ Stream Build(InstructionSelector::Features features,
+ StreamBuilderMode mode = kTargetInstructions);
+
+ private:
+ MachineCallDescriptorBuilder* CallDescriptorBuilder(
+ Zone* zone, MachineRepresentation return_type) {
+ return new (zone) MachineCallDescriptorBuilder(return_type, 0, NULL);
+ }
+
+ MachineCallDescriptorBuilder* CallDescriptorBuilder(
+ Zone* zone, MachineRepresentation return_type,
+ MachineRepresentation parameter0_type) {
+ MachineRepresentation* parameter_types =
+ zone->NewArray<MachineRepresentation>(1);
+ parameter_types[0] = parameter0_type;
+ return new (zone)
+ MachineCallDescriptorBuilder(return_type, 1, parameter_types);
+ }
+
+ MachineCallDescriptorBuilder* CallDescriptorBuilder(
+ Zone* zone, MachineRepresentation return_type,
+ MachineRepresentation parameter0_type,
+ MachineRepresentation parameter1_type) {
+ MachineRepresentation* parameter_types =
+ zone->NewArray<MachineRepresentation>(2);
+ parameter_types[0] = parameter0_type;
+ parameter_types[1] = parameter1_type;
+ return new (zone)
+ MachineCallDescriptorBuilder(return_type, 2, parameter_types);
+ }
+
+ private:
+ InstructionSelectorTest* test_;
+ };
+
+ class Stream V8_FINAL {
+ public:
+ size_t size() const { return instructions_.size(); }
+ const Instruction* operator[](size_t index) const {
+ EXPECT_LT(index, size());
+ return instructions_[index];
+ }
+
+ int32_t ToInt32(const InstructionOperand* operand) const {
+ return ToConstant(operand).ToInt32();
+ }
+
+ private:
+ Constant ToConstant(const InstructionOperand* operand) const {
+ ConstantMap::const_iterator i;
+ if (operand->IsConstant()) {
+ i = constants_.find(operand->index());
+ EXPECT_NE(constants_.end(), i);
+ } else {
+ EXPECT_EQ(InstructionOperand::IMMEDIATE, operand->kind());
+ i = immediates_.find(operand->index());
+ EXPECT_NE(immediates_.end(), i);
+ }
+ EXPECT_EQ(operand->index(), i->first);
+ return i->second;
+ }
+
+ friend class StreamBuilder;
+
+ typedef std::map<int, Constant> ConstantMap;
+
+ ConstantMap constants_;
+ ConstantMap immediates_;
+ std::deque<Instruction*> instructions_;
+ };
+};
+
+} // namespace compiler
+} // namespace internal
+} // namespace v8
+
+#endif // V8_COMPILER_UNITTESTS_INSTRUCTION_SELECTOR_UNITTEST_H_
--- /dev/null
+# Copyright 2014 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.
+
+import os
+import shutil
+
+from testrunner.local import commands
+from testrunner.local import testsuite
+from testrunner.local import utils
+from testrunner.objects import testcase
+
+
+class CompilerUnitTestsSuite(testsuite.TestSuite):
+ def __init__(self, name, root):
+ super(CompilerUnitTestsSuite, self).__init__(name, root)
+
+ def ListTests(self, context):
+ shell = os.path.abspath(os.path.join(context.shell_dir, self.shell()))
+ if utils.IsWindows():
+ shell += ".exe"
+ output = commands.Execute(context.command_prefix +
+ [shell, "--gtest_list_tests"] +
+ context.extra_flags)
+ if output.exit_code != 0:
+ print output.stdout
+ print output.stderr
+ return []
+ tests = []
+ test_case = ''
+ for test_desc in output.stdout.strip().split():
+ if test_desc.endswith('.'):
+ test_case = test_desc
+ else:
+ test = testcase.TestCase(self, test_case + test_desc, dependency=None)
+ tests.append(test)
+ tests.sort()
+ return tests
+
+ def GetFlagsForTestCase(self, testcase, context):
+ return (testcase.flags + ["--gtest_filter=" + testcase.path] +
+ ["--gtest_random_seed=%s" % context.random_seed] +
+ ["--gtest_print_time=0"] +
+ context.mode_flags)
+
+ def shell(self):
+ return "compiler-unittests"
+
+
+def GetSuite(name, root):
+ return CompilerUnitTestsSuite(name, root)
def GetPathsToSearch(self):
return ['src', 'include', 'samples',
join('test', 'base-unittests'),
- join('test', 'cctest')]
+ join('test', 'cctest'),
+ join('test', 'compiler-unittests')]
def GetCpplintScript(self, prio_path):
for path in [prio_path] + os.environ["PATH"].split(os.pathsep):
ARCH_GUESS = utils.DefaultArch()
DEFAULT_TESTS = ["mjsunit", "fuzz-natives", "base-unittests",
- "cctest", "message", "preparser"]
+ "cctest", "compiler-unittests", "message", "preparser"]
TIMEOUT_DEFAULT = 60
TIMEOUT_SCALEFACTOR = {"debug" : 4,
"release" : 1 }