Commit f47572f3 authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Avoid creating singleton state-values for the accumulator.

This saves about 5% of memory and node count consumed by graph building
on the TypeScript benchmark. High watermark goes down by 3-4%.

BUG=v8:5267

Review-Url: https://codereview.chromium.org/2829093002
Cr-Commit-Position: refs/heads/master@{#45113}
parent f5ff422b
...@@ -410,26 +410,15 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint( ...@@ -410,26 +410,15 @@ Node* BytecodeGraphBuilder::Environment::Checkpoint(
liveness ? &liveness->bit_vector() : nullptr, 0); liveness ? &liveness->bit_vector() : nullptr, 0);
bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive(); bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive();
Node* accumulator_state_values; Node* accumulator_state_value =
if (parameter_count() == 1 && accumulator_is_live && accumulator_is_live ? values()->at(accumulator_base())
values()->at(accumulator_base()) == values()->at(0)) { : builder()->jsgraph()->OptimizedOutConstant();
// Re-use the parameter state values if there happens to only be one
// parameter and the accumulator is live and holds that parameter's value.
accumulator_state_values = parameters_state_values_;
} else {
// Otherwise, use the state values cache to hopefully re-use local register
// state values (if there is only one local register), or at the very least
// re-use previous accumulator state values.
accumulator_state_values = GetStateValuesFromCache(
&values()->at(accumulator_base()), 1,
liveness ? &liveness->bit_vector() : nullptr, register_count());
}
const Operator* op = common()->FrameState( const Operator* op = common()->FrameState(
bailout_id, combine, builder()->frame_state_function_info()); bailout_id, combine, builder()->frame_state_function_info());
Node* result = graph()->NewNode( Node* result = graph()->NewNode(
op, parameters_state_values_, registers_state_values, op, parameters_state_values_, registers_state_values,
accumulator_state_values, Context(), builder()->GetFunctionClosure(), accumulator_state_value, Context(), builder()->GetFunctionClosure(),
builder()->graph()->start()); builder()->graph()->start());
return result; return result;
......
...@@ -280,6 +280,14 @@ Node* JSGraph::EmptyStateValues() { ...@@ -280,6 +280,14 @@ Node* JSGraph::EmptyStateValues() {
0, SparseInputMask::Dense()))); 0, SparseInputMask::Dense())));
} }
Node* JSGraph::SingleDeadTypedStateValues() {
return CACHED(kSingleDeadTypedStateValues,
graph()->NewNode(common()->TypedStateValues(
new (graph()->zone()->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(0, graph()->zone()),
SparseInputMask(SparseInputMask::kEndMarker << 1))));
}
Node* JSGraph::Dead() { Node* JSGraph::Dead() {
return CACHED(kDead, graph()->NewNode(common()->Dead())); return CACHED(kDead, graph()->NewNode(common()->Dead()));
} }
......
...@@ -142,6 +142,10 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -142,6 +142,10 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
// values for a certain part of the frame state. // values for a certain part of the frame state.
Node* EmptyStateValues(); Node* EmptyStateValues();
// Typed state values with a single dead input. This is useful to represent
// dead accumulator.
Node* SingleDeadTypedStateValues();
// Create a control node that serves as dependency for dead nodes. // Create a control node that serves as dependency for dead nodes.
Node* Dead(); Node* Dead();
...@@ -181,6 +185,7 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) { ...@@ -181,6 +185,7 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
kOneConstant, kOneConstant,
kNaNConstant, kNaNConstant,
kEmptyStateValues, kEmptyStateValues,
kSingleDeadTypedStateValues,
kDead, kDead,
kNumCachedNodes // Must remain last. kNumCachedNodes // Must remain last.
}; };
......
...@@ -1073,6 +1073,51 @@ class RepresentationSelector { ...@@ -1073,6 +1073,51 @@ class RepresentationSelector {
SetOutput(node, MachineRepresentation::kTagged); SetOutput(node, MachineRepresentation::kTagged);
} }
void VisitFrameState(Node* node) {
DCHECK_EQ(5, node->op()->ValueInputCount());
DCHECK_EQ(1, OperatorProperties::GetFrameStateInputCount(node->op()));
ProcessInput(node, 0, UseInfo::AnyTagged()); // Parameters.
ProcessInput(node, 1, UseInfo::AnyTagged()); // Registers.
// Expression stack/accumulator.
if (node->InputAt(2)->opcode() == IrOpcode::kStateValues ||
node->InputAt(2)->opcode() == IrOpcode::kTypedStateValues) {
// TODO(turbofan): This should only be produced by AST graph builder.
// Remove once we switch to bytecode graph builder exclusively.
ProcessInput(node, 2, UseInfo::AnyTagged());
} else {
// Accumulator is a special flower - we need to remember its type in
// a singleton typed-state-values node (as if it was a singleton
// state-values node).
if (propagate()) {
EnqueueInput(node, 2, UseInfo::Any());
} else if (lower()) {
Zone* zone = jsgraph_->zone();
Node* accumulator = node->InputAt(2);
if (accumulator == jsgraph_->OptimizedOutConstant()) {
node->ReplaceInput(2, jsgraph_->SingleDeadTypedStateValues());
} else {
ZoneVector<MachineType>* types =
new (zone->New(sizeof(ZoneVector<MachineType>)))
ZoneVector<MachineType>(1, zone);
(*types)[0] = DeoptMachineTypeOf(
GetInfo(accumulator)->representation(), TypeOf(accumulator));
node->ReplaceInput(2, jsgraph_->graph()->NewNode(
jsgraph_->common()->TypedStateValues(
types, SparseInputMask::Dense()),
accumulator));
}
}
}
ProcessInput(node, 3, UseInfo::AnyTagged()); // Context.
ProcessInput(node, 4, UseInfo::AnyTagged()); // Closure.
ProcessInput(node, 5, UseInfo::AnyTagged()); // Outer frame state.
return SetOutput(node, MachineRepresentation::kTagged);
}
void VisitObjectState(Node* node) { void VisitObjectState(Node* node) {
if (propagate()) { if (propagate()) {
for (int i = 0; i < node->InputCount(); i++) { for (int i = 0; i < node->InputCount(); i++) {
...@@ -2750,6 +2795,8 @@ class RepresentationSelector { ...@@ -2750,6 +2795,8 @@ class RepresentationSelector {
MachineRepresentation::kFloat64); MachineRepresentation::kFloat64);
if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
return; return;
case IrOpcode::kFrameState:
return VisitFrameState(node);
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
return VisitStateValues(node); return VisitStateValues(node);
case IrOpcode::kObjectState: case IrOpcode::kObjectState:
...@@ -2791,7 +2838,6 @@ class RepresentationSelector { ...@@ -2791,7 +2838,6 @@ class RepresentationSelector {
case IrOpcode::kDeoptimize: case IrOpcode::kDeoptimize:
case IrOpcode::kEffectPhi: case IrOpcode::kEffectPhi:
case IrOpcode::kTerminate: case IrOpcode::kTerminate:
case IrOpcode::kFrameState:
case IrOpcode::kCheckpoint: case IrOpcode::kCheckpoint:
case IrOpcode::kLoop: case IrOpcode::kLoop:
case IrOpcode::kMerge: case IrOpcode::kMerge:
......
...@@ -492,12 +492,19 @@ void Verifier::Visitor::Check(Node* node) { ...@@ -492,12 +492,19 @@ void Verifier::Visitor::Check(Node* node) {
CHECK_EQ(0, control_count); CHECK_EQ(0, control_count);
CHECK_EQ(0, effect_count); CHECK_EQ(0, effect_count);
CHECK_EQ(6, input_count); CHECK_EQ(6, input_count);
for (int i = 0; i < 3; ++i) { // Check that the parameters and registers are kStateValues or
// kTypedStateValues.
for (int i = 0; i < 2; ++i) {
CHECK(NodeProperties::GetValueInput(node, i)->opcode() == CHECK(NodeProperties::GetValueInput(node, i)->opcode() ==
IrOpcode::kStateValues || IrOpcode::kStateValues ||
NodeProperties::GetValueInput(node, i)->opcode() == NodeProperties::GetValueInput(node, i)->opcode() ==
IrOpcode::kTypedStateValues); IrOpcode::kTypedStateValues);
} }
// The accumulator (InputAt(2)) cannot be kStateValues, but it can be
// kTypedStateValues (to signal the type). Once AST graph builder
// is removed, we should check this here. Until then, AST graph
// builder can generate expression stack as InputAt(2), which can
// still be kStateValues.
break; break;
} }
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment