Commit 3161c171 authored by sigurds's avatar sigurds Committed by Commit bot

[turbofan] Stabilize escape analysis (without deopt)

Bugfixes and improvements in escape analysis include:

* Handling of ObjectIsSmi (non-escaping)
* Handling of nested phi replacements
* Handling of phis with arity > 2
* Resilience against effectful nodes dangling from start
* Allocations escape now, if non-const load/store is performed
* Fixed a bug where non-allocated objects where tracked
* Allow fixed double arrays to be tracked

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

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

Cr-Commit-Position: refs/heads/master@{#32833}
parent 4460b85a
...@@ -34,6 +34,8 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) { ...@@ -34,6 +34,8 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) {
return ReduceFinishRegion(node); return ReduceFinishRegion(node);
case IrOpcode::kReferenceEqual: case IrOpcode::kReferenceEqual:
return ReduceReferenceEqual(node); return ReduceReferenceEqual(node);
case IrOpcode::kObjectIsSmi:
return ReduceObjectIsSmi(node);
case IrOpcode::kStateValues: case IrOpcode::kStateValues:
case IrOpcode::kFrameState: case IrOpcode::kFrameState:
return ReplaceWithDeoptDummy(node); return ReplaceWithDeoptDummy(node);
...@@ -146,6 +148,20 @@ Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) { ...@@ -146,6 +148,20 @@ Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) {
} }
Reduction EscapeAnalysisReducer::ReduceObjectIsSmi(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kObjectIsSmi);
Node* input = NodeProperties::GetValueInput(node, 0);
if (escape_analysis()->IsVirtual(input)) {
ReplaceWithValue(node, jsgraph()->FalseConstant());
if (FLAG_trace_turbo_escape) {
PrintF("Replaced ObjectIsSmi #%d with false\n", node->id());
}
return Replace(node);
}
return NoChange();
}
// TODO(sigurds): This is a temporary solution until escape analysis // TODO(sigurds): This is a temporary solution until escape analysis
// supports deoptimization. // supports deoptimization.
Reduction EscapeAnalysisReducer::ReplaceWithDeoptDummy(Node* node) { Reduction EscapeAnalysisReducer::ReplaceWithDeoptDummy(Node* node) {
......
...@@ -29,6 +29,7 @@ class EscapeAnalysisReducer final : public AdvancedReducer { ...@@ -29,6 +29,7 @@ class EscapeAnalysisReducer final : public AdvancedReducer {
Reduction ReduceAllocate(Node* node); Reduction ReduceAllocate(Node* node);
Reduction ReduceFinishRegion(Node* node); Reduction ReduceFinishRegion(Node* node);
Reduction ReduceReferenceEqual(Node* node); Reduction ReduceReferenceEqual(Node* node);
Reduction ReduceObjectIsSmi(Node* node);
Reduction ReplaceWithDeoptDummy(Node* node); Reduction ReplaceWithDeoptDummy(Node* node);
......
This diff is collapsed.
...@@ -35,6 +35,7 @@ class EscapeStatusAnalysis { ...@@ -35,6 +35,7 @@ class EscapeStatusAnalysis {
bool IsVirtual(Node* node); bool IsVirtual(Node* node);
bool IsEscaped(Node* node); bool IsEscaped(Node* node);
bool IsAllocation(Node* node);
void DebugPrint(); void DebugPrint();
...@@ -73,6 +74,30 @@ class EscapeStatusAnalysis { ...@@ -73,6 +74,30 @@ class EscapeStatusAnalysis {
DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::EscapeStatusFlags) DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::EscapeStatusFlags)
class MergeCache {
public:
explicit MergeCache(Zone* zone)
: states_(zone), objects_(zone), fields_(zone) {
states_.reserve(4);
objects_.reserve(4);
fields_.reserve(4);
}
ZoneVector<VirtualState*>& states() { return states_; }
ZoneVector<VirtualObject*>& objects() { return objects_; }
ZoneVector<Node*>& fields() { return fields_; }
void Clear() {
states_.clear();
objects_.clear();
fields_.clear();
}
private:
ZoneVector<VirtualState*> states_;
ZoneVector<VirtualObject*> objects_;
ZoneVector<Node*> fields_;
};
// EscapeObjectAnalysis simulates stores to determine values of loads if // EscapeObjectAnalysis simulates stores to determine values of loads if
// an object is virtual and eliminated. // an object is virtual and eliminated.
class EscapeAnalysis { class EscapeAnalysis {
...@@ -110,6 +135,8 @@ class EscapeAnalysis { ...@@ -110,6 +135,8 @@ class EscapeAnalysis {
VirtualObject* GetVirtualObject(Node* at, NodeId id); VirtualObject* GetVirtualObject(Node* at, NodeId id);
bool SetEscaped(Node* node);
void DebugPrint(); void DebugPrint();
void DebugPrintState(VirtualState* state); void DebugPrintState(VirtualState* state);
void DebugPrintObject(VirtualObject* state, NodeId id); void DebugPrintObject(VirtualObject* state, NodeId id);
...@@ -123,6 +150,7 @@ class EscapeAnalysis { ...@@ -123,6 +150,7 @@ class EscapeAnalysis {
Zone* const zone_; Zone* const zone_;
ZoneVector<VirtualState*> virtual_states_; ZoneVector<VirtualState*> virtual_states_;
EscapeStatusAnalysis escape_status_; EscapeStatusAnalysis escape_status_;
MergeCache cache_;
DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis); DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis);
}; };
......
...@@ -1159,6 +1159,9 @@ Handle<Code> Pipeline::GenerateCode() { ...@@ -1159,6 +1159,9 @@ Handle<Code> Pipeline::GenerateCode() {
} }
if (FLAG_turbo_escape) { if (FLAG_turbo_escape) {
// TODO(sigurds): EscapeAnalysis needs a trimmed graph at the moment,
// because it does a forwards traversal of the effect edges.
Run<EarlyGraphTrimmingPhase>();
Run<EscapeAnalysisPhase>(); Run<EscapeAnalysisPhase>();
RunPrintAndVerify("Escape Analysed"); RunPrintAndVerify("Escape Analysed");
} }
......
// 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() {
"use strict";
function f() {
for (let i = 0; i < 5; ++i) {
function g() { return i }
}
}
f();
})();
...@@ -164,6 +164,7 @@ ...@@ -164,6 +164,7 @@
'compiler/escape-analysis-6': [PASS, NO_VARIANTS], 'compiler/escape-analysis-6': [PASS, NO_VARIANTS],
'compiler/escape-analysis-7': [PASS, NO_VARIANTS], 'compiler/escape-analysis-7': [PASS, NO_VARIANTS],
'compiler/escape-analysis-9': [PASS, NO_VARIANTS], 'compiler/escape-analysis-9': [PASS, NO_VARIANTS],
'compiler/escape-analysis-10': [PASS, NO_VARIANTS],
# TODO(sigurds): Tests that fail because of incomplete use handling (i.e. select). # TODO(sigurds): Tests that fail because of incomplete use handling (i.e. select).
'compiler/escape-analysis-8': [PASS, NO_VARIANTS], '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