Revision: 23149
Author:   [email protected]
Date:     Mon Aug 18 11:36:06 2014 UTC
Log:      [turbofan] Add new ControlEffect and Finish operators.

Fix the ChangeLowering to properly use ControlEffect nodes
to turn the control output of IfTrue nodes into an effect
input for the Load nodes, and to properly use Finish nodes
to ensure that allocation and store were both performed
prior to actually using the allocated heap number.

TEST=compiler-unittests
[email protected]

Review URL: https://codereview.chromium.org/479163002
http://code.google.com/p/v8/source/detail?r=23149

Modified:
 /branches/bleeding_edge/src/compiler/change-lowering.cc
 /branches/bleeding_edge/src/compiler/common-operator.h
 /branches/bleeding_edge/src/compiler/opcodes.h
 /branches/bleeding_edge/src/compiler/operator-properties-inl.h
 /branches/bleeding_edge/src/compiler/typer.cc
 /branches/bleeding_edge/test/compiler-unittests/change-lowering-unittest.cc
 /branches/bleeding_edge/test/compiler-unittests/common-operator-unittest.cc
 /branches/bleeding_edge/test/compiler-unittests/graph-unittest.cc
 /branches/bleeding_edge/test/compiler-unittests/graph-unittest.h

=======================================
--- /branches/bleeding_edge/src/compiler/change-lowering.cc Mon Aug 18 09:12:12 2014 UTC +++ /branches/bleeding_edge/src/compiler/change-lowering.cc Mon Aug 18 11:36:06 2014 UTC
@@ -94,7 +94,6 @@
   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
   Node* number = graph()->NewNode(machine()->ChangeInt32ToFloat64(), val);

-  // TODO(bmeurer): Inline allocation if possible.
   const Runtime::Function* fn =
       Runtime::FunctionForId(Runtime::kAllocateHeapNumber);
   DCHECK_EQ(0, fn->nargs);
@@ -103,17 +102,17 @@
   Node* heap_number = graph()->NewNode(
       common()->Call(desc), jsgraph()->CEntryStubConstant(),
       jsgraph()->ExternalConstant(ExternalReference(fn, isolate())),
-      jsgraph()->ZeroConstant(), context, effect, if_true);
-
+      jsgraph()->Int32Constant(fn->nargs), context, effect, if_true);
   Node* store = graph()->NewNode(
       machine()->Store(kMachFloat64, kNoWriteBarrier), heap_number,
-      HeapNumberValueIndexConstant(), number, effect, heap_number);
+      HeapNumberValueIndexConstant(), number, heap_number, if_true);
+  Node* finish = graph()->NewNode(common()->Finish(1), heap_number, store);

   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
   Node* smi = graph()->NewNode(common()->Projection(0), add);

-  Node* merge = graph()->NewNode(common()->Merge(2), store, if_false);
-  Node* phi = graph()->NewNode(common()->Phi(2), heap_number, smi, merge);
+  Node* merge = graph()->NewNode(common()->Merge(2), if_true, if_false);
+  Node* phi = graph()->NewNode(common()->Phi(2), finish, smi, merge);

   return Replace(phi);
 }
@@ -128,8 +127,9 @@
   Node* branch = graph()->NewNode(common()->Branch(), tag, control);

   Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
-  Node* load = graph()->NewNode(machine()->Load(kMachFloat64), val,
-                                HeapNumberValueIndexConstant(), if_true);
+  Node* load = graph()->NewNode(
+      machine()->Load(kMachFloat64), val, HeapNumberValueIndexConstant(),
+      graph()->NewNode(common()->ControlEffect(), if_true));

   Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
   Node* integer =
=======================================
--- /branches/bleeding_edge/src/compiler/common-operator.h Wed Aug 6 11:49:02 2014 UTC +++ /branches/bleeding_edge/src/compiler/common-operator.h Mon Aug 18 11:36:06 2014 UTC
@@ -130,6 +130,15 @@
return new (zone_) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
                                       0, "EffectPhi", arguments);
   }
