| Index: src/compiler/escape-analysis-reducer.cc
|
| diff --git a/src/compiler/escape-analysis-reducer.cc b/src/compiler/escape-analysis-reducer.cc
|
| index 2675af5118f2052b963c7e39468839dbfce20924..c4d0e950f06cdd918029385e3cb1cc64653c7bf8 100644
|
| --- a/src/compiler/escape-analysis-reducer.cc
|
| +++ b/src/compiler/escape-analysis-reducer.cc
|
| @@ -27,11 +27,16 @@ EscapeAnalysisReducer::EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
|
| jsgraph_(jsgraph),
|
| escape_analysis_(escape_analysis),
|
| zone_(zone),
|
| - visited_(static_cast<int>(jsgraph->graph()->NodeCount() * 2), zone),
|
| + fully_reduced_(static_cast<int>(jsgraph->graph()->NodeCount() * 2), zone),
|
| exists_virtual_allocate_(true) {}
|
|
|
|
|
| Reduction EscapeAnalysisReducer::Reduce(Node* node) {
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length()) &&
|
| + fully_reduced_.Contains(node->id())) {
|
| + return NoChange();
|
| + }
|
| +
|
| switch (node->opcode()) {
|
| case IrOpcode::kLoadField:
|
| case IrOpcode::kLoadElement:
|
| @@ -47,35 +52,38 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) {
|
| return ReduceReferenceEqual(node);
|
| case IrOpcode::kObjectIsSmi:
|
| return ReduceObjectIsSmi(node);
|
| + // FrameStates and Value nodes are preprocessed here,
|
| + // and visited via ReduceFrameStateUses from their user nodes.
|
| case IrOpcode::kFrameState:
|
| case IrOpcode::kStateValues: {
|
| - if (node->id() >= static_cast<NodeId>(visited_.length()) ||
|
| - visited_.Contains(node->id())) {
|
| + if (node->id() >= static_cast<NodeId>(fully_reduced_.length()) ||
|
| + fully_reduced_.Contains(node->id())) {
|
| break;
|
| }
|
| - bool needs_visit = false;
|
| + bool depends_on_object_state = false;
|
| for (int i = 0; i < node->InputCount(); i++) {
|
| Node* input = node->InputAt(i);
|
| switch (input->opcode()) {
|
| case IrOpcode::kAllocate:
|
| case IrOpcode::kFinishRegion:
|
| - needs_visit = needs_visit || escape_analysis()->IsVirtual(input);
|
| + depends_on_object_state =
|
| + depends_on_object_state || escape_analysis()->IsVirtual(input);
|
| break;
|
| case IrOpcode::kFrameState:
|
| case IrOpcode::kStateValues:
|
| - needs_visit =
|
| - needs_visit ||
|
| - input->id() >= static_cast<NodeId>(visited_.length()) ||
|
| - !visited_.Contains(input->id());
|
| + depends_on_object_state =
|
| + depends_on_object_state ||
|
| + input->id() >= static_cast<NodeId>(fully_reduced_.length()) ||
|
| + !fully_reduced_.Contains(input->id());
|
| break;
|
| default:
|
| break;
|
| }
|
| }
|
| - if (!needs_visit) {
|
| - visited_.Add(node->id());
|
| + if (!depends_on_object_state) {
|
| + fully_reduced_.Add(node->id());
|
| }
|
| - break;
|
| + return NoChange();
|
| }
|
| default:
|
| // TODO(sigurds): Change this to GetFrameStateInputCount once
|
| @@ -93,10 +101,10 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) {
|
| Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
|
| DCHECK(node->opcode() == IrOpcode::kLoadField ||
|
| node->opcode() == IrOpcode::kLoadElement);
|
| - if (visited_.Contains(node->id())) return NoChange();
|
| - visited_.Add(node->id());
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length())) {
|
| + fully_reduced_.Add(node->id());
|
| + }
|
| if (Node* rep = escape_analysis()->GetReplacement(node)) {
|
| - visited_.Add(node->id());
|
| counters()->turbo_escape_loads_replaced()->Increment();
|
| TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(),
|
| node->op()->mnemonic(), rep->id(), rep->op()->mnemonic());
|
| @@ -110,8 +118,9 @@ Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
|
| Reduction EscapeAnalysisReducer::ReduceStore(Node* node) {
|
| DCHECK(node->opcode() == IrOpcode::kStoreField ||
|
| node->opcode() == IrOpcode::kStoreElement);
|
| - if (visited_.Contains(node->id())) return NoChange();
|
| - visited_.Add(node->id());
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length())) {
|
| + fully_reduced_.Add(node->id());
|
| + }
|
| if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) {
|
| TRACE("Removed #%d (%s) from effect chain\n", node->id(),
|
| node->op()->mnemonic());
|
| @@ -124,8 +133,6 @@ Reduction EscapeAnalysisReducer::ReduceStore(Node* node) {
|
|
|
| Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) {
|
| DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
|
| - if (visited_.Contains(node->id())) return NoChange();
|
| - visited_.Add(node->id());
|
| if (escape_analysis()->IsVirtual(node)) {
|
| RelaxEffectsAndControls(node);
|
| counters()->turbo_escape_allocs_replaced()->Increment();
|
| @@ -140,6 +147,9 @@ Reduction EscapeAnalysisReducer::ReduceFinishRegion(Node* node) {
|
| DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
|
| Node* effect = NodeProperties::GetEffectInput(node, 0);
|
| if (effect->opcode() == IrOpcode::kBeginRegion) {
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length())) {
|
| + fully_reduced_.Add(node->id());
|
| + }
|
| RelaxEffectsAndControls(effect);
|
| RelaxEffectsAndControls(node);
|
| #ifdef DEBUG
|
| @@ -177,6 +187,7 @@ Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) {
|
| // Left-hand side is not a virtual object.
|
| ReplaceWithValue(node, jsgraph()->FalseConstant());
|
| TRACE("Replaced ref eq #%d with false\n", node->id());
|
| + return Replace(node);
|
| }
|
| return NoChange();
|
| }
|
| @@ -195,8 +206,6 @@ Reduction EscapeAnalysisReducer::ReduceObjectIsSmi(Node* node) {
|
|
|
|
|
| Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) {
|
| - if (visited_.Contains(node->id())) return NoChange();
|
| - visited_.Add(node->id());
|
| DCHECK_GE(node->op()->EffectInputCount(), 1);
|
| bool changed = false;
|
| for (int i = 0; i < node->InputCount(); ++i) {
|
| @@ -220,8 +229,8 @@ Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect,
|
| bool multiple_users) {
|
| DCHECK(node->opcode() == IrOpcode::kFrameState ||
|
| node->opcode() == IrOpcode::kStateValues);
|
| - if (node->id() < static_cast<NodeId>(visited_.length()) &&
|
| - visited_.Contains(node->id())) {
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length()) &&
|
| + fully_reduced_.Contains(node->id())) {
|
| return nullptr;
|
| }
|
| TRACE("Reducing %s %d\n", node->op()->mnemonic(), node->id());
|
| @@ -263,6 +272,9 @@ Node* EscapeAnalysisReducer::ReduceDeoptState(Node* node, Node* effect,
|
| }
|
| }
|
| }
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length())) {
|
| + fully_reduced_.Add(node->id());
|
| + }
|
| return clone;
|
| }
|
|
|
| @@ -274,6 +286,10 @@ Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index,
|
| bool already_cloned,
|
| bool multiple_users) {
|
| Node* input = NodeProperties::GetValueInput(node, node_index);
|
| + if (node->id() < static_cast<NodeId>(fully_reduced_.length()) &&
|
| + fully_reduced_.Contains(node->id())) {
|
| + return nullptr;
|
| + }
|
| TRACE("Reducing State Input #%d (%s)\n", input->id(),
|
| input->op()->mnemonic());
|
| Node* clone = nullptr;
|
| @@ -307,6 +323,36 @@ Counters* EscapeAnalysisReducer::counters() const {
|
| return jsgraph_->isolate()->counters();
|
| }
|
|
|
| +
|
| +class EscapeAnalysisVerifier final : public AdvancedReducer {
|
| + public:
|
| + EscapeAnalysisVerifier(Editor* editor, EscapeAnalysis* escape_analysis)
|
| + : AdvancedReducer(editor), escape_analysis_(escape_analysis) {}
|
| +
|
| + Reduction Reduce(Node* node) final {
|
| + switch (node->opcode()) {
|
| + case IrOpcode::kAllocate:
|
| + CHECK(!escape_analysis_->IsVirtual(node));
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + return NoChange();
|
| + }
|
| +
|
| + private:
|
| + EscapeAnalysis* escape_analysis_;
|
| +};
|
| +
|
| +void EscapeAnalysisReducer::VerifyReplacement() const {
|
| +#ifdef DEBUG
|
| + GraphReducer graph_reducer(zone(), jsgraph()->graph());
|
| + EscapeAnalysisVerifier verifier(&graph_reducer, escape_analysis());
|
| + graph_reducer.AddReducer(&verifier);
|
| + graph_reducer.ReduceGraph();
|
| +#endif // DEBUG
|
| +}
|
| +
|
| } // namespace compiler
|
| } // namespace internal
|
| } // namespace v8
|
|
|