Move input/output counts directly into Operators, simplying OperatorProperties.
authortitzer@chromium.org <titzer@chromium.org>
Wed, 29 Oct 2014 14:40:47 +0000 (14:40 +0000)
committertitzer@chromium.org <titzer@chromium.org>
Wed, 29 Oct 2014 14:41:18 +0000 (14:41 +0000)
This is a first step to refactoring OperatorProperties out of existence.
The next step is to inline OperatorProperties::GetXXXCount into the callers.

R=rossberg@chromium.org
BUG=

Review URL: https://codereview.chromium.org/680313003

Cr-Commit-Position: refs/heads/master@{#24983}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24983 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

27 files changed:
src/compiler/common-operator.cc
src/compiler/common-operator.h
src/compiler/instruction-selector.cc
src/compiler/js-inlining.cc
src/compiler/js-operator.cc
src/compiler/js-operator.h
src/compiler/machine-operator.cc
src/compiler/machine-operator.h
src/compiler/opcodes.h
src/compiler/operator-properties-inl.h
src/compiler/operator.cc
src/compiler/operator.h
src/compiler/simplified-lowering.cc
src/compiler/simplified-operator.cc
src/compiler/simplified-operator.h
src/compiler/verifier.cc
test/cctest/compiler/simplified-graph-builder.cc
test/cctest/compiler/test-graph-reducer.cc
test/cctest/compiler/test-linkage.cc
test/cctest/compiler/test-node-algorithm.cc
test/cctest/compiler/test-node.cc
test/cctest/compiler/test-operator.cc
test/cctest/compiler/test-schedule.cc
test/unittests/compiler/common-operator-unittest.cc
test/unittests/compiler/graph-reducer-unittest.cc
test/unittests/compiler/js-operator-unittest.cc
test/unittests/compiler/value-numbering-reducer-unittest.cc

index f1ac90a..571a7f5 100644 (file)
@@ -14,22 +14,6 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
-namespace {
-
-// TODO(turbofan): Use size_t instead of int here.
-class ControlOperator : public Operator1<int> {
- public:
-  ControlOperator(IrOpcode::Value opcode, Properties properties, int inputs,
-                  int outputs, int controls, const char* mnemonic)
-      : Operator1<int>(opcode, properties, inputs, outputs, mnemonic,
-                       controls) {}
-
-  virtual void PrintParameter(std::ostream& os) const FINAL {}
-};
-
-}  // namespace
-
-
 std::ostream& operator<<(std::ostream& os, BranchHint hint) {
   switch (hint) {
     case BranchHint::kNone:
@@ -117,181 +101,226 @@ std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) {
 }
 
 
-#define SHARED_OP_LIST(V)               \
-  V(Dead, Operator::kFoldable, 0, 0)    \
-  V(End, Operator::kFoldable, 0, 1)     \
-  V(IfTrue, Operator::kFoldable, 0, 1)  \
-  V(IfFalse, Operator::kFoldable, 0, 1) \
-  V(Throw, Operator::kFoldable, 1, 1)   \
-  V(Return, Operator::kNoProperties, 1, 1)
+#define CACHED_OP_LIST(V)                     \
+  V(Dead, Operator::kFoldable, 0, 0, 0, 1)    \
+  V(End, Operator::kFoldable, 0, 0, 1, 0)     \
+  V(IfTrue, Operator::kFoldable, 0, 0, 1, 1)  \
+  V(IfFalse, Operator::kFoldable, 0, 0, 1, 1) \
+  V(Throw, Operator::kFoldable, 1, 1, 1, 1)   \
+  V(Return, Operator::kNoProperties, 1, 1, 1, 1)
 
 
-struct CommonOperatorBuilderImpl FINAL {
-#define SHARED(Name, properties, value_input_count, control_input_count)       \
-  struct Name##Operator FINAL : public ControlOperator {                       \
-    Name##Operator()                                                           \
-        : ControlOperator(IrOpcode::k##Name, properties, value_input_count, 0, \
-                          control_input_count, #Name) {}                       \
-  };                                                                           \
+struct CommonOperatorGlobalCache FINAL {
+#define CACHED(Name, properties, value_input_count, effect_input_count,     \
+               control_input_count, control_output_count)                   \
+  struct Name##Operator FINAL : public Operator {                           \
+    Name##Operator()                                                        \
+        : Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \
+                   effect_input_count, control_input_count, 0, 0,           \
+                   control_output_count) {}                                 \
+  };                                                                        \
   Name##Operator k##Name##Operator;
-  SHARED_OP_LIST(SHARED)
-#undef SHARED
+  CACHED_OP_LIST(CACHED)
+#undef CACHED
 };
 
 
-static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl =
+static base::LazyInstance<CommonOperatorGlobalCache>::type kCache =
     LAZY_INSTANCE_INITIALIZER;
 
 
 CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
-    : impl_(kImpl.Get()), zone_(zone) {}
+    : cache_(kCache.Get()), zone_(zone) {}
 
 
-#define SHARED(Name, properties, value_input_count, control_input_count) \
-  const Operator* CommonOperatorBuilder::Name() {                        \
-    return &impl_.k##Name##Operator;                                     \
+#define CACHED(Name, properties, value_input_count, effect_input_count, \
+               control_input_count, control_output_count)               \
+  const Operator* CommonOperatorBuilder::Name() {                       \
+    return &cache_.k##Name##Operator;                                   \
   }
-SHARED_OP_LIST(SHARED)
-#undef SHARED
+CACHED_OP_LIST(CACHED)
+#undef CACHED
 
 
 const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
   return new (zone()) Operator1<BranchHint>(
-      IrOpcode::kBranch, Operator::kFoldable, 1, 0, "Branch", hint);
+      IrOpcode::kBranch, Operator::kFoldable, "Branch", 1, 0, 1, 0, 0, 2, hint);
 }
 
 
 const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) {
   // Outputs are formal parameters, plus context, receiver, and JSFunction.
   const int value_output_count = num_formal_parameters + 3;
-  return new (zone()) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
-                                      value_output_count, 0, "Start");
+  return new (zone()) Operator(               // --
+      IrOpcode::kStart, Operator::kFoldable,  // opcode
+      "Start",                                // name
+      0, 0, 0, value_output_count, 1, 1);     // counts
 }
 
 
 const Operator* CommonOperatorBuilder::Merge(int controls) {
-  return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
-                                      0, controls, "Merge");
+  return new (zone()) Operator(               // --
+      IrOpcode::kMerge, Operator::kFoldable,  // opcode
+      "Merge",                                // name
+      0, 0, controls, 0, 0, 1);               // counts
 }
 
 
 const Operator* CommonOperatorBuilder::Loop(int controls) {
-  return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
-                                      0, controls, "Loop");
+  return new (zone()) Operator(              // --
+      IrOpcode::kLoop, Operator::kFoldable,  // opcode
+      "Loop",                                // name
+      0, 0, controls, 0, 0, 1);              // counts
 }
 
 
 const Operator* CommonOperatorBuilder::Terminate(int effects) {
-  return new (zone()) Operator1<int>(IrOpcode::kTerminate,
-                                     Operator::kNoRead | Operator::kNoWrite, 0,
-                                     0, "Terminate", effects);
+  return new (zone()) Operator(               // --
+      IrOpcode::kTerminate, Operator::kPure,  // opcode
+      "Terminate",                            // name
+      0, effects, 1, 0, 0, 1);                // counts
 }
 
 
 const Operator* CommonOperatorBuilder::Parameter(int index) {
-  return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
-                                     1, "Parameter", index);
+  return new (zone()) Operator1<int>(         // --
+      IrOpcode::kParameter, Operator::kPure,  // opcode
+      "Parameter",                            // name
+      1, 0, 0, 1, 0, 0,                       // counts
+      index);                                 // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
-  return new (zone()) Operator1<int32_t>(
-      IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value);
+  return new (zone()) Operator1<int32_t>(         // --
+      IrOpcode::kInt32Constant, Operator::kPure,  // opcode
+      "Int32Constant",                            // name
+      0, 0, 0, 1, 0, 0,                           // counts
+      value);                                     // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
-  return new (zone()) Operator1<int64_t>(
-      IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value);
+  return new (zone()) Operator1<int64_t>(         // --
+      IrOpcode::kInt64Constant, Operator::kPure,  // opcode
+      "Int64Constant",                            // name
+      0, 0, 0, 1, 0, 0,                           // counts
+      value);                                     // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
   return new (zone())