+  Operator* ControlEffect() {
+ return new (zone_) SimpleOperator(IrOpcode::kControlEffect, Operator::kPure,
+                                      0, 0, "ControlEffect");
+  }
+  Operator* Finish(int arguments) {
+    DCHECK(arguments > 0);  // Disallow empty finishes.
+ return new (zone_) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1,
+                                      "Finish", arguments);
+  }
   Operator* StateValues(int arguments) {
return new (zone_) Operator1<int>(IrOpcode::kStateValues, Operator::kPure, arguments, 1, "StateValues", arguments);
=======================================
--- /branches/bleeding_edge/src/compiler/opcodes.h Thu Aug 14 09:07:58 2014 UTC +++ /branches/bleeding_edge/src/compiler/opcodes.h Mon Aug 18 11:36:06 2014 UTC
@@ -33,6 +33,8 @@
 #define INNER_OP_LIST(V) \
   V(Phi)                 \
   V(EffectPhi)           \
+  V(ControlEffect)       \
+  V(Finish)              \
   V(FrameState)          \
   V(StateValues)         \
   V(Call)                \
=======================================
--- /branches/bleeding_edge/src/compiler/operator-properties-inl.h Mon Aug 11 12:26:17 2014 UTC +++ /branches/bleeding_edge/src/compiler/operator-properties-inl.h Mon Aug 18 11:36:06 2014 UTC
@@ -42,7 +42,8 @@
 }

 inline int OperatorProperties::GetEffectInputCount(Operator* op) {
-  if (op->opcode() == IrOpcode::kEffectPhi) {
+  if (op->opcode() == IrOpcode::kEffectPhi ||
+      op->opcode() == IrOpcode::kFinish) {
     return static_cast<Operator1<int>*>(op)->parameter();
   }
if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
@@ -54,6 +55,7 @@
   switch (op->opcode()) {
     case IrOpcode::kPhi:
     case IrOpcode::kEffectPhi:
+    case IrOpcode::kControlEffect:
       return 1;
 #define OPCODE_CASE(x) case IrOpcode::k##x:
       CONTROL_OP_LIST(OPCODE_CASE)
@@ -87,7 +89,9 @@
 }

 inline bool OperatorProperties::HasEffectOutput(Operator* op) {
-  return op->opcode() == IrOpcode::kStart || GetEffectInputCount(op) > 0;
+  return op->opcode() == IrOpcode::kStart ||
+         op->opcode() == IrOpcode::kControlEffect ||
+ (op->opcode() != IrOpcode::kFinish && GetEffectInputCount(op) > 0);
 }

 inline bool OperatorProperties::HasControlOutput(Operator* op) {
=======================================
--- /branches/bleeding_edge/src/compiler/typer.cc Thu Aug 7 09:14:47 2014 UTC +++ /branches/bleeding_edge/src/compiler/typer.cc Mon Aug 18 11:36:06 2014 UTC
@@ -265,6 +265,14 @@
 Bounds Typer::Visitor::TypeEffectPhi(Node* node) {
   return Bounds(Type::None(zone()));
 }
+
+
+Bounds Typer::Visitor::TypeControlEffect(Node* node) {
+  return Bounds(Type::None(zone()));
+}
+
+
+Bounds Typer::Visitor::TypeFinish(Node* node) { return OperandType(node, 0); }


 Bounds Typer::Visitor::TypeFrameState(Node* node) {
=======================================
--- /branches/bleeding_edge/test/compiler-unittests/change-lowering-unittest.cc Mon Aug 18 06:54:07 2014 UTC +++ /branches/bleeding_edge/test/compiler-unittests/change-lowering-unittest.cc Mon Aug 18 11:36:06 2014 UTC
@@ -117,34 +117,33 @@
   ASSERT_TRUE(reduction.Changed());

   Node* phi = reduction.replacement();
-  ASSERT_EQ(IrOpcode::kPhi, phi->opcode());
-
-  Node* smi = NodeProperties::GetValueInput(phi, 1);
-  ASSERT_THAT(smi, IsProjection(0, IsInt32AddWithOverflow(val, val)));
-
-  Node* heap_number = NodeProperties::GetValueInput(phi, 0);
-  ASSERT_EQ(IrOpcode::kCall, heap_number->opcode());
-
-  Node* merge = NodeProperties::GetControlInput(phi);
-  ASSERT_EQ(IrOpcode::kMerge, merge->opcode());
-
+  Capture<Node*> add, branch, heap_number, if_true;
   const int32_t kValueOffset = kHeapNumberValueOffset - kHeapObjectTag;
-  EXPECT_THAT(NodeProperties::GetControlInput(merge, 0),
-              IsStore(kMachFloat64, kNoWriteBarrier, heap_number,
+  EXPECT_THAT(
+      phi,
+      IsPhi(
+          IsFinish(
+              AllOf(
+                  CaptureEq(&heap_number),
+                  IsCall(
+                      _, IsHeapConstant(
+                             PrintableUnique<HeapObject>::CreateImmovable(
+ zone(), CEntryStub(isolate(), 1).GetCode())),
+                      IsExternalConstant(ExternalReference(
+ Runtime::FunctionForId(Runtime::kAllocateHeapNumber),
+                          isolate())),
+                      IsInt32Constant(0), IsNumberConstant(0.0),
+                      graph()->start(), CaptureEq(&if_true))),
+ IsStore(kMachFloat64, kNoWriteBarrier, CaptureEq(&heap_number),
                       IsInt32Constant(kValueOffset),
-                      IsChangeInt32ToFloat64(val), _, heap_number));
-
-  Node* if_true = NodeProperties::GetControlInput(heap_number);
-  ASSERT_EQ(IrOpcode::kIfTrue, if_true->opcode());
-
-  Node* if_false = NodeProperties::GetControlInput(merge, 1);
-  ASSERT_EQ(IrOpcode::kIfFalse, if_false->opcode());
-
-  Node* branch = NodeProperties::GetControlInput(if_true);
-  EXPECT_EQ(branch, NodeProperties::GetControlInput(if_false));
-  EXPECT_THAT(branch,
-              IsBranch(IsProjection(1, IsInt32AddWithOverflow(val, val)),
-                       graph()->start()));
+                      IsChangeInt32ToFloat64(val), CaptureEq(&heap_number),
+                      CaptureEq(&if_true))),
+          IsProjection(
+              0, AllOf(CaptureEq(&add), IsInt32AddWithOverflow(val, val))),
+          IsMerge(AllOf(CaptureEq(&if_true), IsIfTrue(CaptureEq(&branch))),
+                  IsIfFalse(AllOf(CaptureEq(&branch),
+ IsBranch(IsProjection(1, CaptureEq(&add)),
+                                           graph()->start()))))));
 }


@@ -161,17 +160,21 @@
       kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize;
   const int32_t kValueOffset = kHeapNumberValueOffset - kHeapObjectTag;
   Node* phi = reduction.replacement();
-  Capture<Node*> branch;
+  Capture<Node*> branch, if_true;
   EXPECT_THAT(
       phi,
-      IsPhi(IsLoad(kMachFloat64, val, IsInt32Constant(kValueOffset), _),
-            IsChangeInt32ToFloat64(
-                IsWord32Sar(val, IsInt32Constant(kShiftAmount))),
-            IsMerge(IsIfTrue(AllOf(
+      IsPhi(
+          IsLoad(kMachFloat64, val, IsInt32Constant(kValueOffset),
+                 IsControlEffect(CaptureEq(&if_true))),
+          IsChangeInt32ToFloat64(
+              IsWord32Sar(val, IsInt32Constant(kShiftAmount))),
+          IsMerge(
+              AllOf(CaptureEq(&if_true),
+                    IsIfTrue(AllOf(
                         CaptureEq(&branch),
IsBranch(IsWord32And(val, IsInt32Constant(kSmiTagMask)),
-                                 graph()->start()))),
-                    IsIfFalse(CaptureEq(&branch)))));
+                                 graph()->start())))),
+              IsIfFalse(CaptureEq(&branch)))));
 }


