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

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

Issue 189543013: Add alias identity information to array allocations. (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
« no previous file with comments | « no previous file | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 4978 matching lines...) Expand 10 before | Expand all | Expand 10 after
4989 // Alias represents a family of locations. It is used to capture aliasing 4989 // Alias represents a family of locations. It is used to capture aliasing
4990 // between stores and loads. Store can alias another load or store if and only 4990 // between stores and loads. Store can alias another load or store if and only
4991 // if they have the same alias. 4991 // if they have the same alias.
4992 class Alias : public ValueObject { 4992 class Alias : public ValueObject {
4993 public: 4993 public:
4994 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { } 4994 Alias(const Alias& other) : ValueObject(), alias_(other.alias_) { }
4995 4995
4996 // All indexed load/stores alias each other. 4996 // All indexed load/stores alias each other.
4997 // TODO(vegorov): incorporate type of array into alias to disambiguate 4997 // TODO(vegorov): incorporate type of array into alias to disambiguate
4998 // different typed data and normal arrays. 4998 // different typed data and normal arrays.
4999 static Alias Indexes() { 4999 static Alias UnknownIndex(intptr_t id) {
5000 return Alias(kIndexesAlias, 0); 5000 return Alias(kUnknownIndexAlias, id);
5001 } 5001 }
5002 5002
5003 static Alias ConstantIndex(intptr_t id) { 5003 static Alias ConstantIndex(intptr_t id) {
5004 ASSERT(id != 0); 5004 ASSERT(id != 0);
5005 return Alias(kConstantIndex, id); 5005 return Alias(kConstantIndex, id);
5006 } 5006 }
5007 5007
5008 // Field load/stores alias each other only when they access the same field. 5008 // Field load/stores alias each other only when they access the same field.
5009 // AliasedSet assigns ids to a combination of instance and field during 5009 // AliasedSet assigns ids to a combination of instance and field during
5010 // the optimization phase. 5010 // the optimization phase.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
5046 // Number of bits required to encode Kind value. 5046 // Number of bits required to encode Kind value.
5047 // The payload occupies the rest of the bits, but leaves the MSB (sign bit) 5047 // The payload occupies the rest of the bits, but leaves the MSB (sign bit)
5048 // empty so that the resulting encoded value is always a positive integer. 5048 // empty so that the resulting encoded value is always a positive integer.
5049 kBitsForKind = 3, 5049 kBitsForKind = 3,
5050 kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind - 1, 5050 kBitsForPayload = kWordSize * kBitsPerByte - kBitsForKind - 1,
5051 }; 5051 };
5052 5052
5053 enum Kind { 5053 enum Kind {
5054 kNoneAlias = -1, 5054 kNoneAlias = -1,
5055 kCurrentContextAlias = 0, 5055 kCurrentContextAlias = 0,
5056 kIndexesAlias = 1, 5056 kUnknownIndexAlias = 1,
5057 kFieldAlias = 2, 5057 kFieldAlias = 2,
5058 kVMFieldAlias = 3, 5058 kVMFieldAlias = 3,
5059 kConstantIndex = 4, 5059 kConstantIndex = 4,
5060 kNumKinds = kConstantIndex + 1 5060 kNumKinds = kConstantIndex + 1
5061 }; 5061 };
5062 COMPILE_ASSERT(kNumKinds < ((1 << kBitsForKind) - 1), InvalidBitFieldSize); 5062 COMPILE_ASSERT(kNumKinds < ((1 << kBitsForKind) - 1), InvalidBitFieldSize);
5063 5063
5064 explicit Alias(intptr_t alias) : alias_(alias) { } 5064 explicit Alias(intptr_t alias) : alias_(alias) { }
5065 5065
5066 Alias(Kind kind, uword payload) 5066 Alias(Kind kind, uword payload)
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
5384 explicit AliasedSet(ZoneGrowableArray<Place*>* places, 5384 explicit AliasedSet(ZoneGrowableArray<Place*>* places,
5385 PhiPlaceMoves* phi_moves) 5385 PhiPlaceMoves* phi_moves)
5386 : places_(*places), 5386 : places_(*places),
5387 phi_moves_(phi_moves), 5387 phi_moves_(phi_moves),
5388 sets_(), 5388 sets_(),
5389 aliased_by_effects_(new BitVector(places->length())), 5389 aliased_by_effects_(new BitVector(places->length())),
5390 max_field_id_(0), 5390 max_field_id_(0),
5391 field_ids_(), 5391 field_ids_(),
5392 max_index_id_(0), 5392 max_index_id_(0),
5393 index_ids_(), 5393 index_ids_(),
5394 max_unknown_index_id_(0),
5395 unknown_index_ids_(),
5394 max_vm_field_id_(0), 5396 max_vm_field_id_(0),
5395 vm_field_ids_() { } 5397 vm_field_ids_() { }
5396 5398
5397 Alias ComputeAlias(Place* place) { 5399 Alias ComputeAlias(Place* place) {
5398 switch (place->kind()) { 5400 switch (place->kind()) {
5399 case Place::kIndexed: 5401 case Place::kIndexed:
5400 if (place->index()->IsConstant()) { 5402 if (place->index()->IsConstant()) {
5401 const Object& index = place->index()->AsConstant()->value(); 5403 const Object& index = place->index()->AsConstant()->value();
5402 if (index.IsSmi()) { 5404 if (index.IsSmi()) {
5403 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); 5405 return Alias::ConstantIndex(
5406 GetInstanceIndexId(place->instance(),
5407 Smi::Cast(index).Value()));
5404 } 5408 }
5405 } 5409 }
5406 return Alias::Indexes(); 5410 return Alias::UnknownIndex(GetUnknownIndexId(place->instance()));
5407 case Place::kField: 5411 case Place::kField:
5408 return Alias::Field( 5412 return Alias::Field(
5409 GetInstanceFieldId(place->instance(), place->field())); 5413 GetInstanceFieldId(place->instance(), place->field()));
5410 case Place::kVMField: 5414 case Place::kVMField:
5411 return Alias::VMField( 5415 return Alias::VMField(
5412 GetVMFieldId(place->instance(), place->offset_in_bytes())); 5416 GetInstanceVMFieldId(place->instance(), place->offset_in_bytes()));
5413 case Place::kContext: 5417 case Place::kContext:
5414 return Alias::CurrentContext(); 5418 return Alias::CurrentContext();
5415 case Place::kNone: 5419 case Place::kNone:
5416 UNREACHABLE(); 5420 UNREACHABLE();
5417 } 5421 }
5418 5422
5419 UNREACHABLE(); 5423 UNREACHABLE();
5420 return Alias::None(); 5424 return Alias::None();
5421 } 5425 }
5422 5426
5423 Alias ComputeAliasForStore(Instruction* instr) { 5427 Alias ComputeAliasForStore(Instruction* instr) {
5424 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed(); 5428 StoreIndexedInstr* store_indexed = instr->AsStoreIndexed();
5425 if (store_indexed != NULL) { 5429 if (store_indexed != NULL) {
5430 Definition* instance = store_indexed->array()->definition();
5426 if (store_indexed->index()->definition()->IsConstant()) { 5431 if (store_indexed->index()->definition()->IsConstant()) {
5427 const Object& index = 5432 const Object& index =
5428 store_indexed->index()->definition()->AsConstant()->value(); 5433 store_indexed->index()->definition()->AsConstant()->value();
5429 if (index.IsSmi()) { 5434 if (index.IsSmi()) {
5430 return Alias::ConstantIndex(GetIndexId(Smi::Cast(index).Value())); 5435 return Alias::ConstantIndex(
5436 GetInstanceIndexId(instance, Smi::Cast(index).Value()));
5431 } 5437 }
5432 } 5438 }
5433 return Alias::Indexes(); 5439 return Alias::UnknownIndex(GetUnknownIndexId(instance));
5434 } 5440 }
5435 5441
5436 StoreInstanceFieldInstr* store_instance_field = 5442 StoreInstanceFieldInstr* store_instance_field =
5437 instr->AsStoreInstanceField(); 5443 instr->AsStoreInstanceField();
5438 if (store_instance_field != NULL) { 5444 if (store_instance_field != NULL) {
5439 Definition* instance = store_instance_field->instance()->definition(); 5445 Definition* instance = store_instance_field->instance()->definition();
5440 if (!store_instance_field->field().IsNull()) { 5446 if (!store_instance_field->field().IsNull()) {
5441 return Alias::Field( 5447 return Alias::Field(
5442 GetInstanceFieldId(instance, store_instance_field->field())); 5448 GetInstanceFieldId(instance, store_instance_field->field()));
5443 } 5449 }
5444 return Alias::VMField( 5450 return Alias::VMField(
5445 GetVMFieldId(instance, store_instance_field->offset_in_bytes())); 5451 GetInstanceVMFieldId(instance,
5452 store_instance_field->offset_in_bytes()));
5446 } 5453 }
5447 5454
5448 if (instr->IsStoreContext()) { 5455 if (instr->IsStoreContext()) {
5449 return Alias::CurrentContext(); 5456 return Alias::CurrentContext();
5450 } 5457 }
5451 5458
5452 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField(); 5459 StoreStaticFieldInstr* store_static_field = instr->AsStoreStaticField();
5453 if (store_static_field != NULL) { 5460 if (store_static_field != NULL) {
5454 return Alias::Field(GetStaticFieldId(store_static_field->field())); 5461 return Alias::Field(GetStaticFieldId(store_static_field->field()));
5455 } 5462 }
5456 5463
5457 return Alias::None(); 5464 return Alias::None();
5458 } 5465 }
5459 5466
5460 BitVector* Get(const Alias alias) { 5467 BitVector* Get(const Alias alias) {
5461 const intptr_t idx = alias.ToIndex(); 5468 const intptr_t idx = alias.ToIndex();
5462 BitVector* ret = (idx < sets_.length()) ? sets_[idx] : NULL; 5469 BitVector* ret = (idx < sets_.length()) ? sets_[idx] : NULL;
5463 return ret; 5470 return ret;
5464 } 5471 }
5465 5472
5466 void AddRepresentative(Place* place) { 5473 void AddRepresentative(Place* place) {
5467 if (!place->IsFinalField()) { 5474 if (!place->IsFinalField()) {
5468 AddIdForAlias(ComputeAlias(place), place->id()); 5475 AddIdForAlias(ComputeAlias(place), place->id());
5469 if (!IsIndependentFromEffects(place)) { 5476 if (!IsIndependentFromEffects(place)) {
5470 aliased_by_effects_->Add(place->id()); 5477 aliased_by_effects_->Add(place->id());
5471 } 5478 }
5472 } 5479 }
5473 } 5480 }
5474 5481
5475 void EnsureAliasingForIndexes() { 5482 void EnsureAliasingForUnknownIndices() {
5476 BitVector* indexes = Get(Alias::Indexes()); 5483 // Ids start at 1 because the hash-map uses 0 for element not found.
5477 if (indexes == NULL) { 5484 for (intptr_t unknown_index_id = 1;
5478 return; 5485 unknown_index_id <= max_unknown_index_id_;
5479 } 5486 unknown_index_id++) {
5487 BitVector* unknown_index = Get(Alias::UnknownIndex(unknown_index_id));
5488 if (unknown_index == NULL) {
5489 return;
5490 }
5480 5491
5481 // Constant indexes alias all non-constant indexes. 5492 // Constant indexes alias all non-constant indexes.
5482 // Non-constant indexes alias all constant indexes. 5493 // Non-constant indexes alias all constant indexes.
5483 // First update alias set for const-indices, then 5494 // First update alias set for const-indices, then
5484 // update set for all indices. Ids start at 1. 5495 // update set for all indices. Ids start at 1.
5485 for (intptr_t id = 1; id <= max_index_id_; id++) { 5496 for (intptr_t id = 1; id <= max_index_id_; id++) {
5486 BitVector* const_indexes = Get(Alias::ConstantIndex(id)); 5497 BitVector* const_indexes = Get(Alias::ConstantIndex(id));
5487 if (const_indexes != NULL) { 5498 if (const_indexes != NULL) {
5488 const_indexes->AddAll(indexes); 5499 const_indexes->AddAll(unknown_index);
5500 }
5489 } 5501 }
5490 }
5491 5502
5492 for (intptr_t id = 1; id <= max_index_id_; id++) { 5503 for (intptr_t id = 1; id <= max_index_id_; id++) {
5493 BitVector* const_indexes = Get(Alias::ConstantIndex(id)); 5504 BitVector* const_indexes = Get(Alias::ConstantIndex(id));
5494 if (const_indexes != NULL) { 5505 if (const_indexes != NULL) {
5495 indexes->AddAll(const_indexes); 5506 unknown_index->AddAll(const_indexes);
5507 }
5496 } 5508 }
5497 } 5509 }
5498 } 5510 }
5499 5511
5500 void AddIdForAlias(const Alias alias, intptr_t place_id) { 5512 void AddIdForAlias(const Alias alias, intptr_t place_id) {
5501 const intptr_t idx = alias.ToIndex(); 5513 const intptr_t idx = alias.ToIndex();
5502 while (sets_.length() <= idx) { 5514 while (sets_.length() <= idx) {
5503 sets_.Add(NULL); 5515 sets_.Add(NULL);
5504 } 5516 }
5505 5517
(...skipping 25 matching lines...) Expand all
5531 comma = true; 5543 comma = true;
5532 } 5544 }
5533 } 5545 }
5534 5546
5535 const PhiPlaceMoves* phi_moves() const { return phi_moves_; } 5547 const PhiPlaceMoves* phi_moves() const { return phi_moves_; }
5536 5548
5537 // Returns true if the result of an allocation instruction can be aliased by 5549 // Returns true if the result of an allocation instruction can be aliased by
5538 // some other SSA variable and false otherwise. Currently simply checks if 5550 // some other SSA variable and false otherwise. Currently simply checks if
5539 // this value is stored in a field, escapes to another function or 5551 // this value is stored in a field, escapes to another function or
5540 // participates in a phi. 5552 // participates in a phi.
5541 static bool CanBeAliased(AllocateObjectInstr* alloc) { 5553 static bool CanBeAliased(Definition* alloc) {
5542 if (alloc->identity() == AllocateObjectInstr::kUnknown) { 5554 ASSERT(alloc->IsAllocateObject() ||
5555 alloc->IsCreateArray() ||
5556 (alloc->IsStaticCall() &&
5557 alloc->AsStaticCall()->is_known_list_constructor()));
5558 if (alloc->Identity() == kIdentityUnknown) {
5543 bool escapes = false; 5559 bool escapes = false;
5544 for (Value* use = alloc->input_use_list(); 5560 for (Value* use = alloc->input_use_list();
5545 use != NULL; 5561 use != NULL;
5546 use = use->next_use()) { 5562 use = use->next_use()) {
5547 Instruction* instr = use->instruction(); 5563 Instruction* instr = use->instruction();
5548 if (instr->IsPushArgument() || 5564 if (instr->IsPushArgument() ||
5549 (instr->IsStoreInstanceField() 5565 (instr->IsStoreInstanceField()
5550 && (use->use_index() != StoreInstanceFieldInstr::kInstancePos)) || 5566 && (use->use_index() != StoreInstanceFieldInstr::kInstancePos)) ||
5551 (instr->IsStoreIndexed() 5567 (instr->IsStoreIndexed()
5552 && (use->use_index() == StoreIndexedInstr::kValuePos)) || 5568 && (use->use_index() == StoreIndexedInstr::kValuePos)) ||
5553 instr->IsStoreStaticField() || 5569 instr->IsStoreStaticField() ||
5554 instr->IsPhi() || 5570 instr->IsPhi() ||
5555 instr->IsAssertAssignable() || 5571 instr->IsAssertAssignable() ||
5556 instr->IsRedefinition()) { 5572 instr->IsRedefinition()) {
5557 escapes = true; 5573 escapes = true;
5558 break; 5574 break;
5559 } 5575 }
5560 } 5576 }
5561 5577
5562 alloc->set_identity(escapes ? AllocateObjectInstr::kAliased 5578 alloc->SetIdentity(escapes ? kIdentityAliased : kIdentityNotAliased);
5563 : AllocateObjectInstr::kNotAliased);
5564 } 5579 }
5565 5580
5566 return alloc->identity() != AllocateObjectInstr::kNotAliased; 5581 return alloc->Identity() != kIdentityNotAliased;
5567 } 5582 }
5568 5583
5569 private: 5584 private:
5570 // Get id assigned to the given field. Assign a new id if the field is seen 5585 // Get id assigned to the given field. Assign a new id if the field is seen
5571 // for the first time. 5586 // for the first time.
5572 intptr_t GetFieldId(intptr_t instance_id, const Field& field) { 5587 intptr_t GetFieldId(intptr_t instance_id, const Field& field) {
5573 intptr_t id = field_ids_.Lookup(FieldIdPair::Key(instance_id, &field)); 5588 intptr_t id = field_ids_.Lookup(FieldIdPair::Key(instance_id, &field));
5574 if (id == 0) { 5589 if (id == 0) {
5575 id = ++max_field_id_; 5590 id = ++max_field_id_;
5576 field_ids_.Insert(FieldIdPair(FieldIdPair::Key(instance_id, &field), id)); 5591 field_ids_.Insert(FieldIdPair(FieldIdPair::Key(instance_id, &field), id));
5577 } 5592 }
5578 return id; 5593 return id;
5579 } 5594 }
5580 5595
5581 intptr_t GetIndexId(intptr_t index) { 5596 intptr_t GetIndexId(intptr_t instance_id, intptr_t index) {
5582 intptr_t id = index_ids_.Lookup(index); 5597 intptr_t id = index_ids_.Lookup(
5598 ConstantIndexIdPair::Key(instance_id, index));
5583 if (id == 0) { 5599 if (id == 0) {
5584 // Zero is used to indicate element not found. The first id is one. 5600 // Zero is used to indicate element not found. The first id is one.
5585 id = ++max_index_id_; 5601 id = ++max_index_id_;
5586 index_ids_.Insert(IndexIdPair(index, id)); 5602 index_ids_.Insert(ConstantIndexIdPair(
5603 ConstantIndexIdPair::Key(instance_id, index), id));
5587 } 5604 }
5588 return id; 5605 return id;
5589 } 5606 }
5590 5607
5591 enum { 5608 enum {
5592 kAnyInstance = -1 5609 kAnyInstance = -1
5593 }; 5610 };
5594 5611
5595 // Get or create an identifier for an instance field belonging to the 5612 // Get or create an identifier for an instance field belonging to the
5596 // given instance. 5613 // given instance.
(...skipping 13 matching lines...) Expand all
5610 AllocateObjectInstr* alloc = defn->AsAllocateObject(); 5627 AllocateObjectInstr* alloc = defn->AsAllocateObject();
5611 if ((alloc != NULL) && !CanBeAliased(alloc)) { 5628 if ((alloc != NULL) && !CanBeAliased(alloc)) {
5612 instance_id = alloc->ssa_temp_index(); 5629 instance_id = alloc->ssa_temp_index();
5613 ASSERT(instance_id != kAnyInstance); 5630 ASSERT(instance_id != kAnyInstance);
5614 } 5631 }
5615 } 5632 }
5616 5633
5617 return GetFieldId(instance_id, field); 5634 return GetFieldId(instance_id, field);
5618 } 5635 }
5619 5636
5620 intptr_t GetVMFieldId(Definition* defn, intptr_t offset) { 5637 intptr_t GetInstanceVMFieldId(Definition* defn, intptr_t offset) {
5621 intptr_t instance_id = kAnyInstance; 5638 intptr_t instance_id = kAnyInstance;
5622 5639
5623 if (defn != NULL) { 5640 ASSERT(defn != NULL);
5624 AllocateObjectInstr* alloc = defn->AsAllocateObject(); 5641 if ((defn->IsAllocateObject() ||
5625 if ((alloc != NULL) && !CanBeAliased(alloc)) { 5642 defn->IsCreateArray() ||
5626 instance_id = alloc->ssa_temp_index(); 5643 (defn->IsStaticCall() &&
5627 ASSERT(instance_id != kAnyInstance); 5644 defn->AsStaticCall()->is_known_list_constructor())) &&
5628 } 5645 !CanBeAliased(defn)) {
5646 instance_id = defn->ssa_temp_index();
5647 ASSERT(instance_id != kAnyInstance);
5629 } 5648 }
5630 5649
5631 intptr_t id = vm_field_ids_.Lookup(VMFieldIdPair::Key(instance_id, offset)); 5650 intptr_t id = vm_field_ids_.Lookup(VMFieldIdPair::Key(instance_id, offset));
5632 if (id == 0) { 5651 if (id == 0) {
5633 id = ++max_vm_field_id_; 5652 id = ++max_vm_field_id_;
5634 vm_field_ids_.Insert( 5653 vm_field_ids_.Insert(
5635 VMFieldIdPair(VMFieldIdPair::Key(instance_id, offset), id)); 5654 VMFieldIdPair(VMFieldIdPair::Key(instance_id, offset), id));
5636 } 5655 }
5637 return id; 5656 return id;
5638 } 5657 }
5639 5658
5659 intptr_t GetInstanceIndexId(Definition* defn, intptr_t index) {
5660 intptr_t instance_id = kAnyInstance;
5661
5662 ASSERT(defn != NULL);
5663 if ((defn->IsCreateArray() ||
5664 (defn->IsStaticCall() &&
5665 defn->AsStaticCall()->is_known_list_constructor())) &&
5666 !CanBeAliased(defn)) {
5667 instance_id = defn->ssa_temp_index();
5668 ASSERT(instance_id != kAnyInstance);
5669 }
5670
5671 return GetIndexId(instance_id, index);
5672 }
5673
5674 intptr_t GetUnknownIndexId(Definition* defn) {
5675 intptr_t instance_id = kAnyInstance;
5676
5677 ASSERT(defn != NULL);
5678 if ((defn->IsCreateArray() ||
5679 (defn->IsStaticCall() &&
5680 defn->AsStaticCall()->is_known_list_constructor())) &&
5681 !CanBeAliased(defn)) {
5682 instance_id = defn->ssa_temp_index();
5683 ASSERT(instance_id != kAnyInstance);
5684 }
5685
5686 intptr_t id = unknown_index_ids_.Lookup(
5687 UnknownIndexIdPair::Key(instance_id));
5688 if (id == 0) {
5689 // Zero is used to indicate element not found. The first id is one.
5690 id = ++max_unknown_index_id_;
5691 unknown_index_ids_.Insert(
5692 UnknownIndexIdPair(UnknownIndexIdPair::Key(instance_id), id));
5693 }
5694 return id;
5695 }
5696
5640 // Get or create an identifier for a static field. 5697 // Get or create an identifier for a static field.
5641 intptr_t GetStaticFieldId(const Field& field) { 5698 intptr_t GetStaticFieldId(const Field& field) {
5642 ASSERT(field.is_static()); 5699 ASSERT(field.is_static());
5643 return GetFieldId(kAnyInstance, field); 5700 return GetFieldId(kAnyInstance, field);
5644 } 5701 }
5645 5702
5646 // Returns true if the given load is unaffected by external side-effects. 5703 // Returns true if the given load is unaffected by external side-effects.
5647 // This essentially means that no stores to the same location can 5704 // This essentially means that no stores to the same location can
5648 // occur in other functions. 5705 // occur in other functions.
5649 bool IsIndependentFromEffects(Place* place) { 5706 bool IsIndependentFromEffects(Place* place) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
5703 static inline bool IsKeyEqual(Pair kv, Key key) { 5760 static inline bool IsKeyEqual(Pair kv, Key key) {
5704 return (KeyOf(kv).field_->raw() == key.field_->raw()) && 5761 return (KeyOf(kv).field_->raw() == key.field_->raw()) &&
5705 (KeyOf(kv).instance_id_ == key.instance_id_); 5762 (KeyOf(kv).instance_id_ == key.instance_id_);
5706 } 5763 }
5707 5764
5708 private: 5765 private:
5709 Key key_; 5766 Key key_;
5710 Value value_; 5767 Value value_;
5711 }; 5768 };
5712 5769
5713 class IndexIdPair { 5770 class ConstantIndexIdPair {
5714 public: 5771 public:
5715 typedef intptr_t Key; 5772 struct Key {
5773 Key(intptr_t instance_id, intptr_t index)
5774 : instance_id_(instance_id), index_(index) { }
5775
5776 intptr_t instance_id_;
5777 intptr_t index_;
5778 };
5716 typedef intptr_t Value; 5779 typedef intptr_t Value;
5717 typedef IndexIdPair Pair; 5780 typedef ConstantIndexIdPair Pair;
5718 5781
5719 IndexIdPair(Key key, Value value) : key_(key), value_(value) { } 5782 ConstantIndexIdPair(Key key, Value value) : key_(key), value_(value) { }
5720 5783
5721 static Key KeyOf(IndexIdPair kv) { 5784 static Key KeyOf(ConstantIndexIdPair kv) {
5722 return kv.key_; 5785 return kv.key_;
5723 } 5786 }
5724 5787
5725 static Value ValueOf(IndexIdPair kv) { 5788 static Value ValueOf(ConstantIndexIdPair kv) {
5726 return kv.value_; 5789 return kv.value_;
5727 } 5790 }
5728 5791
5729 static intptr_t Hashcode(Key key) { 5792 static intptr_t Hashcode(Key key) {
5730 return key; 5793 return (key.instance_id_ + 1) * 1024 + key.index_;
5731 } 5794 }
5732 5795
5733 static inline bool IsKeyEqual(IndexIdPair kv, Key key) { 5796 static inline bool IsKeyEqual(ConstantIndexIdPair kv, Key key) {
5797 return (KeyOf(kv).index_ == key.index_)
5798 && (KeyOf(kv).instance_id_ == key.instance_id_);
5799 }
5800
5801 private:
5802 Key key_;
5803 Value value_;
5804 };
5805
5806 class UnknownIndexIdPair {
5807 public:
5808 typedef intptr_t Key;
5809 typedef intptr_t Value;
5810 typedef UnknownIndexIdPair Pair;
5811
5812 UnknownIndexIdPair(Key key, Value value) : key_(key), value_(value) { }
5813
5814 static Key KeyOf(UnknownIndexIdPair kv) {
5815 return kv.key_;
5816 }
5817
5818 static Value ValueOf(UnknownIndexIdPair kv) {
5819 return kv.value_;
5820 }
5821
5822 static intptr_t Hashcode(Key key) {
5823 return key + 1;
5824 }
5825
5826 static inline bool IsKeyEqual(UnknownIndexIdPair kv, Key key) {
5734 return KeyOf(kv) == key; 5827 return KeyOf(kv) == key;
5735 } 5828 }
5736 5829
5737 private: 5830 private:
5738 Key key_; 5831 Key key_;
5739 Value value_; 5832 Value value_;
5740 }; 5833 };
5741 5834
5742 class VMFieldIdPair { 5835 class VMFieldIdPair {
5743 public: 5836 public:
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
5784 // given alias. 5877 // given alias.
5785 GrowableArray<BitVector*> sets_; 5878 GrowableArray<BitVector*> sets_;
5786 5879
5787 BitVector* aliased_by_effects_; 5880 BitVector* aliased_by_effects_;
5788 5881
5789 // Table mapping static field to their id used during optimization pass. 5882 // Table mapping static field to their id used during optimization pass.
5790 intptr_t max_field_id_; 5883 intptr_t max_field_id_;
5791 DirectChainedHashMap<FieldIdPair> field_ids_; 5884 DirectChainedHashMap<FieldIdPair> field_ids_;
5792 5885
5793 intptr_t max_index_id_; 5886 intptr_t max_index_id_;
5794 DirectChainedHashMap<IndexIdPair> index_ids_; 5887 DirectChainedHashMap<ConstantIndexIdPair> index_ids_;
5888
5889 intptr_t max_unknown_index_id_;
5890 DirectChainedHashMap<UnknownIndexIdPair> unknown_index_ids_;
5795 5891
5796 intptr_t max_vm_field_id_; 5892 intptr_t max_vm_field_id_;
5797 DirectChainedHashMap<VMFieldIdPair> vm_field_ids_; 5893 DirectChainedHashMap<VMFieldIdPair> vm_field_ids_;
5798 }; 5894 };
5799 5895
5800 5896
5801 static Definition* GetStoredValue(Instruction* instr) { 5897 static Definition* GetStoredValue(Instruction* instr) {
5802 if (instr->IsStoreIndexed()) { 5898 if (instr->IsStoreIndexed()) {
5803 return instr->AsStoreIndexed()->value()->definition(); 5899 return instr->AsStoreIndexed()->value()->definition();
5804 } 5900 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
5922 6018
5923 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places); 6019 PhiPlaceMoves* phi_moves = ComputePhiMoves(map, places);
5924 6020
5925 // Build aliasing sets mapping aliases to loads. 6021 // Build aliasing sets mapping aliases to loads.
5926 AliasedSet* aliased_set = new AliasedSet(places, phi_moves); 6022 AliasedSet* aliased_set = new AliasedSet(places, phi_moves);
5927 for (intptr_t i = 0; i < places->length(); i++) { 6023 for (intptr_t i = 0; i < places->length(); i++) {
5928 Place* place = (*places)[i]; 6024 Place* place = (*places)[i];
5929 aliased_set->AddRepresentative(place); 6025 aliased_set->AddRepresentative(place);
5930 } 6026 }
5931 6027
5932 aliased_set->EnsureAliasingForIndexes(); 6028 aliased_set->EnsureAliasingForUnknownIndices();
5933 6029
5934 return aliased_set; 6030 return aliased_set;
5935 } 6031 }
5936 6032
5937 6033
5938 class LoadOptimizer : public ValueObject { 6034 class LoadOptimizer : public ValueObject {
5939 public: 6035 public:
5940 LoadOptimizer(FlowGraph* graph, 6036 LoadOptimizer(FlowGraph* graph,
5941 AliasedSet* aliased_set, 6037 AliasedSet* aliased_set,
5942 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map) 6038 DirectChainedHashMap<PointerKeyValueTrait<Place> >* map)
(...skipping 2771 matching lines...) Expand 10 before | Expand all | Expand 10 after
8714 BlockEntryInstr* block = block_it.Current(); 8810 BlockEntryInstr* block = block_it.Current();
8715 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) { 8811 for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
8716 AllocateObjectInstr* alloc = it.Current()->AsAllocateObject(); 8812 AllocateObjectInstr* alloc = it.Current()->AsAllocateObject();
8717 if ((alloc != NULL) && IsAllocationSinkingCandidate(alloc)) { 8813 if ((alloc != NULL) && IsAllocationSinkingCandidate(alloc)) {
8718 if (FLAG_trace_optimization) { 8814 if (FLAG_trace_optimization) {
8719 OS::Print("discovered allocation sinking candidate: v%" Pd "\n", 8815 OS::Print("discovered allocation sinking candidate: v%" Pd "\n",
8720 alloc->ssa_temp_index()); 8816 alloc->ssa_temp_index());
8721 } 8817 }
8722 8818
8723 // All sinking candidate are known to be not aliased. 8819 // All sinking candidate are known to be not aliased.
8724 alloc->set_identity(AllocateObjectInstr::kNotAliased); 8820 alloc->SetIdentity(kIdentityNotAliased);
8725 8821
8726 candidates.Add(alloc); 8822 candidates.Add(alloc);
8727 } 8823 }
8728 } 8824 }
8729 } 8825 }
8730 8826
8731 // Insert MaterializeObject instructions that will describe the state of the 8827 // Insert MaterializeObject instructions that will describe the state of the
8732 // object at all deoptimization points. Each inserted materialization looks 8828 // object at all deoptimization points. Each inserted materialization looks
8733 // like this (where v_0 is allocation that we are going to eliminate): 8829 // like this (where v_0 is allocation that we are going to eliminate):
8734 // v_1 <- LoadField(v_0, field_1) 8830 // v_1 <- LoadField(v_0, field_1)
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
8890 } 8986 }
8891 8987
8892 // Insert materializations at environment uses. 8988 // Insert materializations at environment uses.
8893 for (intptr_t i = 0; i < exits.length(); i++) { 8989 for (intptr_t i = 0; i < exits.length(); i++) {
8894 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots); 8990 CreateMaterializationAt(exits[i], alloc, alloc->cls(), *slots);
8895 } 8991 }
8896 } 8992 }
8897 8993
8898 8994
8899 } // namespace dart 8995 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698