| Index: src/hydrogen-check-elimination.cc
|
| diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
|
| index 5d4b33b95b97e7ebb625c194991c4931ad7a6160..fb7812e3ce9334cc4603b0a49da468616e922a9a 100644
|
| --- a/src/hydrogen-check-elimination.cc
|
| +++ b/src/hydrogen-check-elimination.cc
|
| @@ -21,7 +21,7 @@
|
| namespace v8 {
|
| namespace internal {
|
|
|
| -typedef UniqueSet<Map>* MapSet;
|
| +typedef const UniqueSet<Map>* MapSet;
|
|
|
| struct HCheckTableEntry {
|
| HValue* object_; // The object being approximated. NULL => invalid entry.
|
| @@ -34,7 +34,7 @@ struct HCheckTableEntry {
|
| // set of known maps for each object.
|
| class HCheckTable : public ZoneObject {
|
| public:
|
| - static const int kMaxTrackedObjects = 10;
|
| + static const int kMaxTrackedObjects = 16;
|
|
|
| explicit HCheckTable(HCheckEliminationPhase* phase)
|
| : phase_(phase),
|
| @@ -80,7 +80,8 @@ class HCheckTable : public ZoneObject {
|
| }
|
| default: {
|
| // If the instruction changes maps uncontrollably, drop everything.
|
| - if (instr->CheckChangesFlag(kMaps) ||
|
| + if (instr->CheckChangesFlag(kElementsKind) ||
|
| + instr->CheckChangesFlag(kMaps) ||
|
| instr->CheckChangesFlag(kOsrEntries)) {
|
| Kill();
|
| }
|
| @@ -127,13 +128,13 @@ class HCheckTable : public ZoneObject {
|
| private:
|
| // Copy state to successor block.
|
| HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) {
|
| - HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_);
|
| + HCheckTable* copy = new(zone) HCheckTable(phase_);
|
| for (int i = 0; i < size_; i++) {
|
| HCheckTableEntry* old_entry = &entries_[i];
|
| ASSERT(old_entry->maps_->size() > 0);
|
| HCheckTableEntry* new_entry = ©->entries_[i];
|
| new_entry->object_ = old_entry->object_;
|
| - new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
|
| + new_entry->maps_ = old_entry->maps_;
|
| // Keep the check if the existing check's block dominates the successor.
|
| if (old_entry->check_ != NULL &&
|
| old_entry->check_->block()->Dominates(succ)) {
|
| @@ -159,7 +160,7 @@ class HCheckTable : public ZoneObject {
|
| HCheckTableEntry* pred_entry = copy->Find(phi_operand);
|
| if (pred_entry != NULL) {
|
| // Create an entry for a phi in the table.
|
| - copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()));
|
| + copy->Insert(phi, NULL, pred_entry->maps_);
|
| }
|
| }
|
| }
|
| @@ -179,15 +180,15 @@ class HCheckTable : public ZoneObject {
|
| if (entry == NULL) {
|
| copy->Insert(object, cmp, cmp->map());
|
| } else {
|
| - MapSet list = new(phase_->zone()) UniqueSet<Map>();
|
| - list->Add(cmp->map(), phase_->zone());
|
| - entry->maps_ = list;
|
| + entry->maps_ = new(zone) UniqueSet<Map>(cmp->map(), zone);
|
| entry->check_ = cmp;
|
| }
|
| } else {
|
| // Learn on the false branch of if(CompareMap(x)).
|
| if (entry != NULL) {
|
| - entry->maps_->Remove(cmp->map());
|
| + UniqueSet<Map>* maps = entry->maps_->Copy(zone);
|
| + maps->Remove(cmp->map());
|
| + entry->maps_ = maps;
|
| }
|
| }
|
| learned = true;
|
| @@ -201,14 +202,12 @@ class HCheckTable : public ZoneObject {
|
| HCheckTableEntry* re = copy->Find(right);
|
| if (le == NULL) {
|
| if (re != NULL) {
|
| - copy->Insert(left, NULL, re->maps_->Copy(zone));
|
| + copy->Insert(left, NULL, re->maps_);
|
| }
|
| } else if (re == NULL) {
|
| - copy->Insert(right, NULL, le->maps_->Copy(zone));
|
| + copy->Insert(right, NULL, le->maps_);
|
| } else {
|
| - MapSet intersect = le->maps_->Intersect(re->maps_, zone);
|
| - le->maps_ = intersect;
|
| - re->maps_ = intersect->Copy(zone);
|
| + le->maps_ = re->maps_ = le->maps_->Intersect(re->maps_, zone);
|
| }
|
| learned = true;
|
| }
|
| @@ -254,7 +253,7 @@ class HCheckTable : public ZoneObject {
|
| compact = true;
|
| } else {
|
| this_entry->maps_ =
|
| - this_entry->maps_->Union(that_entry->maps_, phase_->zone());
|
| + this_entry->maps_->Union(that_entry->maps_, zone);
|
| if (this_entry->check_ != that_entry->check_) {
|
| this_entry->check_ = NULL;
|
| }
|
| @@ -278,7 +277,7 @@ class HCheckTable : public ZoneObject {
|
| if (entry != NULL) {
|
| // entry found;
|
| MapSet a = entry->maps_;
|
| - const UniqueSet<Map>* i = instr->map_set();
|
| + const UniqueSet<Map>* i = instr->maps();
|
| if (a->IsSubset(i)) {
|
| // The first check is more strict; the second is redundant.
|
| if (entry->check_ != NULL) {
|
| @@ -297,7 +296,8 @@ class HCheckTable : public ZoneObject {
|
| }
|
| return;
|
| }
|
| - MapSet intersection = i->Intersect(a, phase_->zone());
|
| + HGraph* graph = instr->block()->graph();
|
| + MapSet intersection = i->Intersect(a, graph->zone());
|
| if (intersection->size() == 0) {
|
| // Intersection is empty; probably megamorphic, which is likely to
|
| // deopt anyway, so just leave things as they are.
|
| @@ -307,7 +307,6 @@ class HCheckTable : public ZoneObject {
|
| entry->maps_ = intersection;
|
| if (intersection->size() != i->size()) {
|
| // Narrow set of maps in the second check maps instruction.
|
| - HGraph* graph = instr->block()->graph();
|
| if (entry->check_ != NULL &&
|
| entry->check_->block() == instr->block() &&
|
| entry->check_->IsCheckMaps()) {
|
| @@ -317,7 +316,7 @@ class HCheckTable : public ZoneObject {
|
| TRACE(("CheckMaps #%d at B%d narrowed\n", check->id(),
|
| check->block()->block_id()));
|
| // Update map set and ensure that the check is alive.
|
| - check->set_map_set(intersection, graph->zone());
|
| + check->set_maps(intersection);
|
| check->ClearFlag(HValue::kIsDead);
|
| TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n",
|
| instr->id(), instr->block()->block_id(), entry->check_->id()));
|
| @@ -325,7 +324,7 @@ class HCheckTable : public ZoneObject {
|
| } else {
|
| TRACE(("CheckMaps #%d at B%d narrowed\n", instr->id(),
|
| instr->block()->block_id()));
|
| - instr->set_map_set(intersection, graph->zone());
|
| + instr->set_maps(intersection);
|
| entry->check_ = instr;
|
| }
|
|
|
| @@ -337,16 +336,16 @@ class HCheckTable : public ZoneObject {
|
| }
|
| } else {
|
| // No entry; insert a new one.
|
| - Insert(object, instr, instr->map_set()->Copy(phase_->zone()));
|
| + Insert(object, instr, instr->maps());
|
| }
|
| }
|
|
|
| void ReduceLoadNamedField(HLoadNamedField* instr) {
|
| // Reduce a load of the map field when it is known to be a constant.
|
| - if (!IsMapAccess(instr->access())) {
|
| + if (!instr->access().IsMap()) {
|
| // Check if we introduce field maps here.
|
| - if (instr->map_set()->size() != 0) {
|
| - Insert(instr, instr, instr->map_set()->Copy(phase_->zone()));
|
| + if (instr->maps()->size() != 0) {
|
| + Insert(instr, instr, instr->maps());
|
| }
|
| return;
|
| }
|
| @@ -371,9 +370,8 @@ class HCheckTable : public ZoneObject {
|
|
|
| HCheckTableEntry* entry = Find(object);
|
| if (entry != NULL) {
|
| - MapSet maps = entry->maps_;
|
| - if (maps->Contains(map)) {
|
| - if (maps->size() == 1) {
|
| + if (entry->maps_->Contains(map)) {
|
| + if (entry->maps_->size() == 1) {
|
| // Object is known to have exactly this map.
|
| if (entry->check_ != NULL) {
|
| instr->DeleteAndReplaceWith(entry->check_);
|
| @@ -386,8 +384,7 @@ class HCheckTable : public ZoneObject {
|
| INC_STAT(removed_);
|
| } else {
|
| // Only one map survives the check.
|
| - maps->Clear();
|
| - maps->Add(map, phase_->zone());
|
| + entry->maps_ = new(zone()) UniqueSet<Map>(map, zone());
|
| entry->check_ = instr;
|
| }
|
| }
|
| @@ -411,7 +408,7 @@ class HCheckTable : public ZoneObject {
|
| // This store transitions the object to a new map.
|
| Kill(object);
|
| Insert(object, NULL, MapConstant(instr->transition()));
|
| - } else if (IsMapAccess(instr->access())) {
|
| + } else if (instr->access().IsMap()) {
|
| // This is a store directly to the map field of the object.
|
| Kill(object);
|
| if (!instr->value()->IsConstant()) return;
|
| @@ -455,7 +452,7 @@ class HCheckTable : public ZoneObject {
|
| if (maps_left == NULL) return;
|
| MapSet maps_right = FindMaps(instr->right()->ActualValue());
|
| if (maps_right == NULL) return;
|
| - MapSet intersection = maps_left->Intersect(maps_right, phase_->zone());
|
| + MapSet intersection = maps_left->Intersect(maps_right, zone());
|
| if (intersection->size() > 0) return;
|
|
|
| TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n",
|
| @@ -468,13 +465,15 @@ class HCheckTable : public ZoneObject {
|
| }
|
|
|
| void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
|
| - MapSet maps = FindMaps(instr->object()->ActualValue());
|
| + HCheckTableEntry* entry = Find(instr->object()->ActualValue());
|
| // Can only learn more about an object that already has a known set of maps.
|
| - if (maps == NULL) return;
|
| - if (maps->Contains(instr->original_map())) {
|
| + if (entry == NULL) return;
|
| + if (entry->maps_->Contains(instr->original_map())) {
|
| // If the object has the original map, it will be transitioned.
|
| + UniqueSet<Map>* maps = entry->maps_->Copy(zone());
|
| maps->Remove(instr->original_map());
|
| - maps->Add(instr->transitioned_map(), phase_->zone());
|
| + maps->Add(instr->transitioned_map(), zone());
|
| + entry->maps_ = maps;
|
| } else {
|
| // Object does not have the given map, thus the transition is redundant.
|
| instr->DeleteAndReplaceWith(instr->object());
|
| @@ -575,9 +574,7 @@ class HCheckTable : public ZoneObject {
|
| }
|
|
|
| void Insert(HValue* object, HInstruction* check, Unique<Map> map) {
|
| - MapSet list = new(phase_->zone()) UniqueSet<Map>();
|
| - list->Add(map, phase_->zone());
|
| - Insert(object, check, list);
|
| + Insert(object, check, new(zone()) UniqueSet<Map>(map, zone()));
|
| }
|
|
|
| void Insert(HValue* object, HInstruction* check, MapSet maps) {
|
| @@ -590,14 +587,12 @@ class HCheckTable : public ZoneObject {
|
| if (size_ < kMaxTrackedObjects) size_++;
|
| }
|
|
|
| - bool IsMapAccess(HObjectAccess access) {
|
| - return access.IsInobject() && access.offset() == JSObject::kMapOffset;
|
| - }
|
| -
|
| Unique<Map> MapConstant(HValue* value) {
|
| return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
|
| }
|
|
|
| + Zone* zone() const { return phase_->zone(); }
|
| +
|
| friend class HCheckMapsEffects;
|
| friend class HCheckEliminationPhase;
|
|
|
| @@ -614,26 +609,28 @@ class HCheckTable : public ZoneObject {
|
| class HCheckMapsEffects : public ZoneObject {
|
| public:
|
| explicit HCheckMapsEffects(Zone* zone)
|
| - : maps_stored_(false),
|
| - stores_(5, zone) { }
|
| + : objects_(0, zone), maps_stored_(false) {}
|
|
|
| - inline bool Disabled() {
|
| - return false; // Effects are _not_ disabled.
|
| - }
|
| + // Effects are _not_ disabled.
|
| + inline bool Disabled() const { return false; }
|
|
|
| // Process a possibly side-effecting instruction.
|
| void Process(HInstruction* instr, Zone* zone) {
|
| switch (instr->opcode()) {
|
| case HValue::kStoreNamedField: {
|
| - stores_.Add(HStoreNamedField::cast(instr), zone);
|
| + HStoreNamedField* store = HStoreNamedField::cast(instr);
|
| + if (store->access().IsMap() && store->has_transition()) {
|
| + objects_.Add(store->object(), zone);
|
| + }
|
| break;
|
| }
|
| - case HValue::kOsrEntry: {
|
| - // Kill everything. Loads must not be hoisted past the OSR entry.
|
| - maps_stored_ = true;
|
| + case HValue::kTransitionElementsKind: {
|
| + objects_.Add(HTransitionElementsKind::cast(instr)->object(), zone);
|
| + break;
|
| }
|
| default: {
|
| maps_stored_ |= (instr->CheckChangesFlag(kMaps) |
|
| + instr->CheckChangesFlag(kOsrEntries) |
|
| instr->CheckChangesFlag(kElementsKind));
|
| }
|
| }
|
| @@ -647,26 +644,23 @@ class HCheckMapsEffects : public ZoneObject {
|
| return;
|
| }
|
|
|
| - // Kill maps for each store contained in these effects.
|
| - for (int i = 0; i < stores_.length(); i++) {
|
| - HStoreNamedField* s = stores_[i];
|
| - if (table->IsMapAccess(s->access()) || s->has_transition()) {
|
| - table->Kill(s->object()->ActualValue());
|
| - }
|
| + // Kill maps for each object contained in these effects.
|
| + for (int i = 0; i < objects_.length(); ++i) {
|
| + table->Kill(objects_[i]->ActualValue());
|
| }
|
| }
|
|
|
| // Union these effects with the other effects.
|
| void Union(HCheckMapsEffects* that, Zone* zone) {
|
| maps_stored_ |= that->maps_stored_;
|
| - for (int i = 0; i < that->stores_.length(); i++) {
|
| - stores_.Add(that->stores_[i], zone);
|
| + for (int i = 0; i < that->objects_.length(); ++i) {
|
| + objects_.Add(that->objects_[i], zone);
|
| }
|
| }
|
|
|
| private:
|
| + ZoneList<HValue*> objects_;
|
| bool maps_stored_ : 1;
|
| - ZoneList<HStoreNamedField*> stores_;
|
| };
|
|
|
|
|
|
|