LCOV - code coverage report
Current view: top level - src/crankshaft - hydrogen-flow-engine.h (source / functions) Hit Total Coverage
Test: app.info Lines: 46 48 95.8 %
Date: 2017-04-26 Functions: 15 15 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             : #ifndef V8_CRANKSHAFT_HYDROGEN_FLOW_ENGINE_H_
       6             : #define V8_CRANKSHAFT_HYDROGEN_FLOW_ENGINE_H_
       7             : 
       8             : #include "src/crankshaft/hydrogen-instructions.h"
       9             : #include "src/crankshaft/hydrogen.h"
      10             : #include "src/zone/zone.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : // An example implementation of effects that doesn't collect anything.
      16             : class NoEffects : public ZoneObject {
      17             :  public:
      18             :   explicit NoEffects(Zone* zone) { }
      19             : 
      20             :   inline bool Disabled() {
      21             :     return true;  // Nothing to do.
      22             :   }
      23             :   template <class State>
      24             :   inline void Apply(State* state) {
      25             :     // do nothing.
      26             :   }
      27             :   inline void Process(HInstruction* value, Zone* zone) {
      28             :     // do nothing.
      29             :   }
      30             :   inline void Union(NoEffects* other, Zone* zone) {
      31             :     // do nothing.
      32             :   }
      33             : };
      34             : 
      35             : 
      36             : // An example implementation of state that doesn't track anything.
      37             : class NoState {
      38             :  public:
      39             :   inline NoState* Copy(HBasicBlock* succ, Zone* zone) {
      40             :     return this;
      41             :   }
      42             :   inline NoState* Process(HInstruction* value, Zone* zone) {
      43             :     return this;
      44             :   }
      45             :   inline NoState* Merge(HBasicBlock* succ, NoState* other, Zone* zone) {
      46             :     return this;
      47             :   }
      48             : };
      49             : 
      50             : 
      51             : // This class implements an engine that can drive flow-sensitive analyses
      52             : // over a graph of basic blocks, either one block at a time (local analysis)
      53             : // or over the entire graph (global analysis). The flow engine is parameterized
      54             : // by the type of the state and the effects collected while walking over the
      55             : // graph.
      56             : //
      57             : // The "State" collects which facts are known while passing over instructions
      58             : // in control flow order, and the "Effects" collect summary information about
      59             : // which facts could be invalidated on other control flow paths. The effects
      60             : // are necessary to correctly handle loops in the control flow graph without
      61             : // doing a fixed-point iteration. Thus the flow engine is guaranteed to visit
      62             : // each block at most twice; once for state, and optionally once for effects.
      63             : //
      64             : // The flow engine requires the State and Effects classes to implement methods
      65             : // like the example NoState and NoEffects above. It's not necessary to provide
      66             : // an effects implementation for local analysis.
      67             : template <class State, class Effects>
      68             : class HFlowEngine {
      69             :  public:
      70      851189 :   HFlowEngine(HGraph* graph, Zone* zone)
      71             :     : graph_(graph),
      72             :       zone_(zone),
      73             : #if DEBUG
      74             :       pred_counts_(graph->blocks()->length(), zone),
      75             : #endif
      76             :       block_states_(graph->blocks()->length(), zone),
      77      851189 :       loop_effects_(graph->blocks()->length(), zone) {
      78      851189 :     loop_effects_.AddBlock(NULL, graph_->blocks()->length(), zone);
      79      851189 :   }
      80             : 
      81             :   // Local analysis. Iterates over the instructions in the given block.
      82             :   State* AnalyzeOneBlock(HBasicBlock* block, State* state) {
      83             :     // Go through all instructions of the current block, updating the state.
      84             :     for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
      85             :       state = state->Process(it.Current(), zone_);
      86             :     }
      87             :     return state;
      88             :   }
      89             : 
      90             :   // Global analysis. Iterates over all blocks that are dominated by the given
      91             :   // block, starting with the initial state. Computes effects for nested loops.
      92     1702365 :   void AnalyzeDominatedBlocks(HBasicBlock* root, State* initial) {
      93      851184 :     InitializeStates();
      94             :     SetStateAt(root, initial);
      95             : 
      96             :     // Iterate all dominated blocks starting from the given start block.
      97    14386118 :     for (int i = root->block_id(); i < graph_->blocks()->length(); i++) {
      98    42401560 :       HBasicBlock* block = graph_->blocks()->at(i);
      99             : 
     100             :       // Skip blocks not dominated by the root node.
     101    13534933 :       if (SkipNonDominatedBlock(root, block)) continue;
     102     4511633 :       State* state = State::Finish(StateAt(block), block, zone_);
     103             : 
     104    13534955 :       if (block->IsReachable()) {
     105             :         DCHECK(state != NULL);
     106    10403702 :         if (block->IsLoopHeader()) {
     107             :           // Apply loop effects before analyzing loop body.
     108      154590 :           ComputeLoopEffects(block)->Apply(state);
     109             :         } else {
     110             :           // Must have visited all predecessors before this block.
     111             :           CheckPredecessorCount(block);
     112             :         }
     113             : 
     114             :         // Go through all instructions of the current block, updating the state.
     115    79300827 :         for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
     116    68897134 :           state = state->Process(it.Current(), zone_);
     117             :         }
     118             :       }
     119             : 
     120             :       // Propagate the block state forward to all successor blocks.
     121    13534946 :       int max = block->end()->SuccessorCount();
     122    28866602 :       for (int i = 0; i < max; i++) {
     123    15331681 :         HBasicBlock* succ = block->end()->SuccessorAt(i);
     124             :         IncrementPredecessorCount(succ);
     125             : 
     126    15331669 :         if (max == 1 && succ->predecessors()->length() == 1) {
     127             :           // Optimization: successor can inherit this state.
     128             :           SetStateAt(succ, state);
     129             :         } else {
     130             :           // Merge the current state with the state already at the successor.
     131             :           SetStateAt(succ,
     132    19735244 :                      State::Merge(StateAt(succ), succ, state, block, zone_));
     133             :         }
     134             :       }
     135             :     }
     136      851185 :   }
     137             : 
     138             :  private:
     139             :   // Computes and caches the loop effects for the loop which has the given
     140             :   // block as its loop header.
     141     2236745 :   Effects* ComputeLoopEffects(HBasicBlock* block) {
     142             :     DCHECK(block->IsLoopHeader());
     143      497397 :     Effects* effects = loop_effects_[block->block_id()];
     144      169642 :     if (effects != NULL) return effects;  // Already analyzed this loop.
     145             : 
     146      264320 :     effects = new(zone_) Effects(zone_);
     147      158113 :     loop_effects_[block->block_id()] = effects;
     148       51906 :     if (effects->Disabled()) return effects;  // No effects for this analysis.
     149             : 
     150             :     HLoopInformation* loop = block->loop_information();
     151      106207 :     int end = loop->GetLastBackEdge()->block_id();
     152             :     // Process the blocks between the header and the end.
     153     1802783 :     for (int i = block->block_id(); i <= end; i++) {
     154     3408204 :       HBasicBlock* member = graph_->blocks()->at(i);
     155     3286945 :       if (i != block->block_id() && member->IsLoopHeader()) {
     156             :         // Recursively compute and cache the effects of the nested loop.
     157             :         DCHECK(member->loop_information()->parent_loop() == loop);
     158       15052 :         Effects* nested = ComputeLoopEffects(member);
     159       15052 :         effects->Union(nested, zone_);
     160             :         // Skip the nested loop's blocks.
     161       15052 :         i = member->loop_information()->GetLastBackEdge()->block_id();
     162             :       } else {
     163             :         // Process all the effects of the block.
     164     1681524 :         if (member->IsUnreachable()) continue;
     165             :         DCHECK(member->current_loop() == loop);
     166     8387119 :         for (HInstructionIterator it(member); !it.Done(); it.Advance()) {
     167     7103054 :           effects->Process(it.Current(), zone_);
     168             :         }
     169             :       }
     170             :     }
     171             :     return effects;
     172             :   }
     173             : 
     174    13534931 :   inline bool SkipNonDominatedBlock(HBasicBlock* root, HBasicBlock* other) {
     175    13534931 :     if (root->block_id() == 0) return false;  // Visit the whole graph.
     176           0 :     if (root == other) return false;          // Always visit the root.
     177           0 :     return !root->Dominates(other);           // Only visit dominated blocks.
     178             :   }
     179             : 
     180    23402552 :   inline State* StateAt(HBasicBlock* block) {
     181    23402552 :     return block_states_.at(block->block_id());
     182             :   }
     183             : 
     184    16182871 :   inline void SetStateAt(HBasicBlock* block, State* state) {
     185    16182871 :     block_states_.Set(block->block_id(), state);
     186             :   }
     187             : 
     188      851184 :   inline void InitializeStates() {
     189             : #if DEBUG
     190             :     pred_counts_.Rewind(0);
     191             :     pred_counts_.AddBlock(0, graph_->blocks()->length(), zone_);
     192             : #endif
     193             :     block_states_.Rewind(0);
     194      851184 :     block_states_.AddBlock(NULL, graph_->blocks()->length(), zone_);
     195      851184 :   }
     196             : 
     197             :   inline void CheckPredecessorCount(HBasicBlock* block) {
     198             :     DCHECK(block->predecessors()->length() == pred_counts_[block->block_id()]);
     199             :   }
     200             : 
     201             :   inline void IncrementPredecessorCount(HBasicBlock* block) {
     202             : #if DEBUG
     203             :     pred_counts_[block->block_id()]++;
     204             : #endif
     205             :   }
     206             : 
     207             :   HGraph* graph_;                    // The hydrogen graph.
     208             :   Zone* zone_;                       // Temporary zone.
     209             : #if DEBUG
     210             :   ZoneList<int> pred_counts_;        // Finished predecessors (by block id).
     211             : #endif
     212             :   ZoneList<State*> block_states_;    // Block states (by block id).
     213             :   ZoneList<Effects*> loop_effects_;  // Loop effects (by block id).
     214             : };
     215             : 
     216             : 
     217             : }  // namespace internal
     218             : }  // namespace v8
     219             : 
     220             : #endif  // V8_CRANKSHAFT_HYDROGEN_FLOW_ENGINE_H_

Generated by: LCOV version 1.10