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

Side by Side Diff: runtime/vm/flow_graph_optimizer.cc

Issue 189513003: Add alias disambiguation for VM fields. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 9 months 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698