[turbofan] Some common operators are globally shared singletons.
authorbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 12 Sep 2014 11:59:26 +0000 (11:59 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org>
Fri, 12 Sep 2014 11:59:26 +0000 (11:59 +0000)
TEST=compiler-unittests,cctest
R=mstarzinger@chromium.org

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

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23913 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

12 files changed:
BUILD.gn
src/compiler/common-operator-unittest.cc
src/compiler/common-operator.cc [new file with mode: 0644]
src/compiler/common-operator.h
src/compiler/instruction.h
src/compiler/operator-properties-inl.h
src/compiler/operator.cc
src/compiler/operator.h
src/compiler/raw-machine-assembler.h
test/cctest/compiler/graph-builder-tester.cc
test/cctest/compiler/test-instruction.cc
tools/gyp/v8.gyp

index 5674e75..dced280 100644 (file)
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -474,6 +474,7 @@ source_set("v8_base") {
     "src/compiler/code-generator.cc",
     "src/compiler/code-generator.h",
     "src/compiler/common-node-cache.h",
+    "src/compiler/common-operator.cc",
     "src/compiler/common-operator.h",
     "src/compiler/control-builders.cc",
     "src/compiler/control-builders.h",
index 41c74b5..128f8dd 100644 (file)
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 #include "src/compiler/common-operator.h"
+
 #include "src/compiler/operator-properties-inl.h"
 #include "src/test/test-utils.h"
 
@@ -10,6 +11,111 @@ namespace v8 {
 namespace internal {
 namespace compiler {
 
+
+// -----------------------------------------------------------------------------
+// Shared operators.
+
+
+namespace {
+
+struct SharedOperator {
+  const Operator* (CommonOperatorBuilder::*constructor)();
+  IrOpcode::Value opcode;
+  Operator::Properties properties;
+  int value_input_count;
+  int effect_input_count;
+  int control_input_count;
+  int effect_output_count;
+  int control_output_count;
+};
+
+
+std::ostream& operator<<(std::ostream& os, const SharedOperator& fop) {
+  return os << IrOpcode::Mnemonic(fop.opcode);
+}
+
+
+const SharedOperator kSharedOperators[] = {
+#define SHARED(Name, properties, value_input_count, effect_input_count,        \
+               control_input_count, effect_output_count, control_output_count) \
+  {                                                                            \
+    &CommonOperatorBuilder::Name, IrOpcode::k##Name, properties,               \
+        value_input_count, effect_input_count, control_input_count,            \
+        effect_output_count, control_output_count                              \
+  }
+    SHARED(Dead, Operator::kFoldable, 0, 0, 0, 0, 1),
+    SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0),
+    SHARED(Branch, Operator::kFoldable, 1, 0, 1, 0, 2),
+    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(ControlEffect, Operator::kPure, 0, 0, 1, 1, 0)
+#undef SHARED
+};
+
+
+class CommonSharedOperatorTest
+    : public TestWithZone,
+      public ::testing::WithParamInterface<SharedOperator> {};
+
+}  // namespace
+
+
+TEST_P(CommonSharedOperatorTest, InstancesAreGloballyShared) {
+  const SharedOperator& sop = GetParam();
+  CommonOperatorBuilder common1(zone());
+  CommonOperatorBuilder common2(zone());
+  EXPECT_EQ((common1.*sop.constructor)(), (common2.*sop.constructor)());
+}
+
+
+TEST_P(CommonSharedOperatorTest, NumberOfInputsAndOutputs) {
+  CommonOperatorBuilder common(zone());
+  const SharedOperator& sop = GetParam();
+  const Operator* op = (common.*sop.constructor)();
+
+  EXPECT_EQ(sop.value_input_count, OperatorProperties::GetValueInputCount(op));
+  EXPECT_EQ(sop.effect_input_count,
+            OperatorProperties::GetEffectInputCount(op));
+  EXPECT_EQ(sop.control_input_count,
+            OperatorProperties::GetControlInputCount(op));
+  EXPECT_EQ(
+      sop.value_input_count + sop.effect_input_count + sop.control_input_count,
+      OperatorProperties::GetTotalInputCount(op));
+
+  EXPECT_EQ(0, OperatorProperties::GetValueOutputCount(op));
+  EXPECT_EQ(sop.effect_output_count,
+            OperatorProperties::GetEffectOutputCount(op));
+  EXPECT_EQ(sop.control_output_count,
+            OperatorProperties::GetControlOutputCount(op));
+}
+
+
+TEST_P(CommonSharedOperatorTest, OpcodeIsCorrect) {
+  CommonOperatorBuilder common(zone());
+  const SharedOperator& sop = GetParam();
+  const Operator* op = (common.*sop.constructor)();
+  EXPECT_EQ(sop.opcode, op->opcode());
+}
+
+
+TEST_P(CommonSharedOperatorTest, Properties) {
+  CommonOperatorBuilder common(zone());
+  const SharedOperator& sop = GetParam();
+  const Operator* op = (common.*sop.constructor)();
+  EXPECT_EQ(sop.properties, op->properties());
+}
+
+
+INSTANTIATE_TEST_CASE_P(CommonOperatorTest, CommonSharedOperatorTest,
+                        ::testing::ValuesIn(kSharedOperators));
+
+
+// -----------------------------------------------------------------------------
+// Other operators.
+
+
 namespace {
 
 class CommonOperatorTest : public TestWithZone {
@@ -29,16 +135,6 @@ const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
 }  // namespace
 
 
-TEST_F(CommonOperatorTest, ControlEffect) {
-  const 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, ValueEffect) {
   TRACED_FOREACH(int, arguments, kArguments) {
     const Operator* op = common()->ValueEffect(arguments);
diff --git a/src/compiler/common-operator.cc b/src/compiler/common-operator.cc
new file mode 100644 (file)
index 0000000..e104b96
--- /dev/null
@@ -0,0 +1,244 @@
+// Copyright 2014 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "src/compiler/common-operator.h"
+
+#include "src/assembler.h"
+#include "src/base/lazy-instance.h"
+#include "src/compiler/linkage.h"
+#include "src/unique.h"
+#include "src/zone.h"
+
+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 OStream& PrintParameter(OStream& os) const FINAL { return os; }
+};
+
+}  // namespace
+
+
+// Specialization for static parameters of type {ExternalReference}.
+template <>
+struct StaticParameterTraits<ExternalReference> {
+  static OStream& PrintTo(OStream& os, ExternalReference reference) {
+    os << reference.address();
+    // TODO(bmeurer): Move to operator<<(os, ExternalReference)
+    const Runtime::Function* function =
+        Runtime::FunctionForEntry(reference.address());
+    if (function) {
+      os << " <" << function->name << ".entry>";
+    }
+    return os;
+  }
+  static int HashCode(ExternalReference reference) {
+    return bit_cast<int>(static_cast<uint32_t>(
+        reinterpret_cast<uintptr_t>(reference.address())));
+  }
+  static bool Equals(ExternalReference lhs, ExternalReference rhs) {
+    return lhs == rhs;
+  }
+};
+
+
+#define SHARED_OP_LIST(V)               \
+  V(Dead, Operator::kFoldable, 0, 0)    \
+  V(End, Operator::kFoldable, 0, 1)     \
+  V(Branch, Operator::kFoldable, 1, 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)
+
+
+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) {}                       \
+  };                                                                           \
+  Name##Operator k##Name##Operator;
+  SHARED_OP_LIST(SHARED)
+#undef SHARED
+
+  struct ControlEffectOperator FINAL : public SimpleOperator {
+    ControlEffectOperator()
+        : SimpleOperator(IrOpcode::kControlEffect, Operator::kPure, 0, 0,
+                         "ControlEffect") {}
+  };
+  ControlEffectOperator kControlEffectOperator;
+};
+
+
+static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl =
+    LAZY_INSTANCE_INITIALIZER;
+
+
+CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
+    : impl_(kImpl.Get()), zone_(zone) {}
+
+
+#define SHARED(Name, properties, value_input_count, control_input_count) \
+  const Operator* CommonOperatorBuilder::Name() {                        \
+    return &impl_.k##Name##Operator;                                     \
+  }
+SHARED_OP_LIST(SHARED)
+#undef SHARED
+
+
+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");
+}
+
+
+const Operator* CommonOperatorBuilder::Merge(int controls) {
+  return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
+                                      0, controls, "Merge");
+}
+
+
+const Operator* CommonOperatorBuilder::Loop(int controls) {
+  return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
+                                      0, controls, "Loop");
+}
+
+
+const Operator* CommonOperatorBuilder::Parameter(int index) {
+  return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
+                                     1, "Parameter", index);
+}
+
+
+const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
+  return new (zone()) Operator1<int32_t>(
+      IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value);
+}
+
+
+const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
+  return new (zone()) Operator1<int64_t>(
+      IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value);
+}
+
+
+const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
+  return new (zone())
+      Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
+                        "Float64Constant", value);
+}
+
+
+const Operator* CommonOperatorBuilder::ExternalConstant(
+    const ExternalReference& value) {
+  return new (zone())
+      Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure,
+                                   0, 1, "ExternalConstant", value);
+}
+
+
+const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
+  return new (zone())
+      Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
+                        "NumberConstant", value);
+}
+
+
+const Operator* CommonOperatorBuilder::HeapConstant(
+    const Unique<Object>& value) {
+  return new (zone()) Operator1<Unique<Object> >(
+      IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
+}
+
+
+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);
+}
+
+
+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);
+}
+
+
+const Operator* CommonOperatorBuilder::ControlEffect() {
+  return &impl_.kControlEffectOperator;
+}
+
+
+const Operator* CommonOperatorBuilder::ValueEffect(int arguments) {
+  DCHECK(arguments > 0);  // Disallow empty value effects.
+  return new (zone()) SimpleOperator(IrOpcode::kValueEffect, Operator::kPure,
+                                     arguments, 0, "ValueEffect");
+}
+
+
+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);
+}
+
+
+const Operator* CommonOperatorBuilder::StateValues(int arguments) {
+  return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
+                                     arguments, 1, "StateValues", arguments);
+}
+
+
+const Operator* CommonOperatorBuilder::FrameState(
+    BailoutId bailout_id, OutputFrameStateCombine combine) {
+  return new (zone()) Operator1<FrameStateCallInfo>(
+      IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
+      FrameStateCallInfo(bailout_id, combine));
+}
+
+
+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) {}
+
+    virtual OStream& PrintParameter(OStream& os) const OVERRIDE {
+      return os << "[" << *parameter() << "]";
+    }
+  };
+  return new (zone()) CallOperator(descriptor, "Call");
+}
+
+
+const Operator* CommonOperatorBuilder::Projection(size_t index) {
+  return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure,
+                                        1, 1, "Projection", index);
+}
+
+}  // namespace compiler
+}  // namespace internal
+}  // namespace v8
index 95bed12..137155e 100644 (file)
@@ -5,48 +5,26 @@
 #ifndef V8_COMPILER_COMMON_OPERATOR_H_
 #define V8_COMPILER_COMMON_OPERATOR_H_
 
