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/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) | 48 #if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_IA32) |
49 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); | 49 DEFINE_FLAG(bool, trace_smi_widening, false, "Trace Smi->Int32 widening pass."); |
50 #endif | 50 #endif |
51 | 51 |
52 DECLARE_FLAG(bool, polymorphic_with_deopt); | 52 DECLARE_FLAG(bool, polymorphic_with_deopt); |
53 DECLARE_FLAG(bool, source_lines); | 53 DECLARE_FLAG(bool, source_lines); |
54 DECLARE_FLAG(bool, trace_cha); | 54 DECLARE_FLAG(bool, trace_cha); |
55 DECLARE_FLAG(bool, trace_field_guards); | 55 DECLARE_FLAG(bool, trace_field_guards); |
56 DECLARE_FLAG(bool, trace_type_check_elimination); | 56 DECLARE_FLAG(bool, trace_type_check_elimination); |
57 DECLARE_FLAG(bool, warn_on_javascript_compatibility); | 57 DECLARE_FLAG(bool, warn_on_javascript_compatibility); |
| 58 DECLARE_FLAG(bool, fields_may_be_reset); |
58 | 59 |
59 // Quick access to the current isolate and zone. | 60 // Quick access to the current isolate and zone. |
60 #define I (isolate()) | 61 #define I (isolate()) |
61 #define Z (zone()) | 62 #define Z (zone()) |
62 | 63 |
63 static bool ShouldInlineSimd() { | 64 static bool ShouldInlineSimd() { |
64 return FlowGraphCompiler::SupportsUnboxedSimd128(); | 65 return FlowGraphCompiler::SupportsUnboxedSimd128(); |
65 } | 66 } |
66 | 67 |
67 | 68 |
(...skipping 5578 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5646 "<%s[%" Pd "|%" Pd "]>", | 5647 "<%s[%" Pd "|%" Pd "]>", |
5647 DefinitionName(instance()), | 5648 DefinitionName(instance()), |
5648 index_constant(), | 5649 index_constant(), |
5649 ElementSizeMultiplier(element_size())); | 5650 ElementSizeMultiplier(element_size())); |
5650 } | 5651 } |
5651 } | 5652 } |
5652 UNREACHABLE(); | 5653 UNREACHABLE(); |
5653 return "<?>"; | 5654 return "<?>"; |
5654 } | 5655 } |
5655 | 5656 |
5656 bool IsFinalField() const { | 5657 // Fields that are considered immutable by load optimization. |
5657 return (kind() == kField) && field().is_final(); | 5658 // Handle static finals as non-final with precompilation because |
| 5659 // they may be reset to uninitialized after compilation. |
| 5660 bool IsImmutableField() const { |
| 5661 return (kind() == kField) |
| 5662 && field().is_final() |
| 5663 && (!field().is_static() || !FLAG_fields_may_be_reset); |
5658 } | 5664 } |
5659 | 5665 |
5660 intptr_t Hashcode() const { | 5666 intptr_t Hashcode() const { |
5661 return (flags_ * 63 + reinterpret_cast<intptr_t>(instance_)) * 31 + | 5667 return (flags_ * 63 + reinterpret_cast<intptr_t>(instance_)) * 31 + |
5662 FieldHashcode(); | 5668 FieldHashcode(); |
5663 } | 5669 } |
5664 | 5670 |
5665 bool Equals(const Place* other) const { | 5671 bool Equals(const Place* other) const { |
5666 return (flags_ == other->flags_) && | 5672 return (flags_ == other->flags_) && |
5667 (instance_ == other->instance_) && | 5673 (instance_ == other->instance_) && |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5984 // Artificial alias that is used to collect all representatives of | 5990 // Artificial alias that is used to collect all representatives of |
5985 // X[*] alias for all X. | 5991 // X[*] alias for all X. |
5986 kAnyAllocationIndexedAlias = 3, | 5992 kAnyAllocationIndexedAlias = 3, |
5987 | 5993 |
5988 // *[*] alias. | 5994 // *[*] alias. |
5989 kAnyInstanceAnyIndexAlias = 4 | 5995 kAnyInstanceAnyIndexAlias = 4 |
5990 }; | 5996 }; |
5991 | 5997 |
5992 // Compute least generic alias for the place and assign alias id to it. | 5998 // Compute least generic alias for the place and assign alias id to it. |
5993 void AddRepresentative(Place* place) { | 5999 void AddRepresentative(Place* place) { |
5994 if (!place->IsFinalField()) { | 6000 if (!place->IsImmutableField()) { |
5995 const Place* alias = CanonicalizeAlias(place->ToAlias()); | 6001 const Place* alias = CanonicalizeAlias(place->ToAlias()); |
5996 EnsureSet(&representatives_, alias->id())->Add(place->id()); | 6002 EnsureSet(&representatives_, alias->id())->Add(place->id()); |
5997 | 6003 |
5998 // Update cumulative representative sets that are used during | 6004 // Update cumulative representative sets that are used during |
5999 // killed sets computation. | 6005 // killed sets computation. |
6000 if (alias->kind() == Place::kConstantIndexed) { | 6006 if (alias->kind() == Place::kConstantIndexed) { |
6001 if (CanBeAliased(alias->instance())) { | 6007 if (CanBeAliased(alias->instance())) { |
6002 EnsureSet(&representatives_, kAnyConstantIndexedAlias)-> | 6008 EnsureSet(&representatives_, kAnyConstantIndexedAlias)-> |
6003 Add(place->id()); | 6009 Add(place->id()); |
6004 } | 6010 } |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6190 | 6196 |
6191 case Place::kNone: | 6197 case Place::kNone: |
6192 UNREACHABLE(); | 6198 UNREACHABLE(); |
6193 } | 6199 } |
6194 } | 6200 } |
6195 | 6201 |
6196 // Returns true if the given load is unaffected by external side-effects. | 6202 // Returns true if the given load is unaffected by external side-effects. |
6197 // This essentially means that no stores to the same location can | 6203 // This essentially means that no stores to the same location can |
6198 // occur in other functions. | 6204 // occur in other functions. |
6199 bool IsIndependentFromEffects(Place* place) { | 6205 bool IsIndependentFromEffects(Place* place) { |
6200 if (place->IsFinalField()) { | 6206 if (place->IsImmutableField()) { |
6201 // Note that we can't use LoadField's is_immutable attribute here because | 6207 // Note that we can't use LoadField's is_immutable attribute here because |
6202 // some VM-fields (those that have no corresponding Field object and | 6208 // some VM-fields (those that have no corresponding Field object and |
6203 // accessed through offset alone) can share offset but have different | 6209 // accessed through offset alone) can share offset but have different |
6204 // immutability properties. | 6210 // immutability properties. |
6205 // One example is the length property of growable and fixed size list. If | 6211 // One example is the length property of growable and fixed size list. If |
6206 // loads of these two properties occur in the same function for the same | 6212 // loads of these two properties occur in the same function for the same |
6207 // receiver then they will get the same expression number. However | 6213 // receiver then they will get the same expression number. However |
6208 // immutability of the length of fixed size list does not mean that | 6214 // immutability of the length of fixed size list does not mean that |
6209 // growable list also has immutable property. Thus we will make a | 6215 // growable list also has immutable property. Thus we will make a |
6210 // conservative assumption for the VM-properties. | 6216 // conservative assumption for the VM-properties. |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6624 | 6630 |
6625 bool is_load = false, is_store = false; | 6631 bool is_load = false, is_store = false; |
6626 Place place(instr, &is_load, &is_store); | 6632 Place place(instr, &is_load, &is_store); |
6627 | 6633 |
6628 BitVector* killed = NULL; | 6634 BitVector* killed = NULL; |
6629 if (is_store) { | 6635 if (is_store) { |
6630 const intptr_t alias_id = | 6636 const intptr_t alias_id = |
6631 aliased_set_->LookupAliasId(place.ToAlias()); | 6637 aliased_set_->LookupAliasId(place.ToAlias()); |
6632 if (alias_id != AliasedSet::kNoAlias) { | 6638 if (alias_id != AliasedSet::kNoAlias) { |
6633 killed = aliased_set_->GetKilledSet(alias_id); | 6639 killed = aliased_set_->GetKilledSet(alias_id); |
6634 } else if (!place.IsFinalField()) { | 6640 } else if (!place.IsImmutableField()) { |
6635 // We encountered unknown alias: this means intrablock load | 6641 // We encountered unknown alias: this means intrablock load |
6636 // forwarding refined parameter of this store, for example | 6642 // forwarding refined parameter of this store, for example |
6637 // | 6643 // |
6638 // o <- alloc() | 6644 // o <- alloc() |
6639 // a.f <- o | 6645 // a.f <- o |
6640 // u <- a.f | 6646 // u <- a.f |
6641 // u.x <- null ;; this store alias is *.x | 6647 // u.x <- null ;; this store alias is *.x |
6642 // | 6648 // |
6643 // after intrablock load forwarding | 6649 // after intrablock load forwarding |
6644 // | 6650 // |
(...skipping 883 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7528 | 7534 |
7529 // Iterate backwards starting at the last instruction. | 7535 // Iterate backwards starting at the last instruction. |
7530 for (BackwardInstructionIterator instr_it(block); | 7536 for (BackwardInstructionIterator instr_it(block); |
7531 !instr_it.Done(); | 7537 !instr_it.Done(); |
7532 instr_it.Advance()) { | 7538 instr_it.Advance()) { |
7533 Instruction* instr = instr_it.Current(); | 7539 Instruction* instr = instr_it.Current(); |
7534 | 7540 |
7535 bool is_load = false; | 7541 bool is_load = false; |
7536 bool is_store = false; | 7542 bool is_store = false; |
7537 Place place(instr, &is_load, &is_store); | 7543 Place place(instr, &is_load, &is_store); |
7538 if (place.IsFinalField()) { | 7544 if (place.IsImmutableField()) { |
7539 // Loads/stores of final fields do not participate. | 7545 // Loads/stores of final fields do not participate. |
7540 continue; | 7546 continue; |
7541 } | 7547 } |
7542 | 7548 |
7543 // Handle stores. | 7549 // Handle stores. |
7544 if (is_store) { | 7550 if (is_store) { |
7545 if (kill->Contains(instr->place_id())) { | 7551 if (kill->Contains(instr->place_id())) { |
7546 if (!live_in->Contains(instr->place_id()) && | 7552 if (!live_in->Contains(instr->place_id()) && |
7547 CanEliminateStore(instr)) { | 7553 CanEliminateStore(instr)) { |
7548 if (FLAG_trace_optimization) { | 7554 if (FLAG_trace_optimization) { |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7617 exposed_stores_[postorder_number]; | 7623 exposed_stores_[postorder_number]; |
7618 if (exposed_stores == NULL) continue; // No exposed stores. | 7624 if (exposed_stores == NULL) continue; // No exposed stores. |
7619 | 7625 |
7620 // Iterate over candidate stores. | 7626 // Iterate over candidate stores. |
7621 for (intptr_t i = 0; i < exposed_stores->length(); ++i) { | 7627 for (intptr_t i = 0; i < exposed_stores->length(); ++i) { |
7622 Instruction* instr = (*exposed_stores)[i]; | 7628 Instruction* instr = (*exposed_stores)[i]; |
7623 bool is_load = false; | 7629 bool is_load = false; |
7624 bool is_store = false; | 7630 bool is_store = false; |
7625 Place place(instr, &is_load, &is_store); | 7631 Place place(instr, &is_load, &is_store); |
7626 ASSERT(!is_load && is_store); | 7632 ASSERT(!is_load && is_store); |
7627 if (place.IsFinalField()) { | 7633 if (place.IsImmutableField()) { |
7628 // Final field do not participate in dead store elimination. | 7634 // Final field do not participate in dead store elimination. |
7629 continue; | 7635 continue; |
7630 } | 7636 } |
7631 // Eliminate a downward exposed store if the corresponding place is not | 7637 // Eliminate a downward exposed store if the corresponding place is not |
7632 // in live-out. | 7638 // in live-out. |
7633 if (!live_out->Contains(instr->place_id()) && | 7639 if (!live_out->Contains(instr->place_id()) && |
7634 CanEliminateStore(instr)) { | 7640 CanEliminateStore(instr)) { |
7635 if (FLAG_trace_optimization) { | 7641 if (FLAG_trace_optimization) { |
7636 THR_Print("Removing dead store to place %" Pd " block B%" Pd "\n", | 7642 THR_Print("Removing dead store to place %" Pd " block B%" Pd "\n", |
7637 instr->place_id(), block->block_id()); | 7643 instr->place_id(), block->block_id()); |
(...skipping 1187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8825 | 8831 |
8826 // Insert materializations at environment uses. | 8832 // Insert materializations at environment uses. |
8827 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { | 8833 for (intptr_t i = 0; i < exits_collector_.exits().length(); i++) { |
8828 CreateMaterializationAt( | 8834 CreateMaterializationAt( |
8829 exits_collector_.exits()[i], alloc, *slots); | 8835 exits_collector_.exits()[i], alloc, *slots); |
8830 } | 8836 } |
8831 } | 8837 } |
8832 | 8838 |
8833 | 8839 |
8834 } // namespace dart | 8840 } // namespace dart |
OLD | NEW |