LCOV - code coverage report
Current view: top level - src/crankshaft - hydrogen-removable-simulates.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 52 60 86.7 %
Date: 2017-04-26 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright 2013 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/crankshaft/hydrogen-removable-simulates.h"
       6             : 
       7             : #include "src/crankshaft/hydrogen-flow-engine.h"
       8             : #include "src/crankshaft/hydrogen-instructions.h"
       9             : #include "src/objects-inl.h"
      10             : 
      11             : namespace v8 {
      12             : namespace internal {
      13             : 
      14             : class State : public ZoneObject {
      15             :  public:
      16             :   explicit State(Zone* zone)
      17      283730 :       : zone_(zone), mergelist_(2, zone), first_(true), mode_(NORMAL) { }
      18             : 
      19    23987620 :   State* Process(HInstruction* instr, Zone* zone) {
      20    23987620 :     if (FLAG_trace_removable_simulates) {
      21             :       PrintF("[%s with state %p in B%d: #%d %s]\n",
      22           0 :              mode_ == NORMAL ? "processing" : "collecting",
      23             :              reinterpret_cast<void*>(this), instr->block()->block_id(),
      24           0 :              instr->id(), instr->Mnemonic());
      25             :     }
      26             :     // Forward-merge "trains" of simulates after an instruction with observable
      27             :     // side effects to keep live ranges short.
      28    23987668 :     if (mode_ == COLLECT_CONSECUTIVE_SIMULATES) {
      29     1934946 :       if (instr->IsSimulate()) {
      30       62794 :         HSimulate* current_simulate = HSimulate::cast(instr);
      31       62794 :         if (current_simulate->is_candidate_for_removal() &&
      32             :             !current_simulate->ast_id().IsNone()) {
      33             :           Remember(current_simulate);
      34        2308 :           return this;
      35             :         }
      36             :       }
      37      965165 :       FlushSimulates();
      38      965164 :       mode_ = NORMAL;
      39             :     }
      40             :     // Ensure there's a non-foldable HSimulate before an HEnterInlined to avoid
      41             :     // folding across HEnterInlined.
      42             :     DCHECK(!(instr->IsEnterInlined() &&
      43             :              HSimulate::cast(instr->previous())->is_candidate_for_removal()));
      44    71684629 :     if (instr->IsLeaveInlined() || instr->IsReturn()) {
      45             :       // Never fold simulates from inlined environments into simulates in the
      46             :       // outer environment. Simply remove all accumulated simulates without
      47             :       // merging. This is safe because simulates after instructions with side
      48             :       // effects are never added to the merge list. The same reasoning holds for
      49             :       // return instructions.
      50      631380 :       RemoveSimulates();
      51      631380 :       return this;
      52             :     }
      53    23353991 :     if (instr->IsControlInstruction()) {
      54             :       // Merge the accumulated simulates at the end of the block.
      55     3113796 :       FlushSimulates();
      56     3113793 :       return this;
      57             :     }
      58    20240506 :     if (instr->IsCapturedObject()) {
      59             :       // Do not merge simulates across captured objects - captured objects
      60             :       // change environments during environment replay, and such changes
      61             :       // would not be reflected in the simulate.
      62        7768 :       FlushSimulates();
      63        7768 :       return this;
      64             :     }
      65             :     // Skip the non-simulates and the first simulate.
      66    20232725 :     if (!instr->IsSimulate()) return this;
      67     3975416 :     if (first_) {
      68     2526423 :       first_ = false;
      69     2526423 :       return this;
      70             :     }
      71     1448993 :     HSimulate* current_simulate = HSimulate::cast(instr);
      72     1448993 :     if (!current_simulate->is_candidate_for_removal()) {
      73             :       Remember(current_simulate);
      74      275377 :       FlushSimulates();
      75     1173617 :     } else if (current_simulate->ast_id().IsNone()) {
      76             :       DCHECK(current_simulate->next()->IsEnterInlined());
      77           0 :       FlushSimulates();
      78     2347234 :     } else if (current_simulate->previous()->HasObservableSideEffects()) {
      79             :       Remember(current_simulate);
      80      965165 :       mode_ = COLLECT_CONSECUTIVE_SIMULATES;
      81             :     } else {
      82             :       Remember(current_simulate);
      83             :     }
      84             : 
      85             :     return this;
      86             :   }
      87             : 
      88     3289206 :   static State* Merge(State* succ_state,
      89             :                       HBasicBlock* succ_block,
      90             :                       State* pred_state,
      91             :                       HBasicBlock* pred_block,
      92             :                       Zone* zone) {
      93             :     return (succ_state == NULL)
      94             :         ? pred_state->Copy(succ_block, pred_block, zone)
      95     6578418 :         : succ_state->Merge(succ_block, pred_state, pred_block, zone);
      96             :   }
      97             : 
      98             :   static State* Finish(State* state, HBasicBlock* block, Zone* zone) {
      99     4511617 :     if (FLAG_trace_removable_simulates) {
     100             :       PrintF("[preparing state %p for B%d]\n", reinterpret_cast<void*>(state),
     101           0 :              block->block_id());
     102             :     }
     103             :     // For our current local analysis, we should not remember simulates across
     104             :     // block boundaries.
     105             :     DCHECK(!state->HasRememberedSimulates());
     106             :     // Nasty heuristic: Never remove the first simulate in a block. This
     107             :     // just so happens to have a beneficial effect on register allocation.
     108     4511639 :     state->first_ = true;
     109             :     return state;
     110             :   }
     111             : 
     112             :  private:
     113             :   explicit State(const State& other)
     114             :       : zone_(other.zone_),
     115             :         mergelist_(other.mergelist_, other.zone_),
     116             :         first_(other.first_),
     117     2406543 :         mode_(other.mode_) { }
     118             : 
     119             :   enum Mode { NORMAL, COLLECT_CONSECUTIVE_SIMULATES };
     120             : 
     121     5090658 :   bool HasRememberedSimulates() const { return !mergelist_.is_empty(); }
     122             : 
     123             :   void Remember(HSimulate* sim) {
     124     1451301 :     mergelist_.Add(sim, zone_);
     125             :   }
     126             : 
     127     4362096 :   void FlushSimulates() {
     128     4362096 :     if (HasRememberedSimulates()) {
     129     2554542 :       mergelist_.RemoveLast()->MergeWith(&mergelist_);
     130             :     }
     131     4362094 :   }
     132             : 
     133      631380 :   void RemoveSimulates() {
     134     1359942 :     while (HasRememberedSimulates()) {
     135      194364 :       mergelist_.RemoveLast()->DeleteAndReplaceWith(NULL);
     136             :     }
     137      631380 :   }
     138             : 
     139     2406542 :   State* Copy(HBasicBlock* succ_block, HBasicBlock* pred_block, Zone* zone) {
     140             :     State* copy = new(zone) State(*this);
     141     2406551 :     if (FLAG_trace_removable_simulates) {
     142             :       PrintF("[copy state %p from B%d to new state %p for B%d]\n",
     143             :              reinterpret_cast<void*>(this), pred_block->block_id(),
     144           0 :              reinterpret_cast<void*>(copy), succ_block->block_id());
     145             :     }
     146     2406551 :     return copy;
     147             :   }
     148             : 
     149           0 :   State* Merge(HBasicBlock* succ_block,
     150             :                State* pred_state,
     151           0 :                HBasicBlock* pred_block,
     152             :                Zone* zone) {
     153             :     // For our current local analysis, we should not remember simulates across
     154             :     // block boundaries.
     155             :     DCHECK(!pred_state->HasRememberedSimulates());
     156             :     DCHECK(!HasRememberedSimulates());
     157      882664 :     if (FLAG_trace_removable_simulates) {
     158             :       PrintF("[merge state %p from B%d into %p for B%d]\n",
     159             :              reinterpret_cast<void*>(pred_state), pred_block->block_id(),
     160           0 :              reinterpret_cast<void*>(this), succ_block->block_id());
     161             :     }
     162             :     return this;
     163             :   }
     164             : 
     165             :   Zone* zone_;
     166             :   ZoneList<HSimulate*> mergelist_;
     167             :   bool first_;
     168             :   Mode mode_;
     169             : };
     170             : 
     171             : 
     172             : // We don't use effects here.
     173             : class Effects : public ZoneObject {
     174             :  public:
     175             :   explicit Effects(Zone* zone) { }
     176             :   bool Disabled() { return true; }
     177             :   void Process(HInstruction* instr, Zone* zone) { }
     178             :   void Apply(State* state) { }
     179             :   void Union(Effects* that, Zone* zone) { }
     180             : };
     181             : 
     182             : 
     183      283729 : void HMergeRemovableSimulatesPhase::Run() {
     184      567458 :   HFlowEngine<State, Effects> engine(graph(), zone());
     185             :   State* state = new(zone()) State(zone());
     186      283729 :   engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), state);
     187      283728 : }
     188             : 
     189             : }  // namespace internal
     190             : }  // namespace v8

Generated by: LCOV version 1.10