Commit 6095d0af authored by sigurds's avatar sigurds Committed by Commit bot

[turbofan] Refactor escape analysis to only expose one class.

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

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

Cr-Commit-Position: refs/heads/master@{#32523}
parent 9b421f26
......@@ -11,12 +11,11 @@ namespace v8 {
namespace internal {
namespace compiler {
EscapeAnalysisReducer::EscapeAnalysisReducer(
Editor* editor, JSGraph* jsgraph, EscapeStatusAnalysis* escape_status,
EscapeObjectAnalysis* escape_analysis, Zone* zone)
EscapeAnalysisReducer::EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
EscapeAnalysis* escape_analysis,
Zone* zone)
: AdvancedReducer(editor),
jsgraph_(jsgraph),
escape_status_(escape_status),
escape_analysis_(escape_analysis),
zone_(zone) {}
......@@ -58,7 +57,7 @@ Reduction EscapeAnalysisReducer::ReduceLoadField(Node* node) {
Reduction EscapeAnalysisReducer::ReduceStoreField(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
if (escape_status()->IsVirtual(NodeProperties::GetValueInput(node, 0))) {
if (escape_analysis()->IsVirtual(NodeProperties::GetValueInput(node, 0))) {
if (FLAG_trace_turbo_escape) {
PrintF("Removed store field #%d from effect chain\n", node->id());
}
......@@ -71,7 +70,7 @@ Reduction EscapeAnalysisReducer::ReduceStoreField(Node* node) {
Reduction EscapeAnalysisReducer::ReduceAllocate(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
if (escape_status()->IsVirtual(node)) {
if (escape_analysis()->IsVirtual(node)) {
RelaxEffectsAndControls(node);
if (FLAG_trace_turbo_escape) {
PrintF("Removed allocate #%d from effect chain\n", node->id());
......@@ -107,8 +106,8 @@ Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual);
Node* left = NodeProperties::GetValueInput(node, 0);
Node* right = NodeProperties::GetValueInput(node, 1);
if (escape_status()->IsVirtual(left)) {
if (escape_status()->IsVirtual(right)) {
if (escape_analysis()->IsVirtual(left)) {
if (escape_analysis()->IsVirtual(right)) {
if (Node* rep = escape_analysis()->GetReplacement(node, left->id())) {
left = rep;
}
......@@ -130,7 +129,7 @@ Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) {
PrintF("Replaced ref eq #%d with false\n", node->id());
}
return Replace(node);
} else if (escape_status()->IsVirtual(right)) {
} else if (escape_analysis()->IsVirtual(right)) {
// Left-hand side is not a virtual object.
ReplaceWithValue(node, jsgraph()->FalseConstant());
if (FLAG_trace_turbo_escape) {
......@@ -152,7 +151,7 @@ Reduction EscapeAnalysisReducer::ReplaceWithDeoptDummy(Node* node) {
if (input->opcode() == IrOpcode::kFinishRegion ||
input->opcode() == IrOpcode::kAllocate ||
input->opcode() == IrOpcode::kPhi) {
if (escape_status()->IsVirtual(input)) {
if (escape_analysis()->IsVirtual(input)) {
NodeProperties::ReplaceValueInput(node, jsgraph()->UndefinedConstant(),
i);
if (FLAG_trace_turbo_escape) {
......
......@@ -19,8 +19,7 @@ class JSGraph;
class EscapeAnalysisReducer final : public AdvancedReducer {
public:
EscapeAnalysisReducer(Editor* editor, JSGraph* jsgraph,
EscapeStatusAnalysis* escape_status,
EscapeObjectAnalysis* escape_analysis, Zone* zone);
EscapeAnalysis* escape_analysis, Zone* zone);
Reduction Reduce(Node* node) final;
......@@ -34,13 +33,11 @@ class EscapeAnalysisReducer final : public AdvancedReducer {
Reduction ReplaceWithDeoptDummy(Node* node);
JSGraph* jsgraph() const { return jsgraph_; }
EscapeObjectAnalysis* escape_analysis() const { return escape_analysis_; }
EscapeStatusAnalysis* escape_status() const { return escape_status_; }
EscapeAnalysis* escape_analysis() const { return escape_analysis_; }
Zone* zone() const { return zone_; }
JSGraph* const jsgraph_;
EscapeStatusAnalysis* escape_status_;
EscapeObjectAnalysis* escape_analysis_;
EscapeAnalysis* escape_analysis_;
Zone* const zone_;
DISALLOW_COPY_AND_ASSIGN(EscapeAnalysisReducer);
......
......@@ -22,6 +22,9 @@ namespace internal {
namespace compiler {
// ------------------------------VirtualObject----------------------------------
class VirtualObject : public ZoneObject {
public:
enum Status { kUntracked = 0, kTracked = 1 };
......@@ -82,6 +85,28 @@ class VirtualObject : public ZoneObject {
};
bool VirtualObject::UpdateFrom(const VirtualObject& other) {
bool changed = status_ != other.status_;
status_ = other.status_;
changed = replacement_ != other.replacement_ || changed;
replacement_ = other.replacement_;
if (fields_.size() != other.fields_.size()) {
fields_ = other.fields_;
return true;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (fields_[i] != other.fields_[i]) {
changed = true;
fields_[i] = other.fields_[i];
}
}
return changed;
}
// ------------------------------VirtualState-----------------------------------
class VirtualState : public ZoneObject {
public:
VirtualState(Zone* zone, size_t size);
......@@ -108,25 +133,6 @@ class VirtualState : public ZoneObject {
};
bool VirtualObject::UpdateFrom(const VirtualObject& other) {
bool changed = status_ != other.status_;
status_ = other.status_;
changed = replacement_ != other.replacement_ || changed;
replacement_ = other.replacement_;
if (fields_.size() != other.fields_.size()) {
fields_ = other.fields_;
return true;
}
for (size_t i = 0; i < fields_.size(); ++i) {
if (fields_[i] != other.fields_[i]) {
changed = true;
fields_[i] = other.fields_[i];
}
}
return changed;
}
VirtualState::VirtualState(Zone* zone, size_t size)
: info_(zone), last_changed_(nullptr) {
info_.resize(size);
......@@ -298,8 +304,8 @@ bool VirtualState::UpdateReplacement(Node* node, Node* rep, Zone* zone) {
// ------------------------------EscapeStatusAnalysis---------------------------
EscapeStatusAnalysis::EscapeStatusAnalysis(
EscapeObjectAnalysis* object_analysis, Graph* graph, Zone* zone)
EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis,
Graph* graph, Zone* zone)
: object_analysis_(object_analysis),
graph_(graph),
zone_(zone),
......@@ -513,19 +519,28 @@ void EscapeStatusAnalysis::DebugPrint() {
}
// -----------------------------EscapeObjectAnalysis---------------------------
// -----------------------------EscapeAnalysis----------------------------------
EscapeObjectAnalysis::EscapeObjectAnalysis(Graph* graph,
CommonOperatorBuilder* common,
Zone* zone)
: graph_(graph), common_(common), zone_(zone), virtual_states_(zone) {}
EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
Zone* zone)
: graph_(graph),
common_(common),
zone_(zone),
virtual_states_(zone),
escape_status_(this, graph, zone) {}
EscapeObjectAnalysis::~EscapeObjectAnalysis() {}
EscapeAnalysis::~EscapeAnalysis() {}
void EscapeAnalysis::Run() {
RunObjectAnalysis();
escape_status_.Run();
}
void EscapeObjectAnalysis::Run() {
void EscapeAnalysis::RunObjectAnalysis() {
virtual_states_.resize(graph()->NodeCount());
ZoneVector<Node*> queue(zone());
queue.push_back(graph()->start());
......@@ -560,7 +575,7 @@ void EscapeObjectAnalysis::Run() {
}
bool EscapeObjectAnalysis::IsDanglingEffectNode(Node* node) {
bool EscapeAnalysis::IsDanglingEffectNode(Node* node) {
if (node->op()->EffectInputCount() == 0) return false;
if (node->op()->EffectOutputCount() == 0) return false;
for (Edge edge : node->use_edges()) {
......@@ -572,7 +587,7 @@ bool EscapeObjectAnalysis::IsDanglingEffectNode(Node* node) {
}
bool EscapeObjectAnalysis::Process(Node* node) {
bool EscapeAnalysis::Process(Node* node) {
switch (node->opcode()) {
case IrOpcode::kAllocate:
ProcessAllocation(node);
......@@ -605,7 +620,7 @@ bool EscapeObjectAnalysis::Process(Node* node) {
}
bool EscapeObjectAnalysis::IsEffectBranchPoint(Node* node) {
bool EscapeAnalysis::IsEffectBranchPoint(Node* node) {
int count = 0;
for (Edge edge : node->use_edges()) {
Node* use = edge.from();
......@@ -620,7 +635,7 @@ bool EscapeObjectAnalysis::IsEffectBranchPoint(Node* node) {
}
void EscapeObjectAnalysis::ForwardVirtualState(Node* node) {
void EscapeAnalysis::ForwardVirtualState(Node* node) {
DCHECK_EQ(node->op()->EffectInputCount(), 1);
if (node->opcode() != IrOpcode::kLoadField && IsDanglingEffectNode(node)) {
PrintF("Dangeling effect node: #%d (%s)\n", node->id(),
......@@ -656,14 +671,14 @@ void EscapeObjectAnalysis::ForwardVirtualState(Node* node) {
}
void EscapeObjectAnalysis::ProcessStart(Node* node) {
void EscapeAnalysis::ProcessStart(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kStart);
virtual_states_[node->id()] =
new (zone()) VirtualState(zone(), graph()->NodeCount());
}
bool EscapeObjectAnalysis::ProcessEffectPhi(Node* node) {
bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi);
// For now only support binary phis.
DCHECK_EQ(node->op()->EffectInputCount(), 2);
......@@ -716,7 +731,7 @@ bool EscapeObjectAnalysis::ProcessEffectPhi(Node* node) {
}
void EscapeObjectAnalysis::ProcessAllocation(Node* node) {
void EscapeAnalysis::ProcessAllocation(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
ForwardVirtualState(node);
......@@ -736,7 +751,7 @@ void EscapeObjectAnalysis::ProcessAllocation(Node* node) {
}
void EscapeObjectAnalysis::ProcessFinishRegion(Node* node) {
void EscapeAnalysis::ProcessFinishRegion(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
ForwardVirtualState(node);
Node* allocation = NodeProperties::GetValueInput(node, 0);
......@@ -756,7 +771,7 @@ void EscapeObjectAnalysis::ProcessFinishRegion(Node* node) {
}
Node* EscapeObjectAnalysis::GetReplacement(Node* at, NodeId id) {
Node* EscapeAnalysis::GetReplacement(Node* at, NodeId id) {
VirtualState* states = virtual_states_[at->id()];
if (VirtualObject* obj = states->GetVirtualObject(id)) {
return obj->GetReplacement();
......@@ -765,13 +780,23 @@ Node* EscapeObjectAnalysis::GetReplacement(Node* at, NodeId id) {
}
int EscapeObjectAnalysis::OffsetFromAccess(Node* node) {
bool EscapeAnalysis::IsVirtual(Node* node) {
return escape_status_.IsVirtual(node);
}
bool EscapeAnalysis::IsEscaped(Node* node) {
return escape_status_.IsEscaped(node);
}
int EscapeAnalysis::OffsetFromAccess(Node* node) {
DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
return OpParameter<FieldAccess>(node).offset / kPointerSize;
}
void EscapeObjectAnalysis::ProcessLoadField(Node* node) {
void EscapeAnalysis::ProcessLoadField(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
ForwardVirtualState(node);
Node* from = NodeProperties::GetValueInput(node, 0);
......@@ -833,7 +858,7 @@ void EscapeObjectAnalysis::ProcessLoadField(Node* node) {
}
void EscapeObjectAnalysis::ProcessStoreField(Node* node) {
void EscapeAnalysis::ProcessStoreField(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
ForwardVirtualState(node);
Node* to = NodeProperties::GetValueInput(node, 0);
......@@ -849,7 +874,7 @@ void EscapeObjectAnalysis::ProcessStoreField(Node* node) {
}
void EscapeObjectAnalysis::DebugPrint() {
void EscapeAnalysis::DebugPrint() {
ZoneVector<VirtualState*> object_states(zone());
for (NodeId id = 0; id < virtual_states_.size(); id++) {
if (VirtualState* states = virtual_states_[id]) {
......
......@@ -14,15 +14,13 @@ namespace compiler {
// Forward declarations.
class CommonOperatorBuilder;
class EscapeObjectAnalysis;
class EscapeAnalysis;
class VirtualState;
// EscapeStatusAnalysis determines for each allocation whether it escapes.
class EscapeStatusAnalysis {
public:
EscapeStatusAnalysis(EscapeObjectAnalysis* object_analysis, Graph* graph,
Zone* zone);
~EscapeStatusAnalysis();
enum EscapeStatusFlag {
......@@ -34,13 +32,16 @@ class EscapeStatusAnalysis {
void Run();
bool HasEntry(Node* node);
bool IsVirtual(Node* node);
bool IsEscaped(Node* node);
void DebugPrint();
friend class EscapeAnalysis;
private:
EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph,
Zone* zone);
void Process(Node* node);
void ProcessAllocate(Node* node);
void ProcessFinishRegion(Node* node);
......@@ -50,11 +51,12 @@ class EscapeStatusAnalysis {
void RevisitUses(Node* node);
void RevisitInputs(Node* node);
bool SetEscaped(Node* node);
bool HasEntry(Node* node);
Graph* graph() const { return graph_; }
Zone* zone() const { return zone_; }
EscapeObjectAnalysis* object_analysis_;
EscapeAnalysis* object_analysis_;
Graph* const graph_;
Zone* const zone_;
ZoneVector<EscapeStatusFlags> info_;
......@@ -69,16 +71,19 @@ DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::EscapeStatusFlags)
// EscapeObjectAnalysis simulates stores to determine values of loads if
// an object is virtual and eliminated.
class EscapeObjectAnalysis {
class EscapeAnalysis {
public:
EscapeObjectAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone);
~EscapeObjectAnalysis();
EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, Zone* zone);
~EscapeAnalysis();
void Run();
Node* GetReplacement(Node* at, NodeId id);
bool IsVirtual(Node* node);
bool IsEscaped(Node* node);
private:
void RunObjectAnalysis();
bool Process(Node* node);
void ProcessLoadField(Node* node);
void ProcessStoreField(Node* node);
......@@ -102,8 +107,9 @@ class EscapeObjectAnalysis {
CommonOperatorBuilder* const common_;
Zone* const zone_;
ZoneVector<VirtualState*> virtual_states_;
EscapeStatusAnalysis escape_status_;
DISALLOW_COPY_AND_ASSIGN(EscapeObjectAnalysis);
DISALLOW_COPY_AND_ASSIGN(EscapeAnalysis);
};
} // namespace compiler
......
......@@ -652,16 +652,12 @@ struct EscapeAnalysisPhase {
static const char* phase_name() { return "escape analysis"; }
void Run(PipelineData* data, Zone* temp_zone) {
EscapeObjectAnalysis escape_analysis(data->graph(),
data->jsgraph()->common(), temp_zone);
EscapeAnalysis escape_analysis(data->graph(), data->jsgraph()->common(),
temp_zone);
escape_analysis.Run();
EscapeStatusAnalysis escape_status(&escape_analysis, data->graph(),
temp_zone);
escape_status.Run();
JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
EscapeAnalysisReducer escape_reducer(&graph_reducer, data->jsgraph(),
&escape_status, &escape_analysis,
temp_zone);
&escape_analysis, temp_zone);
AddReducer(data, &graph_reducer, &escape_reducer);
graph_reducer.ReduceGraph();
}
......
......@@ -22,26 +22,21 @@ class EscapeAnalysisTest : public GraphTest {
EscapeAnalysisTest()
: simplified_(zone()),
jsgraph_(isolate(), graph(), common(), nullptr, nullptr, nullptr),
escape_objects_(graph(), common(), zone()),
escape_status_(&escape_objects_, graph(), zone()),
escape_analysis_(graph(), common(), zone()),
effect_(graph()->start()),
control_(graph()->start()) {}
~EscapeAnalysisTest() {}
EscapeStatusAnalysis* escape_status() { return &escape_status_; }
EscapeObjectAnalysis* escape_objects() { return &escape_objects_; }
EscapeAnalysis* escape_analysis() { return &escape_analysis_; }
protected:
void Analysis() {
escape_objects_.Run();
escape_status_.Run();
}
void Analysis() { escape_analysis_.Run(); }
void Transformation() {
GraphReducer graph_reducer(zone(), graph());
EscapeAnalysisReducer escape_reducer(
&graph_reducer, &jsgraph_, &escape_status_, &escape_objects_, zone());
EscapeAnalysisReducer escape_reducer(&graph_reducer, &jsgraph_,
&escape_analysis_, zone());
graph_reducer.AddReducer(&escape_reducer);
graph_reducer.ReduceGraph();
}
......@@ -145,11 +140,11 @@ class EscapeAnalysisTest : public GraphTest {
// ---------------------------------Assertion Helper--------------------------
void ExpectReplacement(Node* node, Node* rep) {
EXPECT_EQ(rep, escape_objects()->GetReplacement(node, node->id()));
EXPECT_EQ(rep, escape_analysis()->GetReplacement(node, node->id()));
}
void ExpectReplacementPhi(Node* node, Node* left, Node* right) {
Node* rep = escape_objects()->GetReplacement(node, node->id());
Node* rep = escape_analysis()->GetReplacement(node, node->id());
ASSERT_NE(nullptr, rep);
ASSERT_EQ(IrOpcode::kPhi, rep->opcode());
EXPECT_EQ(left, NodeProperties::GetValueInput(rep, 0));
......@@ -159,13 +154,13 @@ class EscapeAnalysisTest : public GraphTest {
void ExpectVirtual(Node* node) {
EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
node->opcode() == IrOpcode::kFinishRegion);
EXPECT_TRUE(escape_status()->IsVirtual(node));
EXPECT_TRUE(escape_analysis()->IsVirtual(node));
}
void ExpectEscaped(Node* node) {
EXPECT_TRUE(node->opcode() == IrOpcode::kAllocate ||
node->opcode() == IrOpcode::kFinishRegion);
EXPECT_TRUE(escape_status()->IsEscaped(node));
EXPECT_TRUE(escape_analysis()->IsEscaped(node));
}
SimplifiedOperatorBuilder* simplified() { return &simplified_; }
......@@ -175,8 +170,7 @@ class EscapeAnalysisTest : public GraphTest {
private:
SimplifiedOperatorBuilder simplified_;
JSGraph jsgraph_;
EscapeObjectAnalysis escape_objects_;
EscapeStatusAnalysis escape_status_;
EscapeAnalysis escape_analysis_;
Node* effect_;
Node* control_;
......@@ -276,7 +270,7 @@ TEST_F(EscapeAnalysisTest, BranchNonEscape) {
ExpectVirtual(allocation);
ExpectReplacementPhi(load, object1, object2);
Node* replacement_phi = escape_objects()->GetReplacement(load, load->id());
Node* replacement_phi = escape_analysis()->GetReplacement(load, load->id());
Transformation();
......
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