-#include "src/assembler.h"
-#include "src/compiler/linkage.h"
 #include "src/compiler/machine-type.h"
-#include "src/compiler/opcodes.h"
-#include "src/compiler/operator.h"
-#include "src/unique.h"
 
 namespace v8 {
 namespace internal {
 
+// Forward declarations.
+class ExternalReference;
 class OStream;
+template <typename>
+class Unique;
+class Zone;
+
 
 namespace compiler {
 
-class ControlOperator FINAL : 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 OStream& PrintParameter(OStream& os) const OVERRIDE {  // NOLINT
-    return os;
-  }
-  int ControlInputCount() const { return parameter(); }
-};
+// Forward declarations.
+class CallDescriptor;
+struct CommonOperatorBuilderImpl;
+class Operator;
 
-class CallOperator FINAL : public Operator1<CallDescriptor*> {
- public:
-  // TODO(titzer): Operator still uses int, whereas CallDescriptor uses size_t.
-  CallOperator(CallDescriptor* descriptor, const char* mnemonic)
-      : Operator1<CallDescriptor*>(
-            IrOpcode::kCall, descriptor->properties(),
-            static_cast<int>(descriptor->InputCount() +
-                             descriptor->FrameStateCount()),
-            static_cast<int>(descriptor->ReturnCount()), mnemonic, descriptor) {
-  }
-
-  virtual OStream& PrintParameter(OStream& os) const OVERRIDE {  // NOLINT
-    return os << "[" << *parameter() << "]";
-  }
-};
 
 // Flag that describes how to combine the current environment with
 // the output of a node to obtain a framestate for lazy bailout.
@@ -56,7 +34,7 @@ enum OutputFrameStateCombine {
 };
 
 
-class FrameStateCallInfo {
+class FrameStateCallInfo FINAL {
  public:
   FrameStateCallInfo(BailoutId bailout_id,
                      OutputFrameStateCombine state_combine)
@@ -70,122 +48,49 @@ class FrameStateCallInfo {
   OutputFrameStateCombine frame_state_combine_;
 };
 
+
 // Interface for building common operators that can be used at any level of IR,
 // including JavaScript, mid-level, and low-level.
-// TODO(titzer): Move the mnemonics into SimpleOperator and Operator1 classes.
-class CommonOperatorBuilder {
+class CommonOperatorBuilder FINAL {
  public:
-  explicit CommonOperatorBuilder(Zone* zone) : zone_(zone) {}
-
-#define CONTROL_OP(name, inputs, controls)                                   \
-  return new (zone_) ControlOperator(IrOpcode::k##name, Operator::kFoldable, \
-                                     inputs, 0, controls, #name);
-
-  const Operator* Start(int num_formal_parameters) {
-    // Outputs are formal parameters, plus context, receiver, and JSFunction.
-    int outputs = num_formal_parameters + 3;
-    return new (zone_) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
-                                       outputs, 0, "Start");
-  }
-  const Operator* Dead() { CONTROL_OP(Dead, 0, 0); }
-  const Operator* End() { CONTROL_OP(End, 0, 1); }
-  const Operator* Branch() { CONTROL_OP(Branch, 1, 1); }
-  const Operator* IfTrue() { CONTROL_OP(IfTrue, 0, 1); }
-  const Operator* IfFalse() { CONTROL_OP(IfFalse, 0, 1); }
-  const Operator* Throw() { CONTROL_OP(Throw, 1, 1); }
-
-  const Operator* Return() {
-    return new (zone_) ControlOperator(
-        IrOpcode::kReturn, Operator::kNoProperties, 1, 0, 1, "Return");
-  }
-
-  const Operator* Merge(int controls) {
-    return new (zone_) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
-                                       0, controls, "Merge");
-  }
-
-  const Operator* Loop(int controls) {
-    return new (zone_) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
-                                       0, controls, "Loop");
-  }
-
-  const Operator* Parameter(int index) {
-    return new (zone_) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
-                                      1, "Parameter", index);
-  }
-  const Operator* Int32Constant(int32_t value) {
-    return new (zone_)
-        Operator1<int32_t>(IrOpcode::kInt32Constant, Operator::kPure, 0, 1,
-                           "Int32Constant", value);
-  }
-  const Operator* Int64Constant(int64_t value) {
-    return new (zone_)
-        Operator1<int64_t>(IrOpcode::kInt64Constant, Operator::kPure, 0, 1,
-                           "Int64Constant", value);
-  }
-  const Operator* Float64Constant(double value) {
-    return new (zone_)
-        Operator1<double>(IrOpcode::kFloat64Constant, Operator::kPure, 0, 1,
-                          "Float64Constant", value);
-  }
-  const Operator* ExternalConstant(ExternalReference value) {
-    return new (zone_) Operator1<ExternalReference>(IrOpcode::kExternalConstant,
-                                                    Operator::kPure, 0, 1,
-                                                    "ExternalConstant", value);
-  }
-  const Operator* NumberConstant(double value) {
-    return new (zone_)
-        Operator1<double>(IrOpcode::kNumberConstant, Operator::kPure, 0, 1,
-                          "NumberConstant", value);
-  }
-  const Operator* HeapConstant(Unique<Object> value) {
-    return new (zone_) Operator1<Unique<Object> >(
-        IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
-  }
-  const Operator* Phi(MachineType type, int arguments) {
-    DCHECK(arguments > 0);  // Disallow empty phis.
-    return new (zone_) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure,
-                                              arguments, 1, "Phi", type);
-  }
-  const Operator* EffectPhi(int arguments) {
-    DCHECK(arguments > 0);  // Disallow empty phis.
-    return new (zone_) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
-                                      0, "EffectPhi", arguments);
-  }
-  const Operator* ControlEffect() {
-    return new (zone_) SimpleOperator(IrOpcode::kControlEffect, Operator::kPure,
-                                      0, 0, "ControlEffect");
-  }
-  const Operator* ValueEffect(int arguments) {
-    DCHECK(arguments > 0);  // Disallow empty value effects.
-    return new (zone_) SimpleOperator(IrOpcode::kValueEffect, Operator::kPure,
-                                      arguments, 0, "ValueEffect");
-  }
-  const Operator* Finish(int arguments) {
-    DCHECK(arguments > 0);  // Disallow empty finishes.
-    return new (zone_) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1,
-                                      "Finish", arguments);
-  }
-  const Operator* StateValues(int arguments) {
-    return new (zone_) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
-                                      arguments, 1, "StateValues", arguments);
-  }
+  explicit CommonOperatorBuilder(Zone* zone);
+
+  const Operator* Dead();
+  const Operator* End();
+  const Operator* Branch();
+  const Operator* IfTrue();
+  const Operator* IfFalse();
+  const Operator* Throw();
+  const Operator* Return();
+
+  const Operator* Start(int num_formal_parameters);
+  const Operator* Merge(int controls);
+  const Operator* Loop(int controls);
+  const Operator* Parameter(int index);
+
+  const Operator* Int32Constant(int32_t);
+  const Operator* Int64Constant(int64_t);
+  const Operator* Float64Constant(volatile double);
+  const Operator* ExternalConstant(const ExternalReference&);
+  const Operator* NumberConstant(volatile double);
+  const Operator* HeapConstant(const Unique<Object>&);
+
+  const Operator* Phi(MachineType type, int arguments);
+  const Operator* EffectPhi(int arguments);
+  const Operator* ControlEffect();
+  const Operator* ValueEffect(int arguments);
+  const Operator* Finish(int arguments);
+  const Operator* StateValues(int arguments);
   const Operator* FrameState(BailoutId bailout_id,
-                             OutputFrameStateCombine combine) {
-    return new (zone_) Operator1<FrameStateCallInfo>(
-        IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
-        FrameStateCallInfo(bailout_id, combine));
-  }
-  const Operator* Call(CallDescriptor* descriptor) {
-    return new (zone_) CallOperator(descriptor, "Call");
-  }
-  const Operator* Projection(size_t index) {
-    return new (zone_) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure,
-                                         1, 1, "Projection", index);
-  }
+                             OutputFrameStateCombine combine);
+  const Operator* Call(const CallDescriptor* descriptor);
+  const Operator* Projection(size_t index);
 
  private:
