Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Unified Diff: src/compiler/escape-analysis.cc

Issue 1654163003: [turbofan] Delay initialization in escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Make --trace-turbo-escape a proper debug flag Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/compiler/escape-analysis.cc
diff --git a/src/compiler/escape-analysis.cc b/src/compiler/escape-analysis.cc
index ccb2346ded7d4bbd40ff5c105ffbe05524389df2..b1a12b201ee16ac2aa849b4354bdf1a2b01addb0 100644
--- a/src/compiler/escape-analysis.cc
+++ b/src/compiler/escape-analysis.cc
@@ -116,6 +116,8 @@ class VirtualObject : public ZoneObject {
return true;
}
bool UpdateFrom(const VirtualObject& other);
+ bool MergeFrom(MergeCache* cache, Node* at, Graph* graph,
+ CommonOperatorBuilder* common);
void SetObjectState(Node* node) { object_state_ = node; }
Node* GetObjectState() const { return object_state_; }
bool IsCopyRequired() const { return status_ & kCopyRequired; }
@@ -131,6 +133,9 @@ class VirtualObject : public ZoneObject {
void id(NodeId id) { id_ = id; }
private:
+ bool MergeFields(size_t i, Node* at, MergeCache* cache, Graph* graph,
+ CommonOperatorBuilder* common);
+
NodeId id_;
StatusFlags status_;
ZoneVector<Node*> fields_;
@@ -176,14 +181,10 @@ class VirtualState : public ZoneObject {
}
VirtualObject* VirtualObjectFromAlias(size_t alias);
- VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id,
- size_t fields,
- bool initialized, Zone* zone,
- bool force_copy);
void SetVirtualObject(Alias alias, VirtualObject* state);
bool UpdateFrom(VirtualState* state, Zone* zone);
bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
- CommonOperatorBuilder* common, Node* control, int arity);
+ CommonOperatorBuilder* common, Node* at);
size_t size() const { return info_.size(); }
Node* owner() const { return owner_; }
VirtualObject* Copy(VirtualObject* obj, Alias alias);
@@ -288,19 +289,6 @@ VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) {
return info_[alias];
}
-VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(
- Alias alias, NodeId id, size_t field_number, bool initialized, Zone* zone,
- bool force_copy) {
- if (!force_copy) {
- if (VirtualObject* obj = VirtualObjectFromAlias(alias)) {
- return obj;
- }
- }
- VirtualObject* obj = new (zone) VirtualObject(id, this, zone, 0, initialized);
- SetVirtualObject(alias, obj);
- return obj;
-}
-
void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) {
info_[alias] = obj;
}
@@ -362,19 +350,72 @@ bool IsEquivalentPhi(Node* phi, ZoneVector<Node*>& inputs) {
} // namespace
-Node* EscapeAnalysis::GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) {
- Node* rep = GetReplacement(objs.front()->id());
- for (VirtualObject* obj : objs) {
- if (GetReplacement(obj->id()) != rep) {
- return nullptr;
+bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache,
+ Graph* graph, CommonOperatorBuilder* common) {
+ bool changed = false;
+ int value_input_count = static_cast<int>(cache->fields().size());
+ Node* rep = GetField(i);
+ if (!rep || !IsCreatedPhi(i)) {
+ Node* control = NodeProperties::GetControlInput(at);
+ cache->fields().push_back(control);
+ Node* phi = graph->NewNode(
+ common->Phi(MachineRepresentation::kTagged, value_input_count),
+ value_input_count + 1, &cache->fields().front());
+ SetField(i, phi, true);
+#ifdef DEBUG
+ if (FLAG_trace_turbo_escape) {
+ PrintF(" Creating Phi #%d as merge of", phi->id());
+ for (int i = 0; i < value_input_count; i++) {
+ PrintF(" #%d (%s)", cache->fields()[i]->id(),
+ cache->fields()[i]->op()->mnemonic());
+ }
+ PrintF("\n");
+ }
+#endif
+ changed = true;
+ } else {
+ DCHECK(rep->opcode() == IrOpcode::kPhi);
+ for (int n = 0; n < value_input_count; ++n) {
+ Node* old = NodeProperties::GetValueInput(rep, n);
+ if (old != cache->fields()[n]) {
+ changed = true;
+ NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n);
+ }
}
}
- return rep;
+ return changed;
+}
+
+bool VirtualObject::MergeFrom(MergeCache* cache, Node* at, Graph* graph,
+ CommonOperatorBuilder* common) {
+ DCHECK(at->opcode() == IrOpcode::kEffectPhi ||
+ at->opcode() == IrOpcode::kPhi);
+ bool changed = false;
+ for (size_t i = 0; i < field_count(); ++i) {
+ if (Node* field = cache->GetFields(i)) {
+ changed = changed || GetField(i) != field;
+ SetField(i, field);
+ TRACE(" Field %zu agree on rep #%d\n", i, field->id());
+ } else {
+ int arity = at->opcode() == IrOpcode::kEffectPhi
+ ? at->op()->EffectInputCount()
+ : at->op()->ValueInputCount();
+ if (cache->fields().size() == arity) {
+ changed = MergeFields(i, at, cache, graph, common) || changed;
+ } else {
+ if (GetField(i) != nullptr) {
+ TRACE(" Field %zu cleared\n", i);
+ changed = true;
+ }
+ SetField(i, nullptr);
+ }
+ }
+ }
+ return changed;
}
bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
- CommonOperatorBuilder* common, Node* control,
- int arity) {
+ CommonOperatorBuilder* common, Node* at) {
DCHECK_GT(cache->states().size(), 0u);
bool changed = false;
for (Alias alias = 0; alias < size(); ++alias) {
@@ -387,16 +428,26 @@ bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
cache->objects().push_back(obj);
if (mergeObject == obj) {
copy_merge_object = true;
- changed = true;
}
fields = std::min(obj->field_count(), fields);
}
}
if (cache->objects().size() == cache->states().size()) {
- mergeObject = GetOrCreateTrackedVirtualObject(
- alias, cache->objects().front()->id(),
- cache->objects().front()->IsInitialized(), fields, zone,
- copy_merge_object);
+ if (!mergeObject) {
+ VirtualObject* obj = new (zone)
+ VirtualObject(cache->objects().front()->id(), this, zone, fields,
+ cache->objects().front()->IsInitialized());
+ SetVirtualObject(alias, obj);
+ mergeObject = obj;
+ changed = true;
+ } else if (copy_merge_object) {
+ VirtualObject* obj = new (zone) VirtualObject(this, *mergeObject);
+ SetVirtualObject(alias, obj);
+ mergeObject = obj;
+ changed = true;
+ } else {
+ changed = mergeObject->ResizeFields(fields) || changed;
+ }
#ifdef DEBUG
if (FLAG_trace_turbo_escape) {
PrintF(" Alias @%d, merging into %p virtual objects", alias,
@@ -407,53 +458,7 @@ bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
PrintF("\n");
}
#endif // DEBUG
- changed = mergeObject->ResizeFields(fields) || changed;
- for (size_t i = 0; i < fields; ++i) {
- if (Node* field = cache->GetFields(i)) {
- changed = changed || mergeObject->GetField(i) != field;
- mergeObject->SetField(i, field);
- TRACE(" Field %zu agree on rep #%d\n", i, field->id());
- } else {
- int value_input_count = static_cast<int>(cache->fields().size());
- if (cache->fields().size() == arity) {
- Node* rep = mergeObject->GetField(i);
- if (!rep || !mergeObject->IsCreatedPhi(i)) {
- cache->fields().push_back(control);
- Node* phi = graph->NewNode(
- common->Phi(MachineRepresentation::kTagged,
- value_input_count),
- value_input_count + 1, &cache->fields().front());
- mergeObject->SetField(i, phi, true);
-#ifdef DEBUG
- if (FLAG_trace_turbo_escape) {
- PrintF(" Creating Phi #%d as merge of", phi->id());
- for (int i = 0; i < value_input_count; i++) {
- PrintF(" #%d (%s)", cache->fields()[i]->id(),
- cache->fields()[i]->op()->mnemonic());
- }
- PrintF("\n");
- }
-#endif // DEBUG
- changed = true;
- } else {
- DCHECK(rep->opcode() == IrOpcode::kPhi);
- for (int n = 0; n < value_input_count; ++n) {
- Node* old = NodeProperties::GetValueInput(rep, n);
- if (old != cache->fields()[n]) {
- changed = true;
- NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n);
- }
- }
- }
- } else {
- if (mergeObject->GetField(i) != nullptr) {
- TRACE(" Field %zu cleared\n", i);
- changed = true;
- }
- mergeObject->SetField(i, nullptr);
- }
- }
- }
+ changed = mergeObject->MergeFrom(cache, at, graph, common) || changed;
} else {
if (mergeObject) {
TRACE(" Alias %d, virtual object removed\n", alias);
@@ -471,7 +476,7 @@ EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis,
object_analysis_(object_analysis),
graph_(graph),
zone_(zone),
- status_(graph->NodeCount(), kUnknown, zone),
+ status_(zone),
next_free_alias_(0),
status_stack_(zone),
aliases_(zone) {}
@@ -777,11 +782,8 @@ void EscapeAnalysis::Run() {
void EscapeStatusAnalysis::AssignAliases() {
size_t max_size = 1024;
size_t min_size = 32;
- size_t stack_size = std::min(
- std::max(
- std::min(graph()->NodeCount() / 5, graph()->NodeCount() / 20 + 128),
- min_size),
- max_size);
+ size_t stack_size =
+ std::min(std::max(graph()->NodeCount() / 5, min_size), max_size);
stack_.reserve(stack_size);
ResizeStatusVector();
stack_.push_back(graph()->end());
@@ -1001,7 +1003,8 @@ void EscapeAnalysis::ProcessAllocationUsers(Node* node) {
break;
default:
VirtualState* state = virtual_states_[node->id()];
- if (VirtualObject* obj = ResolveVirtualObject(state, input)) {
+ if (VirtualObject* obj =
+ GetVirtualObject(state, ResolveReplacement(input))) {
if (!obj->AllFieldsClear()) {
obj = CopyForModificationAt(obj, state, node);
obj->ClearAllFields();
@@ -1113,10 +1116,8 @@ bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
return changed;
}
- changed = mergeState->MergeFrom(cache_, zone(), graph(), common(),
- NodeProperties::GetControlInput(node),
- node->op()->EffectInputCount()) ||
- changed;
+ changed =
+ mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed;
TRACE("Merge %s the node.\n", changed ? "changed" : "did not change");
@@ -1242,11 +1243,6 @@ VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
return nullptr;
}
-VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state,
- Node* node) {
- return GetVirtualObject(state, ResolveReplacement(node));
-}
-
bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
DCHECK(IsVirtual(left) && IsVirtual(right));
left = ResolveReplacement(left);
@@ -1262,13 +1258,13 @@ int EscapeAnalysis::OffsetFromAccess(Node* node) {
return OpParameter<FieldAccess>(node).offset / kPointerSize;
}
-void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
+void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load,
VirtualState* state) {
- TRACE("Load #%d from phi #%d", node->id(), from->id());
+ TRACE("Load #%d from phi #%d", load->id(), from->id());
cache_->fields().clear();
- for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
- Node* input = NodeProperties::GetValueInput(node, i);
+ for (int i = 0; i < load->op()->ValueInputCount(); ++i) {
+ Node* input = NodeProperties::GetValueInput(load, i);
cache_->fields().push_back(input);
}
@@ -1277,7 +1273,7 @@ void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
if (cache_->objects().size() == cache_->fields().size()) {
cache_->GetFields(offset);
if (cache_->fields().size() == cache_->objects().size()) {
- Node* rep = replacement(node);
+ Node* rep = replacement(load);
if (!rep || !IsEquivalentPhi(rep, cache_->fields())) {
int value_input_count = static_cast<int>(cache_->fields().size());
cache_->fields().push_back(NodeProperties::GetControlInput(from));
@@ -1285,7 +1281,7 @@ void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
common()->Phi(MachineRepresentation::kTagged, value_input_count),
value_input_count + 1, &cache_->fields().front());
status_analysis_.ResizeStatusVector();
- SetReplacement(node, phi);
+ SetReplacement(load, phi);
TRACE(" got phi created.\n");
} else {
TRACE(" has already phi #%d.\n", rep->id());
@@ -1441,8 +1437,8 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
if ((node->opcode() == IrOpcode::kFinishRegion ||
node->opcode() == IrOpcode::kAllocate) &&
IsVirtual(node)) {
- if (VirtualObject* vobj =
- ResolveVirtualObject(virtual_states_[effect->id()], node)) {
+ if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()],
+ ResolveReplacement(node))) {
if (Node* object_state = vobj->GetObjectState()) {
return object_state;
} else {
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698