@@ -218,17 +221,21 @@
       kSmiTagSize + SmiTagging<kPointerSize>::kSmiShiftSize;
   const int32_t kValueOffset = kHeapNumberValueOffset - kHeapObjectTag;
   Node* phi = reduction.replacement();
-  Capture<Node*> branch;
+  Capture<Node*> branch, if_true;
   EXPECT_THAT(
       phi,
-      IsPhi(IsLoad(kMachFloat64, val, IsInt32Constant(kValueOffset), _),
-            IsChangeInt32ToFloat64(IsConvertInt64ToInt32(
-                IsWord64Sar(val, IsInt32Constant(kShiftAmount)))),
-            IsMerge(IsIfTrue(AllOf(
+      IsPhi(
+          IsLoad(kMachFloat64, val, IsInt32Constant(kValueOffset),
+                 IsControlEffect(CaptureEq(&if_true))),
+          IsChangeInt32ToFloat64(IsConvertInt64ToInt32(
+              IsWord64Sar(val, IsInt32Constant(kShiftAmount)))),
+          IsMerge(
+              AllOf(CaptureEq(&if_true),
+                    IsIfTrue(AllOf(
                         CaptureEq(&branch),
IsBranch(IsWord64And(val, IsInt32Constant(kSmiTagMask)),
-                                 graph()->start()))),
-                    IsIfFalse(CaptureEq(&branch)))));
+                                 graph()->start())))),
+              IsIfFalse(CaptureEq(&branch)))));
 }

 }  // namespace compiler