-      Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>(
-          IrOpcode::kFloat32Constant, Operator::kPure, 0, 1, "Float32Constant",
-          value);
+      Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>(  // --
+          IrOpcode::kFloat32Constant, Operator::kPure,  // opcode
+          "Float32Constant",                            // name
+          0, 0, 0, 1, 0, 0,                             // counts
+          value);                                       // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
-  return new (zone())
-      Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>(
-          IrOpcode::kFloat64Constant, Operator::kPure, 0, 1, "Float64Constant",
-          value);
+  return new (zone()) Operator1<double, base::bit_equal_to<double>,
+                                base::bit_hash<double>>(  // --
+      IrOpcode::kFloat64Constant, Operator::kPure,        // opcode
+      "Float64Constant",                                  // name
+      0, 0, 0, 1, 0, 0,                                   // counts
+      value);                                             // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::ExternalConstant(
     const ExternalReference& value) {
-  return new (zone())
-      Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure,
-                                   0, 1, "ExternalConstant", value);
+  return new (zone()) Operator1<ExternalReference>(  // --
+      IrOpcode::kExternalConstant, Operator::kPure,  // opcode
+      "ExternalConstant",                            // name
+      0, 0, 0, 1, 0, 0,                              // counts
+      value);                                        // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
-  return new (zone())
-      Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>(
-          IrOpcode::kNumberConstant, Operator::kPure, 0, 1, "NumberConstant",
-          value);
+  return new (zone()) Operator1<double, base::bit_equal_to<double>,
+                                base::bit_hash<double>>(  // --
+      IrOpcode::kNumberConstant, Operator::kPure,         // opcode
+      "NumberConstant",                                   // name
+      0, 0, 0, 1, 0, 0,                                   // counts
+      value);                                             // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::HeapConstant(
     const Unique<HeapObject>& value) {
-  return new (zone()) Operator1<Unique<HeapObject>>(
-      IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
+  return new (zone()) Operator1<Unique<HeapObject>>(  // --
+      IrOpcode::kHeapConstant, Operator::kPure,       // opcode
+      "HeapConstant",                                 // name
+      0, 0, 0, 1, 0, 0,                               // counts
+      value);                                         // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::Select(MachineType type,
                                               BranchHint hint) {
-  return new (zone())
-      Operator1<SelectParameters>(IrOpcode::kSelect, Operator::kPure, 3, 1,
-                                  "Select", SelectParameters(type, hint));
+  return new (zone()) Operator1<SelectParameters>(  // --
+      IrOpcode::kSelect, Operator::kPure,           // opcode
+      "Select",                                     // name
+      3, 0, 0, 1, 0, 0,                             // counts
+      SelectParameters(type, hint));                // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) {
-  DCHECK(arguments > 0);  // Disallow empty phis.
-  return new (zone()) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure,
-                                             arguments, 1, "Phi", type);
+  DCHECK(arguments > 0);                       // Disallow empty phis.
+  return new (zone()) Operator1<MachineType>(  // --
+      IrOpcode::kPhi, Operator::kPure,         // opcode
+      "Phi",                                   // name
+      arguments, 0, 1, 1, 0, 0,                // counts
+      type);                                   // parameter
 }
 
 
 const Operator* CommonOperatorBuilder::EffectPhi(int arguments) {
-  DCHECK(arguments > 0);  // Disallow empty phis.
-  return new (zone()) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
-                                     0, "EffectPhi", arguments);
+  DCHECK(arguments > 0);                      // Disallow empty phis.
+  return new (zone()) Operator(               // --
+      IrOpcode::kEffectPhi, Operator::kPure,  // opcode
+      "EffectPhi",                            // name
+      0, arguments, 1, 0, 1, 0);              // counts
 }
 
 
 const Operator* CommonOperatorBuilder::ValueEffect(int arguments) {
-  DCHECK(arguments > 0);  // Disallow empty value effects.
-  return new (zone()) Operator1<int>(IrOpcode::kValueEffect, Operator::kPure,
-                                     arguments, 0, "ValueEffect", arguments);
+  DCHECK(arguments > 0);                        // Disallow empty value effects.
+  return new (zone()) Operator(                 // --
+      IrOpcode::kValueEffect, Operator::kPure,  // opcode
+      "ValueEffect",                            // name
+      arguments, 0, 0, 0, 1, 0);                // counts
 }
 
 
 const Operator* CommonOperatorBuilder::Finish(int arguments) {
-  DCHECK(arguments > 0);  // Disallow empty finishes.
-  return new (zone()) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1,
-                                     "Finish", arguments);
+  DCHECK(arguments > 0);                   // Disallow empty finishes.
+  return new (zone()) Operator(            // --
+      IrOpcode::kFinish, Operator::kPure,  // opcode
+      "Finish",                            // name
+      1, arguments, 0, 1, 0, 0);           // counts
 }
 
 
 const Operator* CommonOperatorBuilder::StateValues(int arguments) {
-  return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
-                                     arguments, 1, "StateValues", arguments);
+  return new (zone()) Operator(                 // --
+      IrOpcode::kStateValues, Operator::kPure,  // opcode
+      "StateValues",                            // name
+      arguments, 0, 0, 1, 0, 0);                // counts
 }
 
 
 const Operator* CommonOperatorBuilder::FrameState(
     FrameStateType type, BailoutId bailout_id,
     OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
-  return new (zone()) Operator1<FrameStateCallInfo>(
-      IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
+  return new (zone()) Operator1<FrameStateCallInfo>(  // --
+      IrOpcode::kFrameState, Operator::kPure,         // opcode
+      "FrameState",                                   // name
+      4, 0, 0, 1, 0, 0,                               // counts
       FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
 }
 
@@ -299,15 +328,14 @@ const Operator* CommonOperatorBuilder::FrameState(
 const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
   class CallOperator FINAL : public Operator1<const CallDescriptor*> {
    public:
-    // TODO(titzer): Operator still uses int, whereas CallDescriptor uses
-    // size_t.
     CallOperator(const CallDescriptor* descriptor, const char* mnemonic)
         : Operator1<const CallDescriptor*>(
-              IrOpcode::kCall, descriptor->properties(),
-              static_cast<int>(descriptor->InputCount() +
-                               descriptor->FrameStateCount()),
-              static_cast<int>(descriptor->ReturnCount()), mnemonic,
-              descriptor) {}
+              IrOpcode::kCall, descriptor->properties(), mnemonic,
+              descriptor->InputCount() + descriptor->FrameStateCount(),
+              Operator::ZeroIfPure(descriptor->properties()),
+              Operator::ZeroIfPure(descriptor->properties()),
+              descriptor->ReturnCount(),
+              Operator::ZeroIfPure(descriptor->properties()), 0, descriptor) {}
 
     virtual void PrintParameter(std::ostream& os) const OVERRIDE {
       os << "[" << *parameter() << "]";
@@ -318,8 +346,11 @@ const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
 
 
 const Operator* CommonOperatorBuilder::Projection(size_t index) {
-  return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure,
-                                        1, 1, "Projection", index);
+  return new (zone()) Operator1<size_t>(       // --
+      IrOpcode::kProjection, Operator::kPure,  // opcode
+      "Projection",                            // name
+      1, 0, 0, 1, 0, 0,                        // counts
+      index);                                  // parameter
 }
 
 }  // namespace compiler
index 355269c..9938989 100644 (file)
@@ -19,7 +19,7 @@ namespace compiler {
 
 // Forward declarations.
 class CallDescriptor;
-struct CommonOperatorBuilderImpl;
+struct CommonOperatorGlobalCache;
 class Operator;
 
 
@@ -197,7 +197,7 @@ class CommonOperatorBuilder FINAL : public ZoneObject {
  private:
   Zone* zone() const { return zone_; }
 
-  const CommonOperatorBuilderImpl& impl_;
+  const CommonOperatorGlobalCache& cache_;
   Zone* const zone_;
 
   DISALLOW_COPY_AND_ASSIGN(CommonOperatorBuilder);
index b8d2fca..70ab500 100644 (file)
@@ -962,7 +962,7 @@ void InstructionSelector::VisitThrow(Node* value) {
 void InstructionSelector::FillTypeVectorFromStateValues(
     ZoneVector<MachineType>* types, Node* state_values) {
   DCHECK(state_values->opcode() == IrOpcode::kStateValues);
-  int count = OpParameter<int>(state_values);
+  int count = state_values->InputCount();
   types->reserve(static_cast<size_t>(count));
   for (int i = 0; i < count; i++) {
     types->push_back(GetMachineType(state_values->InputAt(i)));
@@ -974,11 +974,14 @@ FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
     Node* state) {
   DCHECK(state->opcode() == IrOpcode::kFrameState);
   DCHECK_EQ(5, state->InputCount());
+  DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(0)->opcode());
+  DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(1)->opcode());
+  DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(2)->opcode());
   FrameStateCallInfo state_info = OpParameter<FrameStateCallInfo>(state);
 
-  int parameters = OpParameter<int>(state->InputAt(0));
-  int locals = OpParameter<int>(state->InputAt(1));
-  int stack = OpParameter<int>(state->InputAt(2));
+  int parameters = state->InputAt(0)->InputCount();
+  int locals = state->InputAt(1)->InputCount();
+  int stack = state->InputAt(2)->InputCount();
 
   FrameStateDescriptor* outer_state = NULL;
   Node* outer_node = state->InputAt(4);
index 58d4904..587d3ae 100644 (file)
@@ -165,8 +165,8 @@ class CopyVisitor : public NullNodeVisitor {
         source_graph_(source_graph),
         target_graph_(target_graph),
         temp_zone_(temp_zone),
-        sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, 0, 0,
-                     "sentinel") {}
+        sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "sentinel", 0, 0,
+                     0, 0, 0, 0) {}
 
   GenericGraphVisit::Control Post(Node* original) {
     NodeVector inputs(temp_zone_);
@@ -224,7 +224,7 @@ class CopyVisitor : public NullNodeVisitor {
   Graph* source_graph_;
   Graph* target_graph_;
   Zone* temp_zone_;
-  SimpleOperator sentinel_op_;
+  Operator sentinel_op_;
 };
 
 
@@ -453,7 +453,7 @@ class JSCallRuntimeAccessor {
   Node* effect() const { return NodeProperties::GetEffectInput(call_); }
 
   const Runtime::Function* function() const {
-    return Runtime::FunctionForId(OpParameter<Runtime::FunctionId>(call_));
+    return Runtime::FunctionForId(CallRuntimeParametersOf(call_->op()).id());
   }
 
   NodeVector inputs(Zone* zone) const {
index ac140b9..12473c1 100644 (file)
@@ -208,7 +208,7 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
 }
 
 
-#define SHARED_OP_LIST(V)                                 \
+#define CACHED_OP_LIST(V)                                 \
   V(Equal, Operator::kNoProperties, 2, 1)                 \
   V(NotEqual, Operator::kNoProperties, 2, 1)              \
   V(StrictEqual, Operator::kPure, 2, 1)                   \
@@ -247,39 +247,45 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
   V(CreateGlobalContext, Operator::kNoProperties, 2, 1)
 
 
-struct JSOperatorBuilderImpl FINAL {
-#define SHARED(Name, properties, value_input_count, value_output_count)      \
-  struct Name##Operator FINAL : public SimpleOperator {                      \
-    Name##Operator()                                                         \
-        : SimpleOperator(IrOpcode::kJS##Name, properties, value_input_count, \
-                         value_output_count, "JS" #Name) {}                  \
-  };                                                                         \
+struct JSOperatorGlobalCache FINAL {
+#define CACHED(Name, properties, value_input_count, value_output_count)  \
+  struct Name##Operator FINAL : public Operator {                        \
+    Name##Operator()                                                     \
+        : Operator(IrOpcode::kJS##Name, properties, "JS" #Name,          \
+                   value_input_count, Operator::ZeroIfPure(properties),  \
+                   Operator::ZeroIfPure(properties), value_output_count, \
+                   Operator::ZeroIfPure(properties), 0) {}               \
+  };                                                                     \
   Name##Operator k##Name##Operator;
-  SHARED_OP_LIST(SHARED)
-#undef SHARED
+  CACHED_OP_LIST(CACHED)
+#undef CACHED
 };
 
 
-static base::LazyInstance<JSOperatorBuilderImpl>::type kImpl =
+static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
     LAZY_INSTANCE_INITIALIZER;
 
 
 JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
-    : impl_(kImpl.Get()), zone_(zone) {}
+    : cache_(kCache.Get()), zone_(zone) {}
 
 
-#define SHARED(Name, properties, value_input_count, value_output_count) \
-  const Operator* JSOperatorBuilder::Name() { return &impl_.k##Name##Operator; }
-SHARED_OP_LIST(SHARED)
-#undef SHARED
+#define CACHED(Name, properties, value_input_count, value_output_count) \
+  const Operator* JSOperatorBuilder::Name() {                           \
+    return &cache_.k##Name##Operator;                                   \
+  }
+CACHED_OP_LIST(CACHED)
+#undef CACHED
 
 
 const Operator* JSOperatorBuilder::CallFunction(size_t arity,
                                                 CallFunctionFlags flags) {
   CallFunctionParameters parameters(arity, flags);
-  return new (zone()) Operator1<CallFunctionParameters>(
-      IrOpcode::kJSCallFunction, Operator::kNoProperties,
-      static_cast<int>(parameters.arity()), 1, "JSCallFunction", parameters);
+  return new (zone()) Operator1<CallFunctionParameters>(   // --
+      IrOpcode::kJSCallFunction, Operator::kNoProperties,  // opcode
+      "JSCallFunction",                                    // name
+      parameters.arity(), 1, 1, 1, 1, 0,                   // inputs/outputs
+      parameters);                                         // parameter
 }
 
 
@@ -287,18 +293,21 @@ const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
                                                size_t arity) {
   CallRuntimeParameters parameters(id, arity);
   const Runtime::Function* f = Runtime::FunctionForId(parameters.id());
-  int arguments = static_cast<int>(parameters.arity());
-  DCHECK(f->nargs == -1 || f->nargs == arguments);
-  return new (zone()) Operator1<CallRuntimeParameters>(
-      IrOpcode::kJSCallRuntime, Operator::kNoProperties, arguments,
-      f->result_size, "JSCallRuntime", parameters);
+  DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
+  return new (zone()) Operator1<CallRuntimeParameters>(   // --
+      IrOpcode::kJSCallRuntime, Operator::kNoProperties,  // opcode
+      "JSCallRuntime",                                    // name
+      parameters.arity(), 1, 1, f->result_size, 1, 0,     // inputs/outputs
+      parameters);                                        // parameter
 }
 
 
 const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
-  return new (zone())
-      Operator1<int>(IrOpcode::kJSCallConstruct, Operator::kNoProperties,
-                     arguments, 1, "JSCallConstruct", arguments);
+  return new (zone()) Operator1<int>(                       // --
+      IrOpcode::kJSCallConstruct, Operator::kNoProperties,  // opcode
+      "JSCallConstruct",                                    // name
+      arguments, 1, 1, 1, 1, 0,                             // counts
+      arguments);                                           // parameter
 }
 
 
@@ -306,66 +315,82 @@ const Operator* JSOperatorBuilder::LoadNamed(const Unique<Name>& name,
                                              const VectorSlotPair& feedback,
                                              ContextualMode contextual_mode) {
   LoadNamedParameters parameters(name, feedback, contextual_mode);
-  return new (zone()) Operator1<LoadNamedParameters>(
-      IrOpcode::kJSLoadNamed, Operator::kNoProperties, 1, 1, "JSLoadNamed",
-      parameters);
+  return new (zone()) Operator1<LoadNamedParameters>(   // --
+      IrOpcode::kJSLoadNamed, Operator::kNoProperties,  // opcode
+      "JSLoadNamed",                                    // name
+      1, 1, 1, 1, 1, 0,                                 // counts
+      parameters);                                      // parameter
 }
 
 
 const Operator* JSOperatorBuilder::LoadProperty(
     const VectorSlotPair& feedback) {
   LoadPropertyParameters parameters(feedback);
-  return new (zone()) Operator1<LoadPropertyParameters>(
-      IrOpcode::kJSLoadProperty, Operator::kNoProperties, 2, 1,
-      "JSLoadProperty", parameters);
+  return new (zone()) Operator1<LoadPropertyParameters>(   // --
+      IrOpcode::kJSLoadProperty, Operator::kNoProperties,  // opcode
+      "JSLoadProperty",                                    // name
+      2, 1, 1, 1, 1, 0,                                    // counts
+      parameters);                                         // parameter
 }
 
 
 const Operator* JSOperatorBuilder::StoreProperty(StrictMode strict_mode) {
-  return new (zone())
-      Operator1<StrictMode>(IrOpcode::kJSStoreProperty, Operator::kNoProperties,
-                            3, 0, "JSStoreProperty", strict_mode);
+  return new (zone()) Operator1<StrictMode>(                // --
+      IrOpcode::kJSStoreProperty, Operator::kNoProperties,  // opcode
+      "JSStoreProperty",                                    // name
+      3, 1, 1, 0, 1, 0,                                     // counts
+      strict_mode);                                         // parameter
 }
 
 
 const Operator* JSOperatorBuilder::StoreNamed(StrictMode strict_mode,
                                               const Unique<Name>& name) {
   StoreNamedParameters parameters(strict_mode, name);
-  return new (zone()) Operator1<StoreNamedParameters>(
-      IrOpcode::kJSStoreNamed, Operator::kNoProperties, 2, 0, "JSStoreNamed",
-      parameters);
+  return new (zone()) Operator1<StoreNamedParameters>(   // --
+      IrOpcode::kJSStoreNamed, Operator::kNoProperties,  // opcode
+      "JSStoreNamed",                                    // name
+      2, 1, 1, 0, 1, 0,                                  // counts
+      parameters);                                       // parameter
 }
 
 
 const Operator* JSOperatorBuilder::DeleteProperty(StrictMode strict_mode) {
-  return new (zone()) Operator1<StrictMode>(IrOpcode::kJSDeleteProperty,
-                                            Operator::kNoProperties, 2, 1,
-                                            "JSDeleteProperty", strict_mode);
+  return new (zone()) Operator1<StrictMode>(                 // --
+      IrOpcode::kJSDeleteProperty, Operator::kNoProperties,  // opcode
+      "JSDeleteProperty",                                    // name
+      2, 1, 1, 1, 1, 0,                                      // counts
+      strict_mode);                                          // parameter
 }
 
 
 const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
                                                bool immutable) {
   ContextAccess access(depth, index, immutable);
-  return new (zone()) Operator1<ContextAccess>(
-      IrOpcode::kJSLoadContext, Operator::kEliminatable | Operator::kNoWrite, 1,
-      1, "JSLoadContext", access);
+  return new (zone()) Operator1<ContextAccess>(      // --
+      IrOpcode::kJSLoadContext, Operator::kNoWrite,  // opcode
+      "JSLoadContext",                               // name
+      1, 1, 0, 1, 1, 0,                              // counts
+      access);                                       // parameter
 }
 
 
 const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
   ContextAccess access(depth, index, false);
-  return new (zone()) Operator1<ContextAccess>(IrOpcode::kJSStoreContext,
-                                               Operator::kNoProperties, 2, 0,
-                                               "JSStoreContext", access);
+  return new (zone()) Operator1<ContextAccess>(      // --
+      IrOpcode::kJSStoreContext, Operator::kNoRead,  // opcode
+      "JSStoreContext",                              // name
+      2, 1, 1, 0, 1, 0,                              // counts
+      access);                                       // parameter
 }
 
 
 const Operator* JSOperatorBuilder::CreateCatchContext(
     const Unique<String>& name) {
-  return new (zone()) Operator1<Unique<String>>(IrOpcode::kJSCreateCatchContext,
-                                                Operator::kNoProperties, 1, 1,
-                                                "JSCreateCatchContext", name);
+  return new (zone()) Operator1<Unique<String>>(                 // --
+      IrOpcode::kJSCreateCatchContext, Operator::kNoProperties,  // opcode
+      "JSCreateCatchContext",                                    // name
+      1, 1, 1, 1, 1, 0,                                          // counts
+      name);                                                     // parameter
 }
 
 }  // namespace compiler
index 4927ce5..ad3277f 100644 (file)
@@ -14,7 +14,7 @@ namespace compiler {
 
 // Forward declarations.
 class Operator;
-struct JSOperatorBuilderImpl;
+struct JSOperatorGlobalCache;
 
 
 // Defines the arity and the call flags for a JavaScript function call. This is
@@ -264,7 +264,7 @@ class JSOperatorBuilder FINAL : public ZoneObject {
  private:
   Zone* zone() const { return zone_; }
 
-  const JSOperatorBuilderImpl& impl_;
+  const JSOperatorGlobalCache& cache_;
   Zone* const zone_;
 
   DISALLOW_COPY_AND_ASSIGN(JSOperatorBuilder);
index 6e1180f..a4aaa66 100644 (file)
@@ -53,71 +53,71 @@ StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
 
 
 #define PURE_OP_LIST(V)                                                       \
-  V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
-  V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
-  V(Word32Xor, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
-  V(Word32Shl, Operator::kNoProperties, 2, 1)                                 \
-  V(Word32Shr, Operator::kNoProperties, 2, 1)                                 \
-  V(Word32Sar, Operator::kNoProperties, 2, 1)                                 \
-  V(Word32Ror, Operator::kNoProperties, 2, 1)                                 \
-  V(Word32Equal, Operator::kCommutative, 2, 1)                                \
-  V(Word64And, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
-  V(Word64Or, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
-  V(Word64Xor, Operator::kAssociative | Operator::kCommutative, 2, 1)         \
-  V(Word64Shl, Operator::kNoProperties, 2, 1)                                 \
-  V(Word64Shr, Operator::kNoProperties, 2, 1)                                 \
-  V(Word64Sar, Operator::kNoProperties, 2, 1)                                 \
-  V(Word64Ror, Operator::kNoProperties, 2, 1)                                 \
-  V(Word64Equal, Operator::kCommutative, 2, 1)                                \
-  V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
+  V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
+  V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
+  V(Word32Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
+  V(Word32Shl, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word32Shr, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word32Sar, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word32Ror, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word32Equal, Operator::kCommutative, 2, 0, 1)                             \
+  V(Word64And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
+  V(Word64Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
+  V(Word64Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)      \
+  V(Word64Shl, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word64Shr, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word64Sar, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word64Ror, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Word64Equal, Operator::kCommutative, 2, 0, 1)                             \
+  V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
   V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
-    2)                                                                        \
-  V(Int32Sub, Operator::kNoProperties, 2, 1)                                  \
-  V(Int32SubWithOverflow, Operator::kNoProperties, 2, 2)                      \
-  V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
-  V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 1)      \
-  V(Int32Div, Operator::kNoProperties, 2, 1)                                  \
-  V(Int32Mod, Operator::kNoProperties, 2, 1)                                  \
-  V(Int32LessThan, Operator::kNoProperties, 2, 1)                             \
-  V(Int32LessThanOrEqual, Operator::kNoProperties, 2, 1)                      \
-  V(Uint32Div, Operator::kNoProperties, 2, 1)                                 \
-  V(Uint32LessThan, Operator::kNoProperties, 2, 1)                            \
-  V(Uint32LessThanOrEqual, Operator::kNoProperties, 2, 1)                     \
-  V(Uint32Mod, Operator::kNoProperties, 2, 1)                                 \
-  V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
-  V(Int64Sub, Operator::kNoProperties, 2, 1)                                  \
-  V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 1)          \
-  V(Int64Div, Operator::kNoProperties, 2, 1)                                  \
-  V(Int64Mod, Operator::kNoProperties, 2, 1)                                  \
-  V(Int64LessThan, Operator::kNoProperties, 2, 1)                             \
-  V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 1)                      \
-  V(Uint64Div, Operator::kNoProperties, 2, 1)                                 \
-  V(Uint64LessThan, Operator::kNoProperties, 2, 1)                            \
-  V(Uint64Mod, Operator::kNoProperties, 2, 1)                                 \
-  V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 1)                    \
-  V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 1)                      \
-  V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 1)                     \
-  V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 1)                      \
-  V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 1)                        \
-  V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 1)                     \
-  V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 1)                      \
-  V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 1)                  \
-  V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 1)                    \
-  V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 1)                      \
-  V(Float64Add, Operator::kCommutative, 2, 1)                                 \
-  V(Float64Sub, Operator::kNoProperties, 2, 1)                                \
-  V(Float64Mul, Operator::kCommutative, 2, 1)                                 \
-  V(Float64Div, Operator::kNoProperties, 2, 1)                                \
-  V(Float64Mod, Operator::kNoProperties, 2, 1)                                \
-  V(Float64Sqrt, Operator::kNoProperties, 1, 1)                               \
-  V(Float64Ceil, Operator::kNoProperties, 1, 1)                               \
-  V(Float64Floor, Operator::kNoProperties, 1, 1)                              \
-  V(Float64RoundTruncate, Operator::kNoProperties, 1, 1)                      \
-  V(Float64RoundTiesAway, Operator::kNoProperties, 1, 1)                      \
-  V(Float64Equal, Operator::kCommutative, 2, 1)                               \
-  V(Float64LessThan, Operator::kNoProperties, 2, 1)                           \
-  V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 1)                    \
-  V(LoadStackPointer, Operator::kNoProperties, 0, 1)
+    0, 2)                                                                     \
+  V(Int32Sub, Operator::kNoProperties, 2, 0, 1)                               \
+  V(Int32SubWithOverflow, Operator::kNoProperties, 2, 0, 2)                   \
+  V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
+  V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)   \
+  V(Int32Div, Operator::kNoProperties, 2, 1, 1)                               \
+  V(Int32Mod, Operator::kNoProperties, 2, 1, 1)                               \
+  V(Int32LessThan, Operator::kNoProperties, 2, 0, 1)                          \
+  V(Int32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                   \
+  V(Uint32Div, Operator::kNoProperties, 2, 1, 1)                              \
+  V(Uint32LessThan, Operator::kNoProperties, 2, 0, 1)                         \
+  V(Uint32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                  \
+  V(Uint32Mod, Operator::kNoProperties, 2, 1, 1)                              \
+  V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
+  V(Int64Sub, Operator::kNoProperties, 2, 0, 1)                               \
+  V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1)       \
+  V(Int64Div, Operator::kNoProperties, 2, 0, 1)                               \
+  V(Int64Mod, Operator::kNoProperties, 2, 0, 1)                               \
+  V(Int64LessThan, Operator::kNoProperties, 2, 0, 1)                          \
+  V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                   \
+  V(Uint64Div, Operator::kNoProperties, 2, 0, 1)                              \
+  V(Uint64LessThan, Operator::kNoProperties, 2, 0, 1)                         \
+  V(Uint64Mod, Operator::kNoProperties, 2, 0, 1)                              \
+  V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1)                 \
+  V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1)                   \
+  V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1)                  \
+  V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1)                   \
+  V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1)                     \
+  V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1)                  \
+  V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1)                   \
+  V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1)               \
+  V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 0, 1)                 \
+  V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Float64Add, Operator::kCommutative, 2, 0, 1)                              \
+  V(Float64Sub, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Float64Mul, Operator::kCommutative, 2, 0, 1)                              \
+  V(Float64Div, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Float64Mod, Operator::kNoProperties, 2, 0, 1)                             \
+  V(Float64Sqrt, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Float64Ceil, Operator::kNoProperties, 1, 0, 1)                            \
+  V(Float64Floor, Operator::kNoProperties, 1, 0, 1)                           \
+  V(Float64RoundTruncate, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Float64RoundTiesAway, Operator::kNoProperties, 1, 0, 1)                   \
+  V(Float64Equal, Operator::kCommutative, 2, 0, 1)                            \
+  V(Float64LessThan, Operator::kNoProperties, 2, 0, 1)                        \
+  V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1)                 \
+  V(LoadStackPointer, Operator::kNoProperties, 0, 0, 1)
 
 
 #define MACHINE_TYPE_LIST(V) \
