Chromium Code Reviews| 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/dart_entry.h" | 9 #include "vm/dart_entry.h" |
| 10 #include "vm/flow_graph_builder.h" | 10 #include "vm/flow_graph_builder.h" |
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 | 290 |
| 291 | 291 |
| 292 | 292 |
| 293 // Used by TryMergeDivMod. | 293 // Used by TryMergeDivMod. |
| 294 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, | 294 // Inserts a load-indexed instruction between a TRUNCDIV or MOD instruction, |
| 295 // and the using instruction. This is an intermediate step before merging. | 295 // and the using instruction. This is an intermediate step before merging. |
| 296 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, | 296 void FlowGraphOptimizer::AppendLoadIndexedForMerged(Definition* instr, |
| 297 intptr_t ix, | 297 intptr_t ix, |
| 298 intptr_t cid) { | 298 intptr_t cid) { |
| 299 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); | 299 const intptr_t index_scale = FlowGraphCompiler::ElementSizeFor(cid); |
| 300 ConstantInstr* index_instr = new ConstantInstr(Smi::Handle(Smi::New(ix))); | 300 ConstantInstr* index_instr = |
| 301 flow_graph()->InsertAfter(instr, index_instr, NULL, Definition::kValue); | 301 flow_graph()->GetConstant(Smi::Handle(Smi::New(ix))); |
|
Florian Schneider
2014/01/23 13:02:29
Unrelated cleanup to use constant pool here.
| |
| 302 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), | 302 LoadIndexedInstr* load = new LoadIndexedInstr(new Value(instr), |
| 303 new Value(index_instr), | 303 new Value(index_instr), |
| 304 index_scale, | 304 index_scale, |
| 305 cid, | 305 cid, |
| 306 Isolate::kNoDeoptId); | 306 Isolate::kNoDeoptId); |
| 307 instr->ReplaceUsesWith(load); | 307 instr->ReplaceUsesWith(load); |
| 308 flow_graph()->InsertAfter(index_instr, load, NULL, Definition::kValue); | 308 flow_graph()->InsertAfter(instr, load, NULL, Definition::kValue); |
| 309 } | 309 } |
| 310 | 310 |
| 311 | 311 |
| 312 // Dart: | 312 // Dart: |
| 313 // var x = d % 10; | 313 // var x = d % 10; |
| 314 // var y = d ~/ 10; | 314 // var y = d ~/ 10; |
| 315 // var z = x + y; | 315 // var z = x + y; |
| 316 // | 316 // |
| 317 // IL: | 317 // IL: |
| 318 // v4 <- %(v2, v3) | 318 // v4 <- %(v2, v3) |
| (...skipping 4298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4617 // between stores and loads. Store can alias another load or store if and only | 4617 // between stores and loads. Store can alias another load or store if and only |
| 4618 // if they have the same alias. | 4618 // if they have the same alias. |
| 4619 class Alias : public ValueObject { | 4619 class Alias : public ValueObject { |
| 4620 public: | 4620 public: |
| 4621 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } | 4621 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } |
| 4622 | 4622 |
| 4623 // All indexed load/stores alias each other. | 4623 // All indexed load/stores alias each other. |
| 4624 // TODO(vegorov): incorporate type of array into alias to disambiguate | 4624 // TODO(vegorov): incorporate type of array into alias to disambiguate |
| 4625 // different typed data and normal arrays. | 4625 // different typed data and normal arrays. |
| 4626 static Alias Indexes() { | 4626 static Alias Indexes() { |
| 4627 return Alias(kIndexesAlias); | 4627 return Alias(kIndexesAlias, 0); |
| 4628 } | |
| 4629 | |
| 4630 static Alias ConstantIndex(intptr_t id) { | |
| 4631 ASSERT(id != 0); | |
| 4632 return Alias(kConstantIndex, id); | |
| 4628 } | 4633 } |
| 4629 | 4634 |
| 4630 // Field load/stores alias each other only when they access the same field. | 4635 // Field load/stores alias each other only when they access the same field. |
| 4631 // AliasedSet assigns ids to a combination of instance and field during | 4636 // AliasedSet assigns ids to a combination of instance and field during |
| 4632 // the optimization phase. | 4637 // the optimization phase. |
| 4633 static Alias Field(intptr_t id) { | 4638 static Alias Field(intptr_t id) { |
| 4634 ASSERT(id >= kFirstFieldAlias); | 4639 ASSERT(id != 0); |
| 4635 return Alias(id * 2 + 1); | 4640 return Alias(kFieldAlias, id); |
| 4636 } | 4641 } |
| 4637 | 4642 |
| 4638 // VMField load/stores alias each other when field offset matches. | 4643 // VMField load/stores alias each other when field offset matches. |
| 4639 // TODO(vegorov) storing a context variable does not alias loading array | 4644 // TODO(vegorov) storing a context variable does not alias loading array |
| 4640 // length. | 4645 // length. |
| 4641 static Alias VMField(intptr_t offset_in_bytes) { | 4646 static Alias VMField(intptr_t offset_in_bytes) { |
| 4647 ASSERT(offset_in_byes >= 0); | |
| 4642 const intptr_t idx = offset_in_bytes / kWordSize; | 4648 const intptr_t idx = offset_in_bytes / kWordSize; |
| 4643 ASSERT(idx >= kFirstFieldAlias); | 4649 return Alias(kVMFieldAlias, idx); |
| 4644 return Alias(idx * 2); | |
| 4645 } | 4650 } |
| 4646 | 4651 |
| 4647 // Current context load/stores alias each other. | 4652 // Current context load/stores alias each other. |
| 4648 static Alias CurrentContext() { | 4653 static Alias CurrentContext() { |
| 4649 return Alias(kCurrentContextAlias); | 4654 return Alias(kCurrentContextAlias, 0); |
| 4650 } | 4655 } |
| 4651 | 4656 |
| 4652 // Operation does not alias anything. | 4657 // Operation does not alias anything. |
| 4653 static Alias None() { | 4658 static Alias None() { |
| 4654 return Alias(kNoneAlias); | 4659 return Alias(kNoneAlias); |
| 4655 } | 4660 } |
| 4656 | 4661 |
| 4657 bool IsNone() const { | 4662 bool IsNone() const { |
| 4658 return alias_ == kNoneAlias; | 4663 return alias_ == kNoneAlias; |
| 4659 } | 4664 } |
| 4660 | 4665 |
| 4661 // Convert this alias to a positive array index. | 4666 // Convert this alias to a positive array index. |
| 4662 intptr_t ToIndex() const { | 4667 intptr_t ToIndex() const { |
| 4663 ASSERT(!IsNone()); | 4668 ASSERT(!IsNone()); |
| 4664 return alias_ - kAliasBase; | 4669 return alias_; |
| 4665 } | 4670 } |
| 4666 | 4671 |
| 4667 private: | 4672 private: |
| 4673 enum { | |
| 4674 // Number of bits required to encode Kind value. | |
| 4675 // The payload occupies the rest of the bits, but leaves the MSB (sign bit) | |
| 4676 // empty so that the resulting encoded value is always a positive integer. | |
| 4677 kBitsForKind = 3, | |
| 4678 kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind - 1, | |
| 4679 }; | |
| 4680 | |
| 4681 enum Kind { | |
| 4682 kNoneAlias = -1, | |
| 4683 kCurrentContextAlias = 0, | |
| 4684 kIndexesAlias = 1, | |
| 4685 kFieldAlias = 2, | |
| 4686 kVMFieldAlias = 3, | |
| 4687 kConstantIndex = 4, | |
| 4688 kNumKinds = kConstantIndex + 1 | |
| 4689 }; | |
| 4690 COMPILE_ASSERT(kNumKinds < ((1 << kBitsForKind) - 1), InvalidBitFieldSize); | |
| 4691 | |
| 4668 explicit Alias(intptr_t alias) : alias_(alias) { } | 4692 explicit Alias(intptr_t alias) : alias_(alias) { } |
| 4669 | 4693 |
| 4670 enum { | 4694 Alias(Kind kind, uword payload) |
| 4671 kNoneAlias = -2, | 4695 : alias_(KindField::encode(kind) | PayloadField::encode(payload)) { } |
| 4672 kCurrentContextAlias = -1, | 4696 |
| 4673 kIndexesAlias = 0, | 4697 uword payload() const { |
| 4674 kFirstFieldAlias = kIndexesAlias + 1, | 4698 return PayloadField::decode(alias_); |
| 4675 kAliasBase = kCurrentContextAlias | 4699 } |
| 4676 }; | 4700 |
| 4701 Kind kind() const { | |
| 4702 return IsNone() ? kNoneAlias : KindField::decode(alias_); | |
| 4703 } | |
| 4704 | |
| 4705 typedef BitField<Kind, 0, kBitsForKind> KindField; | |
| 4706 typedef BitField<uword, kBitsForKind, kBitsForPayload> PayloadField; | |
|
Florian Schneider
2014/01/23 13:02:29
Instead of encoding as the ids as odd/even positiv
| |
| 4677 | 4707 |
| 4678 const intptr_t alias_; | 4708 const intptr_t alias_; |
| 4679 }; | 4709 }; |
| 4680 | 4710 |
| 4681 | 4711 |
| 4682 // Place describes an abstract location (e.g. field) that IR can load | 4712 // Place describes an abstract location (e.g. field) that IR can load |
| 4683 // from or store to. | 4713 // from or store to. |
| 4684 class Place : public ValueObject { | 4714 class Place : public ValueObject { |
| 4685 public: | 4715 public: |
| 4686 enum Kind { | 4716 enum Kind { |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4985 // those that are affected by calls. | 5015 // those that are affected by calls. |
| 4986 class AliasedSet : public ZoneAllocated { | 5016 class AliasedSet : public ZoneAllocated { |
| 4987 public: | 5017 public: |
| 4988 explicit AliasedSet(ZoneGrowableArray<Place*>* places, | 5018 explicit AliasedSet(ZoneGrowableArray<Place*>* places, |
| 4989 PhiPlaceMoves* phi_moves) | 5019 PhiPlaceMoves* phi_moves) |
| 4990 : places_(*places), | 5020 : places_(*places), |
| 4991 phi_moves_(phi_moves), | 5021 phi_moves_(phi_moves), |
| 4992 sets_(), | 5022 sets_(), |
| 4993 aliased_by_effects_(new BitVector(places->length())), | 5023 aliased_by_effects_(new BitVector(places->length())), |
| 4994 max_field_id_(0), | 5024 max_field_id_(0), |
| 4995 field_ids_() { } | 5025 field_ids_(), |
| 5026 max_index_id_(0), | |
| 5027 index_ids_() { } | |
| 4996 | 5028 |
| 4997 Alias ComputeAlias(Place* place) { | 5029 Alias ComputeAlias(Place* place) { |
| 4998 switch (place->kind()) { | 5030 switch (place->kind()) { |
| 4999 case Place::kIndexed: | 5031 case Place::kIndexed: |
| 5032 if (place->index()->IsConstant()) { | |
| 5033 const Object& index = place->index()->AsConstant()->value(); | |
| 5034 if (index.IsSmi()) { | |
| 5035 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); | |
| 5036 } | |
| 5037 } | |
| 5000 return Alias::Indexes(); | 5038 return Alias::Indexes(); |
| 5001 case Place::kField: | 5039 case Place::kField: |
| 5002 return Alias::Field( | 5040 return Alias::Field( |
| 5003 GetInstanceFieldId(place->instance(), place->field())); | 5041 GetInstanceFieldId(place->instance(), place->field())); |
| 5004 case Place::kVMField: | 5042 case Place::kVMField: |
| 5005 return Alias::VMField(place->offset_in_bytes()); | 5043 return Alias::VMField(place->offset_in_bytes()); |
| 5006 case Place::kContext: | 5044 case Place::kContext: |
| 5007 return Alias::CurrentContext(); | 5045 return Alias::CurrentContext(); |
| 5008 case Place::kNone: | 5046 case Place::kNone: |
| 5009 UNREACHABLE(); | 5047 UNREACHABLE(); |
| 5010 } | 5048 } |
| 5011 | 5049 |
| 5012 UNREACHABLE(); | 5050 UNREACHABLE(); |
| 5013 return Alias::None(); | 5051 return Alias::None(); |
| 5014 } | 5052 } |
| 5015 | 5053 |
| 5016 Alias ComputeAliasForStore(Instruction* instr) { | 5054 Alias ComputeAliasForStore(Instruction* instr) { |
| 5017 if (instr->IsStoreIndexed()) { | 5055 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); |
| 5056 if (store_indexed != NULL) { | |
| 5057 if (store_indexed->index()->definition()->IsConstant()) { | |
| 5058 const Object& index = | |
| 5059 store_indexed->index()->definition()->AsConstant()->value(); | |
| 5060 if (index.IsSmi()) { | |
| 5061 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); | |
| 5062 } | |
| 5063 } | |
| 5018 return Alias::Indexes(); | 5064 return Alias::Indexes(); |
| 5019 } | 5065 } |
| 5020 | 5066 |
| 5021 StoreInstanceFieldInstr* store_instance_field = | 5067 StoreInstanceFieldInstr* store_instance_field = |
| 5022 instr->AsStoreInstanceField(); | 5068 instr->AsStoreInstanceField(); |
| 5023 if (store_instance_field != NULL) { | 5069 if (store_instance_field != NULL) { |
| 5024 Definition* instance = store_instance_field->instance()->definition(); | 5070 Definition* instance = store_instance_field->instance()->definition(); |
| 5025 return Alias::Field(GetInstanceFieldId(instance, | 5071 return Alias::Field(GetInstanceFieldId(instance, |
| 5026 store_instance_field->field())); | 5072 store_instance_field->field())); |
| 5027 } | 5073 } |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 5038 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 5084 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
| 5039 if (store_static_field != NULL) { | 5085 if (store_static_field != NULL) { |
| 5040 return Alias::Field(GetStaticFieldId(store_static_field->field())); | 5086 return Alias::Field(GetStaticFieldId(store_static_field->field())); |
| 5041 } | 5087 } |
| 5042 | 5088 |
| 5043 return Alias::None(); | 5089 return Alias::None(); |
| 5044 } | 5090 } |
| 5045 | 5091 |
| 5046 BitVector* Get(const Alias alias) { | 5092 BitVector* Get(const Alias alias) { |
| 5047 const intptr_t idx = alias.ToIndex(); | 5093 const intptr_t idx = alias.ToIndex(); |
| 5048 return (idx < sets_.length()) ? sets_[idx] : NULL; | 5094 BitVector* ret = (idx < sets_.length()) ? sets_[idx] : NULL; |
| 5095 return ret; | |
| 5049 } | 5096 } |
| 5050 | 5097 |
| 5051 void AddRepresentative(Place* place) { | 5098 void AddRepresentative(Place* place) { |
| 5052 if (!place->IsFinalField()) { | 5099 if (!place->IsFinalField()) { |
| 5053 AddIdForAlias(ComputeAlias(place), place->id()); | 5100 AddIdForAlias(ComputeAlias(place), place->id()); |
| 5054 if (!IsIndependentFromEffects(place)) { | 5101 if (!IsIndependentFromEffects(place)) { |
| 5055 aliased_by_effects_->Add(place->id()); | 5102 aliased_by_effects_->Add(place->id()); |
| 5056 } | 5103 } |
| 5057 } | 5104 } |
| 5058 } | 5105 } |
| 5059 | 5106 |
| 5107 void EnsureAliasingForIndexes() { | |
| 5108 BitVector* indexes = Get(Alias::Indexes()); | |
| 5109 if (indexes == NULL) { | |
| 5110 return; | |
| 5111 } | |
| 5112 | |
| 5113 // Constant indexes alias all non-constant indexes. Ids start at 1. | |
| 5114 for (intptr_t id = 1; id <= max_index_id_; id++) { | |
| 5115 BitVector* const_indexes = Get(Alias::ConstantIndex(id)); | |
| 5116 if (const_indexes != NULL) { | |
| 5117 const_indexes->AddAll(indexes); | |
| 5118 } | |
| 5119 } | |
| 5120 | |
| 5121 // Non-constant indexes alias all constant indexes. | |
|
Cutch
2014/01/24 23:07:15
Can these two loops not be merged?
Florian Schneider
2014/01/27 14:29:00
No, at first I thought they can, but Slava pointed
| |
| 5122 for (intptr_t id = 1; id <= max_index_id_; id++) { | |
| 5123 BitVector* const_indexes = Get(Alias::ConstantIndex(id)); | |
| 5124 if (const_indexes != NULL) { | |
| 5125 indexes->AddAll(const_indexes); | |
| 5126 } | |
| 5127 } | |
| 5128 } | |
| 5129 | |
| 5060 void AddIdForAlias(const Alias alias, intptr_t place_id) { | 5130 void AddIdForAlias(const Alias alias, intptr_t place_id) { |
| 5061 const intptr_t idx = alias.ToIndex(); | 5131 const intptr_t idx = alias.ToIndex(); |
| 5062 | |
| 5063 while (sets_.length() <= idx) { | 5132 while (sets_.length() <= idx) { |
| 5064 sets_.Add(NULL); | 5133 sets_.Add(NULL); |
| 5065 } | 5134 } |
| 5066 | 5135 |
| 5067 if (sets_[idx] == NULL) { | 5136 if (sets_[idx] == NULL) { |
| 5068 sets_[idx] = new BitVector(max_place_id()); | 5137 sets_[idx] = new BitVector(max_place_id()); |
| 5069 } | 5138 } |
| 5070 | 5139 |
| 5071 sets_[idx]->Add(place_id); | 5140 sets_[idx]->Add(place_id); |
| 5072 } | 5141 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5132 // for the first time. | 5201 // for the first time. |
| 5133 intptr_t GetFieldId(intptr_t instance_id, const Field& field) { | 5202 intptr_t GetFieldId(intptr_t instance_id, const Field& field) { |
| 5134 intptr_t id = field_ids_.Lookup(FieldIdPair::Key(instance_id, &field)); | 5203 intptr_t id = field_ids_.Lookup(FieldIdPair::Key(instance_id, &field)); |
| 5135 if (id == 0) { | 5204 if (id == 0) { |
| 5136 id = ++max_field_id_; | 5205 id = ++max_field_id_; |
| 5137 field_ids_.Insert(FieldIdPair(FieldIdPair::Key(instance_id, &field), id)); | 5206 field_ids_.Insert(FieldIdPair(FieldIdPair::Key(instance_id, &field), id)); |
| 5138 } | 5207 } |
| 5139 return id; | 5208 return id; |
| 5140 } | 5209 } |
| 5141 | 5210 |
| 5211 intptr_t GetIndexId(intptr_t index) { | |
| 5212 intptr_t id = index_ids_.Lookup(index); | |
| 5213 if (id == 0) { | |
| 5214 // Zero is used to indicate element not found. The first id is one. | |
| 5215 id = ++max_index_id_; | |
| 5216 index_ids_.Insert(IndexIdPair(index, id)); | |
| 5217 } | |
| 5218 return id; | |
| 5219 } | |
| 5220 | |
| 5142 enum { | 5221 enum { |
| 5143 kAnyInstance = -1 | 5222 kAnyInstance = -1 |
| 5144 }; | 5223 }; |
| 5145 | 5224 |
| 5146 // Get or create an identifier for an instance field belonging to the | 5225 // Get or create an identifier for an instance field belonging to the |
| 5147 // given instance. | 5226 // given instance. |
| 5148 // The space of identifiers assigned to instance fields is split into | 5227 // The space of identifiers assigned to instance fields is split into |
| 5149 // parts based on the instance that contains the field. | 5228 // parts based on the instance that contains the field. |
| 5150 // If compiler can prove that instance has a single SSA name in the compiled | 5229 // If compiler can prove that instance has a single SSA name in the compiled |
| 5151 // function then we use that SSA name to distinguish fields of this object | 5230 // function then we use that SSA name to distinguish fields of this object |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5234 static inline bool IsKeyEqual(Pair kv, Key key) { | 5313 static inline bool IsKeyEqual(Pair kv, Key key) { |
| 5235 return (KeyOf(kv).field_->raw() == key.field_->raw()) && | 5314 return (KeyOf(kv).field_->raw() == key.field_->raw()) && |
| 5236 (KeyOf(kv).instance_id_ == key.instance_id_); | 5315 (KeyOf(kv).instance_id_ == key.instance_id_); |
| 5237 } | 5316 } |
| 5238 | 5317 |
| 5239 private: | 5318 private: |
| 5240 Key key_; | 5319 Key key_; |
| 5241 Value value_; | 5320 Value value_; |
| 5242 }; | 5321 }; |
| 5243 | 5322 |
| 5323 class IndexIdPair { | |
| 5324 public: | |
| 5325 typedef intptr_t Key; | |
| 5326 typedef intptr_t Value; | |
| 5327 typedef IndexIdPair Pair; | |
|
Cutch
2014/01/24 23:07:15
Why not just pick one name for this class: Pair or
Florian Schneider
2014/01/27 14:29:00
Done. I can replace Pair below with IndexIdPair, b
| |
| 5328 | |
| 5329 IndexIdPair(Key key, Value value) : key_(key), value_(value) { } | |
| 5330 | |
| 5331 static Key KeyOf(Pair kv) { | |
| 5332 return kv.key_; | |
| 5333 } | |
| 5334 | |
| 5335 static Value ValueOf(Pair kv) { | |
| 5336 return kv.value_; | |
| 5337 } | |
| 5338 | |
| 5339 static intptr_t Hashcode(Key key) { | |
| 5340 return key; | |
| 5341 } | |
| 5342 | |
| 5343 static inline bool IsKeyEqual(Pair kv, Key key) { | |
| 5344 return KeyOf(kv) == key; | |
| 5345 } | |
| 5346 | |
| 5347 private: | |
| 5348 Key key_; | |
| 5349 Value value_; | |
| 5350 }; | |
| 5351 | |
| 5244 const ZoneGrowableArray<Place*>& places_; | 5352 const ZoneGrowableArray<Place*>& places_; |
| 5245 | 5353 |
| 5246 const PhiPlaceMoves* phi_moves_; | 5354 const PhiPlaceMoves* phi_moves_; |
| 5247 | 5355 |
| 5248 // Maps alias index to a set of ssa indexes corresponding to loads with the | 5356 // Maps alias index to a set of ssa indexes corresponding to loads with the |
| 5249 // given alias. | 5357 // given alias. |
| 5250 GrowableArray<BitVector*> sets_; | 5358 GrowableArray<BitVector*> sets_; |
| 5251 | 5359 |
| 5252 BitVector* aliased_by_effects_; | 5360 BitVector* aliased_by_effects_; |
| 5253 | 5361 |
| 5254 // Table mapping static field to their id used during optimization pass. | 5362 // Table mapping static field to their id used during optimization pass. |
| 5255 intptr_t max_field_id_; | 5363 intptr_t max_field_id_; |
| 5256 DirectChainedHashMap<FieldIdPair> field_ids_; | 5364 DirectChainedHashMap<FieldIdPair> field_ids_; |
| 5365 | |
| 5366 intptr_t max_index_id_; | |
| 5367 DirectChainedHashMap<IndexIdPair> index_ids_; | |
| 5257 }; | 5368 }; |
| 5258 | 5369 |
| 5259 | 5370 |
| 5260 static Definition* GetStoredValue(Instruction* instr) { | 5371 static Definition* GetStoredValue(Instruction* instr) { |
| 5261 if (instr->IsStoreIndexed()) { | 5372 if (instr->IsStoreIndexed()) { |
| 5262 return instr->AsStoreIndexed()->value()->definition(); | 5373 return instr->AsStoreIndexed()->value()->definition(); |
| 5263 } | 5374 } |
| 5264 | 5375 |
| 5265 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); | 5376 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); |
| 5266 if (store_instance_field != NULL) { | 5377 if (store_instance_field != NULL) { |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5387 | 5498 |
| 5388 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); | 5499 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); |
| 5389 | 5500 |
| 5390 // Build aliasing sets mapping aliases to loads. | 5501 // Build aliasing sets mapping aliases to loads. |
| 5391 AliasedSet* aliased_set = new AliasedSet(places, phi_moves); | 5502 AliasedSet* aliased_set = new AliasedSet(places, phi_moves); |
| 5392 for (intptr_t i = 0; i < places->length(); i++) { | 5503 for (intptr_t i = 0; i < places->length(); i++) { |
| 5393 Place* place = (*places)[i]; | 5504 Place* place = (*places)[i]; |
| 5394 aliased_set->AddRepresentative(place); | 5505 aliased_set->AddRepresentative(place); |
| 5395 } | 5506 } |
| 5396 | 5507 |
| 5508 aliased_set->EnsureAliasingForIndexes(); | |
| 5509 | |
| 5397 return aliased_set; | 5510 return aliased_set; |
| 5398 } | 5511 } |
| 5399 | 5512 |
| 5400 | 5513 |
| 5401 static bool HasSimpleTypeArguments(AllocateObjectInstr* alloc) { | 5514 static bool HasSimpleTypeArguments(AllocateObjectInstr* alloc) { |
| 5402 if (alloc->ArgumentCount() == 0) return true; | 5515 if (alloc->ArgumentCount() == 0) return true; |
| 5403 ASSERT(alloc->ArgumentCount() == 2); | 5516 ASSERT(alloc->ArgumentCount() == 2); |
| 5404 Value* arg1 = alloc->PushArgumentAt(1)->value(); | 5517 Value* arg1 = alloc->PushArgumentAt(1)->value(); |
| 5405 if (!arg1->BindsToConstant()) return false; | 5518 if (!arg1->BindsToConstant()) return false; |
| 5406 | 5519 |
| (...skipping 2921 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8328 } | 8441 } |
| 8329 | 8442 |
| 8330 // Insert materializations at environment uses. | 8443 // Insert materializations at environment uses. |
| 8331 for (intptr_t i = 0; i < exits.length(); i++) { | 8444 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8332 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8445 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8333 } | 8446 } |
| 8334 } | 8447 } |
| 8335 | 8448 |
| 8336 | 8449 |
| 8337 } // namespace dart | 8450 } // namespace dart |
| OLD | NEW |