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(
liveness ? &liveness->bit_vector() : nullptr, 0);
bool accumulator_is_live = !liveness || liveness->AccumulatorIsLive();
Node* accumulator_state_values;
if (parameter_count() == 1 && accumulator_is_live &&
values()->at(accumulator_base()) == values()->at(0)) {
// 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());
}
Node* accumulator_state_value =
accumulator_is_live ? values()->at(accumulator_base())
: builder()->jsgraph()->OptimizedOutConstant();
const Operator* op = common()->FrameState(
bailout_id, combine, builder()->frame_state_function_info());
Node* result = graph()->NewNode(
op, parameters_state_values_, registers_state_values,
accumulator_state_values, Context(), builder()->GetFunctionClosure(),
accumulator_state_value, Context(), builder()->GetFunctionClosure(),
builder()->graph()->start());
return result;
......
......@@ -280,6 +280,14 @@ Node* JSGraph::EmptyStateValues() {
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() {
return CACHED(kDead, graph()->NewNode(common()->Dead()));
}
......
......@@ -142,6 +142,10 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
// values for a certain part of the frame state.
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.
Node* Dead();
......@@ -181,6 +185,7 @@ class V8_EXPORT_PRIVATE JSGraph : public NON_EXPORTED_BASE(ZoneObject) {
kOneConstant,
kNaNConstant,
kEmptyStateValues,
kSingleDeadTypedStateValues,
kDead,
kNumCachedNodes // Must remain last.
};
......
......@@ -1073,6 +1073,51 @@ class RepresentationSelector {
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) {
if (propagate()) {
for (int i = 0; i < node->InputCount(); i++) {
......@@ -2750,6 +2795,8 @@ class RepresentationSelector {
MachineRepresentation::kFloat64);
if (lower()) NodeProperties::ChangeOp(node, Float64Op(node));
return;
case IrOpcode::kFrameState:
return VisitFrameState(node);
case IrOpcode::kStateValues:
return VisitStateValues(node);
case IrOpcode::kObjectState:
......@@ -2791,7 +2838,6 @@ class RepresentationSelector {
case IrOpcode::kDeoptimize:
case IrOpcode::kEffectPhi:
case IrOpcode::kTerminate:
case IrOpcode::kFrameState:
case IrOpcode::kCheckpoint:
case IrOpcode::kLoop:
case IrOpcode::kMerge:
......
......@@ -492,12 +492,19 @@ void Verifier::Visitor::Check(Node* node) {
CHECK_EQ(0, control_count);
CHECK_EQ(0, effect_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() ==
IrOpcode::kStateValues ||
NodeProperties::GetValueInput(node, i)->opcode() ==
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;
}
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