| Index: src/hydrogen-check-elimination.cc
|
| diff --git a/src/hydrogen-check-elimination.cc b/src/hydrogen-check-elimination.cc
|
| index bbd3042fb7af6659f4107fffb7127e1298000593..ca37fa1c9d9fb3c151aa88b645b1a482b3767cc1 100644
|
| --- a/src/hydrogen-check-elimination.cc
|
| +++ b/src/hydrogen-check-elimination.cc
|
| @@ -101,6 +101,10 @@ class HCheckTable : public ZoneObject {
|
| ReduceCheckHeapObject(HCheckHeapObject::cast(instr));
|
| break;
|
| }
|
| + case HValue::kCompareObjectEqAndBranch: {
|
| + ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr));
|
| + break;
|
| + }
|
| default: {
|
| // If the instruction changes maps uncontrollably, drop everything.
|
| if (instr->CheckGVNFlag(kChangesMaps) ||
|
| @@ -266,6 +270,50 @@ class HCheckTable : public ZoneObject {
|
| }
|
| }
|
|
|
| + void ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch* instr) {
|
| + HCheckMaps* removed = NULL;
|
| + HValue* left = instr->left();
|
| + HValue* right = instr->right();
|
| + if (left->IsCheckMaps() && right->IsCheckMaps()) {
|
| + HCheckMaps* left_check = HCheckMaps::cast(left);
|
| + HCheckMaps* right_check = HCheckMaps::cast(right);
|
| + MapSet left_maps = left_check->map_set().Copy(phase_->zone());
|
| + MapSet right_maps = right_check->map_set().Copy(phase_->zone());
|
| + if (left_maps->Equals(right_maps)) {
|
| + // Object equality comparison guarantees one check suffices, so
|
| + // eliminate the other. After LICM, we could easily find the correct
|
| + // one (loop invariant object's map check could be hoisted out of loop).
|
| + removed = left->block()->block_id() > right->block()->block_id()
|
| + ? left_check : right_check;
|
| + }
|
| + } else if (left->IsCheckMaps() || right->IsCheckMaps()) {
|
| + // For the case one side map check is eliminated by previous optimization.
|
| + HValue* obj = left->IsCheckMaps() ? right : left;
|
| + HCheckMaps* check = (obj == left) ? HCheckMaps::cast(right)
|
| + : HCheckMaps::cast(left);
|
| + MapSet obj_maps = FindMaps(obj);
|
| + MapSet check_maps = check->map_set().Copy(phase_->zone());
|
| + if (obj_maps->IsSubset(check_maps)) {
|
| + // Obj check is more strict; the remaining check is redundant.
|
| + removed = check;
|
| + }
|
| + }
|
| +
|
| + if (removed != NULL) {
|
| + // Check whether there is prior CheckHeapObject refering to the same
|
| + // object as the removed CheckMaps.
|
| + if (removed->previous()->IsCheckHeapObject()) {
|
| + HCheckHeapObject* cho = HCheckHeapObject::cast(removed->previous());
|
| + if (cho->value() == removed->ActualValue()) {
|
| + cho->DeleteAndReplaceWith(cho->value());
|
| + INC_STAT(removed_cho_);
|
| + }
|
| + }
|
| + removed->DeleteAndReplaceWith(removed->ActualValue());
|
| + INC_STAT(removed_);
|
| + }
|
| + }
|
| +
|
| void ReduceStoreNamedField(HStoreNamedField* instr) {
|
| HValue* object = instr->object()->ActualValue();
|
| if (instr->has_transition()) {
|
|
|