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