| Index: src/hydrogen.cc
 | 
| diff --git a/src/hydrogen.cc b/src/hydrogen.cc
 | 
| index f9d41910f31edb9f1bbbda6ac22ec0ce5935d1c0..583a825fe3c2732a714d7ccbe7382fa6d4b18911 100644
 | 
| --- a/src/hydrogen.cc
 | 
| +++ b/src/hydrogen.cc
 | 
| @@ -1321,6 +1321,38 @@ void HValueMap::Insert(HValue* value) {
 | 
|  }
 | 
|  
 | 
|  
 | 
| +HSideEffectMap::HSideEffectMap() : count_(0) {
 | 
| +  memset(data_, 0, kNumberOfTrackedSideEffects * kPointerSize);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +HSideEffectMap::HSideEffectMap(HSideEffectMap* other) : count_(other->count_) {
 | 
| +  memcpy(data_, other->data_, kNumberOfTrackedSideEffects * kPointerSize);
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void HSideEffectMap::Kill(GVNFlagSet flags) {
 | 
| +  for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
 | 
| +    GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
 | 
| +    if (flags.Contains(changes_flag)) {
 | 
| +      if (data_[i] != NULL) count_--;
 | 
| +      data_[i] = NULL;
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
| +void HSideEffectMap::Store(GVNFlagSet flags, HInstruction* instr) {
 | 
| +  for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
 | 
| +    GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
 | 
| +    if (flags.Contains(changes_flag)) {
 | 
| +      if (data_[i] == NULL) count_++;
 | 
| +      data_[i] = instr;
 | 
| +    }
 | 
| +  }
 | 
| +}
 | 
| +
 | 
| +
 | 
|  class HStackCheckEliminator BASE_EMBEDDED {
 | 
|   public:
 | 
|    explicit HStackCheckEliminator(HGraph* graph) : graph_(graph) { }
 | 
| @@ -1427,7 +1459,9 @@ class HGlobalValueNumberer BASE_EMBEDDED {
 | 
|    GVNFlagSet CollectSideEffectsOnPathsToDominatedBlock(
 | 
|        HBasicBlock* dominator,
 | 
|        HBasicBlock* dominated);
 | 
| -  void AnalyzeBlock(HBasicBlock* block, HValueMap* map);
 | 
| +  void AnalyzeBlock(HBasicBlock* block,
 | 
| +                    HValueMap* map,
 | 
| +                    HSideEffectMap* dominators);
 | 
|    void ComputeBlockSideEffects();
 | 
|    void LoopInvariantCodeMotion();
 | 
|    void ProcessLoopBlock(HBasicBlock* block,
 | 
| @@ -1465,7 +1499,8 @@ bool HGlobalValueNumberer::Analyze() {
 | 
|      LoopInvariantCodeMotion();
 | 
|    }
 | 
|    HValueMap* map = new(zone()) HValueMap();
 | 
| -  AnalyzeBlock(graph_->entry_block(), map);
 | 
| +  HSideEffectMap side_effect_dominators;
 | 
| +  AnalyzeBlock(graph_->entry_block(), map, &side_effect_dominators);
 | 
|    return removed_side_effects_;
 | 
|  }
 | 
|  
 | 
| @@ -1660,7 +1695,9 @@ GVNFlagSet HGlobalValueNumberer::CollectSideEffectsOnPathsToDominatedBlock(
 | 
|  }
 | 
|  
 | 
|  
 | 
| -void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
 | 
| +void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block,
 | 
| +                                        HValueMap* map,
 | 
| +                                        HSideEffectMap* dominators) {
 | 
|    TraceGVN("Analyzing block B%d%s\n",
 | 
|             block->block_id(),
 | 
|             block->IsLoopHeader() ? " (loop header)" : "");
 | 
| @@ -1677,7 +1714,9 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
 | 
|      GVNFlagSet flags = instr->ChangesFlags();
 | 
|      if (!flags.IsEmpty()) {
 | 
|        // Clear all instructions in the map that are affected by side effects.
 | 
| +      // Store instruction as the dominating one for tracked side effects.
 | 
|        map->Kill(flags);
 | 
| +      dominators->Store(flags, instr);
 | 
|        TraceGVN("Instruction %d kills\n", instr->id());
 | 
|      }
 | 
|      if (instr->CheckFlag(HValue::kUseGVN)) {
 | 
| @@ -1696,6 +1735,23 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
 | 
|          map->Add(instr);
 | 
|        }
 | 
|      }
 | 
| +    if (instr->CheckFlag(HValue::kTrackSideEffectDominators)) {
 | 
| +      for (int i = 0; i < kNumberOfTrackedSideEffects; i++) {
 | 
| +        HValue* other = dominators->at(i);
 | 
| +        GVNFlag changes_flag = HValue::ChangesFlagFromInt(i);
 | 
| +        GVNFlag depends_on_flag = HValue::DependsOnFlagFromInt(i);
 | 
| +        if (instr->DependsOnFlags().Contains(depends_on_flag) &&
 | 
| +            (other != NULL)) {
 | 
| +          TraceGVN("Side-effect #%d in %d (%s) is dominated by %d (%s)\n",
 | 
| +                   i,
 | 
| +                   instr->id(),
 | 
| +                   instr->Mnemonic(),
 | 
| +                   other->id(),
 | 
| +                   other->Mnemonic());
 | 
| +          instr->SetSideEffectDominator(changes_flag, other);
 | 
| +        }
 | 
| +      }
 | 
| +    }
 | 
|      instr = next;
 | 
|    }
 | 
|  
 | 
| @@ -1705,20 +1761,22 @@ void HGlobalValueNumberer::AnalyzeBlock(HBasicBlock* block, HValueMap* map) {
 | 
|      HBasicBlock* dominated = block->dominated_blocks()->at(i);
 | 
|      // No need to copy the map for the last child in the dominator tree.
 | 
|      HValueMap* successor_map = (i == length - 1) ? map : map->Copy(zone());
 | 
| +    HSideEffectMap successor_dominators(dominators);
 | 
|  
 | 
|      // Kill everything killed on any path between this block and the
 | 
| -    // dominated block.
 | 
| -    // We don't have to traverse these paths if the value map is
 | 
| -    // already empty.
 | 
| -    // If the range of block ids (block_id, dominated_id) is empty
 | 
| -    // there are no such paths.
 | 
| -    if (!successor_map->IsEmpty() &&
 | 
| +    // dominated block.  We don't have to traverse these paths if the
 | 
| +    // value map and the dominators list is already empty.  If the range
 | 
| +    // of block ids (block_id, dominated_id) is empty there are no such
 | 
| +    // paths.
 | 
| +    if ((!successor_map->IsEmpty() || !successor_dominators.IsEmpty()) &&
 | 
|          block->block_id() + 1 < dominated->block_id()) {
 | 
|        visited_on_paths_.Clear();
 | 
| -      successor_map->Kill(CollectSideEffectsOnPathsToDominatedBlock(block,
 | 
| -                                                                    dominated));
 | 
| +      GVNFlagSet side_effects_on_all_paths =
 | 
| +          CollectSideEffectsOnPathsToDominatedBlock(block, dominated);
 | 
| +      successor_map->Kill(side_effects_on_all_paths);
 | 
| +      successor_dominators.Kill(side_effects_on_all_paths);
 | 
|      }
 | 
| -    AnalyzeBlock(dominated, successor_map);
 | 
| +    AnalyzeBlock(dominated, successor_map, &successor_dominators);
 | 
|    }
 | 
|  }
 | 
|  
 | 
| 
 |