| 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 4871 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4882 // AliasedSet assigns ids to a combination of instance and field during | 4882 // AliasedSet assigns ids to a combination of instance and field during |
| 4883 // the optimization phase. | 4883 // the optimization phase. |
| 4884 static Alias Field(intptr_t id) { | 4884 static Alias Field(intptr_t id) { |
| 4885 ASSERT(id != 0); | 4885 ASSERT(id != 0); |
| 4886 return Alias(kFieldAlias, id); | 4886 return Alias(kFieldAlias, id); |
| 4887 } | 4887 } |
| 4888 | 4888 |
| 4889 // VMField load/stores alias each other when field offset matches. | 4889 // VMField load/stores alias each other when field offset matches. |
| 4890 // TODO(vegorov) storing a context variable does not alias loading array | 4890 // TODO(vegorov) storing a context variable does not alias loading array |
| 4891 // length. | 4891 // length. |
| 4892 static Alias VMField(intptr_t offset_in_bytes) { | 4892 static Alias VMField(intptr_t id) { |
| 4893 ASSERT(offset_in_bytes >= 0); | 4893 ASSERT(id != 0); |
| 4894 const intptr_t idx = offset_in_bytes / kWordSize; | 4894 return Alias(kVMFieldAlias, id); |
| 4895 return Alias(kVMFieldAlias, idx); | |
| 4896 } | 4895 } |
| 4897 | 4896 |
| 4898 // Current context load/stores alias each other. | 4897 // Current context load/stores alias each other. |
| 4899 static Alias CurrentContext() { | 4898 static Alias CurrentContext() { |
| 4900 return Alias(kCurrentContextAlias, 0); | 4899 return Alias(kCurrentContextAlias, 0); |
| 4901 } | 4900 } |
| 4902 | 4901 |
| 4903 // Operation does not alias anything. | 4902 // Operation does not alias anything. |
| 4904 static Alias None() { | 4903 static Alias None() { |
| 4905 return Alias(kNoneAlias); | 4904 return Alias(kNoneAlias); |
| (...skipping 351 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5257 public: | 5256 public: |
| 5258 explicit AliasedSet(ZoneGrowableArray<Place*>* places, | 5257 explicit AliasedSet(ZoneGrowableArray<Place*>* places, |
| 5259 PhiPlaceMoves* phi_moves) | 5258 PhiPlaceMoves* phi_moves) |
| 5260 : places_(*places), | 5259 : places_(*places), |
| 5261 phi_moves_(phi_moves), | 5260 phi_moves_(phi_moves), |
| 5262 sets_(), | 5261 sets_(), |
| 5263 aliased_by_effects_(new BitVector(places->length())), | 5262 aliased_by_effects_(new BitVector(places->length())), |
| 5264 max_field_id_(0), | 5263 max_field_id_(0), |
| 5265 field_ids_(), | 5264 field_ids_(), |
| 5266 max_index_id_(0), | 5265 max_index_id_(0), |
| 5267 index_ids_() { } | 5266 index_ids_(), |
| 5267 max_vm_field_id_(0), |
| 5268 vm_field_ids_() { } |
| 5268 | 5269 |
| 5269 Alias ComputeAlias(Place* place) { | 5270 Alias ComputeAlias(Place* place) { |
| 5270 switch (place->kind()) { | 5271 switch (place->kind()) { |
| 5271 case Place::kIndexed: | 5272 case Place::kIndexed: |
| 5272 if (place->index()->IsConstant()) { | 5273 if (place->index()->IsConstant()) { |
| 5273 const Object& index = place->index()->AsConstant()->value(); | 5274 const Object& index = place->index()->AsConstant()->value(); |
| 5274 if (index.IsSmi()) { | 5275 if (index.IsSmi()) { |
| 5275 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); | 5276 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); |
| 5276 } | 5277 } |
| 5277 } | 5278 } |
| 5278 return Alias::Indexes(); | 5279 return Alias::Indexes(); |
| 5279 case Place::kField: | 5280 case Place::kField: |
| 5280 return Alias::Field( | 5281 return Alias::Field( |
| 5281 GetInstanceFieldId(place->instance(), place->field())); | 5282 GetInstanceFieldId(place->instance(), place->field())); |
| 5282 case Place::kVMField: | 5283 case Place::kVMField: |
| 5283 return Alias::VMField(place->offset_in_bytes()); | 5284 return Alias::VMField( |
| 5285 GetVMFieldId(place->instance(), place->offset_in_bytes())); |
| 5284 case Place::kContext: | 5286 case Place::kContext: |
| 5285 return Alias::CurrentContext(); | 5287 return Alias::CurrentContext(); |
| 5286 case Place::kNone: | 5288 case Place::kNone: |
| 5287 UNREACHABLE(); | 5289 UNREACHABLE(); |
| 5288 } | 5290 } |
| 5289 | 5291 |
| 5290 UNREACHABLE(); | 5292 UNREACHABLE(); |
| 5291 return Alias::None(); | 5293 return Alias::None(); |
| 5292 } | 5294 } |
| 5293 | 5295 |
| 5294 Alias ComputeAliasForStore(Instruction* instr) { | 5296 Alias ComputeAliasForStore(Instruction* instr) { |
| 5295 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); | 5297 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); |
| 5296 if (store_indexed != NULL) { | 5298 if (store_indexed != NULL) { |
| 5297 if (store_indexed->index()->definition()->IsConstant()) { | 5299 if (store_indexed->index()->definition()->IsConstant()) { |
| 5298 const Object& index = | 5300 const Object& index = |
| 5299 store_indexed->index()->definition()->AsConstant()->value(); | 5301 store_indexed->index()->definition()->AsConstant()->value(); |
| 5300 if (index.IsSmi()) { | 5302 if (index.IsSmi()) { |
| 5301 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); | 5303 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); |
| 5302 } | 5304 } |
| 5303 } | 5305 } |
| 5304 return Alias::Indexes(); | 5306 return Alias::Indexes(); |
| 5305 } | 5307 } |
| 5306 | 5308 |
| 5307 StoreInstanceFieldInstr* store_instance_field = | 5309 StoreInstanceFieldInstr* store_instance_field = |
| 5308 instr->AsStoreInstanceField(); | 5310 instr->AsStoreInstanceField(); |
| 5309 if (store_instance_field != NULL) { | 5311 if (store_instance_field != NULL) { |
| 5310 Definition* instance = store_instance_field->instance()->definition(); | 5312 Definition* instance = store_instance_field->instance()->definition(); |
| 5311 if (!store_instance_field->field().IsNull()) { | 5313 if (!store_instance_field->field().IsNull()) { |
| 5312 return Alias::Field(GetInstanceFieldId(instance, | 5314 return Alias::Field( |
| 5313 store_instance_field->field())); | 5315 GetInstanceFieldId(instance, store_instance_field->field())); |
| 5314 } | 5316 } |
| 5315 return Alias::VMField(store_instance_field->offset_in_bytes()); | 5317 return Alias::VMField( |
| 5318 GetVMFieldId(instance, store_instance_field->offset_in_bytes())); |
| 5316 } | 5319 } |
| 5317 | 5320 |
| 5318 if (instr->IsStoreContext()) { | 5321 if (instr->IsStoreContext()) { |
| 5319 return Alias::CurrentContext(); | 5322 return Alias::CurrentContext(); |
| 5320 } | 5323 } |
| 5321 | 5324 |
| 5322 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); | 5325 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); |
| 5323 if (store_static_field != NULL) { | 5326 if (store_static_field != NULL) { |
| 5324 return Alias::Field(GetStaticFieldId(store_static_field->field())); | 5327 return Alias::Field(GetStaticFieldId(store_static_field->field())); |
| 5325 } | 5328 } |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5480 AllocateObjectInstr* alloc = defn->AsAllocateObject(); | 5483 AllocateObjectInstr* alloc = defn->AsAllocateObject(); |
| 5481 if ((alloc != NULL) && !CanBeAliased(alloc)) { | 5484 if ((alloc != NULL) && !CanBeAliased(alloc)) { |
| 5482 instance_id = alloc->ssa_temp_index(); | 5485 instance_id = alloc->ssa_temp_index(); |
| 5483 ASSERT(instance_id != kAnyInstance); | 5486 ASSERT(instance_id != kAnyInstance); |
| 5484 } | 5487 } |
| 5485 } | 5488 } |
| 5486 | 5489 |
| 5487 return GetFieldId(instance_id, field); | 5490 return GetFieldId(instance_id, field); |
| 5488 } | 5491 } |
| 5489 | 5492 |
| 5493 intptr_t GetVMFieldId(Definition* defn, intptr_t offset) { |
| 5494 intptr_t instance_id = kAnyInstance; |
| 5495 |
| 5496 if (defn != NULL) { |
| 5497 AllocateObjectInstr* alloc = defn->AsAllocateObject(); |
| 5498 if ((alloc != NULL) && !CanBeAliased(alloc)) { |
| 5499 instance_id = alloc->ssa_temp_index(); |
| 5500 ASSERT(instance_id != kAnyInstance); |
| 5501 } |
| 5502 } |
| 5503 |
| 5504 intptr_t id = vm_field_ids_.Lookup(VMFieldIdPair::Key(instance_id, offset)); |
| 5505 if (id == 0) { |
| 5506 id = ++max_vm_field_id_; |
| 5507 vm_field_ids_.Insert( |
| 5508 VMFieldIdPair(VMFieldIdPair::Key(instance_id, offset), id)); |
| 5509 } |
| 5510 return id; |
| 5511 } |
| 5512 |
| 5490 // Get or create an identifier for a static field. | 5513 // Get or create an identifier for a static field. |
| 5491 intptr_t GetStaticFieldId(const Field& field) { | 5514 intptr_t GetStaticFieldId(const Field& field) { |
| 5492 ASSERT(field.is_static()); | 5515 ASSERT(field.is_static()); |
| 5493 return GetFieldId(kAnyInstance, field); | 5516 return GetFieldId(kAnyInstance, field); |
| 5494 } | 5517 } |
| 5495 | 5518 |
| 5496 // Returns true if the given load is unaffected by external side-effects. | 5519 // Returns true if the given load is unaffected by external side-effects. |
| 5497 // This essentially means that no stores to the same location can | 5520 // This essentially means that no stores to the same location can |
| 5498 // occur in other functions. | 5521 // occur in other functions. |
| 5499 bool IsIndependentFromEffects(Place* place) { | 5522 bool IsIndependentFromEffects(Place* place) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5582 | 5605 |
| 5583 static inline bool IsKeyEqual(IndexIdPair kv, Key key) { | 5606 static inline bool IsKeyEqual(IndexIdPair kv, Key key) { |
| 5584 return KeyOf(kv) == key; | 5607 return KeyOf(kv) == key; |
| 5585 } | 5608 } |
| 5586 | 5609 |
| 5587 private: | 5610 private: |
| 5588 Key key_; | 5611 Key key_; |
| 5589 Value value_; | 5612 Value value_; |
| 5590 }; | 5613 }; |
| 5591 | 5614 |
| 5615 class VMFieldIdPair { |
| 5616 public: |
| 5617 struct Key { |
| 5618 Key(intptr_t instance_id, intptr_t offset) |
| 5619 : instance_id_(instance_id), offset_(offset) { } |
| 5620 |
| 5621 intptr_t instance_id_; |
| 5622 intptr_t offset_; |
| 5623 }; |
| 5624 |
| 5625 typedef intptr_t Value; |
| 5626 typedef VMFieldIdPair Pair; |
| 5627 |
| 5628 VMFieldIdPair(Key key, Value value) : key_(key), value_(value) { } |
| 5629 |
| 5630 static Key KeyOf(Pair kv) { |
| 5631 return kv.key_; |
| 5632 } |
| 5633 |
| 5634 static Value ValueOf(Pair kv) { |
| 5635 return kv.value_; |
| 5636 } |
| 5637 |
| 5638 static intptr_t Hashcode(Key key) { |
| 5639 return (key.instance_id_ + 1) * 1024 + key.offset_; |
| 5640 } |
| 5641 |
| 5642 static inline bool IsKeyEqual(Pair kv, Key key) { |
| 5643 return (KeyOf(kv).offset_ == key.offset_) && |
| 5644 (KeyOf(kv).instance_id_ == key.instance_id_); |
| 5645 } |
| 5646 |
| 5647 private: |
| 5648 Key key_; |
| 5649 Value value_; |
| 5650 }; |
| 5651 |
| 5592 const ZoneGrowableArray<Place*>& places_; | 5652 const ZoneGrowableArray<Place*>& places_; |
| 5593 | 5653 |
| 5594 const PhiPlaceMoves* phi_moves_; | 5654 const PhiPlaceMoves* phi_moves_; |
| 5595 | 5655 |
| 5596 // Maps alias index to a set of ssa indexes corresponding to loads with the | 5656 // Maps alias index to a set of ssa indexes corresponding to loads with the |
| 5597 // given alias. | 5657 // given alias. |
| 5598 GrowableArray<BitVector*> sets_; | 5658 GrowableArray<BitVector*> sets_; |
| 5599 | 5659 |
| 5600 BitVector* aliased_by_effects_; | 5660 BitVector* aliased_by_effects_; |
| 5601 | 5661 |
| 5602 // Table mapping static field to their id used during optimization pass. | 5662 // Table mapping static field to their id used during optimization pass. |
| 5603 intptr_t max_field_id_; | 5663 intptr_t max_field_id_; |
| 5604 DirectChainedHashMap<FieldIdPair> field_ids_; | 5664 DirectChainedHashMap<FieldIdPair> field_ids_; |
| 5605 | 5665 |
| 5606 intptr_t max_index_id_; | 5666 intptr_t max_index_id_; |
| 5607 DirectChainedHashMap<IndexIdPair> index_ids_; | 5667 DirectChainedHashMap<IndexIdPair> index_ids_; |
| 5668 |
| 5669 intptr_t max_vm_field_id_; |
| 5670 DirectChainedHashMap<VMFieldIdPair> vm_field_ids_; |
| 5608 }; | 5671 }; |
| 5609 | 5672 |
| 5610 | 5673 |
| 5611 static Definition* GetStoredValue(Instruction* instr) { | 5674 static Definition* GetStoredValue(Instruction* instr) { |
| 5612 if (instr->IsStoreIndexed()) { | 5675 if (instr->IsStoreIndexed()) { |
| 5613 return instr->AsStoreIndexed()->value()->definition(); | 5676 return instr->AsStoreIndexed()->value()->definition(); |
| 5614 } | 5677 } |
| 5615 | 5678 |
| 5616 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); | 5679 StoreInstanceFieldInstr* store_instance_field = instr->AsStoreInstanceField(); |
| 5617 if (store_instance_field != NULL) { | 5680 if (store_instance_field != NULL) { |
| (...skipping 2931 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8549 // Remove materializations from the graph. Register allocator will treat them | 8612 // Remove materializations from the graph. Register allocator will treat them |
| 8550 // as part of the environment not as a real instruction. | 8613 // as part of the environment not as a real instruction. |
| 8551 void AllocationSinking::DetachMaterializations() { | 8614 void AllocationSinking::DetachMaterializations() { |
| 8552 for (intptr_t i = 0; i < materializations_.length(); i++) { | 8615 for (intptr_t i = 0; i < materializations_.length(); i++) { |
| 8553 ASSERT(materializations_[i]->input_use_list() == NULL); | 8616 ASSERT(materializations_[i]->input_use_list() == NULL); |
| 8554 materializations_[i]->previous()->LinkTo(materializations_[i]->next()); | 8617 materializations_[i]->previous()->LinkTo(materializations_[i]->next()); |
| 8555 } | 8618 } |
| 8556 } | 8619 } |
| 8557 | 8620 |
| 8558 | 8621 |
| 8559 // Add the given field to the list of fields if it is not yet present there. | 8622 // Add a field/offset to the list of fields if it is not yet present there. |
| 8560 static void AddField(ZoneGrowableArray<const Field*>* fields, | 8623 static void AddField(ZoneGrowableArray<const Object*>* fields, |
| 8561 const Field& field) { | 8624 const Object& field) { |
| 8562 for (intptr_t i = 0; i < fields->length(); i++) { | 8625 for (intptr_t i = 0; i < fields->length(); i++) { |
| 8563 if ((*fields)[i]->raw() == field.raw()) { | 8626 if ((*fields)[i]->raw() == field.raw()) { |
| 8564 return; | 8627 return; |
| 8565 } | 8628 } |
| 8566 } | 8629 } |
| 8567 fields->Add(&field); | 8630 fields->Add(&field); |
| 8568 } | 8631 } |
| 8569 | 8632 |
| 8570 | 8633 |
| 8571 // Add given instruction to the list of the instructions if it is not yet | 8634 // Add given instruction to the list of the instructions if it is not yet |
| 8572 // present there. | 8635 // present there. |
| 8573 static void AddInstruction(GrowableArray<Instruction*>* exits, | 8636 static void AddInstruction(GrowableArray<Instruction*>* exits, |
| 8574 Instruction* exit) { | 8637 Instruction* exit) { |
| 8575 ASSERT(!exit->IsGraphEntry()); | 8638 ASSERT(!exit->IsGraphEntry()); |
| 8576 for (intptr_t i = 0; i < exits->length(); i++) { | 8639 for (intptr_t i = 0; i < exits->length(); i++) { |
| 8577 if ((*exits)[i] == exit) { | 8640 if ((*exits)[i] == exit) { |
| 8578 return; | 8641 return; |
| 8579 } | 8642 } |
| 8580 } | 8643 } |
| 8581 exits->Add(exit); | 8644 exits->Add(exit); |
| 8582 } | 8645 } |
| 8583 | 8646 |
| 8584 | 8647 |
| 8585 // Insert MaterializeObject instruction for the given allocation before | 8648 // Insert MaterializeObject instruction for the given allocation before |
| 8586 // the given instruction that can deoptimize. | 8649 // the given instruction that can deoptimize. |
| 8587 void AllocationSinking::CreateMaterializationAt( | 8650 void AllocationSinking::CreateMaterializationAt( |
| 8588 Instruction* exit, | 8651 Instruction* exit, |
| 8589 AllocateObjectInstr* alloc, | 8652 AllocateObjectInstr* alloc, |
| 8590 const Class& cls, | 8653 const Class& cls, |
| 8591 const ZoneGrowableArray<const Field*>& fields) { | 8654 const ZoneGrowableArray<const Object*>& fields) { |
| 8592 ZoneGrowableArray<Value*>* values = | 8655 ZoneGrowableArray<Value*>* values = |
| 8593 new ZoneGrowableArray<Value*>(fields.length()); | 8656 new ZoneGrowableArray<Value*>(fields.length()); |
| 8594 | 8657 |
| 8595 // Insert load instruction for every field. | 8658 // Insert load instruction for every field. |
| 8596 for (intptr_t i = 0; i < fields.length(); i++) { | 8659 for (intptr_t i = 0; i < fields.length(); i++) { |
| 8597 const Field* field = fields[i]; | 8660 LoadFieldInstr* load = fields[i]->IsField() |
| 8598 LoadFieldInstr* load = new LoadFieldInstr(new Value(alloc), | 8661 ? new LoadFieldInstr(new Value(alloc), |
| 8599 field, | 8662 &Field::Cast(*fields[i]), |
| 8600 AbstractType::ZoneHandle()); | 8663 AbstractType::ZoneHandle()) |
| 8664 : new LoadFieldInstr(new Value(alloc), |
| 8665 Smi::Cast(*fields[i]).Value(), |
| 8666 AbstractType::ZoneHandle()); |
| 8601 flow_graph_->InsertBefore( | 8667 flow_graph_->InsertBefore( |
| 8602 exit, load, NULL, Definition::kValue); | 8668 exit, load, NULL, Definition::kValue); |
| 8603 values->Add(new Value(load)); | 8669 values->Add(new Value(load)); |
| 8604 } | 8670 } |
| 8605 | 8671 |
| 8606 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, fields, values); | 8672 MaterializeObjectInstr* mat = new MaterializeObjectInstr(cls, fields, values); |
| 8607 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); | 8673 flow_graph_->InsertBefore(exit, mat, NULL, Definition::kValue); |
| 8608 | 8674 |
| 8609 // Replace all mentions of this allocation with a newly inserted | 8675 // Replace all mentions of this allocation with a newly inserted |
| 8610 // MaterializeObject instruction. | 8676 // MaterializeObject instruction. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 8621 } | 8687 } |
| 8622 } | 8688 } |
| 8623 | 8689 |
| 8624 // Record inserted materialization. | 8690 // Record inserted materialization. |
| 8625 materializations_.Add(mat); | 8691 materializations_.Add(mat); |
| 8626 } | 8692 } |
| 8627 | 8693 |
| 8628 | 8694 |
| 8629 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { | 8695 void AllocationSinking::InsertMaterializations(AllocateObjectInstr* alloc) { |
| 8630 // Collect all fields that are written for this instance. | 8696 // Collect all fields that are written for this instance. |
| 8631 ZoneGrowableArray<const Field*>* fields = | 8697 ZoneGrowableArray<const Object*>* fields = |
| 8632 new ZoneGrowableArray<const Field*>(5); | 8698 new ZoneGrowableArray<const Object*>(5); |
| 8633 | 8699 |
| 8634 for (Value* use = alloc->input_use_list(); | 8700 for (Value* use = alloc->input_use_list(); |
| 8635 use != NULL; | 8701 use != NULL; |
| 8636 use = use->next_use()) { | 8702 use = use->next_use()) { |
| 8637 ASSERT(use->instruction()->IsStoreInstanceField()); | 8703 StoreInstanceFieldInstr* store = use->instruction()->AsStoreInstanceField(); |
| 8638 AddField(fields, use->instruction()->AsStoreInstanceField()->field()); | 8704 if (!store->field().IsNull()) { |
| 8705 AddField(fields, store->field()); |
| 8706 } else { |
| 8707 AddField(fields, Smi::ZoneHandle(Smi::New(store->offset_in_bytes()))); |
| 8708 } |
| 8639 } | 8709 } |
| 8640 | 8710 |
| 8641 if (alloc->ArgumentCount() > 0) { | 8711 if (alloc->ArgumentCount() > 0) { |
| 8642 ASSERT(alloc->ArgumentCount() == 1); | 8712 ASSERT(alloc->ArgumentCount() == 1); |
| 8643 const String& name = String::Handle(Symbols::New(":type_args")); | 8713 intptr_t type_args_offset = alloc->cls().type_arguments_field_offset(); |
| 8644 const Field& type_args_field = | 8714 AddField(fields, Smi::ZoneHandle(Smi::New(type_args_offset))); |
| 8645 Field::ZoneHandle(Field::New( | |
| 8646 name, | |
| 8647 false, // !static | |
| 8648 false, // !final | |
| 8649 false, // !const | |
| 8650 alloc->cls(), | |
| 8651 0)); // No token position. | |
| 8652 type_args_field.SetOffset(alloc->cls().type_arguments_field_offset()); | |
| 8653 AddField(fields, type_args_field); | |
| 8654 } | 8715 } |
| 8655 | 8716 |
| 8656 // Collect all instructions that mention this object in the environment. | 8717 // Collect all instructions that mention this object in the environment. |
| 8657 GrowableArray<Instruction*> exits(10); | 8718 GrowableArray<Instruction*> exits(10); |
| 8658 for (Value* use = alloc->env_use_list(); | 8719 for (Value* use = alloc->env_use_list(); |
| 8659 use != NULL; | 8720 use != NULL; |
| 8660 use = use->next_use()) { | 8721 use = use->next_use()) { |
| 8661 AddInstruction(&exits, use->instruction()); | 8722 AddInstruction(&exits, use->instruction()); |
| 8662 } | 8723 } |
| 8663 | 8724 |
| 8664 // Insert materializations at environment uses. | 8725 // Insert materializations at environment uses. |
| 8665 for (intptr_t i = 0; i < exits.length(); i++) { | 8726 for (intptr_t i = 0; i < exits.length(); i++) { |
| 8666 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); | 8727 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields); |
| 8667 } | 8728 } |
| 8668 } | 8729 } |
| 8669 | 8730 |
| 8670 | 8731 |
| 8671 } // namespace dart | 8732 } // namespace dart |
| OLD | NEW |