-  Zone* zone_;
+  Zone* zone() const { return zone_; }
+
+  const CommonOperatorBuilderImpl& impl_;
+  Zone* const zone_;
 };
 
 }  // namespace compiler
index e04621b..e2399b6 100644 (file)
@@ -9,14 +9,14 @@
 #include <map>
 #include <set>
 
-// TODO(titzer): don't include the assembler?
-#include "src/assembler.h"
 #include "src/compiler/common-operator.h"
 #include "src/compiler/frame.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/instruction-codes.h"
 #include "src/compiler/opcodes.h"
 #include "src/compiler/schedule.h"
+// TODO(titzer): don't include the macro-assembler?
+#include "src/macro-assembler.h"
 #include "src/zone-allocator.h"
 
 namespace v8 {
index 40534f7..9dae106 100644 (file)
@@ -115,7 +115,8 @@ inline int OperatorProperties::GetControlInputCount(const Operator* op) {
 #define OPCODE_CASE(x) case IrOpcode::k##x:
       CONTROL_OP_LIST(OPCODE_CASE)
 #undef OPCODE_CASE
-      return static_cast<const ControlOperator*>(op)->ControlInputCount();
+      // 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
index f37f3aa..35f9c88 100644 (file)
@@ -4,8 +4,6 @@
 
 #include "src/compiler/operator.h"
 
-#include "src/assembler.h"
-
 namespace v8 {
 namespace internal {
 namespace compiler {
@@ -23,34 +21,6 @@ SimpleOperator::SimpleOperator(Opcode opcode, Properties properties,
 
 SimpleOperator::~SimpleOperator() {}
 
-
-// static
-OStream& StaticParameterTraits<ExternalReference>::PrintTo(
-    OStream& os, ExternalReference reference) {
-  os << reference.address();
-  // TODO(bmeurer): Move to operator<<(os, ExternalReference)
-  const Runtime::Function* function =
-      Runtime::FunctionForEntry(reference.address());
-  if (function) {
-    os << " <" << function->name << ".entry>";
-  }
-  return os;
-}
-
-
-// static
-int StaticParameterTraits<ExternalReference>::HashCode(
-    ExternalReference reference) {
-  return reinterpret_cast<intptr_t>(reference.address()) & 0xFFFFFFFF;
-}
-
-
-// static
-bool StaticParameterTraits<ExternalReference>::Equals(ExternalReference lhs,
-                                                      ExternalReference rhs) {
-  return lhs == rhs;
-}
-
 }  // namespace compiler
 }  // namespace internal
 }  // namespace v8
index 8d17bc4..5137806 100644 (file)
 
 namespace v8 {
 namespace internal {
-
-// Forward declarations.
-class ExternalReference;
-
-
 namespace compiler {
 
 // An operator represents description of the "computation" of a node in the
@@ -147,13 +142,6 @@ struct StaticParameterTraits {
   }
 };
 
-template <>
-struct StaticParameterTraits<ExternalReference> {
-  static OStream& PrintTo(OStream& os, ExternalReference reference);  // NOLINT
-  static int HashCode(ExternalReference reference);
-  static bool Equals(ExternalReference lhs, ExternalReference rhs);
-};
-
 // Specialization for static parameters of type {int}.
 template <>
 struct StaticParameterTraits<int> {
index cb0302b..9cb1613 100644 (file)
@@ -15,6 +15,7 @@
 
 #include "src/compiler/common-operator.h"
 #include "src/compiler/graph-builder.h"
+#include "src/compiler/linkage.h"
 #include "src/compiler/machine-operator.h"
 #include "src/compiler/node.h"
 #include "src/compiler/operator.h"
index a22e7e1..bfa8226 100644 (file)
@@ -3,6 +3,8 @@
 // found in the LICENSE file.
 
 #include "test/cctest/compiler/graph-builder-tester.h"
+
+#include "src/compiler/linkage.h"
 #include "src/compiler/pipeline.h"
 
 namespace v8 {
index 08e44ec..a9feaac 100644 (file)
@@ -9,6 +9,7 @@
 #include "src/compiler/common-operator.h"
 #include "src/compiler/graph.h"
 #include "src/compiler/instruction.h"
+#include "src/compiler/linkage.h"
 #include "src/compiler/machine-operator.h"
 #include "src/compiler/node.h"
 #include "src/compiler/operator.h"
index 425c94c..0bcd089 100644 (file)
         '../../src/compiler/code-generator.cc',
         '../../src/compiler/code-generator.h',
         '../../src/compiler/common-node-cache.h',
+        '../../src/compiler/common-operator.cc',
         '../../src/compiler/common-operator.h',
         '../../src/compiler/control-builders.cc',
         '../../src/compiler/control-builders.h',