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:
}
-#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));
}
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() << "]";
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
// Forward declarations.
class CallDescriptor;
-struct CommonOperatorBuilderImpl;
+struct CommonOperatorGlobalCache;
class Operator;
private:
Zone* zone() const { return zone_; }
- const CommonOperatorBuilderImpl& impl_;
+ const CommonOperatorGlobalCache& cache_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(CommonOperatorBuilder);
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)));
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);
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_);
Graph* source_graph_;
Graph* target_graph_;
Zone* temp_zone_;
- SimpleOperator sentinel_op_;
+ Operator sentinel_op_;
};
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 {
}
-#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) \
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
}
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
}
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
// Forward declarations.
class Operator;
-struct JSOperatorBuilderImpl;
+struct JSOperatorGlobalCache;
// Defines the arity and the call flags for a JavaScript function call. This is
private:
Zone* zone() const { return zone_; }
- const JSOperatorBuilderImpl& impl_;
+ const JSOperatorGlobalCache& cache_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(JSOperatorBuilder);
#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) \
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
switch (rep) {
#define LOAD(Type) \
case k##Type: \
- return &impl_.k##Load##Type;
+ return &cache_.k##Load##Type;
MACHINE_TYPE_LIST(LOAD)
#undef LOAD
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
namespace compiler {
// Forward declarations.
-struct MachineOperatorBuilderImpl;
+struct MachineOperatorGlobalCache;
class Operator;
#undef PSEUDO_OP_LIST
private:
- const MachineOperatorBuilderImpl& impl_;
+ const MachineOperatorGlobalCache& cache_;
const MachineType word_;
const Flags flags_;
DISALLOW_COPY_AND_ASSIGN(MachineOperatorBuilder);
// 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: \
static bool IsJsOpcode(Value val) {
switch (val) {
+// TODO(turbofan): make this a range check.
#define RETURN_NAME(x) \
case k##x: \
return true;
static bool IsControlOpcode(Value val) {
switch (val) {
+// TODO(turbofan): make this a range check.
#define RETURN_NAME(x) \
case k##x: \
return true;
static bool IsLeafOpcode(Value val) {
switch (val) {
+// TODO(turbofan): make this a table lookup.
#define RETURN_NAME(x) \
case k##x: \
return true;
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;
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) {
}
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) {
}
inline int OperatorProperties::GetValueInputCount(const Operator* op) {
- return op->InputCount();
+ return op->ValueInputCount();
}
inline int OperatorProperties::GetContextInputCount(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) {
// 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();
}
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
};
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
// 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 {
}
// 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);
};
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) {}
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() << "]";
}
}
private:
- int const input_count_;
- int const output_count_;
T const parameter_;
Pred const pred_;
Hash const hash_;
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);
}
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);
}
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());
}
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
// Forward declarations.
class Operator;
-struct SimplifiedOperatorBuilderImpl;
+struct SimplifiedOperatorGlobalCache;
enum BaseTaggedness { kUntaggedBase, kTaggedBase };
private:
Zone* zone() const { return zone_; }
- const SimplifiedOperatorBuilderImpl& impl_;
+ const SimplifiedOperatorGlobalCache& cache_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorBuilder);
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.
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;
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.
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) {
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:
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;
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));
}
-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));
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));
}
-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));
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));
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));
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());
+}
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;
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
};
};
-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(),
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 {
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),
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 {
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());
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());
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());