| 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 4978 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |