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
This commit is contained in:
titzer@chromium.org 2014-10-29 14:40:47 +00:00
parent eca12478ab
commit 6c6a71b3f7
27 changed files with 608 additions and 523 deletions

View File

@ -14,22 +14,6 @@ namespace v8 {
namespace internal {
namespace compiler {
namespace {
// TODO(turbofan): Use size_t instead of int here.
class ControlOperator : public Operator1<int> {
public:
ControlOperator(IrOpcode::Value opcode, Properties properties, int inputs,
int outputs, int controls, const char* mnemonic)
: Operator1<int>(opcode, properties, inputs, outputs, mnemonic,
controls) {}
virtual void PrintParameter(std::ostream& os) const FINAL {}
};
} // namespace
std::ostream& operator<<(std::ostream& os, BranchHint hint) {
switch (hint) {
case BranchHint::kNone:
@ -117,181 +101,226 @@ std::ostream& operator<<(std::ostream& os, FrameStateCallInfo const& info) {
}
#define SHARED_OP_LIST(V) \
V(Dead, Operator::kFoldable, 0, 0) \
V(End, Operator::kFoldable, 0, 1) \
V(IfTrue, Operator::kFoldable, 0, 1) \
V(IfFalse, Operator::kFoldable, 0, 1) \
V(Throw, Operator::kFoldable, 1, 1) \
V(Return, Operator::kNoProperties, 1, 1)
#define CACHED_OP_LIST(V) \
V(Dead, Operator::kFoldable, 0, 0, 0, 1) \
V(End, Operator::kFoldable, 0, 0, 1, 0) \
V(IfTrue, Operator::kFoldable, 0, 0, 1, 1) \
V(IfFalse, Operator::kFoldable, 0, 0, 1, 1) \
V(Throw, Operator::kFoldable, 1, 1, 1, 1) \
V(Return, Operator::kNoProperties, 1, 1, 1, 1)
struct CommonOperatorBuilderImpl FINAL {
#define SHARED(Name, properties, value_input_count, control_input_count) \
struct Name##Operator FINAL : public ControlOperator { \
Name##Operator() \
: ControlOperator(IrOpcode::k##Name, properties, value_input_count, 0, \
control_input_count, #Name) {} \
}; \
struct CommonOperatorGlobalCache FINAL {
#define CACHED(Name, properties, value_input_count, effect_input_count, \
control_input_count, control_output_count) \
struct Name##Operator FINAL : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, properties, #Name, value_input_count, \
effect_input_count, control_input_count, 0, 0, \
control_output_count) {} \
}; \
Name##Operator k##Name##Operator;
SHARED_OP_LIST(SHARED)
#undef SHARED
CACHED_OP_LIST(CACHED)
#undef CACHED
};
static base::LazyInstance<CommonOperatorBuilderImpl>::type kImpl =
static base::LazyInstance<CommonOperatorGlobalCache>::type kCache =
LAZY_INSTANCE_INITIALIZER;
CommonOperatorBuilder::CommonOperatorBuilder(Zone* zone)
: impl_(kImpl.Get()), zone_(zone) {}
: cache_(kCache.Get()), zone_(zone) {}
#define SHARED(Name, properties, value_input_count, control_input_count) \
const Operator* CommonOperatorBuilder::Name() { \
return &impl_.k##Name##Operator; \
#define CACHED(Name, properties, value_input_count, effect_input_count, \
control_input_count, control_output_count) \
const Operator* CommonOperatorBuilder::Name() { \
return &cache_.k##Name##Operator; \
}
SHARED_OP_LIST(SHARED)
#undef SHARED
CACHED_OP_LIST(CACHED)
#undef CACHED
const Operator* CommonOperatorBuilder::Branch(BranchHint hint) {
return new (zone()) Operator1<BranchHint>(
IrOpcode::kBranch, Operator::kFoldable, 1, 0, "Branch", hint);
IrOpcode::kBranch, Operator::kFoldable, "Branch", 1, 0, 1, 0, 0, 2, hint);
}
const Operator* CommonOperatorBuilder::Start(int num_formal_parameters) {
// Outputs are formal parameters, plus context, receiver, and JSFunction.
const int value_output_count = num_formal_parameters + 3;
return new (zone()) ControlOperator(IrOpcode::kStart, Operator::kFoldable, 0,
value_output_count, 0, "Start");
return new (zone()) Operator( // --
IrOpcode::kStart, Operator::kFoldable, // opcode
"Start", // name
0, 0, 0, value_output_count, 1, 1); // counts
}
const Operator* CommonOperatorBuilder::Merge(int controls) {
return new (zone()) ControlOperator(IrOpcode::kMerge, Operator::kFoldable, 0,
0, controls, "Merge");
return new (zone()) Operator( // --
IrOpcode::kMerge, Operator::kFoldable, // opcode
"Merge", // name
0, 0, controls, 0, 0, 1); // counts
}
const Operator* CommonOperatorBuilder::Loop(int controls) {
return new (zone()) ControlOperator(IrOpcode::kLoop, Operator::kFoldable, 0,
0, controls, "Loop");
return new (zone()) Operator( // --
IrOpcode::kLoop, Operator::kFoldable, // opcode
"Loop", // name
0, 0, controls, 0, 0, 1); // counts
}
const Operator* CommonOperatorBuilder::Terminate(int effects) {
return new (zone()) Operator1<int>(IrOpcode::kTerminate,
Operator::kNoRead | Operator::kNoWrite, 0,
0, "Terminate", effects);
return new (zone()) Operator( // --
IrOpcode::kTerminate, Operator::kPure, // opcode
"Terminate", // name
0, effects, 1, 0, 0, 1); // counts
}
const Operator* CommonOperatorBuilder::Parameter(int index) {
return new (zone()) Operator1<int>(IrOpcode::kParameter, Operator::kPure, 1,
1, "Parameter", index);
return new (zone()) Operator1<int>( // --
IrOpcode::kParameter, Operator::kPure, // opcode
"Parameter", // name
1, 0, 0, 1, 0, 0, // counts
index); // parameter
}
const Operator* CommonOperatorBuilder::Int32Constant(int32_t value) {
return new (zone()) Operator1<int32_t>(
IrOpcode::kInt32Constant, Operator::kPure, 0, 1, "Int32Constant", value);
return new (zone()) Operator1<int32_t>( // --
IrOpcode::kInt32Constant, Operator::kPure, // opcode
"Int32Constant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::Int64Constant(int64_t value) {
return new (zone()) Operator1<int64_t>(
IrOpcode::kInt64Constant, Operator::kPure, 0, 1, "Int64Constant", value);
return new (zone()) Operator1<int64_t>( // --
IrOpcode::kInt64Constant, Operator::kPure, // opcode
"Int64Constant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::Float32Constant(volatile float value) {
return new (zone())
Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>(
IrOpcode::kFloat32Constant, Operator::kPure, 0, 1, "Float32Constant",
value);
Operator1<float, base::bit_equal_to<float>, base::bit_hash<float>>( // --
IrOpcode::kFloat32Constant, Operator::kPure, // opcode
"Float32Constant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::Float64Constant(volatile double value) {
return new (zone())
Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>(
IrOpcode::kFloat64Constant, Operator::kPure, 0, 1, "Float64Constant",
value);
return new (zone()) Operator1<double, base::bit_equal_to<double>,
base::bit_hash<double>>( // --
IrOpcode::kFloat64Constant, Operator::kPure, // opcode
"Float64Constant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::ExternalConstant(
const ExternalReference& value) {
return new (zone())
Operator1<ExternalReference>(IrOpcode::kExternalConstant, Operator::kPure,
0, 1, "ExternalConstant", value);
return new (zone()) Operator1<ExternalReference>( // --
IrOpcode::kExternalConstant, Operator::kPure, // opcode
"ExternalConstant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::NumberConstant(volatile double value) {
return new (zone())
Operator1<double, base::bit_equal_to<double>, base::bit_hash<double>>(
IrOpcode::kNumberConstant, Operator::kPure, 0, 1, "NumberConstant",
value);
return new (zone()) Operator1<double, base::bit_equal_to<double>,
base::bit_hash<double>>( // --
IrOpcode::kNumberConstant, Operator::kPure, // opcode
"NumberConstant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::HeapConstant(
const Unique<HeapObject>& value) {
return new (zone()) Operator1<Unique<HeapObject>>(
IrOpcode::kHeapConstant, Operator::kPure, 0, 1, "HeapConstant", value);
return new (zone()) Operator1<Unique<HeapObject>>( // --
IrOpcode::kHeapConstant, Operator::kPure, // opcode
"HeapConstant", // name
0, 0, 0, 1, 0, 0, // counts
value); // parameter
}
const Operator* CommonOperatorBuilder::Select(MachineType type,
BranchHint hint) {
return new (zone())
Operator1<SelectParameters>(IrOpcode::kSelect, Operator::kPure, 3, 1,
"Select", SelectParameters(type, hint));
return new (zone()) Operator1<SelectParameters>( // --
IrOpcode::kSelect, Operator::kPure, // opcode
"Select", // name
3, 0, 0, 1, 0, 0, // counts
SelectParameters(type, hint)); // parameter
}
const Operator* CommonOperatorBuilder::Phi(MachineType type, int arguments) {
DCHECK(arguments > 0); // Disallow empty phis.
return new (zone()) Operator1<MachineType>(IrOpcode::kPhi, Operator::kPure,
arguments, 1, "Phi", type);
DCHECK(arguments > 0); // Disallow empty phis.
return new (zone()) Operator1<MachineType>( // --
IrOpcode::kPhi, Operator::kPure, // opcode
"Phi", // name
arguments, 0, 1, 1, 0, 0, // counts
type); // parameter
}
const Operator* CommonOperatorBuilder::EffectPhi(int arguments) {
DCHECK(arguments > 0); // Disallow empty phis.
return new (zone()) Operator1<int>(IrOpcode::kEffectPhi, Operator::kPure, 0,
0, "EffectPhi", arguments);
DCHECK(arguments > 0); // Disallow empty phis.
return new (zone()) Operator( // --
IrOpcode::kEffectPhi, Operator::kPure, // opcode
"EffectPhi", // name
0, arguments, 1, 0, 1, 0); // counts
}
const Operator* CommonOperatorBuilder::ValueEffect(int arguments) {
DCHECK(arguments > 0); // Disallow empty value effects.
return new (zone()) Operator1<int>(IrOpcode::kValueEffect, Operator::kPure,
arguments, 0, "ValueEffect", arguments);
DCHECK(arguments > 0); // Disallow empty value effects.
return new (zone()) Operator( // --
IrOpcode::kValueEffect, Operator::kPure, // opcode
"ValueEffect", // name
arguments, 0, 0, 0, 1, 0); // counts
}
const Operator* CommonOperatorBuilder::Finish(int arguments) {
DCHECK(arguments > 0); // Disallow empty finishes.
return new (zone()) Operator1<int>(IrOpcode::kFinish, Operator::kPure, 1, 1,
"Finish", arguments);
DCHECK(arguments > 0); // Disallow empty finishes.
return new (zone()) Operator( // --
IrOpcode::kFinish, Operator::kPure, // opcode
"Finish", // name
1, arguments, 0, 1, 0, 0); // counts
}
const Operator* CommonOperatorBuilder::StateValues(int arguments) {
return new (zone()) Operator1<int>(IrOpcode::kStateValues, Operator::kPure,
arguments, 1, "StateValues", arguments);
return new (zone()) Operator( // --
IrOpcode::kStateValues, Operator::kPure, // opcode
"StateValues", // name
arguments, 0, 0, 1, 0, 0); // counts
}
const Operator* CommonOperatorBuilder::FrameState(
FrameStateType type, BailoutId bailout_id,
OutputFrameStateCombine state_combine, MaybeHandle<JSFunction> jsfunction) {
return new (zone()) Operator1<FrameStateCallInfo>(
IrOpcode::kFrameState, Operator::kPure, 4, 1, "FrameState",
return new (zone()) Operator1<FrameStateCallInfo>( // --
IrOpcode::kFrameState, Operator::kPure, // opcode
"FrameState", // name
4, 0, 0, 1, 0, 0, // counts
FrameStateCallInfo(type, bailout_id, state_combine, jsfunction));
}
@ -299,15 +328,14 @@ const Operator* CommonOperatorBuilder::FrameState(
const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
class CallOperator FINAL : public Operator1<const CallDescriptor*> {
public:
// TODO(titzer): Operator still uses int, whereas CallDescriptor uses
// size_t.
CallOperator(const CallDescriptor* descriptor, const char* mnemonic)
: Operator1<const CallDescriptor*>(
IrOpcode::kCall, descriptor->properties(),
static_cast<int>(descriptor->InputCount() +
descriptor->FrameStateCount()),
static_cast<int>(descriptor->ReturnCount()), mnemonic,
descriptor) {}
IrOpcode::kCall, descriptor->properties(), mnemonic,
descriptor->InputCount() + descriptor->FrameStateCount(),
Operator::ZeroIfPure(descriptor->properties()),
Operator::ZeroIfPure(descriptor->properties()),
descriptor->ReturnCount(),
Operator::ZeroIfPure(descriptor->properties()), 0, descriptor) {}
virtual void PrintParameter(std::ostream& os) const OVERRIDE {
os << "[" << *parameter() << "]";
@ -318,8 +346,11 @@ const Operator* CommonOperatorBuilder::Call(const CallDescriptor* descriptor) {
const Operator* CommonOperatorBuilder::Projection(size_t index) {
return new (zone()) Operator1<size_t>(IrOpcode::kProjection, Operator::kPure,
1, 1, "Projection", index);
return new (zone()) Operator1<size_t>( // --
IrOpcode::kProjection, Operator::kPure, // opcode
"Projection", // name
1, 0, 0, 1, 0, 0, // counts
index); // parameter
}
} // namespace compiler

View File

@ -19,7 +19,7 @@ namespace compiler {
// Forward declarations.
class CallDescriptor;
struct CommonOperatorBuilderImpl;
struct CommonOperatorGlobalCache;
class Operator;
@ -197,7 +197,7 @@ class CommonOperatorBuilder FINAL : public ZoneObject {
private:
Zone* zone() const { return zone_; }
const CommonOperatorBuilderImpl& impl_;
const CommonOperatorGlobalCache& cache_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(CommonOperatorBuilder);

View File

@ -962,7 +962,7 @@ void InstructionSelector::VisitThrow(Node* value) {
void InstructionSelector::FillTypeVectorFromStateValues(
ZoneVector<MachineType>* types, Node* state_values) {
DCHECK(state_values->opcode() == IrOpcode::kStateValues);
int count = OpParameter<int>(state_values);
int count = state_values->InputCount();
types->reserve(static_cast<size_t>(count));
for (int i = 0; i < count; i++) {
types->push_back(GetMachineType(state_values->InputAt(i)));
@ -974,11 +974,14 @@ FrameStateDescriptor* InstructionSelector::GetFrameStateDescriptor(
Node* state) {
DCHECK(state->opcode() == IrOpcode::kFrameState);
DCHECK_EQ(5, state->InputCount());
DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(0)->opcode());
DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(1)->opcode());
DCHECK_EQ(IrOpcode::kStateValues, state->InputAt(2)->opcode());
FrameStateCallInfo state_info = OpParameter<FrameStateCallInfo>(state);
int parameters = OpParameter<int>(state->InputAt(0));
int locals = OpParameter<int>(state->InputAt(1));
int stack = OpParameter<int>(state->InputAt(2));
int parameters = state->InputAt(0)->InputCount();
int locals = state->InputAt(1)->InputCount();
int stack = state->InputAt(2)->InputCount();
FrameStateDescriptor* outer_state = NULL;
Node* outer_node = state->InputAt(4);

View File

@ -165,8 +165,8 @@ class CopyVisitor : public NullNodeVisitor {
source_graph_(source_graph),
target_graph_(target_graph),
temp_zone_(temp_zone),
sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, 0, 0,
"sentinel") {}
sentinel_op_(IrOpcode::kDead, Operator::kNoProperties, "sentinel", 0, 0,
0, 0, 0, 0) {}
GenericGraphVisit::Control Post(Node* original) {
NodeVector inputs(temp_zone_);
@ -224,7 +224,7 @@ class CopyVisitor : public NullNodeVisitor {
Graph* source_graph_;
Graph* target_graph_;
Zone* temp_zone_;
SimpleOperator sentinel_op_;
Operator sentinel_op_;
};
@ -453,7 +453,7 @@ class JSCallRuntimeAccessor {
Node* effect() const { return NodeProperties::GetEffectInput(call_); }
const Runtime::Function* function() const {
return Runtime::FunctionForId(OpParameter<Runtime::FunctionId>(call_));
return Runtime::FunctionForId(CallRuntimeParametersOf(call_->op()).id());
}
NodeVector inputs(Zone* zone) const {

View File

@ -208,7 +208,7 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
}
#define SHARED_OP_LIST(V) \
#define CACHED_OP_LIST(V) \
V(Equal, Operator::kNoProperties, 2, 1) \
V(NotEqual, Operator::kNoProperties, 2, 1) \
V(StrictEqual, Operator::kPure, 2, 1) \
@ -247,39 +247,45 @@ const StoreNamedParameters& StoreNamedParametersOf(const Operator* op) {
V(CreateGlobalContext, Operator::kNoProperties, 2, 1)
struct JSOperatorBuilderImpl FINAL {
#define SHARED(Name, properties, value_input_count, value_output_count) \
struct Name##Operator FINAL : public SimpleOperator { \
Name##Operator() \
: SimpleOperator(IrOpcode::kJS##Name, properties, value_input_count, \
value_output_count, "JS" #Name) {} \
}; \
struct JSOperatorGlobalCache FINAL {
#define CACHED(Name, properties, value_input_count, value_output_count) \
struct Name##Operator FINAL : public Operator { \
Name##Operator() \
: Operator(IrOpcode::kJS##Name, properties, "JS" #Name, \
value_input_count, Operator::ZeroIfPure(properties), \
Operator::ZeroIfPure(properties), value_output_count, \
Operator::ZeroIfPure(properties), 0) {} \
}; \
Name##Operator k##Name##Operator;
SHARED_OP_LIST(SHARED)
#undef SHARED
CACHED_OP_LIST(CACHED)
#undef CACHED
};
static base::LazyInstance<JSOperatorBuilderImpl>::type kImpl =
static base::LazyInstance<JSOperatorGlobalCache>::type kCache =
LAZY_INSTANCE_INITIALIZER;
JSOperatorBuilder::JSOperatorBuilder(Zone* zone)
: impl_(kImpl.Get()), zone_(zone) {}
: cache_(kCache.Get()), zone_(zone) {}
#define SHARED(Name, properties, value_input_count, value_output_count) \
const Operator* JSOperatorBuilder::Name() { return &impl_.k##Name##Operator; }
SHARED_OP_LIST(SHARED)
#undef SHARED
#define CACHED(Name, properties, value_input_count, value_output_count) \
const Operator* JSOperatorBuilder::Name() { \
return &cache_.k##Name##Operator; \
}
CACHED_OP_LIST(CACHED)
#undef CACHED
const Operator* JSOperatorBuilder::CallFunction(size_t arity,
CallFunctionFlags flags) {
CallFunctionParameters parameters(arity, flags);
return new (zone()) Operator1<CallFunctionParameters>(
IrOpcode::kJSCallFunction, Operator::kNoProperties,
static_cast<int>(parameters.arity()), 1, "JSCallFunction", parameters);
return new (zone()) Operator1<CallFunctionParameters>( // --
IrOpcode::kJSCallFunction, Operator::kNoProperties, // opcode
"JSCallFunction", // name
parameters.arity(), 1, 1, 1, 1, 0, // inputs/outputs
parameters); // parameter
}
@ -287,18 +293,21 @@ const Operator* JSOperatorBuilder::CallRuntime(Runtime::FunctionId id,
size_t arity) {
CallRuntimeParameters parameters(id, arity);
const Runtime::Function* f = Runtime::FunctionForId(parameters.id());
int arguments = static_cast<int>(parameters.arity());
DCHECK(f->nargs == -1 || f->nargs == arguments);
return new (zone()) Operator1<CallRuntimeParameters>(
IrOpcode::kJSCallRuntime, Operator::kNoProperties, arguments,
f->result_size, "JSCallRuntime", parameters);
DCHECK(f->nargs == -1 || f->nargs == static_cast<int>(parameters.arity()));
return new (zone()) Operator1<CallRuntimeParameters>( // --
IrOpcode::kJSCallRuntime, Operator::kNoProperties, // opcode
"JSCallRuntime", // name
parameters.arity(), 1, 1, f->result_size, 1, 0, // inputs/outputs
parameters); // parameter
}
const Operator* JSOperatorBuilder::CallConstruct(int arguments) {
return new (zone())
Operator1<int>(IrOpcode::kJSCallConstruct, Operator::kNoProperties,
arguments, 1, "JSCallConstruct", arguments);
return new (zone()) Operator1<int>( // --
IrOpcode::kJSCallConstruct, Operator::kNoProperties, // opcode
"JSCallConstruct", // name
arguments, 1, 1, 1, 1, 0, // counts
arguments); // parameter
}
@ -306,66 +315,82 @@ const Operator* JSOperatorBuilder::LoadNamed(const Unique<Name>& name,
const VectorSlotPair& feedback,
ContextualMode contextual_mode) {
LoadNamedParameters parameters(name, feedback, contextual_mode);
return new (zone()) Operator1<LoadNamedParameters>(
IrOpcode::kJSLoadNamed, Operator::kNoProperties, 1, 1, "JSLoadNamed",
parameters);
return new (zone()) Operator1<LoadNamedParameters>( // --
IrOpcode::kJSLoadNamed, Operator::kNoProperties, // opcode
"JSLoadNamed", // name
1, 1, 1, 1, 1, 0, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::LoadProperty(
const VectorSlotPair& feedback) {
LoadPropertyParameters parameters(feedback);
return new (zone()) Operator1<LoadPropertyParameters>(
IrOpcode::kJSLoadProperty, Operator::kNoProperties, 2, 1,
"JSLoadProperty", parameters);
return new (zone()) Operator1<LoadPropertyParameters>( // --
IrOpcode::kJSLoadProperty, Operator::kNoProperties, // opcode
"JSLoadProperty", // name
2, 1, 1, 1, 1, 0, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::StoreProperty(StrictMode strict_mode) {
return new (zone())
Operator1<StrictMode>(IrOpcode::kJSStoreProperty, Operator::kNoProperties,
3, 0, "JSStoreProperty", strict_mode);
return new (zone()) Operator1<StrictMode>( // --
IrOpcode::kJSStoreProperty, Operator::kNoProperties, // opcode
"JSStoreProperty", // name
3, 1, 1, 0, 1, 0, // counts
strict_mode); // parameter
}
const Operator* JSOperatorBuilder::StoreNamed(StrictMode strict_mode,
const Unique<Name>& name) {
StoreNamedParameters parameters(strict_mode, name);
return new (zone()) Operator1<StoreNamedParameters>(
IrOpcode::kJSStoreNamed, Operator::kNoProperties, 2, 0, "JSStoreNamed",
parameters);
return new (zone()) Operator1<StoreNamedParameters>( // --
IrOpcode::kJSStoreNamed, Operator::kNoProperties, // opcode
"JSStoreNamed", // name
2, 1, 1, 0, 1, 0, // counts
parameters); // parameter
}
const Operator* JSOperatorBuilder::DeleteProperty(StrictMode strict_mode) {
return new (zone()) Operator1<StrictMode>(IrOpcode::kJSDeleteProperty,
Operator::kNoProperties, 2, 1,
"JSDeleteProperty", strict_mode);
return new (zone()) Operator1<StrictMode>( // --
IrOpcode::kJSDeleteProperty, Operator::kNoProperties, // opcode
"JSDeleteProperty", // name
2, 1, 1, 1, 1, 0, // counts
strict_mode); // parameter
}
const Operator* JSOperatorBuilder::LoadContext(size_t depth, size_t index,
bool immutable) {
ContextAccess access(depth, index, immutable);
return new (zone()) Operator1<ContextAccess>(
IrOpcode::kJSLoadContext, Operator::kEliminatable | Operator::kNoWrite, 1,
1, "JSLoadContext", access);
return new (zone()) Operator1<ContextAccess>( // --
IrOpcode::kJSLoadContext, Operator::kNoWrite, // opcode
"JSLoadContext", // name
1, 1, 0, 1, 1, 0, // counts
access); // parameter
}
const Operator* JSOperatorBuilder::StoreContext(size_t depth, size_t index) {
ContextAccess access(depth, index, false);
return new (zone()) Operator1<ContextAccess>(IrOpcode::kJSStoreContext,
Operator::kNoProperties, 2, 0,
"JSStoreContext", access);
return new (zone()) Operator1<ContextAccess>( // --
IrOpcode::kJSStoreContext, Operator::kNoRead, // opcode
"JSStoreContext", // name
2, 1, 1, 0, 1, 0, // counts
access); // parameter
}
const Operator* JSOperatorBuilder::CreateCatchContext(
const Unique<String>& name) {
return new (zone()) Operator1<Unique<String>>(IrOpcode::kJSCreateCatchContext,
Operator::kNoProperties, 1, 1,
"JSCreateCatchContext", name);
return new (zone()) Operator1<Unique<String>>( // --
IrOpcode::kJSCreateCatchContext, Operator::kNoProperties, // opcode
"JSCreateCatchContext", // name
1, 1, 1, 1, 1, 0, // counts
name); // parameter
}
} // namespace compiler

View File

@ -14,7 +14,7 @@ namespace compiler {
// Forward declarations.
class Operator;
struct JSOperatorBuilderImpl;
struct JSOperatorGlobalCache;
// Defines the arity and the call flags for a JavaScript function call. This is
@ -264,7 +264,7 @@ class JSOperatorBuilder FINAL : public ZoneObject {
private:
Zone* zone() const { return zone_; }
const JSOperatorBuilderImpl& impl_;
const JSOperatorGlobalCache& cache_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(JSOperatorBuilder);

View File

@ -53,71 +53,71 @@ StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
#define PURE_OP_LIST(V) \
V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word32Xor, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word32Shl, Operator::kNoProperties, 2, 1) \
V(Word32Shr, Operator::kNoProperties, 2, 1) \
V(Word32Sar, Operator::kNoProperties, 2, 1) \
V(Word32Ror, Operator::kNoProperties, 2, 1) \
V(Word32Equal, Operator::kCommutative, 2, 1) \
V(Word64And, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word64Or, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word64Xor, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word64Shl, Operator::kNoProperties, 2, 1) \
V(Word64Shr, Operator::kNoProperties, 2, 1) \
V(Word64Sar, Operator::kNoProperties, 2, 1) \
V(Word64Ror, Operator::kNoProperties, 2, 1) \
V(Word64Equal, Operator::kCommutative, 2, 1) \
V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Word32And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Word32Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Word32Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Word32Shl, Operator::kNoProperties, 2, 0, 1) \
V(Word32Shr, Operator::kNoProperties, 2, 0, 1) \
V(Word32Sar, Operator::kNoProperties, 2, 0, 1) \
V(Word32Ror, Operator::kNoProperties, 2, 0, 1) \
V(Word32Equal, Operator::kCommutative, 2, 0, 1) \
V(Word64And, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Word64Or, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Word64Xor, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Word64Shl, Operator::kNoProperties, 2, 0, 1) \
V(Word64Shr, Operator::kNoProperties, 2, 0, 1) \
V(Word64Sar, Operator::kNoProperties, 2, 0, 1) \
V(Word64Ror, Operator::kNoProperties, 2, 0, 1) \
V(Word64Equal, Operator::kCommutative, 2, 0, 1) \
V(Int32Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int32AddWithOverflow, Operator::kAssociative | Operator::kCommutative, 2, \
2) \
V(Int32Sub, Operator::kNoProperties, 2, 1) \
V(Int32SubWithOverflow, Operator::kNoProperties, 2, 2) \
V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Int32Div, Operator::kNoProperties, 2, 1) \
V(Int32Mod, Operator::kNoProperties, 2, 1) \
V(Int32LessThan, Operator::kNoProperties, 2, 1) \
V(Int32LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(Uint32Div, Operator::kNoProperties, 2, 1) \
V(Uint32LessThan, Operator::kNoProperties, 2, 1) \
V(Uint32LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(Uint32Mod, Operator::kNoProperties, 2, 1) \
V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Int64Sub, Operator::kNoProperties, 2, 1) \
V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 1) \
V(Int64Div, Operator::kNoProperties, 2, 1) \
V(Int64Mod, Operator::kNoProperties, 2, 1) \
V(Int64LessThan, Operator::kNoProperties, 2, 1) \
V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(Uint64Div, Operator::kNoProperties, 2, 1) \
V(Uint64LessThan, Operator::kNoProperties, 2, 1) \
V(Uint64Mod, Operator::kNoProperties, 2, 1) \
V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 1) \
V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 1) \
V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 1) \
V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 1) \
V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 1) \
V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 1) \
V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 1) \
V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 1) \
V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 1) \
V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 1) \
V(Float64Add, Operator::kCommutative, 2, 1) \
V(Float64Sub, Operator::kNoProperties, 2, 1) \
V(Float64Mul, Operator::kCommutative, 2, 1) \
V(Float64Div, Operator::kNoProperties, 2, 1) \
V(Float64Mod, Operator::kNoProperties, 2, 1) \
V(Float64Sqrt, Operator::kNoProperties, 1, 1) \
V(Float64Ceil, Operator::kNoProperties, 1, 1) \
V(Float64Floor, Operator::kNoProperties, 1, 1) \
V(Float64RoundTruncate, Operator::kNoProperties, 1, 1) \
V(Float64RoundTiesAway, Operator::kNoProperties, 1, 1) \
V(Float64Equal, Operator::kCommutative, 2, 1) \
V(Float64LessThan, Operator::kNoProperties, 2, 1) \
V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 1) \
V(LoadStackPointer, Operator::kNoProperties, 0, 1)
0, 2) \
V(Int32Sub, Operator::kNoProperties, 2, 0, 1) \
V(Int32SubWithOverflow, Operator::kNoProperties, 2, 0, 2) \
V(Int32Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int32MulHigh, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int32Div, Operator::kNoProperties, 2, 1, 1) \
V(Int32Mod, Operator::kNoProperties, 2, 1, 1) \
V(Int32LessThan, Operator::kNoProperties, 2, 0, 1) \
V(Int32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1) \
V(Uint32Div, Operator::kNoProperties, 2, 1, 1) \
V(Uint32LessThan, Operator::kNoProperties, 2, 0, 1) \
V(Uint32LessThanOrEqual, Operator::kNoProperties, 2, 0, 1) \
V(Uint32Mod, Operator::kNoProperties, 2, 1, 1) \
V(Int64Add, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int64Sub, Operator::kNoProperties, 2, 0, 1) \
V(Int64Mul, Operator::kAssociative | Operator::kCommutative, 2, 0, 1) \
V(Int64Div, Operator::kNoProperties, 2, 0, 1) \
V(Int64Mod, Operator::kNoProperties, 2, 0, 1) \
V(Int64LessThan, Operator::kNoProperties, 2, 0, 1) \
V(Int64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1) \
V(Uint64Div, Operator::kNoProperties, 2, 0, 1) \
V(Uint64LessThan, Operator::kNoProperties, 2, 0, 1) \
V(Uint64Mod, Operator::kNoProperties, 2, 0, 1) \
V(ChangeFloat32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
V(ChangeFloat64ToUint32, Operator::kNoProperties, 1, 0, 1) \
V(ChangeInt32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeInt32ToInt64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeUint32ToFloat64, Operator::kNoProperties, 1, 0, 1) \
V(ChangeUint32ToUint64, Operator::kNoProperties, 1, 0, 1) \
V(TruncateFloat64ToFloat32, Operator::kNoProperties, 1, 0, 1) \
V(TruncateFloat64ToInt32, Operator::kNoProperties, 1, 0, 1) \
V(TruncateInt64ToInt32, Operator::kNoProperties, 1, 0, 1) \
V(Float64Add, Operator::kCommutative, 2, 0, 1) \
V(Float64Sub, Operator::kNoProperties, 2, 0, 1) \
V(Float64Mul, Operator::kCommutative, 2, 0, 1) \
V(Float64Div, Operator::kNoProperties, 2, 0, 1) \
V(Float64Mod, Operator::kNoProperties, 2, 0, 1) \
V(Float64Sqrt, Operator::kNoProperties, 1, 0, 1) \
V(Float64Ceil, Operator::kNoProperties, 1, 0, 1) \
V(Float64Floor, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTruncate, Operator::kNoProperties, 1, 0, 1) \
V(Float64RoundTiesAway, Operator::kNoProperties, 1, 0, 1) \
V(Float64Equal, Operator::kCommutative, 2, 0, 1) \
V(Float64LessThan, Operator::kNoProperties, 2, 0, 1) \
V(Float64LessThanOrEqual, Operator::kNoProperties, 2, 0, 1) \
V(LoadStackPointer, Operator::kNoProperties, 0, 0, 1)
#define MACHINE_TYPE_LIST(V) \
@ -142,64 +142,68 @@ StoreRepresentation const& StoreRepresentationOf(Operator const* op) {
V(RepTagged)
struct MachineOperatorBuilderImpl {
#define PURE(Name, properties, input_count, output_count) \
struct Name##Operator FINAL : public SimpleOperator { \
Name##Operator() \
: SimpleOperator(IrOpcode::k##Name, Operator::kPure | properties, \
input_count, output_count, #Name) {} \
}; \
struct MachineOperatorGlobalCache {
#define PURE(Name, properties, value_input_count, control_input_count, \
output_count) \
struct Name##Operator FINAL : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
value_input_count, 0, control_input_count, output_count, 0, \
0) {} \
}; \
Name##Operator k##Name;
PURE_OP_LIST(PURE)
#undef PURE
#define LOAD(Type) \
struct Load##Type##Operator FINAL : public Operator1<LoadRepresentation> { \
Load##Type##Operator() \
: Operator1<LoadRepresentation>( \
IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite, 2, 1, \
"Load", k##Type) {} \
}; \
#define LOAD(Type) \
struct Load##Type##Operator FINAL : public Operator1<LoadRepresentation> { \
Load##Type##Operator() \
: Operator1<LoadRepresentation>( \
IrOpcode::kLoad, Operator::kNoThrow | Operator::kNoWrite, \
"Load", 2, 1, 1, 1, 1, 0, k##Type) {} \
}; \
Load##Type##Operator k##Load##Type;
MACHINE_TYPE_LIST(LOAD)
#undef LOAD
#define STORE(Type) \
struct Store##Type##Operator : public Operator1<StoreRepresentation> { \
explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind) \
: Operator1<StoreRepresentation>( \
IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow, 3, 0, \
"Store", StoreRepresentation(k##Type, write_barrier_kind)) {} \
}; \
struct Store##Type##NoWriteBarrier##Operator FINAL \
: public Store##Type##Operator { \
Store##Type##NoWriteBarrier##Operator() \
: Store##Type##Operator(kNoWriteBarrier) {} \
}; \
struct Store##Type##FullWriteBarrier##Operator FINAL \
: public Store##Type##Operator { \
Store##Type##FullWriteBarrier##Operator() \
: Store##Type##Operator(kFullWriteBarrier) {} \
}; \
Store##Type##NoWriteBarrier##Operator k##Store##Type##NoWriteBarrier; \
#define STORE(Type) \
struct Store##Type##Operator : public Operator1<StoreRepresentation> { \
explicit Store##Type##Operator(WriteBarrierKind write_barrier_kind) \
: Operator1<StoreRepresentation>( \
IrOpcode::kStore, Operator::kNoRead | Operator::kNoThrow, \
"Store", 3, 1, 1, 0, 1, 0, \
StoreRepresentation(k##Type, write_barrier_kind)) {} \
}; \
struct Store##Type##NoWriteBarrier##Operator FINAL \
: public Store##Type##Operator { \
Store##Type##NoWriteBarrier##Operator() \
: Store##Type##Operator(kNoWriteBarrier) {} \
}; \
struct Store##Type##FullWriteBarrier##Operator FINAL \
: public Store##Type##Operator { \
Store##Type##FullWriteBarrier##Operator() \
: Store##Type##Operator(kFullWriteBarrier) {} \
}; \
Store##Type##NoWriteBarrier##Operator k##Store##Type##NoWriteBarrier; \
Store##Type##FullWriteBarrier##Operator k##Store##Type##FullWriteBarrier;
MACHINE_TYPE_LIST(STORE)
#undef STORE
};
static base::LazyInstance<MachineOperatorBuilderImpl>::type kImpl =
static base::LazyInstance<MachineOperatorGlobalCache>::type kCache =
LAZY_INSTANCE_INITIALIZER;
MachineOperatorBuilder::MachineOperatorBuilder(MachineType word, Flags flags)
: impl_(kImpl.Get()), word_(word), flags_(flags) {
: cache_(kCache.Get()), word_(word), flags_(flags) {
DCHECK(word == kRepWord32 || word == kRepWord64);
}
#define PURE(Name, properties, input_count, output_count) \
const Operator* MachineOperatorBuilder::Name() { return &impl_.k##Name; }
#define PURE(Name, properties, value_input_count, control_input_count, \
output_count) \
const Operator* MachineOperatorBuilder::Name() { return &cache_.k##Name; }
PURE_OP_LIST(PURE)
#undef PURE
@ -208,7 +212,7 @@ const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
switch (rep) {
#define LOAD(Type) \
case k##Type: \
return &impl_.k##Load##Type;
return &cache_.k##Load##Type;
MACHINE_TYPE_LIST(LOAD)
#undef LOAD
@ -222,14 +226,14 @@ const Operator* MachineOperatorBuilder::Load(LoadRepresentation rep) {
const Operator* MachineOperatorBuilder::Store(StoreRepresentation rep) {
switch (rep.machine_type()) {
#define STORE(Type) \
case k##Type: \
switch (rep.write_barrier_kind()) { \
case kNoWriteBarrier: \
return &impl_.k##Store##Type##NoWriteBarrier; \
case kFullWriteBarrier: \
return &impl_.k##Store##Type##FullWriteBarrier; \
} \
#define STORE(Type) \
case k##Type: \
switch (rep.write_barrier_kind()) { \
case kNoWriteBarrier: \
return &cache_.k##Store##Type##NoWriteBarrier; \
case kFullWriteBarrier: \
return &cache_.k##Store##Type##FullWriteBarrier; \
} \
break;
MACHINE_TYPE_LIST(STORE)
#undef STORE

View File

@ -13,7 +13,7 @@ namespace internal {
namespace compiler {
// Forward declarations.
struct MachineOperatorBuilderImpl;
struct MachineOperatorGlobalCache;
class Operator;
@ -210,7 +210,7 @@ class MachineOperatorBuilder FINAL : public ZoneObject {
#undef PSEUDO_OP_LIST
private:
const MachineOperatorBuilderImpl& impl_;
const MachineOperatorGlobalCache& cache_;
const MachineType word_;
const Flags flags_;
DISALLOW_COPY_AND_ASSIGN(MachineOperatorBuilder);

View File

@ -264,6 +264,7 @@ class IrOpcode {
// Returns the mnemonic name of an opcode.
static const char* Mnemonic(Value val) {
// TODO(turbofan): make this a table lookup.
switch (val) {
#define RETURN_NAME(x) \
case k##x: \
@ -277,6 +278,7 @@ class IrOpcode {
static bool IsJsOpcode(Value val) {
switch (val) {
// TODO(turbofan): make this a range check.
#define RETURN_NAME(x) \
case k##x: \
return true;
@ -289,6 +291,7 @@ class IrOpcode {
static bool IsControlOpcode(Value val) {
switch (val) {
// TODO(turbofan): make this a range check.
#define RETURN_NAME(x) \
case k##x: \
return true;
@ -301,6 +304,7 @@ class IrOpcode {
static bool IsLeafOpcode(Value val) {
switch (val) {
// TODO(turbofan): make this a table lookup.
#define RETURN_NAME(x) \
case k##x: \
return true;
@ -313,6 +317,7 @@ class IrOpcode {
static bool IsCommonOpcode(Value val) {
switch (val) {
// TODO(turbofan): make this a table lookup or a range check.
#define RETURN_NAME(x) \
case k##x: \
return true;

View File

@ -16,7 +16,7 @@ namespace internal {
namespace compiler {
inline bool OperatorProperties::HasValueInput(const Operator* op) {
return OperatorProperties::GetValueInputCount(op) > 0;
return op->ValueInputCount() > 0;
}
inline bool OperatorProperties::HasContextInput(const Operator* op) {
@ -25,11 +25,11 @@ inline bool OperatorProperties::HasContextInput(const Operator* op) {
}
inline bool OperatorProperties::HasEffectInput(const Operator* op) {
return OperatorProperties::GetEffectInputCount(op) > 0;
return op->EffectInputCount() > 0;
}
inline bool OperatorProperties::HasControlInput(const Operator* op) {
return OperatorProperties::GetControlInputCount(op) > 0;
return op->ControlInputCount() > 0;
}
inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
@ -94,7 +94,7 @@ inline bool OperatorProperties::HasFrameStateInput(const Operator* op) {
}
inline int OperatorProperties::GetValueInputCount(const Operator* op) {
return op->InputCount();
return op->ValueInputCount();
}
inline int OperatorProperties::GetContextInputCount(const Operator* op) {
@ -106,44 +106,11 @@ inline int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
}
inline int OperatorProperties::GetEffectInputCount(const Operator* op) {
if (op->opcode() == IrOpcode::kEffectPhi ||
op->opcode() == IrOpcode::kFinish ||
op->opcode() == IrOpcode::kTerminate) {
return OpParameter<int>(op);
}
if (op->HasProperty(Operator::kNoRead) && op->HasProperty(Operator::kNoWrite))
return 0; // no effects.
return 1;
return op->EffectInputCount();
}
inline int OperatorProperties::GetControlInputCount(const Operator* op) {
// TODO(titzer): fix this mess; just make them a count on the operator.
switch (op->opcode()) {
case IrOpcode::kPhi:
case IrOpcode::kEffectPhi:
case IrOpcode::kLoad:
case IrOpcode::kLoadField:
case IrOpcode::kInt32Div:
case IrOpcode::kInt32Mod:
case IrOpcode::kUint32Div:
case IrOpcode::kUint32Mod:
return 1;
#define OPCODE_CASE(x) case IrOpcode::k##x:
CONTROL_OP_LIST(OPCODE_CASE)
#undef OPCODE_CASE
if (op->opcode() == IrOpcode::kBranch) return 1;
if (op->opcode() == IrOpcode::kTerminate) return 1;
// Control operators are Operator1<int>.
return OpParameter<int>(op);
default:
// Operators that have write effects must have a control
// dependency. Effect dependencies only ensure the correct order of
// write/read operations without consideration of control flow. Without an
// explicit control dependency writes can be float in the schedule too
// early along a path that shouldn't generate a side-effect.
return op->HasProperty(Operator::kNoWrite) ? 0 : 1;
}
return 0;
return op->ControlInputCount();
}
inline int OperatorProperties::GetTotalInputCount(const Operator* op) {
@ -156,33 +123,28 @@ inline int OperatorProperties::GetTotalInputCount(const Operator* op) {
// Output properties.
inline bool OperatorProperties::HasValueOutput(const Operator* op) {
return GetValueOutputCount(op) > 0;
return op->ValueOutputCount() > 0;
}
inline bool OperatorProperties::HasEffectOutput(const Operator* op) {
return op->opcode() == IrOpcode::kStart ||
op->opcode() == IrOpcode::kValueEffect ||
(op->opcode() != IrOpcode::kFinish &&
op->opcode() != IrOpcode::kTerminate && GetEffectInputCount(op) > 0);
return op->EffectOutputCount() > 0;
}
inline bool OperatorProperties::HasControlOutput(const Operator* op) {
IrOpcode::Value opcode = static_cast<IrOpcode::Value>(op->opcode());
return (opcode != IrOpcode::kEnd && IrOpcode::IsControlOpcode(opcode));
return op->ControlOutputCount() > 0;
}
inline int OperatorProperties::GetValueOutputCount(const Operator* op) {
return op->OutputCount();
return op->ValueOutputCount();
}
inline int OperatorProperties::GetEffectOutputCount(const Operator* op) {
return HasEffectOutput(op) ? 1 : 0;
return op->EffectOutputCount();
}
inline int OperatorProperties::GetControlOutputCount(const Operator* node) {
return node->opcode() == IrOpcode::kBranch ? 2 : HasControlOutput(node) ? 1
: 0;
inline int OperatorProperties::GetControlOutputCount(const Operator* op) {
return op->ControlOutputCount();
}

View File

@ -10,7 +10,26 @@ namespace v8 {
namespace internal {
namespace compiler {
Operator::~Operator() {}
template <typename N>
static inline N CheckRange(size_t val) {
CHECK(val <= std::numeric_limits<N>::max());
return static_cast<N>(val);
}
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)) {}
std::ostream& operator<<(std::ostream& os, const Operator& op) {
@ -19,37 +38,7 @@ std::ostream& operator<<(std::ostream& os, const Operator& op) {
}
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());
}
SimpleOperator::~SimpleOperator() {}
bool SimpleOperator::Equals(const Operator* that) const {
return opcode() == that->opcode();
}
size_t SimpleOperator::HashCode() const {
return base::hash<Opcode>()(opcode());
}
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

View File

@ -49,9 +49,12 @@ class Operator : public ZoneObject {
};
typedef base::Flags<Property, uint8_t> Properties;
Operator(Opcode opcode, Properties properties, const char* mnemonic)
: opcode_(opcode), properties_(properties), mnemonic_(mnemonic) {}
virtual ~Operator();
// Constructor.
Operator(Opcode opcode, Properties properties, const char* mnemonic,
size_t value_in, size_t effect_in, size_t control_in,
size_t value_out, size_t effect_out, size_t control_out);
virtual ~Operator() {}
// A small integer unique to all instances of a particular kind of operator,
// useful for quick matching for specific kinds of operators. For fast access
@ -65,12 +68,14 @@ class Operator : public ZoneObject {
// Check if this operator equals another operator. Equivalent operators can
// be merged, and nodes with equivalent operators and equivalent inputs
// can be merged.
virtual bool Equals(const Operator*) const = 0;
virtual bool Equals(const Operator* that) const {
return this->opcode() == that->opcode();
}
// Compute a hashcode to speed up equivalence-set checking.
// Equal operators should always have equal hashcodes, and unequal operators
// should have unequal hashcodes with high probability.
virtual size_t HashCode() const = 0;
virtual size_t HashCode() const { return base::hash<Opcode>()(opcode()); }
// Check whether this operator has the given property.
bool HasProperty(Property property) const {
@ -78,24 +83,45 @@ class Operator : public ZoneObject {
}
// Number of data inputs to the operator, for verifying graph structure.
virtual int InputCount() const = 0;
// TODO(titzer): convert callers to ValueInputCount();
int InputCount() const { return ValueInputCount(); }
// Number of data outputs from the operator, for verifying graph structure.
virtual int OutputCount() const = 0;
// TODO(titzer): convert callers to ValueOutputCount();
int OutputCount() const { return ValueOutputCount(); }
Properties properties() const { return properties_; }
// TODO(titzer): convert return values here to size_t.
int ValueInputCount() const { return value_in_; }
int EffectInputCount() const { return effect_in_; }
int ControlInputCount() const { return control_in_; }
int ValueOutputCount() const { return value_out_; }
int EffectOutputCount() const { return effect_out_; }
int ControlOutputCount() const { return control_out_; }
static inline size_t ZeroIfPure(Properties properties) {
return (properties & kPure) == kPure ? 0 : 1;
}
// TODO(titzer): API for input and output types, for typechecking graph.
protected:
// Print the full operator into the given stream, including any
// static parameters. Useful for debugging and visualizing the IR.
virtual void PrintTo(std::ostream& os) const = 0; // NOLINT
virtual void PrintTo(std::ostream& os) const;
friend std::ostream& operator<<(std::ostream& os, const Operator& op);
private:
Opcode opcode_;
Properties properties_;
const char* mnemonic_;
uint32_t value_in_;
uint16_t effect_in_;
uint16_t control_in_;
uint16_t value_out_;
uint8_t effect_out_;
uint8_t control_out_;
DISALLOW_COPY_AND_ASSIGN(Operator);
};
@ -105,42 +131,18 @@ DEFINE_OPERATORS_FOR_FLAGS(Operator::Properties)
std::ostream& operator<<(std::ostream& os, const Operator& op);
// An implementation of Operator that has no static parameters. Such operators
// have just a name, an opcode, and a fixed number of inputs and outputs.
// They can represented by singletons and shared globally.
class SimpleOperator : public Operator {
public:
SimpleOperator(Opcode opcode, Properties properties, size_t input_count,
size_t output_count, const char* mnemonic);
~SimpleOperator();
virtual bool Equals(const Operator* that) const FINAL;
virtual size_t HashCode() const FINAL;
virtual int InputCount() const FINAL;
virtual int OutputCount() const FINAL;
private:
virtual void PrintTo(std::ostream& os) const FINAL;
uint8_t input_count_;
uint8_t output_count_;
DISALLOW_COPY_AND_ASSIGN(SimpleOperator);
};
// A templatized implementation of Operator that has one static parameter of
// type {T}.
template <typename T, typename Pred = std::equal_to<T>,
typename Hash = base::hash<T>>
class Operator1 : public Operator {
public:
Operator1(Opcode opcode, Properties properties, int input_count,
int output_count, const char* mnemonic, T parameter,
Pred const& pred = Pred(), Hash const& hash = Hash())
: Operator(opcode, properties, mnemonic),
input_count_(input_count),
output_count_(output_count),
Operator1(Opcode opcode, Properties properties, const char* mnemonic,
size_t value_in, size_t effect_in, size_t control_in,
size_t value_out, size_t effect_out, size_t control_out,
T parameter, Pred const& pred = Pred(), Hash const& hash = Hash())
: Operator(opcode, properties, mnemonic, value_in, effect_in, control_in,
value_out, effect_out, control_out),
parameter_(parameter),
pred_(pred),
hash_(hash) {}
@ -155,8 +157,6 @@ class Operator1 : public Operator {
virtual size_t HashCode() const FINAL {
return base::hash_combine(this->opcode(), this->hash_(this->parameter()));
}
virtual int InputCount() const FINAL { return input_count_; }
virtual int OutputCount() const FINAL { return output_count_; }
virtual void PrintParameter(std::ostream& os) const {
os << "[" << this->parameter() << "]";
}
@ -168,8 +168,6 @@ class Operator1 : public Operator {
}
private:
int const input_count_;
int const output_count_;
T const parameter_;
Pred const pred_;
Hash const hash_;

View File

@ -1122,7 +1122,7 @@ void SimplifiedLowering::DoLoadField(Node* node) {
const FieldAccess& access = FieldAccessOf(node->op());
node->set_op(machine()->Load(access.machine_type));
Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
node->InsertInput(zone(), 1, offset);
node->InsertInput(graph()->zone(), 1, offset);
}
@ -1133,7 +1133,7 @@ void SimplifiedLowering::DoStoreField(Node* node) {
node->set_op(
machine()->Store(StoreRepresentation(access.machine_type, kind)));
Node* offset = jsgraph()->Int32Constant(access.offset - access.tag());
node->InsertInput(zone(), 1, offset);
node->InsertInput(graph()->zone(), 1, offset);
}
@ -1336,10 +1336,11 @@ void SimplifiedLowering::DoStringAdd(Node* node) {
CallDescriptor* desc =
Linkage::GetStubCallDescriptor(callable.descriptor(), 0, flags, zone());
node->set_op(common()->Call(desc));
node->InsertInput(zone(), 0, jsgraph()->HeapConstant(callable.code()));
node->AppendInput(zone(), jsgraph()->UndefinedConstant());
node->AppendInput(zone(), graph()->start());
node->AppendInput(zone(), graph()->start());
node->InsertInput(graph()->zone(), 0,
jsgraph()->HeapConstant(callable.code()));
node->AppendInput(graph()->zone(), jsgraph()->UndefinedConstant());
node->AppendInput(graph()->zone(), graph()->start());
node->AppendInput(graph()->zone(), graph()->start());
}

View File

@ -140,53 +140,55 @@ const ElementAccess& ElementAccessOf(const Operator* op) {
V(ObjectIsNonNegativeSmi, Operator::kNoProperties, 1)
#define ACCESS_OP_LIST(V) \
V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1) \
V(StoreField, FieldAccess, Operator::kNoRead, 2, 0) \
V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 1) \
V(StoreElement, ElementAccess, Operator::kNoRead, 4, 0)
struct SimplifiedOperatorBuilderImpl FINAL {
#define PURE(Name, properties, input_count) \
struct Name##Operator FINAL : public SimpleOperator { \
Name##Operator() \
: SimpleOperator(IrOpcode::k##Name, Operator::kPure | properties, \
input_count, 1, #Name) {} \
}; \
struct SimplifiedOperatorGlobalCache FINAL {
#define PURE(Name, properties, input_count) \
struct Name##Operator FINAL : public Operator { \
Name##Operator() \
: Operator(IrOpcode::k##Name, Operator::kPure | properties, #Name, \
input_count, 0, 0, 1, 0, 0) {} \
}; \
Name##Operator k##Name;
PURE_OP_LIST(PURE)
#undef PURE
};
static base::LazyInstance<SimplifiedOperatorBuilderImpl>::type kImpl =
static base::LazyInstance<SimplifiedOperatorGlobalCache>::type kCache =
LAZY_INSTANCE_INITIALIZER;
SimplifiedOperatorBuilder::SimplifiedOperatorBuilder(Zone* zone)
: impl_(kImpl.Get()), zone_(zone) {}
: cache_(kCache.Get()), zone_(zone) {}
#define PURE(Name, properties, input_count) \
const Operator* SimplifiedOperatorBuilder::Name() { return &impl_.k##Name; }
const Operator* SimplifiedOperatorBuilder::Name() { return &cache_.k##Name; }
PURE_OP_LIST(PURE)
#undef PURE
const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
// TODO(titzer): What about the type parameter?
return new (zone()) SimpleOperator(IrOpcode::kReferenceEqual,
Operator::kCommutative | Operator::kPure,
2, 1, "ReferenceEqual");
return new (zone()) Operator(IrOpcode::kReferenceEqual,
Operator::kCommutative | Operator::kPure,
"ReferenceEqual", 2, 0, 0, 1, 0, 0);
}
#define ACCESS(Name, Type, properties, input_count, output_count) \
const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \
return new (zone()) \
Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \
input_count, output_count, #Name, access); \
#define ACCESS_OP_LIST(V) \
V(LoadField, FieldAccess, Operator::kNoWrite, 1, 1, 1) \
V(StoreField, FieldAccess, Operator::kNoRead, 2, 1, 0) \
V(LoadElement, ElementAccess, Operator::kNoWrite, 3, 0, 1) \
V(StoreElement, ElementAccess, Operator::kNoRead, 4, 1, 0)
#define ACCESS(Name, Type, properties, value_input_count, control_input_count, \
output_count) \
const Operator* SimplifiedOperatorBuilder::Name(const Type& access) { \
return new (zone()) \
Operator1<Type>(IrOpcode::k##Name, Operator::kNoThrow | properties, \
#Name, value_input_count, 1, control_input_count, \
output_count, 1, 0, access); \
}
ACCESS_OP_LIST(ACCESS)
#undef ACCESS

View File

@ -25,7 +25,7 @@ namespace compiler {
// Forward declarations.
class Operator;
struct SimplifiedOperatorBuilderImpl;
struct SimplifiedOperatorGlobalCache;
enum BaseTaggedness { kUntaggedBase, kTaggedBase };
@ -161,7 +161,7 @@ class SimplifiedOperatorBuilder FINAL {
private:
Zone* zone() const { return zone_; }
const SimplifiedOperatorBuilderImpl& impl_;
const SimplifiedOperatorGlobalCache& cache_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(SimplifiedOperatorBuilder);

View File

@ -301,7 +301,7 @@ GenericGraphVisit::Control Verifier::Visitor::Pre(Node* node) {
break;
case IrOpcode::kProjection: {
// Projection has an input that produces enough values.
int index = OpParameter<int>(node->op());
int index = static_cast<int>(OpParameter<size_t>(node->op()));
Node* input = NodeProperties::GetValueInput(node, 0);
CHECK_GT(OperatorProperties::GetValueOutputCount(input->op()), index);
// Type can be anything.

View File

@ -76,10 +76,8 @@ Node* SimplifiedGraphBuilder::MakeNode(const Operator* op,
if (has_effect) {
effect_ = result;
}
if (OperatorProperties::HasControlOutput(result->op())) {
// This graph builder does not support control flow.
UNREACHABLE();
}
// This graph builder does not support control flow.
CHECK_EQ(0, op->ControlOutputCount());
}
return result;

View File

@ -21,15 +21,15 @@ const uint8_t OPCODE_C0 = 30;
const uint8_t OPCODE_C1 = 31;
const uint8_t OPCODE_C2 = 32;
static SimpleOperator OPA0(OPCODE_A0, Operator::kNoWrite, 0, 0, "opa0");
static SimpleOperator OPA1(OPCODE_A1, Operator::kNoWrite, 1, 0, "opa1");
static SimpleOperator OPA2(OPCODE_A2, Operator::kNoWrite, 2, 0, "opa2");
static SimpleOperator OPB0(OPCODE_B0, Operator::kNoWrite, 0, 0, "opa0");
static SimpleOperator OPB1(OPCODE_B1, Operator::kNoWrite, 1, 0, "opa1");
static SimpleOperator OPB2(OPCODE_B2, Operator::kNoWrite, 2, 0, "opa2");
static SimpleOperator OPC0(OPCODE_C0, Operator::kNoWrite, 0, 0, "opc0");
static SimpleOperator OPC1(OPCODE_C1, Operator::kNoWrite, 1, 0, "opc1");
static SimpleOperator OPC2(OPCODE_C2, Operator::kNoWrite, 2, 0, "opc2");
static Operator OPA0(OPCODE_A0, Operator::kNoWrite, "opa0", 0, 0, 0, 0, 0, 0);
static Operator OPA1(OPCODE_A1, Operator::kNoWrite, "opa1", 1, 0, 0, 0, 0, 0);
static Operator OPA2(OPCODE_A2, Operator::kNoWrite, "opa2", 2, 0, 0, 0, 0, 0);
static Operator OPB0(OPCODE_B0, Operator::kNoWrite, "opa0", 0, 0, 0, 0, 0, 0);
static Operator OPB1(OPCODE_B1, Operator::kNoWrite, "opa1", 1, 0, 0, 0, 0, 0);
static Operator OPB2(OPCODE_B2, Operator::kNoWrite, "opa2", 2, 0, 0, 0, 0, 0);
static Operator OPC0(OPCODE_C0, Operator::kNoWrite, "opc0", 0, 0, 0, 0, 0, 0);
static Operator OPC1(OPCODE_C1, Operator::kNoWrite, "opc1", 1, 0, 0, 0, 0, 0);
static Operator OPC2(OPCODE_C2, Operator::kNoWrite, "opc2", 2, 0, 0, 0, 0, 0);
// Replaces all "A" operators with "B" operators without creating new nodes.

View File

@ -23,8 +23,8 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
0, 0, "dummy");
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 0, 0, 0);
// So we can get a real JS function.
static Handle<JSFunction> Compile(const char* source) {

View File

@ -18,8 +18,8 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
0, 0, "dummy");
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 1, 0, 0);
class PreNodeVisitor : public NullNodeVisitor {
public:

View File

@ -14,8 +14,8 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
0, 0, "dummy");
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 1, 0, 0);
TEST(NodeAllocation) {
GraphTester graph;

View File

@ -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<int> op3(12, Operator::kNoProperties, 0, 1, "Mnemonic1", 12333);
Operator1<int> op3(12, NONE, "Mnemonic1", 0, 0, 0, 1, 0, 0, 12333);
CHECK_EQ(0, strcmp(op3.mnemonic(), "Mnemonic1"));
Operator1<double> op4(13, Operator::kNoProperties, 0, 1, "TheOther", 99.9);
Operator1<double> op4(13, NONE, "TheOther", 0, 0, 0, 1, 0, 0, 99.9);
CHECK_EQ(0, strcmp(op4.mnemonic(), "TheOther"));
}
TEST(TestSimpleOperatorHash) {
SimpleOperator op1(17, Operator::kNoProperties, 0, 0, "Another");
TEST(TestOperator_Hash) {
Operator op1(17, NONE, "Another", 0, 0, 0, 0, 0, 0);
CHECK_EQ(17, static_cast<int>(op1.HashCode()));
SimpleOperator op2(18, Operator::kNoProperties, 0, 0, "Falsch");
Operator op2(18, NONE, "Falsch", 0, 0, 0, 0, 0, 0);
CHECK_EQ(18, static_cast<int>(op2.HashCode()));
}
TEST(TestSimpleOperatorEquals) {
SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");
TEST(TestOperator_Equals) {
Operator op1a(19, NONE, "Another1", 0, 0, 0, 0, 0, 0);
Operator op1b(19, FOLD, "Another2", 2, 0, 0, 2, 0, 0);
CHECK(op1a.Equals(&op1a));
CHECK(op1a.Equals(&op1b));
CHECK(op1b.Equals(&op1a));
CHECK(op1b.Equals(&op1b));
SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Falsch1");
SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Falsch2");
Operator op2a(20, NONE, "Falsch1", 0, 0, 0, 0, 0, 0);
Operator op2b(20, FOLD, "Falsch2", 1, 0, 0, 1, 0, 0);
CHECK(op2a.Equals(&op2a));
CHECK(op2a.Equals(&op2b));
@ -72,46 +76,46 @@ static SmartArrayPointer<const char> OperatorToString(Operator* op) {
}
TEST(TestSimpleOperatorPrint) {
SimpleOperator op1a(19, Operator::kNoProperties, 0, 0, "Another1");
SimpleOperator op1b(19, Operator::kFoldable, 2, 2, "Another2");
TEST(TestOperator_Print) {
Operator op1a(19, NONE, "Another1", 0, 0, 0, 0, 0, 0);
Operator op1b(19, FOLD, "Another2", 2, 0, 0, 2, 0, 0);
CHECK_EQ("Another1", OperatorToString(&op1a).get());
CHECK_EQ("Another2", OperatorToString(&op1b).get());
SimpleOperator op2a(20, Operator::kNoProperties, 0, 0, "Flog1");
SimpleOperator op2b(20, Operator::kFoldable, 1, 1, "Flog2");
Operator op2a(20, NONE, "Flog1", 0, 0, 0, 0, 0, 0);
Operator op2b(20, FOLD, "Flog2", 1, 0, 0, 1, 0, 0);
CHECK_EQ("Flog1", OperatorToString(&op2a).get());
CHECK_EQ("Flog2", OperatorToString(&op2b).get());
}
TEST(TestOperator1intHash) {
Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11);
Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11);
TEST(TestOperator1int_Hash) {
Operator1<int> op1a(23, NONE, "Wolfie", 0, 0, 0, 0, 0, 0, 11);
Operator1<int> op1b(23, FOLD, "Doggie", 2, 0, 0, 2, 0, 0, 11);
CHECK(op1a.HashCode() == op1b.HashCode());
Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", 3);
Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", 4);
Operator1<int> op2a(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, 3);
Operator1<int> op2b(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, 4);
CHECK(op1a.HashCode() != op2a.HashCode());
CHECK(op2a.HashCode() != op2b.HashCode());
}
TEST(TestOperator1intEquals) {
Operator1<int> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11);
Operator1<int> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11);
TEST(TestOperator1int_Equals) {
Operator1<int> op1a(23, NONE, "Scratchy", 0, 0, 0, 0, 0, 0, 11);
Operator1<int> op1b(23, FOLD, "Scratchy", 2, 0, 0, 2, 0, 0, 11);
CHECK(op1a.Equals(&op1a));
CHECK(op1a.Equals(&op1b));
CHECK(op1b.Equals(&op1a));
CHECK(op1b.Equals(&op1b));
Operator1<int> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3);
Operator1<int> op2b(24, Operator::kNoProperties, 0, 0, "Im", 4);
Operator1<int> op2a(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 3);
Operator1<int> op2b(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 4);
CHECK(op2a.Equals(&op2a));
CHECK(!op2a.Equals(&op2b));
@ -128,7 +132,7 @@ TEST(TestOperator1intEquals) {
CHECK(!op2b.Equals(&op1a));
CHECK(!op2b.Equals(&op1b));
SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");
Operator op3(25, NONE, "Weepy", 0, 0, 0, 0, 0, 0);
CHECK(!op1a.Equals(&op3));
CHECK(!op1b.Equals(&op3));
@ -142,46 +146,55 @@ TEST(TestOperator1intEquals) {
}
TEST(TestOperator1intPrint) {
Operator1<int> op1(12, Operator::kNoProperties, 0, 1, "Op1Test", 0);
TEST(TestOperator1int_Print) {
Operator1<int> op1(12, NONE, "Op1Test", 0, 0, 0, 1, 0, 0, 0);
CHECK_EQ("Op1Test[0]", OperatorToString(&op1).get());
Operator1<int> op2(12, Operator::kNoProperties, 0, 1, "Op1Test", 66666666);
Operator1<int> op2(12, NONE, "Op1Test", 0, 0, 0, 1, 0, 0, 66666666);
CHECK_EQ("Op1Test[66666666]", OperatorToString(&op2).get());
Operator1<int> op3(12, Operator::kNoProperties, 0, 1, "FooBar", 2347);
Operator1<int> op3(12, NONE, "FooBar", 0, 0, 0, 1, 0, 0, 2347);
CHECK_EQ("FooBar[2347]", OperatorToString(&op3).get());
Operator1<int> op4(12, Operator::kNoProperties, 0, 1, "BarFoo", -879);
Operator1<int> op4(12, NONE, "BarFoo", 0, 0, 0, 1, 0, 0, -879);
CHECK_EQ("BarFoo[-879]", OperatorToString(&op4).get());
}
TEST(TestOperator1doubleHash) {
Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Wolfie", 11.77);
Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Doggie", 11.77);
TEST(TestOperator1double_Hash) {
Operator1<double> op1a(23, NONE, "Wolfie", 0, 0, 0, 0, 0, 0, 11.77);
Operator1<double> op1b(23, FOLD, "Doggie", 2, 0, 0, 2, 0, 0, 11.77);
CHECK(op1a.HashCode() == op1b.HashCode());
Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Arfie", -6.7);
Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Arfie", -6.8);
Operator1<double> op2a(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, -6.7);
Operator1<double> op2b(24, NONE, "Arfie", 0, 0, 0, 0, 0, 0, -6.8);
CHECK(op1a.HashCode() != op2a.HashCode());
CHECK(op2a.HashCode() != op2b.HashCode());
}
TEST(TestOperator1doubleEquals) {
Operator1<double> op1a(23, Operator::kNoProperties, 0, 0, "Scratchy", 11.77);
Operator1<double> op1b(23, Operator::kFoldable, 2, 2, "Scratchy", 11.77);
TEST(TestOperator1doublePrint) {
Operator1<double> op1a(23, NONE, "Canary", 0, 0, 0, 0, 0, 0, 0.5);
Operator1<double> op1b(23, FOLD, "Finch", 2, 0, 0, 2, 0, 0, -1.5);
CHECK_EQ("Canary[0.5]", OperatorToString(&op1a).get());
CHECK_EQ("Finch[-1.5]", OperatorToString(&op1b).get());
}
TEST(TestOperator1double_Equals) {
Operator1<double> op1a(23, NONE, "Scratchy", 0, 0, 0, 0, 0, 0, 11.77);
Operator1<double> op1b(23, FOLD, "Scratchy", 2, 0, 0, 2, 0, 0, 11.77);
CHECK(op1a.Equals(&op1a));
CHECK(op1a.Equals(&op1b));
CHECK(op1b.Equals(&op1a));
CHECK(op1b.Equals(&op1b));
Operator1<double> op2a(24, Operator::kNoProperties, 0, 0, "Im", 3.1);
Operator1<double> op2b(24, Operator::kNoProperties, 0, 0, "Im", 3.2);
Operator1<double> op2a(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 3.1);
Operator1<double> op2b(24, NONE, "Im", 0, 0, 0, 0, 0, 0, 3.2);
CHECK(op2a.Equals(&op2a));
CHECK(!op2a.Equals(&op2b));
@ -198,7 +211,7 @@ TEST(TestOperator1doubleEquals) {
CHECK(!op2b.Equals(&op1a));
CHECK(!op2b.Equals(&op1b));
SimpleOperator op3(25, Operator::kNoProperties, 0, 0, "Weepy");
Operator op3(25, NONE, "Weepy", 0, 0, 0, 0, 0, 0);
CHECK(!op1a.Equals(&op3));
CHECK(!op1b.Equals(&op3));
@ -210,8 +223,8 @@ TEST(TestOperator1doubleEquals) {
CHECK(!op3.Equals(&op2a));
CHECK(!op3.Equals(&op2b));
Operator1<double> op4a(24, Operator::kNoProperties, 0, 0, "Bashful", 1.0);
Operator1<double> op4b(24, Operator::kNoProperties, 0, 0, "Bashful", 1.0);
Operator1<double> op4a(24, NONE, "Bashful", 0, 0, 0, 0, 0, 0, 1.0);
Operator1<double> op4b(24, NONE, "Bashful", 0, 0, 0, 0, 0, 0, 1.0);
CHECK(op4a.Equals(&op4a));
CHECK(op4a.Equals(&op4b));
@ -223,3 +236,48 @@ TEST(TestOperator1doubleEquals) {
CHECK(!op3.Equals(&op4a));
CHECK(!op3.Equals(&op4b));
}
TEST(TestOpParameter_Operator1double) {
double values[] = {7777.5, -66, 0, 11, 0.1};
for (size_t i = 0; i < arraysize(values); i++) {
Operator1<double> op(33, NONE, "Scurvy", 0, 0, 0, 0, 0, 0, values[i]);
CHECK_EQ(values[i], OpParameter<double>(&op));
}
}
TEST(TestOpParameter_Operator1float) {
float values[] = {// thanks C++.
static_cast<float>(7777.5), static_cast<float>(-66),
static_cast<float>(0), static_cast<float>(11),
static_cast<float>(0.1)};
for (size_t i = 0; i < arraysize(values); i++) {
Operator1<float> op(33, NONE, "Scurvy", 0, 0, 0, 0, 0, 0, values[i]);
CHECK_EQ(values[i], OpParameter<float>(&op));
}
}
TEST(TestOpParameter_Operator1int) {
int values[] = {7777, -66, 0, 11, 1, 0x666aff};
for (size_t i = 0; i < arraysize(values); i++) {
Operator1<int> op(33, NONE, "Scurvy", 0, 0, 0, 0, 0, 0, values[i]);
CHECK_EQ(values[i], OpParameter<int>(&op));
}
}
TEST(Operator_CountsOrder) {
Operator op(29, NONE, "Flashy", 11, 22, 33, 44, 55, 66);
CHECK_EQ(11, op.ValueInputCount());
CHECK_EQ(22, op.EffectInputCount());
CHECK_EQ(33, op.ControlInputCount());
CHECK_EQ(44, op.ValueOutputCount());
CHECK_EQ(55, op.EffectOutputCount());
CHECK_EQ(66, op.ControlOutputCount());
}

View File

@ -16,8 +16,8 @@
using namespace v8::internal;
using namespace v8::internal::compiler;
static SimpleOperator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
0, 0, "dummy");
static Operator dummy_operator(IrOpcode::kParameter, Operator::kNoWrite,
"dummy", 0, 0, 0, 0, 0, 0);
TEST(TestScheduleAllocation) {
HandleAndZoneScope scope;

View File

@ -49,8 +49,8 @@ const SharedOperator kSharedOperators[] = {
SHARED(End, Operator::kFoldable, 0, 0, 1, 0, 0),
SHARED(IfTrue, Operator::kFoldable, 0, 0, 1, 0, 1),
SHARED(IfFalse, Operator::kFoldable, 0, 0, 1, 0, 1),
SHARED(Throw, Operator::kFoldable, 1, 0, 1, 0, 1),
SHARED(Return, Operator::kNoProperties, 1, 1, 1, 1, 1)
SHARED(Throw, Operator::kFoldable, 1, 1, 1, 0, 1),
SHARED(Return, Operator::kNoProperties, 1, 1, 1, 0, 1)
#undef SHARED
};
@ -130,7 +130,7 @@ class CommonOperatorTest : public TestWithZone {
};
const int kArguments[] = {1, 5, 6, 42, 100, 10000, kMaxInt};
const int kArguments[] = {1, 5, 6, 42, 100, 10000, 65000};
const float kFloatValues[] = {-std::numeric_limits<float>::infinity(),

View File

@ -18,10 +18,18 @@ namespace v8 {
namespace internal {
namespace compiler {
struct TestOperator : public Operator {
TestOperator(Operator::Opcode opcode, Operator::Properties properties,
size_t value_in, size_t value_out)
: Operator(opcode, properties, "TestOp", value_in, 0, 0, value_out, 0,
0) {}
};
namespace {
SimpleOperator OP0(0, Operator::kNoWrite, 0, 1, "op0");
SimpleOperator OP1(1, Operator::kNoProperties, 1, 1, "op1");
TestOperator OP0(0, Operator::kNoWrite, 0, 1);
TestOperator OP1(1, Operator::kNoProperties, 1, 1);
struct MockReducer : public Reducer {

View File

@ -68,7 +68,7 @@ const SharedOperator kSharedOperators[] = {
SHARED(ToName, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(ToObject, Operator::kNoProperties, 1, 1, 1, 1, 1, 1),
SHARED(Yield, Operator::kNoProperties, 1, 0, 1, 1, 1, 1),
SHARED(Create, Operator::kEliminatable, 0, 0, 1, 0, 1, 1),
SHARED(Create, Operator::kEliminatable, 0, 0, 1, 1, 1, 1),
SHARED(HasProperty, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),
SHARED(TypeOf, Operator::kPure, 1, 0, 0, 0, 1, 0),
SHARED(InstanceOf, Operator::kNoProperties, 2, 1, 1, 1, 1, 1),

View File

@ -12,12 +12,16 @@ namespace v8 {
namespace internal {
namespace compiler {
namespace {
struct TestOperator : public Operator {
TestOperator(Operator::Opcode opcode, Operator::Properties properties,
size_t value_in, size_t value_out)
: Operator(opcode, properties, "TestOp", value_in, 0, 0, value_out, 0,
0) {}
};
const SimpleOperator kOp0(0, Operator::kEliminatable, 0, 1, "op0");
const SimpleOperator kOp1(1, Operator::kEliminatable, 1, 1, "op1");
} // namespace
static const TestOperator kOp0(0, Operator::kEliminatable, 0, 1);
static const TestOperator kOp1(1, Operator::kEliminatable, 1, 1);
class ValueNumberingReducerTest : public TestWithZone {
@ -55,7 +59,7 @@ TEST_F(ValueNumberingReducerTest, DeadNodesAreNeverReturned) {
TEST_F(ValueNumberingReducerTest, OnlyEliminatableNodesAreReduced) {
SimpleOperator op(0, Operator::kNoProperties, 0, 1, "op");
TestOperator op(0, Operator::kNoProperties, 0, 1);
Node* n0 = graph()->NewNode(&op);
Node* n1 = graph()->NewNode(&op);
EXPECT_FALSE(Reduce(n0).Changed());
@ -69,20 +73,18 @@ TEST_F(ValueNumberingReducerTest, OperatorEqualityNotIdentity) {
for (size_t i = 0; i < arraysize(inputs); ++i) {
Operator::Opcode opcode = static_cast<Operator::Opcode>(
std::numeric_limits<Operator::Opcode>::max() - i);
inputs[i] = graph()->NewNode(new (zone()) SimpleOperator(
opcode, Operator::kEliminatable, 0, 1, "Operator"));
inputs[i] = graph()->NewNode(
new (zone()) TestOperator(opcode, Operator::kEliminatable, 0, 1));
}
TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
const SimpleOperator op1(static_cast<Operator::Opcode>(input_count),
Operator::kEliminatable,
static_cast<int>(input_count), 1, "op");
const TestOperator op1(static_cast<Operator::Opcode>(input_count),
Operator::kEliminatable, input_count, 1);
Node* n1 = graph()->NewNode(&op1, static_cast<int>(input_count), inputs);
Reduction r1 = Reduce(n1);
EXPECT_FALSE(r1.Changed());
const SimpleOperator op2(static_cast<Operator::Opcode>(input_count),
Operator::kEliminatable,
static_cast<int>(input_count), 1, "op");
const TestOperator op2(static_cast<Operator::Opcode>(input_count),
Operator::kEliminatable, input_count, 1);
Node* n2 = graph()->NewNode(&op2, static_cast<int>(input_count), inputs);
Reduction r2 = Reduce(n2);
EXPECT_TRUE(r2.Changed());
@ -97,12 +99,11 @@ TEST_F(ValueNumberingReducerTest, SubsequentReductionsYieldTheSameNode) {
for (size_t i = 0; i < arraysize(inputs); ++i) {
Operator::Opcode opcode = static_cast<Operator::Opcode>(
std::numeric_limits<Operator::Opcode>::max() - i);
inputs[i] = graph()->NewNode(new (zone()) SimpleOperator(
opcode, Operator::kEliminatable, 0, 1, "Operator"));
inputs[i] = graph()->NewNode(
new (zone()) TestOperator(opcode, Operator::kEliminatable, 0, 1));
}
TRACED_FORRANGE(size_t, input_count, 0, arraysize(inputs)) {
const SimpleOperator op1(1, Operator::kEliminatable,
static_cast<int>(input_count), 1, "op1");
const TestOperator op1(1, Operator::kEliminatable, input_count, 1);
Node* n = graph()->NewNode(&op1, static_cast<int>(input_count), inputs);
Reduction r = Reduce(n);
EXPECT_FALSE(r.Changed());