OLD | NEW |
---|---|
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
9 #include "vm/cpu.h" | 9 #include "vm/cpu.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 5417 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5428 return (kind_ == other->kind_) && | 5428 return (kind_ == other->kind_) && |
5429 (representation_ == other->representation_) && | 5429 (representation_ == other->representation_) && |
5430 (instance_ == other->instance_) && | 5430 (instance_ == other->instance_) && |
5431 SameField(other); | 5431 SameField(other); |
5432 } | 5432 } |
5433 | 5433 |
5434 // Create a zone allocated copy of this place and assign given id to it. | 5434 // Create a zone allocated copy of this place and assign given id to it. |
5435 static Place* Wrap(Isolate* isolate, const Place& place, intptr_t id); | 5435 static Place* Wrap(Isolate* isolate, const Place& place, intptr_t id); |
5436 | 5436 |
5437 static bool IsAllocation(Definition* defn) { | 5437 static bool IsAllocation(Definition* defn) { |
5438 // TODO(vegorov): add CreateContext to this list. | |
5439 return (defn != NULL) && | 5438 return (defn != NULL) && |
5440 (defn->IsAllocateObject() || | 5439 (defn->IsAllocateObject() || |
5441 defn->IsCreateArray() || | 5440 defn->IsCreateArray() || |
5441 defn->IsAllocateUninitializedContext() || | |
5442 (defn->IsStaticCall() && | 5442 (defn->IsStaticCall() && |
5443 defn->AsStaticCall()->IsRecognizedFactory())); | 5443 defn->AsStaticCall()->IsRecognizedFactory())); |
5444 } | 5444 } |
5445 | 5445 |
5446 private: | 5446 private: |
5447 Place(Kind kind, Definition* instance, intptr_t selector) | 5447 Place(Kind kind, Definition* instance, intptr_t selector) |
5448 : kind_(kind), | 5448 : kind_(kind), |
5449 representation_(kNoRepresentation), | 5449 representation_(kNoRepresentation), |
5450 instance_(instance), | 5450 instance_(instance), |
5451 raw_selector_(selector), | 5451 raw_selector_(selector), |
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5892 // Can add more objects into aliasing_worklist_. | 5892 // Can add more objects into aliasing_worklist_. |
5893 bool AnyUseCreatesAlias(Definition* defn) { | 5893 bool AnyUseCreatesAlias(Definition* defn) { |
5894 for (Value* use = defn->input_use_list(); | 5894 for (Value* use = defn->input_use_list(); |
5895 use != NULL; | 5895 use != NULL; |
5896 use = use->next_use()) { | 5896 use = use->next_use()) { |
5897 Instruction* instr = use->instruction(); | 5897 Instruction* instr = use->instruction(); |
5898 if (instr->IsPushArgument() || | 5898 if (instr->IsPushArgument() || |
5899 (instr->IsStoreIndexed() | 5899 (instr->IsStoreIndexed() |
5900 && (use->use_index() == StoreIndexedInstr::kValuePos)) || | 5900 && (use->use_index() == StoreIndexedInstr::kValuePos)) || |
5901 instr->IsStoreStaticField() || | 5901 instr->IsStoreStaticField() || |
5902 instr->IsPhi() || | 5902 instr->IsPhi()) { |
5903 instr->IsAssertAssignable() || | |
5904 instr->IsRedefinition()) { | |
5905 return true; | 5903 return true; |
5904 } else if (instr->IsAssertAssignable() || | |
5905 instr->IsRedefinition()) { | |
5906 return AnyUseCreatesAlias(instr->AsDefinition()); | |
5906 } else if ((instr->IsStoreInstanceField() | 5907 } else if ((instr->IsStoreInstanceField() |
5907 && (use->use_index() != StoreInstanceFieldInstr::kInstancePos))) { | 5908 && (use->use_index() != StoreInstanceFieldInstr::kInstancePos))) { |
5908 ASSERT(use->use_index() == StoreInstanceFieldInstr::kValuePos); | 5909 ASSERT(use->use_index() == StoreInstanceFieldInstr::kValuePos); |
5909 // If we store this value into an object that is not aliased itself | 5910 // If we store this value into an object that is not aliased itself |
5910 // and we never load again then the store does not create an alias. | 5911 // and we never load again then the store does not create an alias. |
5911 StoreInstanceFieldInstr* store = instr->AsStoreInstanceField(); | 5912 StoreInstanceFieldInstr* store = instr->AsStoreInstanceField(); |
5912 Definition* instance = store->instance()->definition(); | 5913 Definition* instance = store->instance()->definition(); |
5913 if (instance->IsAllocateObject() && !instance->Identity().IsAliased()) { | 5914 if (Place::IsAllocation(instance) && |
5915 !instance->Identity().IsAliased()) { | |
5914 bool is_load, is_store; | 5916 bool is_load, is_store; |
5915 Place store_place(instr, &is_load, &is_store); | 5917 Place store_place(instr, &is_load, &is_store); |
5916 | 5918 |
5917 if (!HasLoadsFromPlace(instance, &store_place)) { | 5919 if (!HasLoadsFromPlace(instance, &store_place)) { |
Vyacheslav Egorov (Google)
2014/11/03 13:37:48
HasLoadsFromPlace has to account for redifinitions
| |
5918 // No loads found that match this store. If it is yet unknown if | 5920 // No loads found that match this store. If it is yet unknown if |
5919 // the object is not aliased then optimistically assume this but | 5921 // the object is not aliased then optimistically assume this but |
5920 // add it to the worklist to check its uses transitively. | 5922 // add it to the worklist to check its uses transitively. |
5921 if (instance->Identity().IsUnknown()) { | 5923 if (instance->Identity().IsUnknown()) { |
5922 instance->SetIdentity(AliasIdentity::NotAliased()); | 5924 instance->SetIdentity(AliasIdentity::NotAliased()); |
5923 aliasing_worklist_.Add(instance); | 5925 aliasing_worklist_.Add(instance); |
5924 } | 5926 } |
5925 continue; | 5927 continue; |
5926 } | 5928 } |
5927 } | 5929 } |
5928 | 5930 |
5929 return true; | 5931 return true; |
5930 } | 5932 } |
5931 } | 5933 } |
5932 return false; | 5934 return false; |
5933 } | 5935 } |
5934 | 5936 |
5935 // Mark any value stored into the given object as potentially aliased. | 5937 // Mark any value stored into the given object as potentially aliased. |
5936 void MarkStoredValuesEscaping(Definition* defn) { | 5938 void MarkStoredValuesEscaping(Definition* defn) { |
5937 if (!defn->IsAllocateObject()) { | 5939 if (!Place::IsAllocation(defn)) { |
5938 return; | 5940 return; |
5939 } | 5941 } |
5940 | 5942 |
5941 // Find all stores into this object. | 5943 // Find all stores into this object. |
5942 for (Value* use = defn->input_use_list(); | 5944 for (Value* use = defn->input_use_list(); |
5943 use != NULL; | 5945 use != NULL; |
5944 use = use->next_use()) { | 5946 use = use->next_use()) { |
5945 if ((use->use_index() == StoreInstanceFieldInstr::kInstancePos) && | 5947 if ((use->use_index() == StoreInstanceFieldInstr::kInstancePos) && |
5946 use->instruction()->IsStoreInstanceField()) { | 5948 use->instruction()->IsStoreInstanceField()) { |
5947 StoreInstanceFieldInstr* store = | 5949 StoreInstanceFieldInstr* store = |
(...skipping 3432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9380 } | 9382 } |
9381 | 9383 |
9382 return false; | 9384 return false; |
9383 } | 9385 } |
9384 | 9386 |
9385 | 9387 |
9386 // Right now we are attempting to sink allocation only into | 9388 // Right now we are attempting to sink allocation only into |
9387 // deoptimization exit. So candidate should only be used in StoreInstanceField | 9389 // deoptimization exit. So candidate should only be used in StoreInstanceField |
9388 // instructions that write into fields of the allocated object. | 9390 // instructions that write into fields of the allocated object. |
9389 // We do not support materialization of the object that has type arguments. | 9391 // We do not support materialization of the object that has type arguments. |
9390 static bool IsAllocationSinkingCandidate(AllocateObjectInstr* alloc, | 9392 static bool IsAllocationSinkingCandidate(Definition* alloc, |
9391 SafeUseCheck check_type) { | 9393 SafeUseCheck check_type) { |
9392 for (Value* use = alloc->input_use_list(); | 9394 for (Value* use = alloc->input_use_list(); |
9393 use != NULL; | 9395 use != NULL; |
9394 use = use->next_use()) { | 9396 use = use->next_use()) { |
9395 if (!IsSafeUse(use, check_type)) { | 9397 if (!IsSafeUse(use, check_type)) { |
9396 if (FLAG_trace_optimization) { | 9398 if (FLAG_trace_optimization) { |
9397 OS::Print("use of %s at %s is unsafe for allocation sinking\n", | 9399 OS::Print("use of %s at %s is unsafe for allocation sinking\n", |
9398 alloc->ToCString(), | 9400 alloc->ToCString(), |
9399 use->instruction()->ToCString()); | 9401 use->instruction()->ToCString()); |
9400 } | 9402 } |
(...skipping 12 matching lines...) Expand all Loading... | |
9413 if (store != NULL) { | 9415 if (store != NULL) { |
9414 return store->instance()->definition(); | 9416 return store->instance()->definition(); |
9415 } | 9417 } |
9416 | 9418 |
9417 return NULL; | 9419 return NULL; |
9418 } | 9420 } |
9419 | 9421 |
9420 | 9422 |
9421 // Remove the given allocation from the graph. It is not observable. | 9423 // Remove the given allocation from the graph. It is not observable. |
9422 // If deoptimization occurs the object will be materialized. | 9424 // If deoptimization occurs the object will be materialized. |
9423 void AllocationSinking::EliminateAllocation(AllocateObjectInstr* alloc) { | 9425 void AllocationSinking::EliminateAllocation(Definition* alloc) { |
9424 ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck)); | 9426 ASSERT(IsAllocationSinkingCandidate(alloc, kStrictCheck)); |
9425 | 9427 |
9426 if (FLAG_trace_optimization) { | 9428 if (FLAG_trace_optimization) { |
9427 OS::Print("removing allocation from the graph: v%" Pd "\n", | 9429 OS::Print("removing allocation from the graph: v%" Pd "\n", |
9428 alloc->ssa_temp_index()); | 9430 alloc->ssa_temp_index()); |
9429 } | 9431 } |
9430 | 9432 |
9431 // As an allocation sinking candidate it is only used in stores to its own | 9433 // As an allocation sinking candidate it is only used in stores to its own |
9432 // fields. Remove these stores. | 9434 // fields. Remove these stores. |
9433 for (Value* use = alloc->input_use_list(); | 9435 for (Value* use = alloc->input_use_list(); |
(...skipping 25 matching lines...) Expand all Loading... | |
9459 // Find allocation instructions that can be potentially eliminated and | 9461 // Find allocation instructions that can be potentially eliminated and |
9460 // rematerialized at deoptimization exits if needed. See IsSafeUse | 9462 // rematerialized at deoptimization exits if needed. See IsSafeUse |
9461 // for the description of algorithm used below. | 9463 // for the description of algorithm used below. |
9462 void AllocationSinking::CollectCandidates() { | 9464 void AllocationSinking::CollectCandidates() { |
9463 // Optimistically collect all potential candidates. | 9465 // Optimistically collect all potential candidates. |
9464 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); | 9466 for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator(); |
9465 !block_it.Done(); | 9467 !block_it.Done(); |
9466 block_it.Advance()) { | 9468 block_it.Advance()) { |
9467 BlockEntryInstr* block = block_it.Current(); | 9469 BlockEntryInstr* block = block_it.Current(); |
9468 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { | 9470 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { |
9469 AllocateObjectInstr* alloc = it.Current()->AsAllocateObject(); | 9471 { AllocateObjectInstr* alloc = it.Current()->AsAllocateObject(); |
9470 if ((alloc != NULL) && | 9472 if ((alloc != NULL) && |
9471 IsAllocationSinkingCandidate(alloc, kOptimisticCheck)) { | 9473 IsAllocationSinkingCandidate(alloc, kOptimisticCheck)) { |
9472 alloc->SetIdentity(AliasIdentity::AllocationSinkingCandidate()); | 9474 alloc->SetIdentity(AliasIdentity::AllocationSinkingCandidate()); |
9473 candidates_.Add(alloc); | 9475 candidates_.Add(alloc); |
9476 } | |
9477 } | |
9478 { AllocateUninitializedContextInstr* alloc = | |
9479 it.Current()->AsAllocateUninitializedContext(); | |
9480 if ((alloc != NULL) && | |
9481 IsAllocationSinkingCandidate(alloc, kOptimisticCheck)) { | |
9482 alloc->SetIdentity(AliasIdentity::AllocationSinkingCandidate()); | |
9483 candidates_.Add(alloc); | |
9484 } | |
9474 } | 9485 } |
9475 } | 9486 } |
9476 } | 9487 } |
9477 | 9488 |
9478 // Transitively unmark all candidates that are not strictly valid. | 9489 // Transitively unmark all candidates that are not strictly valid. |
9479 bool changed; | 9490 bool changed; |
9480 do { | 9491 do { |
9481 changed = false; | 9492 changed = false; |
9482 for (intptr_t i = 0; i < candidates_.length(); i++) { | 9493 for (intptr_t i = 0; i < candidates_.length(); i++) { |
9483 AllocateObjectInstr* alloc = candidates_[i]; | 9494 Definition* alloc = candidates_[i]; |
9484 if (alloc->Identity().IsAllocationSinkingCandidate()) { | 9495 if (alloc->Identity().IsAllocationSinkingCandidate()) { |
9485 if (!IsAllocationSinkingCandidate(alloc, kStrictCheck)) { | 9496 if (!IsAllocationSinkingCandidate(alloc, kStrictCheck)) { |
9486 alloc->SetIdentity(AliasIdentity::Unknown()); | 9497 alloc->SetIdentity(AliasIdentity::Unknown()); |
9487 changed = true; | 9498 changed = true; |
9488 } | 9499 } |
9489 } | 9500 } |
9490 } | 9501 } |
9491 } while (changed); | 9502 } while (changed); |
9492 | 9503 |
9493 // Shrink the list of candidates removing all unmarked ones. | 9504 // Shrink the list of candidates removing all unmarked ones. |
9494 intptr_t j = 0; | 9505 intptr_t j = 0; |
9495 for (intptr_t i = 0; i < candidates_.length(); i++) { | 9506 for (intptr_t i = 0; i < candidates_.length(); i++) { |
9496 AllocateObjectInstr* alloc = candidates_[i]; | 9507 Definition* alloc = candidates_[i]; |
9497 if (alloc->Identity().IsAllocationSinkingCandidate()) { | 9508 if (alloc->Identity().IsAllocationSinkingCandidate()) { |
9498 if (FLAG_trace_optimization) { | 9509 if (FLAG_trace_optimization) { |
9499 OS::Print("discovered allocation sinking candidate: v%" Pd "\n", | 9510 OS::Print("discovered allocation sinking candidate: v%" Pd "\n", |
9500 alloc->ssa_temp_index()); | 9511 alloc->ssa_temp_index()); |
9501 } | 9512 } |
9502 | 9513 |
9503 if (j != i) { | 9514 if (j != i) { |
9504 candidates_[j] = alloc; | 9515 candidates_[j] = alloc; |
9505 } | 9516 } |
9506 j++; | 9517 j++; |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9568 // the load forwarding because they flow into phis that load forwarding | 9579 // the load forwarding because they flow into phis that load forwarding |
9569 // inserts. Discover such allocations and remove them from the list | 9580 // inserts. Discover such allocations and remove them from the list |
9570 // of allocation sinking candidates undoing all changes that we did | 9581 // of allocation sinking candidates undoing all changes that we did |
9571 // in preparation for sinking these allocations. | 9582 // in preparation for sinking these allocations. |
9572 void AllocationSinking::DiscoverFailedCandidates() { | 9583 void AllocationSinking::DiscoverFailedCandidates() { |
9573 // Transitively unmark all candidates that are not strictly valid. | 9584 // Transitively unmark all candidates that are not strictly valid. |
9574 bool changed; | 9585 bool changed; |
9575 do { | 9586 do { |
9576 changed = false; | 9587 changed = false; |
9577 for (intptr_t i = 0; i < candidates_.length(); i++) { | 9588 for (intptr_t i = 0; i < candidates_.length(); i++) { |
9578 AllocateObjectInstr* alloc = candidates_[i]; | 9589 Definition* alloc = candidates_[i]; |
9579 if (alloc->Identity().IsAllocationSinkingCandidate()) { | 9590 if (alloc->Identity().IsAllocationSinkingCandidate()) { |
9580 if (!IsAllocationSinkingCandidate(alloc, kStrictCheck)) { | 9591 if (!IsAllocationSinkingCandidate(alloc, kStrictCheck)) { |
9581 alloc->SetIdentity(AliasIdentity::Unknown()); | 9592 alloc->SetIdentity(AliasIdentity::Unknown()); |
9582 changed = true; | 9593 changed = true; |
9583 } | 9594 } |
9584 } | 9595 } |
9585 } | 9596 } |
9586 } while (changed); | 9597 } while (changed); |
9587 | 9598 |
9588 // Remove all failed candidates from the candidates list. | 9599 // Remove all failed candidates from the candidates list. |
9589 intptr_t j = 0; | 9600 intptr_t j = 0; |
9590 for (intptr_t i = 0; i < candidates_.length(); i++) { | 9601 for (intptr_t i = 0; i < candidates_.length(); i++) { |
9591 AllocateObjectInstr* alloc = candidates_[i]; | 9602 Definition* alloc = candidates_[i]; |
9592 if (!alloc->Identity().IsAllocationSinkingCandidate()) { | 9603 if (!alloc->Identity().IsAllocationSinkingCandidate()) { |
9593 if (FLAG_trace_optimization) { | 9604 if (FLAG_trace_optimization) { |
9594 OS::Print("allocation v%" Pd " can't be eliminated\n", | 9605 OS::Print("allocation v%" Pd " can't be eliminated\n", |
9595 alloc->ssa_temp_index()); | 9606 alloc->ssa_temp_index()); |
9596 } | 9607 } |
9597 | 9608 |
9598 #ifdef DEBUG | 9609 #ifdef DEBUG |
9599 for (Value* use = alloc->env_use_list(); | 9610 for (Value* use = alloc->env_use_list(); |
9600 use != NULL; | 9611 use != NULL; |
9601 use = use->next_use()) { | 9612 use = use->next_use()) { |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9765 } | 9776 } |
9766 | 9777 |
9767 return NULL; | 9778 return NULL; |
9768 } | 9779 } |
9769 | 9780 |
9770 | 9781 |
9771 // Insert MaterializeObject instruction for the given allocation before | 9782 // Insert MaterializeObject instruction for the given allocation before |
9772 // the given instruction that can deoptimize. | 9783 // the given instruction that can deoptimize. |
9773 void AllocationSinking::CreateMaterializationAt( | 9784 void AllocationSinking::CreateMaterializationAt( |
9774 Instruction* exit, | 9785 Instruction* exit, |
9775 AllocateObjectInstr* alloc, | 9786 Definition* alloc, |
9776 const Class& cls, | |
9777 const ZoneGrowableArray<const Object*>& slots) { | 9787 const ZoneGrowableArray<const Object*>& slots) { |
9778 ZoneGrowableArray<Value*>* values = | 9788 ZoneGrowableArray<Value*>* values = |
9779 new(I) ZoneGrowableArray<Value*>(slots.length()); | 9789 new(I) ZoneGrowableArray<Value*>(slots.length()); |
9780 | 9790 |
9781 // All loads should be inserted before the first materialization so that | 9791 // All loads should be inserted before the first materialization so that |
9782 // IR follows the following pattern: loads, materializations, deoptimizing | 9792 // IR follows the following pattern: loads, materializations, deoptimizing |
9783 // instruction. | 9793 // instruction. |
9784 Instruction* load_point = FirstMaterializationAt(exit); | 9794 Instruction* load_point = FirstMaterializationAt(exit); |
9785 | 9795 |
9786 // Insert load instruction for every field. | 9796 // Insert load instruction for every field. |
9787 for (intptr_t i = 0; i < slots.length(); i++) { | 9797 for (intptr_t i = 0; i < slots.length(); i++) { |
9788 LoadFieldInstr* load = slots[i]->IsField() | 9798 LoadFieldInstr* load = slots[i]->IsField() |
9789 ? new(I) LoadFieldInstr( | 9799 ? new(I) LoadFieldInstr( |
9790 new(I) Value(alloc), | 9800 new(I) Value(alloc), |
9791 &Field::Cast(*slots[i]), | 9801 &Field::Cast(*slots[i]), |
9792 AbstractType::ZoneHandle(I), | 9802 AbstractType::ZoneHandle(I), |
9793 alloc->token_pos()) | 9803 alloc->token_pos()) |
9794 : new(I) LoadFieldInstr( | 9804 : new(I) LoadFieldInstr( |
9795 new(I) Value(alloc), | 9805 new(I) Value(alloc), |
9796 Smi::Cast(*slots[i]).Value(), | 9806 Smi::Cast(*slots[i]).Value(), |
9797 AbstractType::ZoneHandle(I), | 9807 AbstractType::ZoneHandle(I), |
9798 alloc->token_pos()); | 9808 alloc->token_pos()); |
9799 flow_graph_->InsertBefore( | 9809 flow_graph_->InsertBefore( |
9800 load_point, load, NULL, FlowGraph::kValue); | 9810 load_point, load, NULL, FlowGraph::kValue); |
9801 values->Add(new(I) Value(load)); | 9811 values->Add(new(I) Value(load)); |
9802 } | 9812 } |
9803 | 9813 |
9804 MaterializeObjectInstr* mat = | 9814 MaterializeObjectInstr* mat = NULL; |
9805 new(I) MaterializeObjectInstr(alloc, cls, slots, values); | 9815 if (alloc->IsAllocateObject()) { |
9816 mat = new(I) MaterializeObjectInstr( | |
9817 alloc->AsAllocateObject(), slots, values); | |
9818 } else { | |
9819 ASSERT(alloc->IsAllocateUninitializedContext()); | |
9820 mat = new(I) MaterializeObjectInstr( | |
9821 alloc->AsAllocateUninitializedContext(), slots, values); | |
9822 } | |
9823 | |
9806 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); | 9824 flow_graph_->InsertBefore(exit, mat, NULL, FlowGraph::kValue); |
9807 | 9825 |
9808 // Replace all mentions of this allocation with a newly inserted | 9826 // Replace all mentions of this allocation with a newly inserted |
9809 // MaterializeObject instruction. | 9827 // MaterializeObject instruction. |
9810 // We must preserve the identity: all mentions are replaced by the same | 9828 // We must preserve the identity: all mentions are replaced by the same |
9811 // materialization. | 9829 // materialization. |
9812 for (Environment::DeepIterator env_it(exit->env()); | 9830 for (Environment::DeepIterator env_it(exit->env()); |
9813 !env_it.Done(); | 9831 !env_it.Done(); |
9814 env_it.Advance()) { | 9832 env_it.Advance()) { |
9815 Value* use = env_it.CurrentValue(); | 9833 Value* use = env_it.CurrentValue(); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
9888 // We are not removing allocations from the worklist not to waste space on | 9906 // We are not removing allocations from the worklist not to waste space on |
9889 // the side maintaining BitVector of already processed allocations: worklist | 9907 // the side maintaining BitVector of already processed allocations: worklist |
9890 // is expected to be very small thus linear search in it is just as effecient | 9908 // is expected to be very small thus linear search in it is just as effecient |
9891 // as a bitvector. | 9909 // as a bitvector. |
9892 for (intptr_t i = 0; i < worklist_.length(); i++) { | 9910 for (intptr_t i = 0; i < worklist_.length(); i++) { |
9893 Collect(worklist_[i]); | 9911 Collect(worklist_[i]); |
9894 } | 9912 } |
9895 } | 9913 } |
9896 | 9914 |
9897 | 9915 |
9898 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { | 9916 void AllocationSinking::InsertMaterializations(Definition* alloc) { |
9899 // Collect all fields that are written for this instance. | 9917 // Collect all fields that are written for this instance. |
9900 ZoneGrowableArray<const Object*>* slots = | 9918 ZoneGrowableArray<const Object*>* slots = |
9901 new(I) ZoneGrowableArray<const Object*>(5); | 9919 new(I) ZoneGrowableArray<const Object*>(5); |
9902 | 9920 |
9903 for (Value* use = alloc->input_use_list(); | 9921 for (Value* use = alloc->input_use_list(); |
9904 use != NULL; | 9922 use != NULL; |
9905 use = use->next_use()) { | 9923 use = use->next_use()) { |
9906 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); | 9924 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); |
9907 if ((store != NULL) && (store->instance()->definition() == alloc)) { | 9925 if ((store != NULL) && (store->instance()->definition() == alloc)) { |
9908 if (!store->field().IsNull()) { | 9926 if (!store->field().IsNull()) { |
9909 AddSlot(slots, store->field()); | 9927 AddSlot(slots, store->field()); |
9910 } else { | 9928 } else { |
9911 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(store->offset_in_bytes()))); | 9929 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(store->offset_in_bytes()))); |
9912 } | 9930 } |
9913 } | 9931 } |
9914 } | 9932 } |
9915 | 9933 |
9916 if (alloc->ArgumentCount() > 0) { | 9934 if (alloc->ArgumentCount() > 0) { |
9917 ASSERT(alloc->ArgumentCount() == 1); | 9935 AllocateObjectInstr* alloc_object = alloc->AsAllocateObject(); |
9918 intptr_t type_args_offset = alloc->cls().type_arguments_field_offset(); | 9936 ASSERT(alloc_object->ArgumentCount() == 1); |
9937 intptr_t type_args_offset = | |
9938 alloc_object->cls().type_arguments_field_offset(); | |
9919 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(type_args_offset))); | 9939 AddSlot(slots, Smi::ZoneHandle(I, Smi::New(type_args_offset))); |
9920 } | 9940 } |
9921 | 9941 |
9922 // Collect all instructions that mention this object in the environment. | 9942 // Collect all instructions that mention this object in the environment. |
9923 exits_collector_.CollectTransitively(alloc); | 9943 exits_collector_.CollectTransitively(alloc); |
9924 | 9944 |
9925 // Insert materializations at environment uses. | 9945 // Insert materializations at environment uses. |
9926 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 9946 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
9927 CreateMaterializationAt( | 9947 CreateMaterializationAt( |
9928 exits_collector_.exits()[i], alloc, alloc->cls(), *slots); | 9948 exits_collector_.exits()[i], alloc, *slots); |
9929 } | 9949 } |
9930 } | 9950 } |
9931 | 9951 |
9932 | 9952 |
9933 } // namespace dart | 9953 } // namespace dart |
OLD | NEW |