@@ -142,64 +142,68 @@ StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
   V(RepTagged)
 
 
-struct MachineOperatorBuilderImpl {
-#define PURE(Name, properties, input_count, output_count)                 \
-  struct Name##Operator FINAL : public SimpleOperator {                   \
-    Name##Operator()                                                      \
-        : SimpleOperator(IrOpcode::k##Name, Operator::kPure | properties, \
-                         input_count, output_count, #Name) {}             \
-  };                                                                      \
+struct MachineOperatorGlobalCache {
+#define PURE(Name, properties, value_input_count, control_input_count,         \
+             output_count)                                                     \
+  struct Name##Operator FINAL : public Operator {                              \
+    Name##Operator()                                                           \
+        : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name,     \
+                   value_input_count, 0, control_input_count, output_count, 0, \
+                   0) {}                                                       \
+  };                                                                           \
   Name##Operator k##Name;
   PURE_OP_LIST(PURE)
 #undef PURE
 
-#define LOAD(Type)                                                            \
-  struct Load##Type##Operator FINAL : public Operator1<LoadRepresentation> {  \
-    Load##Type##Operator()                                                    \
-        : Operator1<LoadRepresentation>(                                      \
-              IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite, 2, 1, \
-              "Load", k##Type) {}                                             \
-  };                                                                          \
+#define LOAD(Type)                                                           \
+  struct Load##Type##Operator FINAL : public Operator1<LoadRepresentation> { \
+    Load##Type##Operator()                                                   \
+        : Operator1<LoadRepresentation>(                                     \
+              IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite,      \
+              "Load", 2, 1, 1, 1, 1, 0, k##Type) {}                          \
+  };                                                                         \
   Load##Type##Operator k##Load##Type;
   MACHINE_TYPE_LIST(LOAD)
 #undef LOAD
 