=======================================
--- /branches/bleeding_edge/test/compiler-unittests/common-operator-unittest.cc Mon Aug 18 06:54:07 2014 UTC +++ /branches/bleeding_edge/test/compiler-unittests/common-operator-unittest.cc Mon Aug 18 11:36:06 2014 UTC
@@ -14,6 +14,30 @@


 CommonOperatorTest::~CommonOperatorTest() {}
+
+
+TEST_F(CommonOperatorTest, ControlEffect) {
+  Operator* op = common()->ControlEffect();
+  EXPECT_EQ(1, OperatorProperties::GetControlInputCount(op));
+  EXPECT_EQ(1, OperatorProperties::GetTotalInputCount(op));
+  EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
+  EXPECT_EQ(1, OperatorProperties::GetEffectOutputCount(op));
+  EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
+}
+
+
+TEST_F(CommonOperatorTest, Finish) {
+  static const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
+  TRACED_FOREACH(int, arguments, kArguments) {
+    Operator* op = common()->Finish(arguments);
+    EXPECT_EQ(1, OperatorProperties::GetValueInputCount(op));
+    EXPECT_EQ(arguments, OperatorProperties::GetEffectInputCount(op));
+    EXPECT_EQ(arguments + 1, OperatorProperties::GetTotalInputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetControlOutputCount(op));
+    EXPECT_EQ(0, OperatorProperties::GetEffectOutputCount(op));
+    EXPECT_EQ(1, OperatorProperties::GetValueOutputCount(op));
+  }
+}

 }  // namespace compiler
 }  // namespace internal
=======================================
--- /branches/bleeding_edge/test/compiler-unittests/graph-unittest.cc Mon Aug 18 06:54:07 2014 UTC +++ /branches/bleeding_edge/test/compiler-unittests/graph-unittest.cc Mon Aug 18 11:36:06 2014 UTC
@@ -22,6 +22,12 @@
                                 const PrintableUnique<T>& value) {
   return os << value.string();
 }
+inline std::ostream& operator<<(std::ostream& os,
+                                const ExternalReference& value) {
+  OStringStream ost;
+  compiler::StaticParameterTraits<ExternalReference>::PrintTo(ost, value);
+  return os << ost.c_str();
+}

 namespace compiler {

@@ -66,7 +72,8 @@
       return false;
     }
     if (node->opcode() != opcode_) {
- *listener << "whose opcode is " << IrOpcode::Mnemonic(node->opcode());
+      *listener << "whose opcode is " << IrOpcode::Mnemonic(node->opcode())
+                << " but should have been " << IrOpcode::Mnemonic(opcode_);
       return false;
     }
     return true;
@@ -141,10 +148,11 @@
 };


