Chromium Code Reviews| Index: src/hydrogen-check-elimination.cc |
| diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc |
| index 506a04588995fbd25c858424b1461adf1155b781..27eb2eb501d56336308633aaade1f2686870edf8 100644 |
| --- a/src/hydrogen-check-elimination.cc |
| +++ b/src/hydrogen-check-elimination.cc |
| @@ -104,6 +104,10 @@ class HCheckTable : public ZoneObject { |
| ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr)); |
| break; |
| } |
| + case HValue::kIsStringAndBranch: { |
| + ReduceIsStringAndBranch(HIsStringAndBranch::cast(instr)); |
| + break; |
| + } |
| case HValue::kTransitionElementsKind: { |
| ReduceTransitionElementsKind( |
| HTransitionElementsKind::cast(instr)); |
| @@ -113,6 +117,10 @@ class HCheckTable : public ZoneObject { |
| ReduceCheckHeapObject(HCheckHeapObject::cast(instr)); |
| break; |
| } |
| + case HValue::kCheckInstanceType: { |
| + ReduceCheckInstanceType(HCheckInstanceType::cast(instr)); |
| + break; |
| + } |
| default: { |
| // If the instruction changes maps uncontrollably, drop everything. |
| if (instr->CheckChangesFlag(kOsrEntries)) { |
| @@ -125,7 +133,7 @@ class HCheckTable : public ZoneObject { |
| } |
| } |
| // Improvements possible: |
| - // - eliminate redundant HCheckSmi, HCheckInstanceType instructions |
| + // - eliminate redundant HCheckSmi instructions |
| // - track which values have been HCheckHeapObject'd |
| } |
| @@ -261,6 +269,33 @@ class HCheckTable : public ZoneObject { |
| ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, re->state_); |
| } |
| learned = true; |
| + } else if (end->IsIsStringAndBranch()) { |
| + HIsStringAndBranch* cmp = HIsStringAndBranch::cast(end); |
| + HValue* object = cmp->value()->ActualValue(); |
| + HCheckTableEntry* entry = copy->Find(object); |
| + if (is_true_branch) { |
| + // Learn on the true branch of if(IsString(x)). |
| + if (entry == NULL) { |
| + copy->Insert(object, NULL, string_maps(), |
| + HCheckTableEntry::CHECKED); |
| + } else { |
| + EnsureChecked(entry, object, cmp); |
| + entry->maps_ = entry->maps_->Intersect(string_maps(), zone); |
| + ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); |
| + } |
| + } else { |
| + // Learn on the false branch of if(IsString(x)). |
| + if (entry != NULL) { |
| + EnsureChecked(entry, object, cmp); |
| + UniqueSet<Map>* maps = new(zone) UniqueSet<Map>(); |
| + for (int i = 0; i < entry->maps_->size(); ++i) { |
| + Unique<Map> map = entry->maps_->at(i); |
| + if (!string_maps()->Contains(map)) maps->Add(map, zone); |
| + } |
|
Igor Sheludko
2014/05/30 10:00:41
Suggestion: What about adding Subtract() method to
Benedikt Meurer
2014/05/31 11:15:46
Done.
|
| + entry->maps_ = maps; |
| + ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); |
| + } |
| + } |
| } |
| // Learning on false branches requires storing negative facts. |
| } |
| @@ -415,6 +450,37 @@ class HCheckTable : public ZoneObject { |
| } |
| } |
| + void ReduceCheckInstanceType(HCheckInstanceType* instr) { |
| + HValue* value = instr->value()->ActualValue(); |
| + HCheckTableEntry* entry = Find(value); |
| + if (entry == NULL) return; |
| + for (int i = 0; i < entry->maps_->size(); ++i) { |
| + InstanceType type; |
| + Handle<Map> map = entry->maps_->at(i).handle(); |
| + { |
| + // This is safe, because maps don't move and their instance type does |
| + // not change. |
| + AllowHandleDereference allow_deref; |
| + type = map->instance_type(); |
| + } |
| + if (instr->is_interval_check()) { |
| + InstanceType first_type, last_type; |
| + instr->GetCheckInterval(&first_type, &last_type); |
| + if (type < first_type || last_type < type) return; |
| + } else { |
| + uint8_t mask, tag; |
| + instr->GetCheckMaskAndTag(&mask, &tag); |
| + if ((type & mask) != tag) return; |
| + } |
| + } |
|
Igor Sheludko
2014/05/30 10:00:41
Does it make sense to update set of entry maps if
Benedikt Meurer
2014/05/31 11:15:46
Done.
|
| + TRACE(("Removing redundant CheckInstanceType #%d at B%d\n", |
| + instr->id(), instr->block()->block_id())); |
| + EnsureChecked(entry, value, instr); |
| + instr->DeleteAndReplaceWith(value); |
| + INC_STAT(removed_cit_); |
| + return; |
| + } |
| + |
| void ReduceLoadNamedField(HLoadNamedField* instr) { |
| // Reduce a load of the map field when it is known to be a constant. |
| if (!instr->access().IsMap()) { |
| @@ -528,6 +594,35 @@ class HCheckTable : public ZoneObject { |
| instr->block()->MarkSuccEdgeUnreachable(unreachable_succ); |
| } |
| + void ReduceIsStringAndBranch(HIsStringAndBranch* instr) { |
| + HValue* value = instr->value()->ActualValue(); |
| + HCheckTableEntry* entry = Find(value); |
| + if (entry == NULL) return; |
| + EnsureChecked(entry, value, instr); |
| + if (entry->maps_->IsSubset(string_maps())) { |
| + TRACE(("Marking redundant IsStringAndBranch #%d at B%d as true\n", |
| + instr->id(), instr->block()->block_id())); |
| + int succ = 0; |
| + instr->set_known_successor_index(succ); |
| + |
| + int unreachable_succ = 1 - succ; |
| + instr->block()->MarkSuccEdgeUnreachable(unreachable_succ); |
| + return; |
| + } |
| + |
| + // TODO(bmeurer): Add a predicate here instead of computing the intersection |
| + MapSet intersection = entry->maps_->Intersect(string_maps(), zone()); |
| + if (intersection->size() > 0) return; |
| + |
| + TRACE(("Marking redundant IsStringAndBranch #%d at B%d as false\n", |
| + instr->id(), instr->block()->block_id())); |
| + int succ = 1; |
| + instr->set_known_successor_index(succ); |
| + |
| + int unreachable_succ = 1 - succ; |
| + instr->block()->MarkSuccEdgeUnreachable(unreachable_succ); |
|
Igor Sheludko
2014/05/30 10:00:41
I would suggest to avoid duplication of the three
Benedikt Meurer
2014/05/31 11:15:46
Done.
|
| + } |
| + |
| void ReduceTransitionElementsKind(HTransitionElementsKind* instr) { |
| HValue* object = instr->object()->ActualValue(); |
| HCheckTableEntry* entry = Find(object); |
| @@ -688,6 +783,7 @@ class HCheckTable : public ZoneObject { |
| } |
| Zone* zone() const { return phase_->zone(); } |
| + MapSet string_maps() const { return phase_->string_maps(); } |
| friend class HCheckMapsEffects; |
| friend class HCheckEliminationPhase; |
| @@ -794,6 +890,7 @@ void HCheckEliminationPhase::PrintStats() { |
| PRINT_STAT(redundant); |
| PRINT_STAT(removed); |
| PRINT_STAT(removed_cho); |
| + PRINT_STAT(removed_cit); |
| PRINT_STAT(narrowed); |
| PRINT_STAT(loads); |
| PRINT_STAT(empty); |