-#define STORE(Type)                                                           \
-  struct Store##Type##Operator : public Operator1<StoreRepresentation> {      \
-    explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind)       \
-        : Operator1<StoreRepresentation>(                                     \
-              IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow, 3, 0, \
-              "Store", StoreRepresentation(k##Type, write_barrier_kind)) {}   \
-  };                                                                          \
-  struct Store##Type##NoWriteBarrier##Operator FINAL                          \
-      : public Store##Type##Operator {                                        \
-    Store##Type##NoWriteBarrier##Operator()                                   \
-        : Store##Type##Operator(kNoWriteBarrier) {}                           \
-  };                                                                          \
-  struct Store##Type##FullWriteBarrier##Operator FINAL                        \
-      : public Store##Type##Operator {                                        \
-    Store##Type##FullWriteBarrier##Operator()                                 \
-        : Store##Type##Operator(kFullWriteBarrier) {}                         \
-  };                                                                          \
-  Store##Type##NoWriteBarrier##Operator k##Store##Type##NoWriteBarrier;       \
+#define STORE(Type)                                                      \
+  struct Store##Type##Operator : public Operator1<StoreRepresentation> { \
+    explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind)  \
+        : Operator1<StoreRepresentation>(                                \
+              IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow,  \
+              "Store", 3, 1, 1, 0, 1, 0,                                 \
+              StoreRepresentation(k##Type, write_barrier_kind)) {}       \
+  };                                                                     \
+  struct Store##Type##NoWriteBarrier##Operator FINAL                     \
+      : public Store##Type##Operator {                                   \
+    Store##Type##NoWriteBarrier##Operator()                              \
+        : Store##Type##Operator(kNoWriteBarrier) {}                      \
+  };                                                                     \
+  struct Store##Type##FullWriteBarrier##Operator FINAL                   \
+      : public Store##Type##Operator {                                   \
+    Store##Type##FullWriteBarrier##Operator()                            \
+        : Store##Type##Operator(kFullWriteBarrier) {}                    \
+  };                                                                     \
+  Store##Type##NoWriteBarrier##Operator k##Store##Type##NoWriteBarrier;  \
   Store##Type##FullWriteBarrier##Operator k##Store##Type##FullWriteBarrier;
   MACHINE_TYPE_LIST(STORE)
 #undef STORE
 };
 
 
-static base::LazyInstance<MachineOperatorBuilderImpl>::type kImpl =
+static base::LazyInstance<MachineOperatorGlobalCache>::type kCache =
     LAZY_INSTANCE_INITIALIZER;
 
 
 MachineOperatorBuilder::MachineOperatorBuilder(MachineType word, Flags flags)
