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

Unified Diff: runtime/vm/flow_graph_optimizer.cc

Issue 184523002: Allocation sinking for contexts. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: added new test Created 6 years, 1 month 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
Index: runtime/vm/flow_graph_optimizer.cc
===================================================================
--- runtime/vm/flow_graph_optimizer.cc (revision 41687)
+++ runtime/vm/flow_graph_optimizer.cc (working copy)
@@ -5487,10 +5487,10 @@
static Place* Wrap(Isolate* isolate, const Place& place, intptr_t id);
static bool IsAllocation(Definition* defn) {
- // TODO(vegorov): add CreateContext to this list.
return (defn != NULL) &&
(defn->IsAllocateObject() ||
defn->IsCreateArray() ||
+ defn->IsAllocateUninitializedContext() ||
(defn->IsStaticCall() &&
defn->AsStaticCall()->IsRecognizedFactory()));
}
@@ -5924,13 +5924,18 @@
bool HasLoadsFromPlace(Definition* defn, const Place* place) {
ASSERT((place->kind() == Place::kField) ||
(place->kind() == Place::kVMField));
- ASSERT(place->instance() == defn);
for (Value* use = defn->input_use_list();
use != NULL;
use = use->next_use()) {
+ Instruction* instr = use->instruction();
+ if ((instr->IsRedefinition() ||
+ instr->IsAssertAssignable()) &&
+ HasLoadsFromPlace(instr->AsDefinition(), place)) {
+ return true;
+ }
bool is_load = false, is_store;
- Place load_place(use->instruction(), &is_load, &is_store);
+ Place load_place(instr, &is_load, &is_store);
if (is_load && load_place.Equals(place)) {
return true;
@@ -5951,10 +5956,11 @@
(instr->IsStoreIndexed()
&& (use->use_index() == StoreIndexedInstr::kValuePos)) ||
instr->IsStoreStaticField() ||
- instr->IsPhi() ||
- instr->IsAssertAssignable() ||
- instr->IsRedefinition()) {
+ instr->IsPhi()) {
return true;
+ } else if ((instr->IsAssertAssignable() || instr->IsRedefinition()) &&
+ AnyUseCreatesAlias(instr->AsDefinition())) {
+ return true;
} else if ((instr->IsStoreInstanceField()
&& (use->use_index() != StoreInstanceFieldInstr::kInstancePos))) {
ASSERT(use->use_index() == StoreInstanceFieldInstr::kValuePos);
@@ -5961,8 +5967,10 @@
// If we store this value into an object that is not aliased itself
// and we never load again then the store does not create an alias.
StoreInstanceFieldInstr* store = instr->AsStoreInstanceField();
- Definition* instance = store->instance()->definition();
- if (instance->IsAllocateObject() && !instance->Identity().IsAliased()) {
+ Definition* instance =
+ store->instance()->definition()->OriginalDefinition();
+ if (Place::IsAllocation(instance) &&
+ !instance->Identity().IsAliased()) {
bool is_load, is_store;
Place store_place(instr, &is_load, &is_store);
@@ -5977,7 +5985,6 @@
continue;
}
}
-
return true;
}
}
@@ -5986,19 +5993,20 @@
// Mark any value stored into the given object as potentially aliased.
void MarkStoredValuesEscaping(Definition* defn) {
- if (!defn->IsAllocateObject()) {
- return;
- }
-
// Find all stores into this object.
for (Value* use = defn->input_use_list();
use != NULL;
use = use->next_use()) {
+ if (use->instruction()->IsRedefinition() ||
+ use->instruction()->IsAssertAssignable()) {
+ MarkStoredValuesEscaping(use->instruction()->AsDefinition());
+ continue;
+ }
if ((use->use_index() == StoreInstanceFieldInstr::kInstancePos) &&
use->instruction()->IsStoreInstanceField()) {
StoreInstanceFieldInstr* store =
use->instruction()->AsStoreInstanceField();
- Definition* value = store->value()->definition();
+ Definition* value = store->value()->definition()->OriginalDefinition();
if (value->Identity().IsNotAliased()) {
value->SetIdentity(AliasIdentity::Aliased());
identity_rollback_.Add(value);
@@ -6012,6 +6020,7 @@
// Determine if the given definition can't be aliased.
void ComputeAliasing(Definition* alloc) {
+ ASSERT(Place::IsAllocation(alloc));
ASSERT(alloc->Identity().IsUnknown());
ASSERT(aliasing_worklist_.is_empty());
@@ -6020,7 +6029,7 @@
while (!aliasing_worklist_.is_empty()) {
Definition* defn = aliasing_worklist_.RemoveLast();
-
+ ASSERT(Place::IsAllocation(defn));
// If the definition in the worklist was optimistically marked as
// not-aliased check that optimistic assumption still holds: check if
// any of its uses can create an alias.
@@ -9442,7 +9451,7 @@
// deoptimization exit. So candidate should only be used in StoreInstanceField
// instructions that write into fields of the allocated object.
// We do not support materialization of the object that has type arguments.
-static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc,
+static bool IsAllocationSinkingCandidate(Definition* alloc,
SafeUseCheck check_type) {
for (Value* use = alloc->input_use_list();
use != NULL;
@@ -9475,7 +9484,7 @@
// Remove the given allocation from the graph. It is not observable.
// If deoptimization occurs the object will be materialized.
-void AllocationSinking::EliminateAllocation(AllocateObjectInstr* alloc) {
+void AllocationSinking::EliminateAllocation(Definition* alloc) {
ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck));
if (FLAG_trace_optimization) {
@@ -9521,12 +9530,21 @@
block_it.Advance()) {
BlockEntryInstr* block = block_it.Current();
for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
- AllocateObjectInstr* alloc = it.Current()->AsAllocateObject();
- if ((alloc != NULL) &&
- IsAllocationSinkingCandidate(alloc, kOptimisticCheck)) {
- alloc->SetIdentity(AliasIdentity::AllocationSinkingCandidate());
- candidates_.Add(alloc);
+ { AllocateObjectInstr* alloc = it.Current()->AsAllocateObject();
+ if ((alloc != NULL) &&
+ IsAllocationSinkingCandidate(alloc, kOptimisticCheck)) {
+ alloc->SetIdentity(AliasIdentity::AllocationSinkingCandidate());
+ candidates_.Add(alloc);
+ }
}
+ { AllocateUninitializedContextInstr* alloc =
+ it.Current()->AsAllocateUninitializedContext();
+ if ((alloc != NULL) &&
+ IsAllocationSinkingCandidate(alloc, kOptimisticCheck)) {
+ alloc->SetIdentity(AliasIdentity::AllocationSinkingCandidate());
+ candidates_.Add(alloc);
+ }
+ }
}
}
@@ -9535,7 +9553,7 @@
do {
changed = false;
for (intptr_t i = 0; i < candidates_.length(); i++) {
- AllocateObjectInstr* alloc = candidates_[i];
+ Definition* alloc = candidates_[i];
if (alloc->Identity().IsAllocationSinkingCandidate()) {
if (!IsAllocationSinkingCandidate(alloc, kStrictCheck)) {
alloc->SetIdentity(AliasIdentity::Unknown());
@@ -9548,7 +9566,7 @@
// Shrink the list of candidates removing all unmarked ones.
intptr_t j = 0;
for (intptr_t i = 0; i < candidates_.length(); i++) {
- AllocateObjectInstr* alloc = candidates_[i];
+ Definition* alloc = candidates_[i];
if (alloc->Identity().IsAllocationSinkingCandidate()) {
if (FLAG_trace_optimization) {
OS::Print("discovered allocation sinking candidate: v%" Pd "\n",
@@ -9630,7 +9648,7 @@
do {
changed = false;
for (intptr_t i = 0; i < candidates_.length(); i++) {
- AllocateObjectInstr* alloc = candidates_[i];
+ Definition* alloc = candidates_[i];
if (alloc->Identity().IsAllocationSinkingCandidate()) {
if (!IsAllocationSinkingCandidate(alloc, kStrictCheck)) {
alloc->SetIdentity(AliasIdentity::Unknown());
@@ -9643,7 +9661,7 @@
// Remove all failed candidates from the candidates list.
intptr_t j = 0;
for (intptr_t i = 0; i < candidates_.length(); i++) {
- AllocateObjectInstr* alloc = candidates_[i];
+ Definition* alloc = candidates_[i];
if (!alloc->Identity().IsAllocationSinkingCandidate()) {
if (FLAG_trace_optimization) {
OS::Print("allocation v%" Pd " can't be eliminated\n",
@@ -9827,8 +9845,7 @@
// the given instruction that can deoptimize.
void AllocationSinking::CreateMaterializationAt(
Instruction* exit,
- AllocateObjectInstr* alloc,
- const Class& cls,
+ Definition* alloc,
const ZoneGrowableArray<const Object*>& slots) {
ZoneGrowableArray<Value*>* values =
new(I) ZoneGrowableArray<Value*>(slots.length());
@@ -9856,8 +9873,16 @@
values->Add(new(I) Value(load));
}
- MaterializeObjectInstr* mat =
- new(I) MaterializeObjectInstr(alloc, cls, slots, values);
+ MaterializeObjectInstr* mat = NULL;
+ if (alloc->IsAllocateObject()) {
+ mat = new(I) MaterializeObjectInstr(
+ alloc->AsAllocateObject(), slots, values);
+ } else {
+ ASSERT(alloc->IsAllocateUninitializedContext());
+ mat = new(I) MaterializeObjectInstr(
+ alloc->AsAllocateUninitializedContext(), slots, values);
+ }
+
flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue);
// Replace all mentions of this allocation with a newly inserted
@@ -9950,7 +9975,7 @@
}
-void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) {
+void AllocationSinking::InsertMaterializations(Definition* alloc) {
// Collect all fields that are written for this instance.
ZoneGrowableArray<const Object*>* slots =
new(I) ZoneGrowableArray<const Object*>(5);
@@ -9969,8 +9994,10 @@
}
if (alloc->ArgumentCount() > 0) {
- ASSERT(alloc->ArgumentCount() == 1);
- intptr_t type_args_offset = alloc->cls().type_arguments_field_offset();
+ AllocateObjectInstr* alloc_object = alloc->AsAllocateObject();
+ ASSERT(alloc_object->ArgumentCount() == 1);
+ intptr_t type_args_offset =
+ alloc_object->cls().type_arguments_field_offset();
AddSlot(slots, Smi::ZoneHandle(I, Smi::New(type_args_offset)));
}
@@ -9980,7 +10007,7 @@
// Insert materializations at environment uses.
for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) {
CreateMaterializationAt(
- exits_collector_.exits()[i], alloc, alloc->cls(), *slots);
+ exits_collector_.exits()[i], alloc, *slots);
}
}

Powered by Google App Engine
This is Rietveld 408576698