Chromium Code Reviews| Index: src/hydrogen-check-elimination.cc |
| diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc |
| index dafb632dc7ea9b77dc0eacf4803e32b7bbf16603..f1274696db90085396925ffeb1233e3fa8992a24 100644 |
| --- a/src/hydrogen-check-elimination.cc |
| +++ b/src/hydrogen-check-elimination.cc |
| @@ -50,6 +50,7 @@ struct HCheckTableEntry { |
| HValue* object_; // The object being approximated. NULL => invalid entry. |
| HInstruction* check_; // The last check instruction. |
| MapSet maps_; // The set of known maps for the object. |
| + bool is_stable_; |
| }; |
| @@ -103,8 +104,9 @@ class HCheckTable : public ZoneObject { |
| } |
| default: { |
| // If the instruction changes maps uncontrollably, drop everything. |
| - if (instr->CheckChangesFlag(kMaps) || |
| - instr->CheckChangesFlag(kOsrEntries)) { |
| + if (instr->CheckChangesFlag(kOsrEntries)) { |
| + Reset(); |
| + } else if (instr->CheckChangesFlag(kMaps)) { |
| Kill(); |
| } |
| } |
| @@ -126,6 +128,7 @@ class HCheckTable : public ZoneObject { |
| new_entry->object_ = old_entry->object_; |
| new_entry->check_ = NULL; |
| new_entry->maps_ = old_entry->maps_->Copy(phase_->zone()); |
| + new_entry->is_stable_ = old_entry->is_stable_; |
| } |
| copy->cursor_ = cursor_; |
| copy->size_ = size_; |
| @@ -142,7 +145,8 @@ 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_->Copy(phase_->zone()), |
| + pred_entry->is_stable_); |
| } |
| } |
| } |
| @@ -158,7 +162,7 @@ class HCheckTable : public ZoneObject { |
| HValue* object = cmp->value()->ActualValue(); |
| HCheckTableEntry* entry = copy->Find(object); |
| if (entry == NULL) { |
| - copy->Insert(object, cmp->map()); |
| + copy->Insert(object, cmp->map(), cmp->is_stable()); |
| } else { |
| MapSet list = new(phase_->zone()) UniqueSet<Map>(); |
| list->Add(cmp->map(), phase_->zone()); |
| @@ -175,10 +179,10 @@ 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_->Copy(zone), re->is_stable_); |
| } |
| } else if (re == NULL) { |
| - copy->Insert(right, NULL, le->maps_->Copy(zone)); |
| + copy->Insert(right, NULL, le->maps_->Copy(zone), le->is_stable_); |
| } else { |
| MapSet intersect = le->maps_->Intersect(re->maps_, zone); |
| le->maps_ = intersect; |
| @@ -230,6 +234,8 @@ class HCheckTable : public ZoneObject { |
| } else { |
| this_entry->maps_ = |
| this_entry->maps_->Union(that_entry->maps_, phase_->zone()); |
| + this_entry->is_stable_ = |
| + this_entry->is_stable_ && that_entry->is_stable_; |
| if (this_entry->check_ != that_entry->check_) { |
| this_entry->check_ = NULL; |
| } |
| @@ -310,7 +316,8 @@ class HCheckTable : public ZoneObject { |
| } |
| } else { |
| // No entry; insert a new one. |
| - Insert(object, instr, instr->map_set().Copy(phase_->zone())); |
| + Insert(object, instr, instr->map_set().Copy(phase_->zone()), |
| + instr->is_stable()); |
| } |
| } |
| @@ -362,7 +369,8 @@ class HCheckTable : public ZoneObject { |
| } |
| } else { |
| // No prior information. |
| - Insert(object, map); |
| + // TODO(verwaest): Tag map constants with stability. |
| + Insert(object, map, false); |
| } |
| } |
| @@ -379,12 +387,13 @@ class HCheckTable : public ZoneObject { |
| if (instr->has_transition()) { |
| // This store transitions the object to a new map. |
| Kill(object); |
| - Insert(object, MapConstant(instr->transition())); |
| + Insert(object, MapConstant(instr->transition()), instr->is_stable()); |
| } else if (IsMapAccess(instr->access())) { |
| // This is a store directly to the map field of the object. |
| Kill(object); |
| if (!instr->value()->IsConstant()) return; |
| - Insert(object, MapConstant(instr->value())); |
| + // TODO(verwaest): Tag with stability. |
| + Insert(object, MapConstant(instr->value()), false); |
| } else { |
| // If the instruction changes maps, it should be handled above. |
| CHECK(!instr->CheckChangesFlag(kMaps)); |
| @@ -424,12 +433,26 @@ class HCheckTable : public ZoneObject { |
| } |
| } |
| - // Kill everything in the table. |
| - void Kill() { |
| + // Reset the table. |
| + void Reset() { |
| size_ = 0; |
| cursor_ = 0; |
| } |
| + // Kill everything in the table. |
| + void Kill() { |
|
Igor Sheludko
2014/02/12 12:58:20
KillNonStableEntries(); ?
Toon Verwaest
2014/02/12 14:53:34
Done.
|
| + bool compact = false; |
| + for (int i = 0; i < size_; i++) { |
| + HCheckTableEntry* entry = &entries_[i]; |
| + ASSERT(entry->object_ != NULL); |
| + if (!entry->is_stable_) { |
| + entry->object_ = NULL; |
| + compact = true; |
| + } |
| + } |
| + if (compact) Compact(); |
| + } |
| + |
| // Kill everything in the table that may alias {object}. |
| void Kill(HValue* object) { |
| bool compact = false; |
| @@ -513,17 +536,18 @@ class HCheckTable : public ZoneObject { |
| return entry == NULL ? NULL : entry->maps_; |
| } |
| - void Insert(HValue* object, Unique<Map> map) { |
| + void Insert(HValue* object, Unique<Map> map, bool is_stable) { |
| MapSet list = new(phase_->zone()) UniqueSet<Map>(); |
| list->Add(map, phase_->zone()); |
| - Insert(object, NULL, list); |
| + Insert(object, NULL, list, is_stable); |
| } |
| - void Insert(HValue* object, HCheckMaps* check, MapSet maps) { |
| + void Insert(HValue* object, HCheckMaps* check, MapSet maps, bool is_stable) { |
| HCheckTableEntry* entry = &entries_[cursor_++]; |
| entry->object_ = object; |
| entry->check_ = check; |
| entry->maps_ = maps; |
| + entry->is_stable_ = is_stable; |
| // If the table becomes full, wrap around and overwrite older entries. |
| if (cursor_ == kMaxTrackedObjects) cursor_ = 0; |
| if (size_ < kMaxTrackedObjects) size_++; |
| @@ -553,6 +577,7 @@ class HCheckMapsEffects : public ZoneObject { |
| public: |
| explicit HCheckMapsEffects(Zone* zone) |
| : maps_stored_(false), |
| + requires_reset_(false), |
| stores_(5, zone) { } |
| inline bool Disabled() { |
| @@ -568,7 +593,8 @@ class HCheckMapsEffects : public ZoneObject { |
| } |
| case HValue::kOsrEntry: { |
| // Kill everything. Loads must not be hoisted past the OSR entry. |
| - maps_stored_ = true; |
| + requires_reset_ = true; |
| + break; |
| } |
| default: { |
| maps_stored_ |= (instr->CheckChangesFlag(kMaps) | |
| @@ -579,6 +605,10 @@ class HCheckMapsEffects : public ZoneObject { |
| // Apply these effects to the given check elimination table. |
| void Apply(HCheckTable* table) { |
| + if (requires_reset_) { |
| + table->Reset(); |
| + return; |
| + } |
| if (maps_stored_) { |
| // Uncontrollable map modifications; kill everything. |
| table->Kill(); |
| @@ -596,6 +626,7 @@ class HCheckMapsEffects : public ZoneObject { |
| // Union these effects with the other effects. |
| void Union(HCheckMapsEffects* that, Zone* zone) { |
| + requires_reset_ |= that->requires_reset_; |
| maps_stored_ |= that->maps_stored_; |
| for (int i = 0; i < that->stores_.length(); i++) { |
| stores_.Add(that->stores_[i], zone); |
| @@ -604,6 +635,7 @@ class HCheckMapsEffects : public ZoneObject { |
| private: |
| bool maps_stored_ : 1; |
| + bool requires_reset_ : 1; |
|
Igor Sheludko
2014/02/12 12:58:20
Consider replacing these flags with GVNFlagSet as
Toon Verwaest
2014/02/12 14:53:34
Done.
|
| ZoneList<HStoreNamedField*> stores_; |
| }; |
| @@ -620,7 +652,7 @@ void HCheckEliminationPhase::Run() { |
| } else { |
| // Perform only local analysis. |
| for (int i = 0; i < graph()->blocks()->length(); i++) { |
| - table->Kill(); |
| + table->Reset(); |
| engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); |
| } |
| } |