-    : impl_(kImpl.Get()), word_(word), flags_(flags) {
+    : cache_(kCache.Get()), word_(word), flags_(flags) {
   DCHECK(word == kRepWord32 || word == kRepWord64);
 }
 
 
-#define PURE(Name, properties, input_count, output_count) \
-  const Operator* MachineOperatorBuilder::Name() { return &impl_.k##Name; }
+#define PURE(Name, properties, value_input_count, control_input_count, \
+             output_count)                                             \
+  const Operator* MachineOperatorBuilder::Name() { return &cache_.k##Name; }
 PURE_OP_LIST(PURE)
 #undef PURE
 
@@ -208,7 +212,7 @@ const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
   switch (rep) {
 #define LOAD(Type) \
   case k##Type:    \
-    return &impl_.k##Load##Type;
+    return &cache_.k##Load##Type;
     MACHINE_TYPE_LIST(LOAD)
 #undef LOAD
 
@@ -222,14 +226,14 @@ const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
 
 const Operator* MachineOperatorBuilder::Store(StoreRepresentation rep) {
   switch (rep.machine_type()) {
-#define STORE(Type)                                     \
-  case k##Type:                                         \
-    switch (rep.write_barrier_kind()) {                 \
-      case kNoWriteBarrier:                             \
-        return &impl_.k##Store##Type##NoWriteBarrier;   \
-      case kFullWriteBarrier:                           \
-        return &impl_.k##Store##Type##FullWriteBarrier; \
-    }                                                   \
+#define STORE(Type)                                      \
+  case k##Type:                                          \
+    switch (rep.write_barrier_kind()) {                  \
+      case kNoWriteBarrier:                              \
+        return &cache_.k##Store##Type##NoWriteBarrier;   \
+      case kFullWriteBarrier:                            \
+        return &cache_.k##Store##Type##FullWriteBarrier; \
+    }                                                    \
     break;
     MACHINE_TYPE_LIST(STORE)
 #undef STORE
index f717729..eff9b8b 100644 (file)
@@ -13,7 +13,7 @@ namespace internal {
 namespace compiler {
 
 // Forward declarations.
-struct MachineOperatorBuilderImpl;
+struct MachineOperatorGlobalCache;
 class Operator;
 
 
@@ -210,7 +210,7 @@ class MachineOperatorBuilder FINAL : public ZoneObject {
 #undef PSEUDO_OP_LIST
 
  private:
-  const MachineOperatorBuilderImpl& impl_;
+  const MachineOperatorGlobalCache& cache_;
   const MachineType word_;
   const Flags flags_;
   DISALLOW_COPY_AND_ASSIGN(MachineOperatorBuilder);
index 1d20685..ac3f062 100644 (file)
@@ -264,6 +264,7 @@ class IrOpcode {
 
   // Returns the mnemonic name of an opcode.
   static const char* Mnemonic(Value val) {
+    // TODO(turbofan): make this a table lookup.
     switch (val) {
 #define RETURN_NAME(x) \
   case k##x:           \
@@ -277,6 +278,7 @@ class IrOpcode {
 
   static bool IsJsOpcode(Value val) {
     switch (val) {
+// TODO(turbofan): make this a range check.
 #define RETURN_NAME(x) \
   case k##x:           \
     return true;
@@ -289,6 +291,7 @@ class IrOpcode {
 
   static bool IsControlOpcode(Value val) {
     switch (val) {
+// TODO(turbofan): make this a range check.
 #define RETURN_NAME(x) \
   case k##x:           \
     return true;
@@ -301,6 +304,7 @@ class IrOpcode {
 
   static bool IsLeafOpcode(Value val) {
     switch (val) {
+// TODO(turbofan): make this a table lookup.
 #define RETURN_NAME(x) \
   case k##x:           \
     return true;
@@ -313,6 +317,7 @@ class IrOpcode {
 
   static bool IsCommonOpcode(Value val) {
     switch (val) {
+// TODO(turbofan): make this a table lookup or a range check.
 #define RETURN_NAME(x) \
   case k##x:           \
     return true;
index 0488b1b..409e4f0 100644 (file)
@@ -16,7 +16,7 @@ namespace internal {
 namespace compiler {
 
 inline bool OperatorProperties::HasValueInput(const Operator* op) {
-  return OperatorProperties::GetValueInputCount(op) > 0;
+  return op->ValueInputCount() > 0;
 }
 
 inline bool OperatorProperties::HasContextInput(const Operator* op) {
@@ -25,11 +25,11 @@ inline bool OperatorProperties::HasContextInput(const Operator* op) {
 }
 
 inline bool OperatorProperties::HasEffectInput(const Operator* op) {
-  return OperatorProperties::GetEffectInputCount(op) > 0;
+  return op->EffectInputCount() > 0;
 }
 
 inline bool OperatorProperties::HasControlInput(const Operator* op) {
-  return OperatorProperties::GetControlInputCount(op) > 0;
+  return op->ControlInputCount() > 0;
 }
 
 inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
@@ -94,7 +94,7 @@ inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
 }
 
 inline int OperatorProperties::GetValueInputCount(const Operator* op) {
-  return op->InputCount();
+  return op->ValueInputCount();
 }
 
 inline int OperatorProperties::GetContextInputCount(const Operator* op) {
@@ -106,44 +106,11 @@ inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
 }
 
 inline int OperatorProperties::GetEffectInputCount(const Operator* op) {
-  if (op->opcode() == IrOpcode::kEffectPhi ||
-      op->opcode() == IrOpcode::kFinish ||
-      op->opcode() == IrOpcode::kTerminate) {
-    return OpParameter<int>(op);
-  }
-  if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
-    return 0;  // no effects.
-  return 1;
+  return op->EffectInputCount();
 }
 
 inline int OperatorProperties::GetControlInputCount(const Operator* op) {
-  // TODO(titzer): fix this mess; just make them a count on the operator.
-  switch (op->opcode()) {
-    case IrOpcode::kPhi:
-    case IrOpcode::kEffectPhi:
-    case IrOpcode::kLoad:
-    case IrOpcode::kLoadField:
-    case IrOpcode::kInt32Div:
-    case IrOpcode::kInt32Mod:
-    case IrOpcode::kUint32Div:
-    case IrOpcode::kUint32Mod:
-      return 1;
-#define OPCODE_CASE(x) case IrOpcode::k##x:
-      CONTROL_OP_LIST(OPCODE_CASE)
-#undef OPCODE_CASE
-      if (op->opcode() == IrOpcode::kBranch) return 1;
-      if (op->opcode() == IrOpcode::kTerminate) return 1;
-      // Control operators are Operator1<int>.
-      return OpParameter<int>(op);
-    default:
-      // Operators that have write effects must have a control
-      // dependency. Effect dependencies only ensure the correct order of
-      // write/read operations without consideration of control flow. Without an
-      // explicit control dependency writes can be float in the schedule too
-      // early along a path that shouldn't generate a side-effect.
-      return op->HasProperty(Operator::kNoWrite) ? 0 : 1;
-  }
-  return 0;
+  return op->ControlInputCount();
 }
 
 inline int OperatorProperties::GetTotalInputCount(const Operator* op) {
@@ -156,33 +123,28 @@ inline int OperatorProperties::GetTotalInputCount(const Operator* op) {
 // Output properties.
 
 inline bool OperatorProperties::HasValueOutput(const Operator* op) {
-  return GetValueOutputCount(op) > 0;
+  return op->ValueOutputCount() > 0;
 }
 
 inline bool OperatorProperties::HasEffectOutput(const Operator* op) {
-  return op->opcode() == IrOpcode::kStart ||
-         op->opcode() == IrOpcode::kValueEffect ||
-         (op->opcode() != IrOpcode::kFinish &&
-          op->opcode() != IrOpcode::kTerminate && GetEffectInputCount(op) > 0);
+  return op->EffectOutputCount() > 0;
 }
 
 inline bool OperatorProperties::HasControlOutput(const Operator* op) {
-  IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
-  return (opcode != IrOpcode::kEnd && IrOpcode::IsControlOpcode(opcode));
+  return op->ControlOutputCount() > 0;
 }
 
 
 inline int OperatorProperties::GetValueOutputCount(const Operator* op) {
-  return op->OutputCount();
+  return op->ValueOutputCount();
 }
 
 inline int OperatorProperties::GetEffectOutputCount(const Operator* op) {
-  return HasEffectOutput(op) ? 1 : 0;
+  return op->EffectOutputCount();
 }
 
-inline int OperatorProperties::GetControlOutputCount(const Operator* node) {
-  return node->opcode() == IrOpcode::kBranch ? 2 : HasControlOutput(node) ? 1
-                                                                          : 0;
+inline int OperatorProperties::GetControlOutputCount(const Operator* op) {
+  return op->ControlOutputCount();
 }
 
 
index 5935424..c8687f4 100644 (file)
@@ -10,46 +10,35 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
-Operator::~Operator() {}
 
-
-std::ostream& operator<<(std::ostream& os, const Operator& op) {
-  op.PrintTo(os);
-  return os;
+template <typename N>
+static inline N CheckRange(size_t val) {
+  CHECK(val <= std::numeric_limits<N>::max());
+  return static_cast<N>(val);
 }
 
 
-SimpleOperator::SimpleOperator(Opcode opcode, Properties properties,
-                               size_t input_count, size_t output_count,
-                               const char* mnemonic)
-    : Operator(opcode, properties, mnemonic),
-      input_count_(static_cast<uint8_t>(input_count)),
-      output_count_(static_cast<uint8_t>(output_count)) {
-  DCHECK(input_count <= std::numeric_limits<uint8_t>::max());
-  DCHECK(output_count <= std::numeric_limits<uint8_t>::max());
-}
+Operator::Operator(Opcode opcode, Properties properties, const char* mnemonic,
+                   size_t value_in, size_t effect_in, size_t control_in,
+                   size_t value_out, size_t effect_out, size_t control_out)
+    : opcode_(opcode),
+      properties_(properties),
+      mnemonic_(mnemonic),
+      value_in_(CheckRange<uint32_t>(value_in)),
+      effect_in_(CheckRange<uint16_t>(effect_in)),
+      control_in_(CheckRange<uint16_t>(control_in)),
+      value_out_(CheckRange<uint16_t>(value_out)),
+      effect_out_(CheckRange<uint8_t>(effect_out)),
+      control_out_(CheckRange<uint8_t>(control_out)) {}
 
 
-SimpleOperator::~SimpleOperator() {}
-
-
-bool SimpleOperator::Equals(const Operator* that) const {
-  return opcode() == that->opcode();
-}
-
-
-size_t SimpleOperator::HashCode() const {
-  return base::hash<Opcode>()(opcode());
+std::ostream& operator<<(std::ostream& os, const Operator& op) {
+  op.PrintTo(os);
+  return os;
 }
 
 
-int SimpleOperator::InputCount() const { return input_count_; }
-
-
-int SimpleOperator::OutputCount() const { return output_count_; }
-
-
-void SimpleOperator::PrintTo(std::ostream& os) const { os << mnemonic(); }
+void Operator::PrintTo(std::ostream& os) const { os << mnemonic(); }
 
 }  // namespace compiler
 }  // namespace internal
index f87a3e4..74b714b 100644 (file)
@@ -49,9 +49,12 @@ class Operator : public ZoneObject {
   };
   typedef base::Flags<Property, uint8_t> Properties;
 
-  Operator(Opcode opcode, Properties properties, const char* mnemonic)
-      : opcode_(opcode), properties_(properties), mnemonic_(mnemonic) {}
-  virtual ~Operator();
+  // Constructor.
+  Operator(Opcode opcode, Properties properties, const char* mnemonic,
+           size_t value_in, size_t effect_in, size_t control_in,
+           size_t value_out, size_t effect_out, size_t control_out);
+
+  virtual ~Operator() {}
 
   // A small integer unique to all instances of a particular kind of operator,
   // useful for quick matching for specific kinds of operators. For fast access
@@ -65,12 +68,14 @@ class Operator : public ZoneObject {
   // Check if this operator equals another operator. Equivalent operators can
   // be merged, and nodes with equivalent operators and equivalent inputs
   // can be merged.
-  virtual bool Equals(const Operator*) const = 0;
+  virtual bool Equals(const Operator* that) const {
+    return this->opcode() == that->opcode();
+  }
 
   // Compute a hashcode to speed up equivalence-set checking.
   // Equal operators should always have equal hashcodes, and unequal operators
   // should have unequal hashcodes with high probability.
-  virtual size_t HashCode() const = 0;
+  virtual size_t HashCode() const { return base::hash<Opcode>()(opcode()); }
 
   // Check whether this operator has the given property.
   bool HasProperty(Property property) const {
@@ -78,24 +83,45 @@ class Operator : public ZoneObject {
   }
 
   // Number of data inputs to the operator, for verifying graph structure.
-  virtual int InputCount() const = 0;
+  // TODO(titzer): convert callers to ValueInputCount();
+  int InputCount() const { return ValueInputCount(); }
 
   // Number of data outputs from the operator, for verifying graph structure.
-  virtual int OutputCount() const = 0;
+  // TODO(titzer): convert callers to ValueOutputCount();
+  int OutputCount() const { return ValueOutputCount(); }
 
   Properties properties() const { return properties_; }
 
+  // TODO(titzer): convert return values here to size_t.
+  int ValueInputCount() const { return value_in_; }
+  int EffectInputCount() const { return effect_in_; }
+  int ControlInputCount() const { return control_in_; }
+
+  int ValueOutputCount() const { return value_out_; }
+  int EffectOutputCount() const { return effect_out_; }
+  int ControlOutputCount() const { return control_out_; }
+
+  static inline size_t ZeroIfPure(Properties properties) {
+    return (properties & kPure) == kPure ? 0 : 1;
+  }
+
   // TODO(titzer): API for input and output types, for typechecking graph.
  protected:
   // Print the full operator into the given stream, including any
   // static parameters. Useful for debugging and visualizing the IR.
-  virtual void PrintTo(std::ostream& os) const = 0;  // NOLINT
+  virtual void PrintTo(std::ostream& os) const;
   friend std::ostream& operator<<(std::ostream& os, const Operator& op);
 
  private:
   Opcode opcode_;
   Properties properties_;
   const char* mnemonic_;
+  uint32_t value_in_;
+  uint16_t effect_in_;
+  uint16_t control_in_;
+  uint16_t value_out_;
+  uint8_t effect_out_;
+  uint8_t control_out_;
 
   DISALLOW_COPY_AND_ASSIGN(Operator);
 };
@@ -105,42 +131,18 @@ DEFINE_OPERATORS_FOR_FLAGS(Operator::Properties)
 std::ostream& operator<<(std::ostream& os, const Operator& op);
 
 
-// An implementation of Operator that has no static parameters. Such operators
-// have just a name, an opcode, and a fixed number of inputs and outputs.
-// They can represented by singletons and shared globally.
-class SimpleOperator : public Operator {
- public:
-  SimpleOperator(Opcode opcode, Properties properties, size_t input_count,
-                 size_t output_count, const char* mnemonic);
-  ~SimpleOperator();
-
-  virtual bool Equals(const Operator* that) const FINAL;
-  virtual size_t HashCode() const FINAL;
-  virtual int InputCount() const FINAL;
-  virtual int OutputCount() const FINAL;
-
- private:
-  virtual void PrintTo(std::ostream& os) const FINAL;
-
-  uint8_t input_count_;
-  uint8_t output_count_;
-
-  DISALLOW_COPY_AND_ASSIGN(SimpleOperator);
-};
-
-
 // A templatized implementation of Operator that has one static parameter of
 // type {T}.
 template <typename T, typename Pred = std::equal_to<T>,
           typename Hash = base::hash<T>>
 class Operator1 : public Operator {
  public:
-  Operator1(Opcode opcode, Properties properties, int input_count,
-            int output_count, const char* mnemonic, T parameter,
-            Pred const& pred = Pred(), Hash const& hash = Hash())
-      : Operator(opcode, properties, mnemonic),
-        input_count_(input_count),
-        output_count_(output_count),
+  Operator1(Opcode opcode, Properties properties, const char* mnemonic,
+            size_t value_in, size_t effect_in, size_t control_in,
+            size_t value_out, size_t effect_out, size_t control_out,
+            T parameter, Pred const& pred = Pred(), Hash const& hash = Hash())
+      : Operator(opcode, properties, mnemonic, value_in, effect_in, control_in,
+                 value_out, effect_out, control_out),
         parameter_(parameter),
         pred_(pred),
         hash_(hash) {}
@@ -155,8 +157,6 @@ class Operator1 : public Operator {
   virtual size_t HashCode() const FINAL {
     return base::hash_combine(this->opcode(), this->hash_(this->parameter()));
   }
-  virtual int InputCount() const FINAL { return input_count_; }
-  virtual int OutputCount() const FINAL { return output_count_; }
   virtual void PrintParameter(std::ostream& os) const {
     os << "[" << this->parameter() << "]";
   }
@@ -168,8 +168,6 @@ class Operator1 : public Operator {
   }
 
  private:
-  int const input_count_;
-  int const output_count_;
   T const parameter_;
   Pred const pred_;
   Hash const hash_;
index 43a0d52..ea691f9 100644 (file)
@@ -1122,7 +1122,7 @@ void SimplifiedLowering::DoLoadField(Node* node) {
   const FieldAccess& access = FieldAccessOf(node->op());
   node->set_op(machine()->Load(access.machine_type));
   Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
-  node->InsertInput(zone(), 1, offset);
+  node->InsertInput(graph()->zone(), 1, offset);
 }
 
 
@@ -1133,7 +1133,7 @@ void SimplifiedLowering::DoStoreField(Node* node) {
   node->set_op(
       machine()->Store(StoreRepresentation(access.machine_type, kind)));
   Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
-  node->InsertInput(zone(), 1, offset);
+  node->InsertInput(graph()->zone(), 1, offset);
 }
 
 
@@ -1336,10 +1336,11 @@ void SimplifiedLowering::DoStringAdd(Node* node) {
   CallDescriptor* desc =
       Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone());
   node->set_op(common()->Call(desc));
-  node->InsertInput(zone(), 0, jsgraph()->HeapConstant(callable.code()));
-  node->AppendInput(zone(), jsgraph()->UndefinedConstant());
-  node->AppendInput(zone(), graph()->start());
-  node->AppendInput(zone(), graph()->start());
+  node->InsertInput(graph()->zone(), 0,
+                    jsgraph()->HeapConstant(callable.code()));
+  node->AppendInput(graph()->zone(), jsgraph()->UndefinedConstant());
+  node->AppendInput(graph()->zone(), graph()->start());
+  node->AppendInput(graph()->zone(), graph()->start());
 }
 
 
index fc8415f..15b34f9 100644 (file)
@@ -140,53 +140,55 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
   V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
 
 
-#define ACCESS_OP_LIST(V)                                 \
-  V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1)     \
-  V(StoreField, FieldAccess, Operator::kNoRead, 2, 0)     \
-  V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 1) \
-  V(StoreElement, ElementAccess, Operator::kNoRead, 4, 0)
-
-
-struct SimplifiedOperatorBuilderImpl FINAL {
-#define PURE(Name, properties, input_count)                               \
-  struct Name##Operator FINAL : public SimpleOperator {                   \
-    Name##Operator()                                                      \
-        : SimpleOperator(IrOpcode::k##Name, Operator::kPure | properties, \
-                         input_count, 1, #Name) {}                        \
-  };                                                                      \
+struct SimplifiedOperatorGlobalCache FINAL {
+#define PURE(Name, properties, input_count)                                \
+  struct Name##Operator FINAL : public Operator {                          \
+    Name##Operator()                                                       \
+        : Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
+                   input_count, 0, 0, 1, 0, 0) {}                          \
+  };                                                                       \
   Name##Operator k##Name;
   PURE_OP_LIST(PURE)
 #undef PURE
 };
 
 
-static base::LazyInstance<SimplifiedOperatorBuilderImpl>::type kImpl =
+static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
     LAZY_INSTANCE_INITIALIZER;
 
 
 SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
-    : impl_(kImpl.Get()), zone_(zone) {}
+    : cache_(kCache.Get()), zone_(zone) {}
 
 
 #define PURE(Name, properties, input_count) \
-  const Operator* SimplifiedOperatorBuilder::Name() { return &impl_.k##Name; }
+  const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
 PURE_OP_LIST(PURE)
 #undef PURE
 
 
 const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
   // TODO(titzer): What about the type parameter?
-  return new (zone()) SimpleOperator(IrOpcode::kReferenceEqual,
-                                     Operator::kCommutative | Operator::kPure,
-                                     2, 1, "ReferenceEqual");
+  return new (zone()) Operator(IrOpcode::kReferenceEqual,
+                               Operator::kCommutative | Operator::kPure,
+                               "ReferenceEqual", 2, 0, 0, 1, 0, 0);
 }
 
 
-#define ACCESS(Name, Type, properties, input_count, output_count)           \
-  const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {     \
-    return new (zone())                                                     \
-        Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \
-                        input_count, output_count, #Name, access);          \
+#define ACCESS_OP_LIST(V)                                    \
+  V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1)     \
+  V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0)     \
+  V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 0, 1) \
+  V(StoreElement, ElementAccess, Operator::kNoRead, 4, 1, 0)
+
+
+#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
+               output_count)                                                   \
+  const Operator* SimplifiedOperatorBuilder::Name(const Type& access) {        \
+    return new (zone())                                                        \
+        Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties,    \
+                        #Name, value_input_count, 1, control_input_count,      \
+                        output_count, 1, 0, access);                           \
   }
 ACCESS_OP_LIST(ACCESS)
 #undef ACCESS
index 7e80fc3..c918042 100644 (file)
@@ -25,7 +25,7 @@ namespace compiler {
 
 // Forward declarations.
 class Operator;
-struct SimplifiedOperatorBuilderImpl;
+struct SimplifiedOperatorGlobalCache;
 
 
 enum BaseTaggedness { kUntaggedBase, kTaggedBase };
@@ -161,7 +161,7 @@ class SimplifiedOperatorBuilder FINAL {
  private:
   Zone* zone() const { return zone_; }
 
-  const SimplifiedOperatorBuilderImpl& impl_;
+  const SimplifiedOperatorGlobalCache& cache_;
   Zone* const zone_;
 
   DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorBuilder);
index 42b582c..013613d 100644 (file)
@@ -301,7 +301,7 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
       break;
     case IrOpcode::kProjection: {
       // Projection has an input that produces enough values.
-      int index = OpParameter<int>(node->op());
+      int index = static_cast<int>(OpParameter<size_t>(node->op()));
       Node* input = NodeProperties::GetValueInput(node, 0);
       CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
       // Type can be anything.
index 03b4b22..03a7887 100644 (file)
@@ -76,10 +76,8 @@ Node* SimplifiedGraphBuilder::MakeNode(const Operator* op,
     if (has_effect) {
       effect_ = result;
     }
-    if (OperatorProperties::HasControlOutput(result->op())) {
-      // This graph builder does not support control flow.
-      UNREACHABLE();
-    }
+    // This graph builder does not support control flow.
+    CHECK_EQ(0, op->ControlOutputCount());
   }
 
   return result;
index b94ca45..7f217d7 100644 (file)
@@ -21,15 +21,15 @@ const uint8_t OPCODE_C0 = 30;
 const uint8_t OPCODE_C1 = 31;
 const uint8_t OPCODE_C2 = 32;
 
-static SimpleOperator OPA0(OPCODE_A0, Operator::kNoWrite, 0, 0, "opa0");
-static SimpleOperator OPA1(OPCODE_A1, Operator::kNoWrite, 1, 0, "opa1");
-static SimpleOperator OPA2(OPCODE_A2, Operator::kNoWrite, 2, 0, "opa2");
-static SimpleOperator OPB0(OPCODE_B0, Operator::kNoWrite, 0, 0, "opa0");
-static SimpleOperator OPB1(OPCODE_B1, Operator::kNoWrite, 1, 0, "opa1");
-static SimpleOperator OPB2(OPCODE_B2, Operator::kNoWrite, 2, 0, "opa2");
-static SimpleOperator OPC0(OPCODE_C0, Operator::kNoWrite, 0, 0, "opc0");
-static SimpleOperator OPC1(OPCODE_C1, Operator::kNoWrite, 1, 0, "opc1");
-static SimpleOperator OPC2(OPCODE_C2, Operator::kNoWrite, 2, 0, "opc2");
+static Operator OPA0(OPCODE_A0, Operator::kNoWrite, "opa0", 0, 0, 0, 0, 0, 0);
+static Operator OPA1(OPCODE_A1, Operator::kNoWrite, "opa1", 1, 0, 0, 0, 0, 0);
+static Operator OPA2(OPCODE_A2, Operator::kNoWrite, "opa2", 2, 0, 0, 0, 0, 0);
+static Operator OPB0(OPCODE_B0, Operator::kNoWrite, "opa0", 0, 0, 0, 0, 0, 0);
+static Operator OPB1(OPCODE_B1, Operator::kNoWrite, "opa1", 1, 0, 0, 0, 0, 0);
+static Operator OPB2(OPCODE_B2, Operator::kNoWrite, "opa2", 2, 0, 0, 0, 0, 0);
+static Operator OPC0(OPCODE_C0, Operator::kNoWrite, "opc0", 0, 0, 0, 0, 0, 0);
+static Operator OPC1(OPCODE_C1, Operator::kNoWrite, "opc1", 1, 0, 0, 0, 0, 0);
+static Operator OPC2(OPCODE_C2, Operator::kNoWrite, "opc2", 2, 0, 0, 0, 0, 0);
 
 
 // Replaces all "A" operators with "B" operators without creating new nodes.
index 923f7fc..267d464 100644 (file)
@@ -23,8 +23,8 @@
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
-                                     0, 0, "dummy");
+static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
+                               "dummy", 0, 0, 0, 0, 0, 0);
 
 // So we can get a real JS function.
 static Handle<JSFunction> Compile(const char* source) {
index 10f98a6..c5e762d 100644 (file)
@@ -18,8 +18,8 @@
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
-                                     0, 0, "dummy");
+static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
+                               "dummy", 0, 0, 0, 1, 0, 0);
 
 class PreNodeVisitor : public NullNodeVisitor {
  public:
index 28d807e..5ac2e4a 100644 (file)
@@ -14,8 +14,8 @@
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
-                                     0, 0, "dummy");
+static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
+                               "dummy", 0, 0, 0, 1, 0, 0);
 
 TEST(NodeAllocation) {
   GraphTester graph;
index 37cf3a3..39f660f 100644 (file)
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 
-TEST(TestOperatorMnemonic) {
-  SimpleOperator op1(10, Operator::kNoProperties, 0, 0, "ThisOne");
+#define NONE Operator::kNoProperties
+#define FOLD Operator::kFoldable
+
+
+TEST(TestOperator_Mnemonic) {
+  Operator op1(10, NONE, "ThisOne", 0, 0, 0, 0, 0, 0);
   CHECK_EQ(0, strcmp(op1.mnemonic(), "ThisOne"));
 
-  SimpleOperator op2(11, Operator::kNoProperties, 0, 0, "ThatOne");
+  Operator op2(11, NONE, "ThatOne", 0, 0, 0, 0, 0, 0);
   CHECK_EQ(0, strcmp(op2.mnemonic(), "ThatOne"));
 
-  Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "Mnemonic1", 12333);
+  Operator1<int> op3(12, NONE, "Mnemonic1", 0, 0, 0, 1, 0, 0, 12333);
   CHECK_EQ(0, strcmp(op3.mnemonic(), "Mnemonic1"));
 
-  Operator1<double> op4(13, Operator::kNoProperties, 0, 1, "TheOther", 99.9);
+  Operator1<double> op4(13, NONE, "TheOther", 0, 0, 0, 1, 0, 0, 99.9);
   CHECK_EQ(0, strcmp(op4.mnemonic(), "TheOther"));
 }
 
 
-TEST(TestSimpleOperatorHash) {
-  SimpleOperator op1(17, Operator::kNoProperties, 0, 0, "Another");
+TEST(TestOperator_Hash) {
+  Operator op1(17, NONE, "Another", 0, 0, 0, 0, 0, 0);
   CHECK_EQ(17, static_cast<int>(op1.HashCode()));
 
-  SimpleOperator op2(18, Operator::kNoProperties, 0, 0, "Falsch");
+  Operator op2(18, NONE, "Falsch", 0, 0, 0, 0, 0, 0);
   CHECK_EQ(18, static_cast<int>(op2.HashCode()));
 }
 
 
-TEST(TestSimpleOperatorEquals) {
-  SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
-  SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");
+TEST(TestOperator_Equals) {
+  Operator op1a(19, NONE, "Another1", 0, 0, 0, 0, 0, 0);
+  Operator op1b(19, FOLD, "Another2", 2, 0, 0, 2, 0, 0);
 
   CHECK(op1a.Equals(&op1a));
   CHECK(op1a.Equals(&op1b));
   CHECK(op1b.Equals(&op1a));
   CHECK(op1b.Equals(&op1b));
 
-  SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Falsch1");
-  SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Falsch2");
+  Operator op2a(20, NONE, "Falsch1", 0, 0, 0, 0, 0, 0);
+  Operator op2b(20, FOLD, "Falsch2", 1, 0, 0, 1, 0, 0);
 
   CHECK(op2a.Equals(&op2a));
   CHECK(op2a.Equals(&op2b));
@@ -72,46 +76,46 @@ static SmartArrayPointer<const char> OperatorToString(Operator* op) {
 }
 
 
-TEST(TestSimpleOperatorPrint) {
-  SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
-  SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");
+TEST(TestOperator_Print) {
+  Operator op1a(19, NONE, "Another1", 0, 0, 0, 0, 0, 0);
+  Operator op1b(19, FOLD, "Another2", 2, 0, 0, 2, 0, 0);
 
   CHECK_EQ("Another1", OperatorToString(&op1a).get());
   CHECK_EQ("Another2", OperatorToString(&op1b).get());
 
-  SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Flog1");
-  SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Flog2");
+  Operator op2a(20, NONE, "Flog1", 0, 0, 0, 0, 0, 0);
+  Operator op2b(20, FOLD, "Flog2", 1, 0, 0, 1, 0, 0);
 
   CHECK_EQ("Flog1", OperatorToString(&op2a).get());
   CHECK_EQ("Flog2", OperatorToString(&op2b).get());
 }
 
 
-TEST(TestOperator1intHash) {
-  Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11);
-  Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11);
+TEST(TestOperator1int_Hash) {
+  Operator1<int> op1a(23, NONE, "Wolfie", 0, 0, 0, 0, 0, 0, 11);
+  Operator1<int> op1b(23, FOLD, "Doggie", 2, 0, 0, 2, 0, 0, 11);
 
   CHECK(op1a.HashCode() == op1b.HashCode());
 
-  Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", 3);
-  Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", 4);
+  Operator1<int> op2a(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, 3);
+  Operator1<int> op2b(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, 4);
 
   CHECK(op1a.HashCode() != op2a.HashCode());
   CHECK(op2a.HashCode() != op2b.HashCode());
 }
 
 
-TEST(TestOperator1intEquals) {
-  Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11);
-  Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11);
+TEST(TestOperator1int_Equals) {
+  Operator1<int> op1a(23, NONE, "Scratchy", 0, 0, 0, 0, 0, 0, 11);
+  Operator1<int> op1b(23, FOLD, "Scratchy", 2, 0, 0, 2, 0, 0, 11);
 
   CHECK(op1a.Equals(&op1a));
   CHECK(op1a.Equals(&op1b));
   CHECK(op1b.Equals(&op1a));
   CHECK(op1b.Equals(&op1b));
 
-  Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3);
-  Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Im", 4);
+  Operator1<int> op2a(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 3);
+  Operator1<int> op2b(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 4);
 
   CHECK(op2a.Equals(&op2a));
   CHECK(!op2a.Equals(&op2b));
@@ -128,7 +132,7 @@ TEST(TestOperator1intEquals) {
   CHECK(!op2b.Equals(&op1a));
   CHECK(!op2b.Equals(&op1b));
 
-  SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");
+  Operator op3(25, NONE, "Weepy", 0, 0, 0, 0, 0, 0);
 
   CHECK(!op1a.Equals(&op3));
   CHECK(!op1b.Equals(&op3));
@@ -142,46 +146,55 @@ TEST(TestOperator1intEquals) {
 }
 
 
-TEST(TestOperator1intPrint) {
-  Operator1<int> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
+TEST(TestOperator1int_Print) {
+  Operator1<int> op1(12, NONE, "Op1Test", 0, 0, 0, 1, 0, 0, 0);
   CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
 
-  Operator1<int> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 66666666);
+  Operator1<int> op2(12, NONE, "Op1Test", 0, 0, 0, 1, 0, 0, 66666666);
   CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());
 
-  Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2347);
+  Operator1<int> op3(12, NONE, "FooBar", 0, 0, 0, 1, 0, 0, 2347);
   CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());
 
-  Operator1<int> op4(12, Operator::kNoProperties, 0, 1, "BarFoo", -879);
+  Operator1<int> op4(12, NONE, "BarFoo", 0, 0, 0, 1, 0, 0, -879);
   CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
 }
 
 
-TEST(TestOperator1doubleHash) {
-  Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11.77);
-  Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11.77);
+TEST(TestOperator1double_Hash) {
+  Operator1<double> op1a(23, NONE, "Wolfie", 0, 0, 0, 0, 0, 0, 11.77);
+  Operator1<double> op1b(23, FOLD, "Doggie", 2, 0, 0, 2, 0, 0, 11.77);
 
   CHECK(op1a.HashCode() == op1b.HashCode());
 
-  Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", -6.7);
-  Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", -6.8);
+  Operator1<double> op2a(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, -6.7);
+  Operator1<double> op2b(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, -6.8);
 
   CHECK(op1a.HashCode() != op2a.HashCode());
   CHECK(op2a.HashCode() != op2b.HashCode());
 }
 
 
-TEST(TestOperator1doubleEquals) {
-  Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11.77);
-  Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11.77);
+TEST(TestOperator1doublePrint) {
+  Operator1<double> op1a(23, NONE, "Canary", 0, 0, 0, 0, 0, 0, 0.5);
+  Operator1<double> op1b(23, FOLD, "Finch", 2, 0, 0, 2, 0, 0, -1.5);
+
+  CHECK_EQ("Canary[0.5]", OperatorToString(&op1a).get());
+  CHECK_EQ("Finch[-1.5]", OperatorToString(&op1b).get());
+}
+
+
+TEST(TestOperator1double_Equals) {
+  Operator1<double> op1a(23, NONE, "Scratchy", 0, 0, 0, 0, 0, 0, 11.77);
+  Operator1<double> op1b(23, FOLD, "Scratchy", 2, 0, 0, 2, 0, 0, 11.77);
 
   CHECK(op1a.Equals(&op1a));
   CHECK(op1a.Equals(&op1b));
   CHECK(op1b.Equals(&op1a));
   CHECK(op1b.Equals(&op1b));
 
-  Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3.1);
-  Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Im", 3.2);
+  Operator1<double> op2a(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 3.1);
+  Operator1<double> op2b(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 3.2);
 
   CHECK(op2a.Equals(&op2a));
   CHECK(!op2a.Equals(&op2b));
@@ -198,7 +211,7 @@ TEST(TestOperator1doubleEquals) {
   CHECK(!op2b.Equals(&op1a));
   CHECK(!op2b.Equals(&op1b));
 
-  SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");
+  Operator op3(25, NONE, "Weepy", 0, 0, 0, 0, 0, 0);
 
   CHECK(!op1a.Equals(&op3));
   CHECK(!op1b.Equals(&op3));
@@ -210,8 +223,8 @@ TEST(TestOperator1doubleEquals) {
   CHECK(!op3.Equals(&op2a));
   CHECK(!op3.Equals(&op2b));
 
-  Operator1<double> op4a(24, Operator::kNoProperties, 0, 0, "Bashful", 1.0);
-  Operator1<double> op4b(24, Operator::kNoProperties, 0, 0, "Bashful", 1.0);
+  Operator1<double> op4a(24, NONE, "Bashful", 0, 0, 0, 0, 0, 0, 1.0);
+  Operator1<double> op4b(24, NONE, "Bashful", 0, 0, 0, 0, 0, 0, 1.0);
 
   CHECK(op4a.Equals(&op4a));
   CHECK(op4a.Equals(&op4b));
@@ -223,3 +236,48 @@ TEST(TestOperator1doubleEquals) {
   CHECK(!op3.Equals(&op4a));
   CHECK(!op3.Equals(&op4b));
 }
+
+
+TEST(TestOpParameter_Operator1double) {
+  double values[] = {7777.5, -66, 0, 11, 0.1};
+
+  for (size_t i = 0; i < arraysize(values); i++) {
+    Operator1<double> op(33, NONE, "Scurvy", 0, 0, 0, 0, 0, 0, values[i]);
+    CHECK_EQ(values[i], OpParameter<double>(&op));
+  }
+}
+
+
+TEST(TestOpParameter_Operator1float) {
+  float values[] = {// thanks C++.
+                    static_cast<float>(7777.5), static_cast<float>(-66),
+                    static_cast<float>(0), static_cast<float>(11),
+                    static_cast<float>(0.1)};
+
+  for (size_t i = 0; i < arraysize(values); i++) {
+    Operator1<float> op(33, NONE, "Scurvy", 0, 0, 0, 0, 0, 0, values[i]);
+    CHECK_EQ(values[i], OpParameter<float>(&op));
+  }
+}
+
+
+TEST(TestOpParameter_Operator1int) {
+  int values[] = {7777, -66, 0, 11, 1, 0x666aff};
+
+  for (size_t i = 0; i < arraysize(values); i++) {
+    Operator1<int> op(33, NONE, "Scurvy", 0, 0, 0, 0, 0, 0, values[i]);
+    CHECK_EQ(values[i], OpParameter<int>(&op));
+  }
+}
+
+
+TEST(Operator_CountsOrder) {
+  Operator op(29, NONE, "Flashy", 11, 22, 33, 44, 55, 66);
+  CHECK_EQ(11, op.ValueInputCount());
+  CHECK_EQ(22, op.EffectInputCount());
+  CHECK_EQ(33, op.ControlInputCount());
+
+  CHECK_EQ(44, op.ValueOutputCount());
+  CHECK_EQ(55, op.EffectOutputCount());
+  CHECK_EQ(66, op.ControlOutputCount());
+}
index da52a66..7b4f975 100644 (file)
@@ -16,8 +16,8 @@
 using namespace v8::internal;
 using namespace v8::internal::compiler;
 
-static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
-                                     0, 0, "dummy");
+static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
+                               "dummy", 0, 0, 0, 0, 0, 0);
 
 TEST(TestScheduleAllocation) {
   HandleAndZoneScope scope;
index 802d78c..269049e 100644 (file)
@@ -49,8 +49,8 @@ const SharedOperator kSharedOperators[] = {
     SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0),
     SHARED(IfTrue, Operator::kFoldable, 0, 0, 1, 0, 1),
     SHARED(IfFalse, Operator::kFoldable, 0, 0, 1, 0, 1),
-    SHARED(Throw, Operator::kFoldable, 1, 0, 1, 0, 1),
-    SHARED(Return, Operator::kNoProperties, 1, 1, 1, 1, 1)
+    SHARED(Throw, Operator::kFoldable, 1, 1, 1, 0, 1),
+    SHARED(Return, Operator::kNoProperties, 1, 1, 1, 0, 1)
 #undef SHARED
 };
 
@@ -130,7 +130,7 @@ class CommonOperatorTest : public TestWithZone {
 };
 
 
-const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
+const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
 
 
 const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),
index 4cd4dd9..88f25f7 100644 (file)
@@ -18,10 +18,18 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
+struct TestOperator : public Operator {
+  TestOperator(Operator::Opcode opcode, Operator::Properties properties,
+               size_t value_in, size_t value_out)
+      : Operator(opcode, properties, "TestOp", value_in, 0, 0, value_out, 0,
+                 0) {}
+};
+
+
 namespace {
 
-SimpleOperator OP0(0, Operator::kNoWrite, 0, 1, "op0");
-SimpleOperator OP1(1, Operator::kNoProperties, 1, 1, "op1");
+TestOperator OP0(0, Operator::kNoWrite, 0, 1);
+TestOperator OP1(1, Operator::kNoProperties, 1, 1);
 
 
 struct MockReducer : public Reducer {
index 5de4235..08fabfd 100644 (file)
@@ -68,7 +68,7 @@ const SharedOperator kSharedOperators[] = {
     SHARED(ToName, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
     SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1),
     SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
-    SHARED(Create, Operator::kEliminatable, 0, 0, 1, 0, 1, 1),
+    SHARED(Create, Operator::kEliminatable, 0, 0, 1, 1, 1, 1),
     SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
     SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0),
     SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
index 7fa3f55..b6be0bf 100644 (file)
@@ -12,12 +12,16 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
-namespace {
+struct TestOperator : public Operator {
+  TestOperator(Operator::Opcode opcode, Operator::Properties properties,
+               size_t value_in, size_t value_out)
+      : Operator(opcode, properties, "TestOp", value_in, 0, 0, value_out, 0,
+                 0) {}
+};
 
-const SimpleOperator kOp0(0, Operator::kEliminatable, 0, 1, "op0");
-const SimpleOperator kOp1(1, Operator::kEliminatable, 1, 1, "op1");
 
-}  // namespace
+static const TestOperator kOp0(0, Operator::kEliminatable, 0, 1);
+static const TestOperator kOp1(1, Operator::kEliminatable, 1, 1);
 
 
 class ValueNumberingReducerTest : public TestWithZone {
@@ -55,7 +59,7 @@ TEST_F(ValueNumberingReducerTest, DeadNodesAreNeverReturned) {
 
 
 TEST_F(ValueNumberingReducerTest, OnlyEliminatableNodesAreReduced) {
-  SimpleOperator op(0, Operator::kNoProperties, 0, 1, "op");
+  TestOperator op(0, Operator::kNoProperties, 0, 1);
   Node* n0 = graph()->NewNode(&op);
   Node* n1 = graph()->NewNode(&op);
   EXPECT_FALSE(Reduce(n0).Changed());
@@ -69,20 +73,18 @@ TEST_F(ValueNumberingReducerTest, OperatorEqualityNotIdentity) {
   for (size_t i = 0; i < arraysize(inputs); ++i) {
     Operator::Opcode opcode = static_cast<Operator::Opcode>(
         std::numeric_limits<Operator::Opcode>::max() - i);
-    inputs[i] = graph()->NewNode(new (zone()) SimpleOperator(
-        opcode, Operator::kEliminatable, 0, 1, "Operator"));
+    inputs[i] = graph()->NewNode(
+        new (zone()) TestOperator(opcode, Operator::kEliminatable, 0, 1));
   }
   TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
-    const SimpleOperator op1(static_cast<Operator::Opcode>(input_count),
-                             Operator::kEliminatable,
-                             static_cast<int>(input_count), 1, "op");
+    const TestOperator op1(static_cast<Operator::Opcode>(input_count),
+                           Operator::kEliminatable, input_count, 1);
     Node* n1 = graph()->NewNode(&op1, static_cast<int>(input_count), inputs);
     Reduction r1 = Reduce(n1);
     EXPECT_FALSE(r1.Changed());
 
-    const SimpleOperator op2(static_cast<Operator::Opcode>(input_count),
-                             Operator::kEliminatable,
-                             static_cast<int>(input_count), 1, "op");
+    const TestOperator op2(static_cast<Operator::Opcode>(input_count),
+                           Operator::kEliminatable, input_count, 1);
     Node* n2 = graph()->NewNode(&op2, static_cast<int>(input_count), inputs);
     Reduction r2 = Reduce(n2);
     EXPECT_TRUE(r2.Changed());
@@ -97,12 +99,11 @@ TEST_F(ValueNumberingReducerTest, SubsequentReductionsYieldTheSameNode) {
   for (size_t i = 0; i < arraysize(inputs); ++i) {
     Operator::Opcode opcode = static_cast<Operator::Opcode>(
         std::numeric_limits<Operator::Opcode>::max() - i);
-    inputs[i] = graph()->NewNode(new (zone()) SimpleOperator(
-        opcode, Operator::kEliminatable, 0, 1, "Operator"));
+    inputs[i] = graph()->NewNode(
+        new (zone()) TestOperator(opcode, Operator::kEliminatable, 0, 1));
   }
   TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
-    const SimpleOperator op1(1, Operator::kEliminatable,
-                             static_cast<int>(input_count), 1, "op1");
+    const TestOperator op1(1, Operator::kEliminatable, input_count, 1);
     Node* n = graph()->NewNode(&op1, static_cast<int>(input_count), inputs);
     Reduction r = Reduce(n);
     EXPECT_FALSE(r.Changed());