| Index: test/unittests/compiler/bytecode-graph-builder-unittest.cc | 
| diff --git a/test/unittests/compiler/bytecode-graph-builder-unittest.cc b/test/unittests/compiler/bytecode-graph-builder-unittest.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..22b9b893e85fce619e26c998c842b3f69c89fa29 | 
| --- /dev/null | 
| +++ b/test/unittests/compiler/bytecode-graph-builder-unittest.cc | 
| @@ -0,0 +1,248 @@ | 
| +// 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 <iostream> | 
| + | 
| +#include "src/compiler/bytecode-graph-builder.h" | 
| +#include "src/compiler/common-operator.h" | 
| +#include "src/compiler/graph-visualizer.h" | 
| +#include "src/compiler/instruction.h" | 
| +#include "src/compiler/instruction-selector.h" | 
| +#include "src/compiler/js-graph.h" | 
| +#include "src/compiler/js-operator.h" | 
| +#include "src/interpreter/bytecode-array-builder.h" | 
| +#include "src/parser.h" | 
| +#include "test/unittests/compiler/compiler-test-utils.h" | 
| +#include "test/unittests/compiler/graph-unittest.h" | 
| +#include "test/unittests/compiler/node-test-utils.h" | 
| +#include "test/unittests/test-utils.h" | 
| + | 
| +using ::testing::_; | 
| + | 
| +namespace v8 { | 
| +namespace internal { | 
| +namespace compiler { | 
| + | 
| +class BytecodeGraphBuilderTest : public TestWithIsolateAndZone { | 
| + public: | 
| +  BytecodeGraphBuilderTest() : array_builder_(isolate(), zone()) {} | 
| + | 
| +  Graph* GetCompletedGraph(); | 
| + | 
| +  Matcher<Node*> IsUndefinedConstant(); | 
| +  Matcher<Node*> IsNullConstant(); | 
| +  Matcher<Node*> IsTheHoleConstant(); | 
| +  Matcher<Node*> IsFalseConstant(); | 
| +  Matcher<Node*> IsTrueConstant(); | 
| + | 
| +  interpreter::BytecodeArrayBuilder* array_builder() { return &array_builder_; } | 
| + | 
| + private: | 
| +  interpreter::BytecodeArrayBuilder array_builder_; | 
| + | 
| +  DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilderTest); | 
| +}; | 
| + | 
| + | 
| +Graph* BytecodeGraphBuilderTest::GetCompletedGraph() { | 
| +  MachineOperatorBuilder* machine = new (zone()) MachineOperatorBuilder( | 
| +      zone(), kMachPtr, InstructionSelector::SupportedMachineOperatorFlags()); | 
| +  CommonOperatorBuilder* common = new (zone()) CommonOperatorBuilder(zone()); | 
| +  JSOperatorBuilder* javascript = new (zone()) JSOperatorBuilder(zone()); | 
| +  Graph* graph = new (zone()) Graph(zone()); | 
| +  JSGraph* jsgraph = | 
| +      new (zone()) JSGraph(isolate(), graph, common, javascript, machine); | 
| + | 
| +  Handle<String> name = factory()->NewStringFromStaticChars("test"); | 
| +  Handle<String> script = factory()->NewStringFromStaticChars("test() {}"); | 
| +  Handle<SharedFunctionInfo> shared_info = | 
| +      factory()->NewSharedFunctionInfo(name, MaybeHandle<Code>()); | 
| +  shared_info->set_script(*factory()->NewScript(script)); | 
| + | 
| +  ParseInfo parse_info(zone(), shared_info); | 
| +  CompilationInfo info(&parse_info); | 
| +  Handle<BytecodeArray> bytecode_array = array_builder()->ToBytecodeArray(); | 
| +  info.shared_info()->set_function_data(*bytecode_array); | 
| + | 
| +  BytecodeGraphBuilder graph_builder(zone(), &info, jsgraph); | 
| +  graph_builder.CreateGraph(); | 
| +  return graph; | 
| +} | 
| + | 
| + | 
| +Matcher<Node*> BytecodeGraphBuilderTest::IsUndefinedConstant() { | 
| +  return IsHeapConstant(factory()->undefined_value()); | 
| +} | 
| + | 
| + | 
| +Matcher<Node*> BytecodeGraphBuilderTest::IsNullConstant() { | 
| +  return IsHeapConstant(factory()->null_value()); | 
| +} | 
| + | 
| + | 
| +Matcher<Node*> BytecodeGraphBuilderTest::IsTheHoleConstant() { | 
| +  return IsHeapConstant(factory()->the_hole_value()); | 
| +} | 
| + | 
| + | 
| +Matcher<Node*> BytecodeGraphBuilderTest::IsFalseConstant() { | 
| +  return IsHeapConstant(factory()->false_value()); | 
| +} | 
| + | 
| + | 
| +Matcher<Node*> BytecodeGraphBuilderTest::IsTrueConstant() { | 
| +  return IsHeapConstant(factory()->true_value()); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnUndefined) { | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadUndefined().Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  Node* effect = graph->start(); | 
| +  Node* control = graph->start(); | 
| +  EXPECT_THAT(ret, IsReturn(IsUndefinedConstant(), effect, control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnNull) { | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadNull().Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  EXPECT_THAT(ret, IsReturn(IsNullConstant(), graph->start(), graph->start())); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnTheHole) { | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadTheHole().Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  Node* effect = graph->start(); | 
| +  Node* control = graph->start(); | 
| +  EXPECT_THAT(ret, IsReturn(IsTheHoleConstant(), effect, control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnTrue) { | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadTrue().Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  Node* effect = graph->start(); | 
| +  Node* control = graph->start(); | 
| +  EXPECT_THAT(ret, IsReturn(IsTrueConstant(), effect, control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnFalse) { | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadFalse().Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  Node* effect = graph->start(); | 
| +  Node* control = graph->start(); | 
| +  EXPECT_THAT(ret, IsReturn(IsFalseConstant(), effect, control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnInt8) { | 
| +  static const int kValue = 3; | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadLiteral(Smi::FromInt(kValue)).Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  Node* effect = graph->start(); | 
| +  Node* control = graph->start(); | 
| +  EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), effect, control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, ReturnDouble) { | 
| +  const double kValue = 0.123456789; | 
| +  array_builder()->set_locals_count(0); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder()->LoadLiteral(factory()->NewHeapNumber(kValue)); | 
| +  array_builder()->Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  Node* effect = graph->start(); | 
| +  Node* control = graph->start(); | 
| +  EXPECT_THAT(ret, IsReturn(IsNumberConstant(kValue), effect, control)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithParameters) { | 
| +  array_builder()->set_locals_count(1); | 
| +  array_builder()->set_parameter_count(3); | 
| +  array_builder() | 
| +      ->LoadAccumulatorWithRegister(array_builder()->Parameter(1)) | 
| +      .BinaryOperation(Token::Value::ADD, array_builder()->Parameter(2)) | 
| +      .StoreAccumulatorInRegister(interpreter::Register(0)) | 
| +      .Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  // NB binary operation is <reg> <op> <acc>. The register represents | 
| +  // the left-hand side, which is why parameters appear in opposite | 
| +  // order to construction via the builder. | 
| +  EXPECT_THAT(ret, IsReturn(IsJSAdd(IsParameter(2), IsParameter(1)), _, _)); | 
| +} | 
| + | 
| + | 
| +TEST_F(BytecodeGraphBuilderTest, SimpleExpressionWithRegister) { | 
| +  static const int kLeft = -655371; | 
| +  static const int kRight = +2000000; | 
| +  array_builder()->set_locals_count(1); | 
| +  array_builder()->set_parameter_count(1); | 
| +  array_builder() | 
| +      ->LoadLiteral(Smi::FromInt(kLeft)) | 
| +      .StoreAccumulatorInRegister(interpreter::Register(0)) | 
| +      .LoadLiteral(Smi::FromInt(kRight)) | 
| +      .BinaryOperation(Token::Value::ADD, interpreter::Register(0)) | 
| +      .Return(); | 
| + | 
| +  Graph* graph = GetCompletedGraph(); | 
| +  Node* end = graph->end(); | 
| +  EXPECT_EQ(1, end->InputCount()); | 
| +  Node* ret = end->InputAt(0); | 
| +  EXPECT_THAT( | 
| +      ret, IsReturn(IsJSAdd(IsNumberConstant(kLeft), IsNumberConstant(kRight)), | 
| +                    _, _)); | 
| +} | 
| + | 
| +}  // namespace compiler | 
| +}  // namespace internal | 
| +}  // namespace v8 | 
|  |