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); |
} |
} |