Commit 5b582114 authored by sigurds's avatar sigurds Committed by Commit bot

[turbofan] Improve escape analysis

This patch improves escape analysis and fixes bugs
triggered by clusterfuzz. Impovements include:
* Handling of LoadElement/StoreElement if index is a
  constant
* Handling of JSStoreProperty: invalidate all information,
  as the store could have altered any field.
* Treat phis that use an allocation as escaping
* Improve resolution of replacements

R=mstarzinger@chromium.org
BUG=v8:4586
LOG=n

Review URL: https://codereview.chromium.org/1499143002

Cr-Commit-Position: refs/heads/master@{#32656}
parent 063920e2
......@@ -23,9 +23,11 @@ EscapeAnalysisReducer::EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
Reduction EscapeAnalysisReducer::Reduce(Node* node) {
switch (node->opcode()) {
case IrOpcode::kLoadField:
return ReduceLoadField(node);
case IrOpcode::kLoadElement:
return ReduceLoad(node);
case IrOpcode::kStoreField:
return ReduceStoreField(node);
case IrOpcode::kStoreElement:
return ReduceStore(node);
case IrOpcode::kAllocate:
return ReduceAllocate(node);
case IrOpcode::kFinishRegion:
......@@ -42,11 +44,13 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) {
}
Reduction EscapeAnalysisReducer::ReduceLoadField(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
DCHECK(node->opcode() == IrOpcode::kLoadField ||
node->opcode() == IrOpcode::kLoadElement);
if (Node* rep = escape_analysis()->GetReplacement(node, node->id())) {
if (FLAG_trace_turbo_escape) {
PrintF("Replaced #%d with #%d\n", node->id(), rep->id());
PrintF("Replaced #%d (%s) with #%d (%s)\n", node->id(),
node->op()->mnemonic(), rep->id(), rep->op()->mnemonic());
}
ReplaceWithValue(node, rep);
return Changed(rep);
......@@ -55,11 +59,13 @@ Reduction EscapeAnalysisReducer::ReduceLoadField(Node* node) {
}
Reduction EscapeAnalysisReducer::ReduceStoreField(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
Reduction EscapeAnalysisReducer::ReduceStore(Node* node) {
DCHECK(node->opcode() == IrOpcode::kStoreField ||
node->opcode() == IrOpcode::kStoreElement);
if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) {
if (FLAG_trace_turbo_escape) {
PrintF("Removed store field #%d from effect chain\n", node->id());
PrintF("Removed #%d (%s) from effect chain\n", node->id(),
node->op()->mnemonic());
}
RelaxEffectsAndControls(node);
return Changed(node);
......@@ -90,7 +96,7 @@ Reduction EscapeAnalysisReducer::ReduceFinishRegion(Node* node) {
if (FLAG_trace_turbo_escape) {
PrintF("Removed region #%d / #%d from effect chain,", effect->id(),
node->id());
PrintF("%d user(s) of #%d remain(s):", node->UseCount(), node->id());
PrintF(" %d user(s) of #%d remain(s):", node->UseCount(), node->id());
for (Edge edge : node->use_edges()) {
PrintF(" #%d", edge.from()->id());
}
......
......@@ -24,8 +24,8 @@ class EscapeAnalysisReducer final : public AdvancedReducer {
Reduction Reduce(Node* node) final;
private:
Reduction ReduceLoadField(Node* node);
Reduction ReduceStoreField(Node* node);
Reduction ReduceLoad(Node* node);
Reduction ReduceStore(Node* node);
Reduction ReduceAllocate(Node* node);
Reduction ReduceFinishRegion(Node* node);
Reduction ReduceReferenceEqual(Node* node);
......
This diff is collapsed.
......@@ -16,6 +16,7 @@ namespace compiler {
class CommonOperatorBuilder;
class EscapeAnalysis;
class VirtualState;
class VirtualObject;
// EscapeStatusAnalysis determines for each allocation whether it escapes.
......@@ -46,8 +47,11 @@ class EscapeStatusAnalysis {
void ProcessAllocate(Node* node);
void ProcessFinishRegion(Node* node);
void ProcessStoreField(Node* node);
bool CheckUsesForEscape(Node* node) { return CheckUsesForEscape(node, node); }
bool CheckUsesForEscape(Node* node, Node* rep);
void ProcessStoreElement(Node* node);
bool CheckUsesForEscape(Node* node, bool phi_escaping = false) {
return CheckUsesForEscape(node, node, phi_escaping);
}
bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false);
void RevisitUses(Node* node);
void RevisitInputs(Node* node);
bool SetEscaped(Node* node);
......@@ -87,17 +91,28 @@ class EscapeAnalysis {
bool Process(Node* node);
void ProcessLoadField(Node* node);
void ProcessStoreField(Node* node);
void ProcessLoadElement(Node* node);
void ProcessStoreElement(Node* node);
void ProcessAllocationUsers(Node* node);
void ProcessAllocation(Node* node);
void ProcessFinishRegion(Node* node);
void ProcessCall(Node* node);
void ProcessStart(Node* node);
bool ProcessEffectPhi(Node* node);
void ProcessLoadFromPhi(int offset, Node* from, Node* node,
VirtualState* states);
void ForwardVirtualState(Node* node);
bool IsEffectBranchPoint(Node* node);
bool IsDanglingEffectNode(Node* node);
int OffsetFromAccess(Node* node);
VirtualObject* GetVirtualObject(Node* at, NodeId id);
void DebugPrint();
void DebugPrintState(VirtualState* state);
void DebugPrintObject(VirtualObject* state, NodeId id);
Graph* graph() const { return graph_; }
CommonOperatorBuilder* common() const { return common_; }
......
......@@ -28,24 +28,25 @@
// Flags: --allow-natives-syntax --turbo-escape
//
function f(a) {
"use strict";
return arguments;
function f() {
this.x=0;
}
function g(a) {
"use strict";
var x = f(1,2,3);
var o = new f();
if (a) {
x[1] = 5;
o.x = 5;
} else {
x[1] = 7;
o.x = 7;
}
return x[1];
return o.x;
}
assertEquals(7, g());
assertEquals(7, g());
assertEquals(5, g(true));
assertEquals(7, g(false));
%OptimizeFunctionOnNextCall(g);
assertEquals(5, g(true));
assertEquals(7, g(false));
assertEquals(7, g());
// Copyright 2015 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --allow-natives-syntax --turbo-escape
//
function f() {
return arguments;
}
function g(a) {
"use strict";
var o = f(1,2);
if (a) {
o[0] = 5;
} else {
o[0] = 7;
}
return o[0];
}
assertEquals(7, g());
assertEquals(7, g());
%OptimizeFunctionOnNextCall(g);
assertEquals(5, g(true));
assertEquals(7, g(false));
assertEquals(7, g());
......@@ -172,9 +172,9 @@
'compiler/escape-analysis-3': [PASS, NO_VARIANTS],
'compiler/escape-analysis-4': [PASS, NO_VARIANTS],
'compiler/escape-analysis-5': [PASS, NO_VARIANTS],
'compiler/escape-analysis-7': [PASS, NO_VARIANTS],
# TODO(sigurds): Tests that fail because of incomplete phi handling.
'compiler/escape-analysis-6': [PASS, NO_VARIANTS],
'compiler/escape-analysis-7': [PASS, NO_VARIANTS],
'compiler/escape-analysis-9': [PASS, NO_VARIANTS],
# TODO(sigurds): Tests that fail because of incomplete use handling (i.e. select).
'compiler/escape-analysis-8': [PASS, NO_VARIANTS],
......
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