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

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

Issue 1499143002: Improve escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix bug Created 5 years 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.h » ('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 dc331bbbe68e0e344f2f6e44258dd2fe32f08add..7fc8fbfced01ce30c28df6dd6303903527ee506d 100644
--- a/src/compiler/escape-analysis.cc
+++ b/src/compiler/escape-analysis.cc
@@ -63,15 +63,25 @@ class VirtualObject : public ZoneObject {
return changed;
}
- size_t fields() { return fields_.size(); }
- bool ResizeFields(size_t field_number) {
- if (field_number != fields_.size()) {
- fields_.resize(field_number);
+ Node** fields_array() { return &fields_.front(); }
+ size_t field_count() { return fields_.size(); }
+ bool ResizeFields(size_t field_count) {
+ if (field_count != fields_.size()) {
+ fields_.resize(field_count);
return true;
}
return false;
}
-
+ bool ClearAllFields() {
+ bool changed = false;
+ for (size_t i = 0; i < fields_.size(); ++i) {
+ if (fields_[i] != nullptr) {
+ fields_[i] = nullptr;
+ changed = true;
+ }
+ }
+ return changed;
+ }
bool UpdateFrom(const VirtualObject& other);
NodeId id() { return id_; }
@@ -112,6 +122,7 @@ class VirtualState : public ZoneObject {
VirtualState(Zone* zone, size_t size);
VirtualState(const VirtualState& states);
+ VirtualObject* ResolveVirtualObject(Node* node);
VirtualObject* GetVirtualObject(Node* node);
VirtualObject* GetVirtualObject(size_t id);
VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone);
@@ -157,7 +168,10 @@ VirtualState::VirtualState(const VirtualState& state)
}
-VirtualObject* VirtualState::GetVirtualObject(size_t id) { return info_[id]; }
+VirtualObject* VirtualState::GetVirtualObject(size_t id) {
+ if (id >= info_.size()) return nullptr;
+ return info_[id];
+}
VirtualObject* VirtualState::GetVirtualObject(Node* node) {
@@ -165,6 +179,16 @@ VirtualObject* VirtualState::GetVirtualObject(Node* node) {
}
+VirtualObject* VirtualState::ResolveVirtualObject(Node* node) {
+ VirtualObject* obj = GetVirtualObject(node->id());
+ while (obj && !obj->IsTracked() && obj->GetReplacement() &&
+ GetVirtualObject(obj->GetReplacement())) {
+ obj = GetVirtualObject(obj->GetReplacement());
+ }
+ return obj;
+}
+
+
VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(NodeId id,
Zone* zone) {
if (VirtualObject* obj = GetVirtualObject(id)) {
@@ -246,7 +270,7 @@ bool VirtualState::MergeFrom(VirtualState* left, VirtualState* right,
PrintF(" Merging fields of #%d\n", id);
}
VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
- size_t fields = std::max(ls->fields(), rs->fields());
+ size_t fields = std::max(ls->field_count(), rs->field_count());
changed = mergeObject->ResizeFields(fields) || changed;
for (size_t i = 0; i < fields; ++i) {
if (ls->GetField(i) == rs->GetField(i)) {
@@ -256,19 +280,36 @@ bool VirtualState::MergeFrom(VirtualState* left, VirtualState* right,
ls->GetField(i)->id());
}
} else if (ls->GetField(i) != nullptr && rs->GetField(i) != nullptr) {
- Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2),
- ls->GetField(i), rs->GetField(i), control);
- if (mergeObject->SetField(i, phi)) {
+ Node* rep = mergeObject->GetField(i);
+ if (!rep || rep->opcode() != IrOpcode::kPhi ||
+ NodeProperties::GetValueInput(rep, 0) != ls->GetField(i) ||
+ NodeProperties::GetValueInput(rep, 1) != rs->GetField(i)) {
+ Node* phi =
+ graph->NewNode(common->Phi(kMachAnyTagged, 2), ls->GetField(i),
+ rs->GetField(i), control);
+ if (mergeObject->SetField(i, phi)) {
+ if (FLAG_trace_turbo_escape) {
+ PrintF(" Creating Phi #%d as merge of #%d and #%d\n",
+ phi->id(), ls->GetField(i)->id(), rs->GetField(i)->id());
+ }
+ changed = true;
+ }
+ } else {
if (FLAG_trace_turbo_escape) {
- PrintF(" Creating Phi #%d as merge of #%d and #%d\n",
- phi->id(), ls->GetField(i)->id(), rs->GetField(i)->id());
+ PrintF(" Retaining Phi #%d as merge of #%d and #%d\n",
+ rep->id(), ls->GetField(i)->id(), rs->GetField(i)->id());
}
- changed = true;
}
} else {
changed = mergeObject->SetField(i, nullptr) || changed;
}
}
+ } else if (ls) {
+ VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
+ changed = mergeObject->UpdateFrom(*ls) || changed;
+ } else if (rs) {
+ VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
+ changed = mergeObject->UpdateFrom(*rs) || changed;
}
}
return changed;
@@ -276,12 +317,13 @@ bool VirtualState::MergeFrom(VirtualState* left, VirtualState* right,
Node* VirtualState::ResolveReplacement(Node* node) {
- if (VirtualObject* obj = GetVirtualObject(node)) {
- if (Node* rep = obj->GetReplacement()) {
- return rep;
- }
+ Node* replacement = node;
+ VirtualObject* obj = GetVirtualObject(node);
+ while (obj != nullptr && obj->GetReplacement()) {
+ replacement = obj->GetReplacement();
+ obj = GetVirtualObject(replacement);
}
- return node;
+ return replacement;
}
@@ -388,7 +430,11 @@ void EscapeStatusAnalysis::Process(Node* node) {
case IrOpcode::kStoreField:
ProcessStoreField(node);
break;
- case IrOpcode::kLoadField: {
+ case IrOpcode::kStoreElement:
+ ProcessStoreElement(node);
+ break;
+ case IrOpcode::kLoadField:
+ case IrOpcode::kLoadElement: {
if (Node* rep = object_analysis_->GetReplacement(node, node->id())) {
if (rep->opcode() == IrOpcode::kAllocate ||
rep->opcode() == IrOpcode::kFinishRegion) {
@@ -425,6 +471,20 @@ void EscapeStatusAnalysis::ProcessStoreField(Node* node) {
}
+void EscapeStatusAnalysis::ProcessStoreElement(Node* node) {
+ DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
+ Node* to = NodeProperties::GetValueInput(node, 0);
+ Node* val = NodeProperties::GetValueInput(node, 2);
+ if (IsEscaped(to) && SetEscaped(val)) {
+ RevisitUses(val);
+ if (FLAG_trace_turbo_escape) {
+ PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n",
+ val->id(), val->op()->mnemonic(), to->id());
+ }
+ }
+}
+
+
void EscapeStatusAnalysis::ProcessAllocate(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
if (!HasEntry(node)) {
@@ -444,19 +504,24 @@ void EscapeStatusAnalysis::ProcessAllocate(Node* node) {
return;
}
}
- if (CheckUsesForEscape(node)) {
+ if (CheckUsesForEscape(node, true)) {
RevisitUses(node);
}
}
-bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep) {
+bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
+ bool phi_escaping) {
for (Edge edge : uses->use_edges()) {
Node* use = edge.from();
- if (!NodeProperties::IsValueEdge(edge)) continue;
+ if (!NodeProperties::IsValueEdge(edge) &&
+ !NodeProperties::IsContextEdge(edge))
+ continue;
switch (use->opcode()) {
case IrOpcode::kStoreField:
case IrOpcode::kLoadField:
+ case IrOpcode::kStoreElement:
+ case IrOpcode::kLoadElement:
case IrOpcode::kFrameState:
case IrOpcode::kStateValues:
case IrOpcode::kReferenceEqual:
@@ -472,6 +537,17 @@ bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep) {
}
return true;
}
+ if (phi_escaping && use->opcode() == IrOpcode::kPhi &&
+ SetEscaped(rep)) {
+ if (FLAG_trace_turbo_escape) {
+ PrintF(
+ "Setting #%d (%s) to escaped because of use by phi node "
+ "#%d (%s)\n",
+ rep->id(), rep->op()->mnemonic(), use->id(),
+ use->op()->mnemonic());
+ }
+ return true;
+ }
break;
default:
if (SetEscaped(rep)) {
@@ -503,7 +579,7 @@ void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) {
info_[node->id()] = kVirtual;
RevisitUses(node);
}
- if (CheckUsesForEscape(node)) {
+ if (CheckUsesForEscape(node, true)) {
RevisitInputs(node);
}
}
@@ -542,18 +618,19 @@ void EscapeAnalysis::Run() {
void EscapeAnalysis::RunObjectAnalysis() {
virtual_states_.resize(graph()->NodeCount());
- ZoneVector<Node*> queue(zone());
- queue.push_back(graph()->start());
- while (!queue.empty()) {
- Node* node = queue.back();
- queue.pop_back();
+ ZoneVector<Node*> stack(zone());
+ stack.push_back(graph()->start());
+ while (!stack.empty()) {
+ Node* node = stack.back();
+ stack.pop_back();
if (Process(node)) {
for (Edge edge : node->use_edges()) {
if (NodeProperties::IsEffectEdge(edge)) {
Node* use = edge.from();
- if (use->opcode() != IrOpcode::kLoadField ||
+ if ((use->opcode() != IrOpcode::kLoadField &&
+ use->opcode() != IrOpcode::kLoadElement) ||
!IsDanglingEffectNode(use)) {
- queue.push_back(use);
+ stack.push_back(use);
}
}
}
@@ -561,9 +638,12 @@ void EscapeAnalysis::RunObjectAnalysis() {
for (Edge edge : node->use_edges()) {
if (NodeProperties::IsEffectEdge(edge)) {
Node* use = edge.from();
- if (use->opcode() == IrOpcode::kLoadField &&
+ if ((use->opcode() == IrOpcode::kLoadField ||
+ use->opcode() == IrOpcode::kLoadElement) &&
+
+
IsDanglingEffectNode(use)) {
- queue.push_back(use);
+ stack.push_back(use);
}
}
}
@@ -604,6 +684,12 @@ bool EscapeAnalysis::Process(Node* node) {
case IrOpcode::kLoadField:
ProcessLoadField(node);
break;
+ case IrOpcode::kStoreElement:
+ ProcessStoreElement(node);
+ break;
+ case IrOpcode::kLoadElement:
+ ProcessLoadElement(node);
+ break;
case IrOpcode::kStart:
ProcessStart(node);
break;
@@ -614,12 +700,43 @@ bool EscapeAnalysis::Process(Node* node) {
if (node->op()->EffectInputCount() > 0) {
ForwardVirtualState(node);
}
+ ProcessAllocationUsers(node);
break;
}
return true;
}
+void EscapeAnalysis::ProcessAllocationUsers(Node* node) {
+ for (Edge edge : node->input_edges()) {
+ Node* input = edge.to();
+ if (!NodeProperties::IsValueEdge(edge) &&
+ !NodeProperties::IsContextEdge(edge))
+ continue;
+ switch (node->opcode()) {
+ case IrOpcode::kStoreField:
+ case IrOpcode::kLoadField:
+ case IrOpcode::kStoreElement:
+ case IrOpcode::kLoadElement:
+ case IrOpcode::kFrameState:
+ case IrOpcode::kStateValues:
+ case IrOpcode::kReferenceEqual:
+ case IrOpcode::kFinishRegion:
+ case IrOpcode::kPhi:
+ break;
+ default:
+ VirtualState* states = virtual_states_[node->id()];
+ if (VirtualObject* obj = states->ResolveVirtualObject(input)) {
+ if (obj->ClearAllFields()) {
+ states->LastChangedAt(node);
+ }
+ }
+ break;
+ }
+ }
+}
+
+
bool EscapeAnalysis::IsEffectBranchPoint(Node* node) {
int count = 0;
for (Edge edge : node->use_edges()) {
@@ -637,10 +754,12 @@ bool EscapeAnalysis::IsEffectBranchPoint(Node* node) {
void EscapeAnalysis::ForwardVirtualState(Node* node) {
DCHECK_EQ(node->op()->EffectInputCount(), 1);
- if (node->opcode() != IrOpcode::kLoadField && IsDanglingEffectNode(node)) {
+ if (node->opcode() != IrOpcode::kLoadField &&
+ node->opcode() != IrOpcode::kLoadElement &&
+ node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) {
PrintF("Dangeling effect node: #%d (%s)\n", node->id(),
node->op()->mnemonic());
- DCHECK(false);
+ UNREACHABLE();
}
Node* effect = NodeProperties::GetEffectInput(node);
// Break the cycle for effect phis.
@@ -652,9 +771,13 @@ void EscapeAnalysis::ForwardVirtualState(Node* node) {
}
DCHECK_NOT_NULL(virtual_states_[effect->id()]);
if (IsEffectBranchPoint(effect)) {
- if (virtual_states_[node->id()]) return;
- virtual_states_[node->id()] =
- new (zone()) VirtualState(*virtual_states_[effect->id()]);
+ if (!virtual_states_[node->id()]) {
+ virtual_states_[node->id()] =
+ new (zone()) VirtualState(*virtual_states_[effect->id()]);
+ } else {
+ virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()],
+ zone());
+ }
if (FLAG_trace_turbo_escape) {
PrintF("Copying object state %p from #%d (%s) to #%d (%s)\n",
static_cast<void*>(virtual_states_[effect->id()]), effect->id(),
@@ -681,7 +804,7 @@ void EscapeAnalysis::ProcessStart(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);
+ CHECK_EQ(node->op()->EffectInputCount(), 2);
Node* left = NodeProperties::GetEffectInput(node, 0);
Node* right = NodeProperties::GetEffectInput(node, 1);
bool changed = false;
@@ -692,7 +815,7 @@ bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
virtual_states_[node->id()] = mergeState;
changed = true;
if (FLAG_trace_turbo_escape) {
- PrintF("Phi #%d got new states map %p.\n", node->id(),
+ PrintF("Effect Phi #%d got new states map %p.\n", node->id(),
static_cast<void*>(mergeState));
}
} else if (mergeState->GetLastChanged() != node) {
@@ -707,9 +830,11 @@ bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
}
if (FLAG_trace_turbo_escape) {
- PrintF("At Phi #%d, merging states %p (from #%d) and %p (from #%d)\n",
- node->id(), static_cast<void*>(l), left->id(), static_cast<void*>(r),
- right->id());
+ PrintF(
+ "At Effect Phi #%d, merging states %p (from #%d) and %p (from #%d) "
+ "into %p\n",
+ node->id(), static_cast<void*>(l), left->id(), static_cast<void*>(r),
+ right->id(), static_cast<void*>(mergeState));
}
if (r && l == nullptr) {
@@ -790,68 +915,119 @@ bool EscapeAnalysis::IsEscaped(Node* node) {
}
+VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
+ if (VirtualState* states = virtual_states_[at->id()]) {
+ return states->GetVirtualObject(id);
+ }
+ return nullptr;
+}
+
+
int EscapeAnalysis::OffsetFromAccess(Node* node) {
DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
return OpParameter<FieldAccess>(node).offset / kPointerSize;
}
+void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
+ VirtualState* state) {
+ // Only binary phis are supported for now.
+ CHECK_EQ(from->op()->ValueInputCount(), 2);
+ if (FLAG_trace_turbo_escape) {
+ PrintF("Load #%d from phi #%d", node->id(), from->id());
+ }
+ Node* left = NodeProperties::GetValueInput(from, 0);
+ Node* right = NodeProperties::GetValueInput(from, 1);
+ VirtualObject* l = state->GetVirtualObject(left);
+ VirtualObject* r = state->GetVirtualObject(right);
+ if (l && r) {
+ Node* lv = l->GetField(offset);
+ Node* rv = r->GetField(offset);
+ if (lv && rv) {
+ if (!state->GetVirtualObject(node)) {
+ state->SetVirtualObject(node->id(),
+ new (zone()) VirtualObject(node->id(), zone()));
+ }
+ Node* rep = state->GetVirtualObject(node)->GetReplacement();
+ if (!rep || rep->opcode() != IrOpcode::kPhi ||
+ NodeProperties::GetValueInput(rep, 0) != lv ||
+ NodeProperties::GetValueInput(rep, 1) != rv) {
+ Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), lv, rv,
+ NodeProperties::GetControlInput(from));
+ state->GetVirtualObject(node)->SetReplacement(phi);
+ state->LastChangedAt(node);
+ if (FLAG_trace_turbo_escape) {
+ PrintF(" got phi of #%d is #%d created.\n", lv->id(), rv->id());
+ }
+ } else if (FLAG_trace_turbo_escape) {
+ PrintF(" has already the right phi representation.\n");
+ }
+ } else if (FLAG_trace_turbo_escape) {
+ PrintF(" has incomplete field info: %p %p\n", static_cast<void*>(lv),
+ static_cast<void*>(rv));
+ }
+ } else if (FLAG_trace_turbo_escape) {
+ PrintF(" has incomplete virtual object info: %p %p\n",
+ static_cast<void*>(l), static_cast<void*>(r));
+ }
+}
+
+
void EscapeAnalysis::ProcessLoadField(Node* node) {
DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
ForwardVirtualState(node);
Node* from = NodeProperties::GetValueInput(node, 0);
- int offset = OffsetFromAccess(node);
- VirtualState* states = virtual_states_[node->id()];
- if (VirtualObject* state = states->GetVirtualObject(from)) {
- if (!state->IsTracked()) return;
- Node* value = state->GetField(offset);
+ VirtualState* state = virtual_states_[node->id()];
+ if (VirtualObject* object = state->ResolveVirtualObject(from)) {
+ int offset = OffsetFromAccess(node);
+ if (!object->IsTracked()) return;
+ Node* value = object->GetField(offset);
if (value) {
+ value = state->ResolveReplacement(value);
// Record that the load has this alias.
- states->UpdateReplacement(node, value, zone());
+ state->UpdateReplacement(node, value, zone());
} else if (FLAG_trace_turbo_escape) {
PrintF("No field %d on record for #%d\n", offset, from->id());
}
} else {
if (from->opcode() == IrOpcode::kPhi) {
+ int offset = OffsetFromAccess(node);
// Only binary phis are supported for now.
- CHECK_EQ(from->op()->ValueInputCount(), 2);
- if (FLAG_trace_turbo_escape) {
- PrintF("Load #%d from phi #%d", node->id(), from->id());
- }
- Node* left = NodeProperties::GetValueInput(from, 0);
- Node* right = NodeProperties::GetValueInput(from, 1);
- VirtualObject* l = states->GetVirtualObject(left);
- VirtualObject* r = states->GetVirtualObject(right);
- if (l && r) {
- Node* lv = l->GetField(offset);
- Node* rv = r->GetField(offset);
- if (lv && rv) {
- if (!states->GetVirtualObject(node)) {
- states->SetVirtualObject(
- node->id(), new (zone()) VirtualObject(node->id(), zone()));
- }
- Node* rep = states->GetVirtualObject(node)->GetReplacement();
- if (!rep || rep->opcode() != IrOpcode::kPhi ||
- NodeProperties::GetValueInput(rep, 0) != lv ||
- NodeProperties::GetValueInput(rep, 1) != rv) {
- Node* phi =
- graph()->NewNode(common()->Phi(kMachAnyTagged, 2), lv, rv,
- NodeProperties::GetControlInput(from));
- states->GetVirtualObject(node)->SetReplacement(phi);
- states->LastChangedAt(node);
- if (FLAG_trace_turbo_escape) {
- PrintF(" got phi of #%d is #%d created.\n", lv->id(), rv->id());
- }
- } else if (FLAG_trace_turbo_escape) {
- PrintF(" has already the right phi representation.\n");
- }
- } else if (FLAG_trace_turbo_escape) {
- PrintF(" has incomplete field info: %p %p\n", static_cast<void*>(lv),
- static_cast<void*>(rv));
- }
+ ProcessLoadFromPhi(offset, from, node, state);
+ }
+ }
+}
+
+
+void EscapeAnalysis::ProcessLoadElement(Node* node) {
+ DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
+ ForwardVirtualState(node);
+ Node* from = NodeProperties::GetValueInput(node, 0);
+ VirtualState* state = virtual_states_[node->id()];
+ if (VirtualObject* object = state->ResolveVirtualObject(from)) {
+ NumberMatcher index(node->InputAt(1));
+ ElementAccess access = OpParameter<ElementAccess>(node);
+ if (index.HasValue()) {
+ CHECK_EQ(ElementSizeLog2Of(access.machine_type), kPointerSizeLog2);
+ CHECK_EQ(access.header_size % kPointerSize, 0);
+ int offset = index.Value() + access.header_size / kPointerSize;
+ if (!object->IsTracked()) return;
+ Node* value = object->GetField(offset);
+ if (value) {
+ value = state->ResolveReplacement(value);
+ // Record that the load has this alias.
+ state->UpdateReplacement(node, value, zone());
} else if (FLAG_trace_turbo_escape) {
- PrintF(" has incomplete virtual object info: %p %p\n",
- static_cast<void*>(l), static_cast<void*>(r));
+ PrintF("No field %d on record for #%d\n", offset, from->id());
+ }
+ }
+ } else {
+ if (from->opcode() == IrOpcode::kPhi) {
+ NumberMatcher index(node->InputAt(1));
+ ElementAccess access = OpParameter<ElementAccess>(node);
+ int offset = index.Value() + access.header_size / kPointerSize;
+ if (index.HasValue()) {
+ ProcessLoadFromPhi(offset, from, node, state);
}
}
}
@@ -865,7 +1041,7 @@ void EscapeAnalysis::ProcessStoreField(Node* node) {
Node* val = NodeProperties::GetValueInput(node, 1);
int offset = OffsetFromAccess(node);
VirtualState* states = virtual_states_[node->id()];
- if (VirtualObject* obj = states->GetVirtualObject(to)) {
+ if (VirtualObject* obj = states->ResolveVirtualObject(to)) {
if (!obj->IsTracked()) return;
if (obj->SetField(offset, states->ResolveReplacement(val))) {
states->LastChangedAt(node);
@@ -874,6 +1050,56 @@ void EscapeAnalysis::ProcessStoreField(Node* node) {
}
+void EscapeAnalysis::ProcessStoreElement(Node* node) {
+ DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
+ ForwardVirtualState(node);
+ Node* to = NodeProperties::GetValueInput(node, 0);
+ NumberMatcher index(node->InputAt(1));
+ ElementAccess access = OpParameter<ElementAccess>(node);
+ Node* val = NodeProperties::GetValueInput(node, 2);
+ if (index.HasValue()) {
+ CHECK_EQ(ElementSizeLog2Of(access.machine_type), kPointerSizeLog2);
+ CHECK_EQ(access.header_size % kPointerSize, 0);
+ int offset = index.Value() + access.header_size / kPointerSize;
+ VirtualState* states = virtual_states_[node->id()];
+ if (VirtualObject* obj = states->ResolveVirtualObject(to)) {
+ if (!obj->IsTracked()) return;
+ if (obj->SetField(offset, states->ResolveReplacement(val))) {
+ states->LastChangedAt(node);
+ }
+ }
+ }
+}
+
+
+void EscapeAnalysis::DebugPrintObject(VirtualObject* object, NodeId id) {
+ PrintF(" Object #%d with %zu fields", id, object->field_count());
+ if (Node* rep = object->GetReplacement()) {
+ PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic());
+ }
+ PrintF("\n");
+ for (size_t i = 0; i < object->field_count(); ++i) {
+ if (Node* f = object->GetField(i)) {
+ PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
+ }
+ }
+}
+
+
+void EscapeAnalysis::DebugPrintState(VirtualState* state) {
+ PrintF("Dumping object state %p\n", static_cast<void*>(state));
+ for (size_t id = 0; id < state->size(); id++) {
+ if (VirtualObject* object = state->GetVirtualObject(id)) {
+ if (object->id() == id) {
+ DebugPrintObject(object, static_cast<int>(id));
+ } else {
+ PrintF(" Object #%zu links to object #%d\n", id, object->id());
+ }
+ }
+ }
+}
+
+
void EscapeAnalysis::DebugPrint() {
ZoneVector<VirtualState*> object_states(zone());
for (NodeId id = 0; id < virtual_states_.size(); id++) {
@@ -885,26 +1111,7 @@ void EscapeAnalysis::DebugPrint() {
}
}
for (size_t n = 0; n < object_states.size(); n++) {
- PrintF("Dumping object state %p\n", static_cast<void*>(object_states[n]));
- for (size_t id = 0; id < object_states[n]->size(); id++) {
- if (VirtualObject* obj = object_states[n]->GetVirtualObject(id)) {
- if (obj->id() == id) {
- PrintF(" Object #%zu with %zu fields", id, obj->fields());
- if (Node* rep = obj->GetReplacement()) {
- PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic());
- }
- PrintF("\n");
- for (size_t i = 0; i < obj->fields(); ++i) {
- if (Node* f = obj->GetField(i)) {
- PrintF(" Field %zu = #%d (%s)\n", i, f->id(),
- f->op()->mnemonic());
- }
- }
- } else {
- PrintF(" Object #%zu links to object #%d\n", id, obj->id());
- }
- }
- }
+ DebugPrintState(object_states[n]);
}
}
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698