-class IsIfTrueMatcher V8_FINAL : public NodeMatcher {
+class IsControl1Matcher V8_FINAL : public NodeMatcher {
  public:
-  explicit IsIfTrueMatcher(const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kIfTrue), control_matcher_(control_matcher) {}
+  IsControl1Matcher(IrOpcode::Value opcode,
+                    const Matcher<Node*>& control_matcher)
+      : NodeMatcher(opcode), control_matcher_(control_matcher) {}

   virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
     NodeMatcher::DescribeTo(os);
@@ -165,27 +173,35 @@
 };


-class IsIfFalseMatcher V8_FINAL : public NodeMatcher {
+class IsFinishMatcher V8_FINAL : public NodeMatcher {
  public:
-  explicit IsIfFalseMatcher(const Matcher<Node*>& control_matcher)
- : NodeMatcher(IrOpcode::kIfFalse), control_matcher_(control_matcher) {}
+  IsFinishMatcher(const Matcher<Node*>& value_matcher,
+                  const Matcher<Node*>& effect_matcher)
+      : NodeMatcher(IrOpcode::kFinish),
+        value_matcher_(value_matcher),
+        effect_matcher_(effect_matcher) {}

   virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
     NodeMatcher::DescribeTo(os);
-    *os << " whose control (";
-    control_matcher_.DescribeTo(os);
+    *os << " whose value (";
+    value_matcher_.DescribeTo(os);
+    *os << ") and effect (";
+    effect_matcher_.DescribeTo(os);
     *os << ")";
   }

virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
       V8_OVERRIDE {
     return (NodeMatcher::MatchAndExplain(node, listener) &&
-            PrintMatchAndExplain(NodeProperties::GetControlInput(node),
-                                 "control", control_matcher_, listener));
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
+                                 "value", value_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
+                                 effect_matcher_, listener));
   }

  private:
-  const Matcher<Node*> control_matcher_;
+  const Matcher<Node*> value_matcher_;
+  const Matcher<Node*> effect_matcher_;
 };


@@ -284,6 +300,71 @@
   const Matcher<Node*> base_matcher_;
 };

+
+class IsCallMatcher V8_FINAL : public NodeMatcher {
+ public:
+  IsCallMatcher(const Matcher<CallDescriptor*>& 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*>& effect_matcher,
+                const Matcher<Node*>& control_matcher)
+      : NodeMatcher(IrOpcode::kCall),
+        descriptor_matcher_(descriptor_matcher),
+        value0_matcher_(value0_matcher),
+        value1_matcher_(value1_matcher),
+        value2_matcher_(value2_matcher),
+        value3_matcher_(value3_matcher),
+        effect_matcher_(effect_matcher),
+        control_matcher_(control_matcher) {}
+
+  virtual void DescribeTo(std::ostream* os) const V8_OVERRIDE {
+    NodeMatcher::DescribeTo(os);
+    *os << " whose value0 (";
+    value0_matcher_.DescribeTo(os);
+    *os << ") and value1 (";
+    value1_matcher_.DescribeTo(os);
+    *os << ") and value2 (";
+    value2_matcher_.DescribeTo(os);
+    *os << ") and value3 (";
+    value3_matcher_.DescribeTo(os);
+    *os << ") and effect (";
+    effect_matcher_.DescribeTo(os);
+    *os << ") and control (";
+    control_matcher_.DescribeTo(os);
+    *os << ")";
+  }
+
+ virtual bool MatchAndExplain(Node* node, MatchResultListener* listener) const
+      V8_OVERRIDE {
+    return (NodeMatcher::MatchAndExplain(node, listener) &&
+            PrintMatchAndExplain(OpParameter<CallDescriptor*>(node),
+ "descriptor", descriptor_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 0),
+                                 "value0", value0_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 1),
+                                 "value1", value1_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 2),
+                                 "value2", value2_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetValueInput(node, 3),
+                                 "value3", value3_matcher_, listener) &&
+ PrintMatchAndExplain(NodeProperties::GetEffectInput(node), "effect",
+                                 effect_matcher_, listener) &&
+            PrintMatchAndExplain(NodeProperties::GetControlInput(node),
+                                 "control", control_matcher_, listener));
+  }
+
+ private:
+  const Matcher<CallDescriptor*> 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*> effect_matcher_;
+  const Matcher<Node*> control_matcher_;
+};
+

 class IsLoadMatcher V8_FINAL : public NodeMatcher {
  public:
@@ -470,18 +551,32 @@


 Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher) {
-  return MakeMatcher(new IsIfTrueMatcher(control_matcher));
+ return MakeMatcher(new IsControl1Matcher(IrOpcode::kIfTrue, control_matcher));
 }


 Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher) {
-  return MakeMatcher(new IsIfFalseMatcher(control_matcher));
+  return MakeMatcher(
+      new IsControl1Matcher(IrOpcode::kIfFalse, control_matcher));
 }


-Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher) {
+Matcher<Node*> IsControlEffect(const Matcher<Node*>& control_matcher) {
   return MakeMatcher(
- new IsConstantMatcher<int32_t>(IrOpcode::kInt32Constant, value_matcher));
+      new IsControl1Matcher(IrOpcode::kControlEffect, control_matcher));
+}
+
+
+Matcher<Node*> IsFinish(const Matcher<Node*>& value_matcher,
+                        const Matcher<Node*>& effect_matcher) {
+  return MakeMatcher(new IsFinishMatcher(value_matcher, effect_matcher));
+}
+
+
+Matcher<Node*> IsExternalConstant(
+    const Matcher<ExternalReference>& value_matcher) {
+  return MakeMatcher(new IsConstantMatcher<ExternalReference>(
+      IrOpcode::kExternalConstant, value_matcher));
 }


@@ -490,6 +585,18 @@
   return MakeMatcher(new IsConstantMatcher<PrintableUnique<HeapObject> >(
       IrOpcode::kHeapConstant, value_matcher));
 }
+
+
+Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher) {
+  return MakeMatcher(
+ new IsConstantMatcher<int32_t>(IrOpcode::kInt32Constant, value_matcher));
+}
+
+
+Matcher<Node*> IsNumberConstant(const Matcher<double>& value_matcher) {
+  return MakeMatcher(
+ new IsConstantMatcher<double>(IrOpcode::kNumberConstant, value_matcher));
+}


 Matcher<Node*> IsPhi(const Matcher<Node*>& value0_matcher,
@@ -504,6 +611,19 @@
                             const Matcher<Node*>& base_matcher) {
   return MakeMatcher(new IsProjectionMatcher(index_matcher, base_matcher));
 }
+
+
+Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& 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*>& effect_matcher,
+                      const Matcher<Node*>& control_matcher) {
+  return MakeMatcher(new IsCallMatcher(
+      descriptor_matcher, value0_matcher, value1_matcher, value2_matcher,
+      value3_matcher, effect_matcher, control_matcher));
+}


 Matcher<Node*> IsLoad(const Matcher<MachineType>& type_matcher,
=======================================
--- /branches/bleeding_edge/test/compiler-unittests/graph-unittest.h Mon Aug 18 06:54:07 2014 UTC +++ /branches/bleeding_edge/test/compiler-unittests/graph-unittest.h Mon Aug 18 11:36:06 2014 UTC
@@ -41,14 +41,27 @@
                        const Matcher<Node*>& control1_matcher);
 Matcher<Node*> IsIfTrue(const Matcher<Node*>& control_matcher);
 Matcher<Node*> IsIfFalse(const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsControlEffect(const Matcher<Node*>& control_matcher);
+Matcher<Node*> IsFinish(const Matcher<Node*>& value_matcher,
+                        const Matcher<Node*>& effect_matcher);
+Matcher<Node*> IsExternalConstant(
+    const Matcher<ExternalReference>& value_matcher);
 Matcher<Node*> IsHeapConstant(
     const Matcher<PrintableUnique<HeapObject> >& value_matcher);
 Matcher<Node*> IsInt32Constant(const Matcher<int32_t>& value_matcher);
+Matcher<Node*> IsNumberConstant(const Matcher<double>& value_matcher);
 Matcher<Node*> IsPhi(const Matcher<Node*>& value0_matcher,
                      const Matcher<Node*>& value1_matcher,
                      const Matcher<Node*>& merge_matcher);
 Matcher<Node*> IsProjection(const Matcher<int32_t>& index_matcher,
                             const Matcher<Node*>& base_matcher);
+Matcher<Node*> IsCall(const Matcher<CallDescriptor*>& 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*>& effect_matcher,
+                      const Matcher<Node*>& control_matcher);

 Matcher<Node*> IsLoad(const Matcher<MachineType>& type_matcher,
                       const Matcher<Node*>& base_matcher,

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to