LCOV - code coverage report
Current view: top level - src/compiler - schedule.h (source / functions) Hit Total Coverage
Test: app.info Lines: 20 21 95.2 %
Date: 2019-04-17 Functions: 0 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_COMPILER_SCHEDULE_H_
       6             : #define V8_COMPILER_SCHEDULE_H_
       7             : 
       8             : #include <iosfwd>
       9             : 
      10             : #include "src/base/compiler-specific.h"
      11             : #include "src/globals.h"
      12             : #include "src/zone/zone-containers.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : namespace compiler {
      17             : 
      18             : // Forward declarations.
      19             : class BasicBlock;
      20             : class BasicBlockInstrumentor;
      21             : class Node;
      22             : 
      23             : using BasicBlockVector = ZoneVector<BasicBlock*>;
      24             : using NodeVector = ZoneVector<Node*>;
      25             : 
      26             : // A basic block contains an ordered list of nodes and ends with a control
      27             : // node. Note that if a basic block has phis, then all phis must appear as the
      28             : // first nodes in the block.
      29           9 : class V8_EXPORT_PRIVATE BasicBlock final
      30             :     : public NON_EXPORTED_BASE(ZoneObject) {
      31             :  public:
      32             :   // Possible control nodes that can end a block.
      33             :   enum Control {
      34             :     kNone,        // Control not initialized yet.
      35             :     kGoto,        // Goto a single successor block.
      36             :     kCall,        // Call with continuation as first successor, exception
      37             :                   // second.
      38             :     kBranch,      // Branch if true to first successor, otherwise second.
      39             :     kSwitch,      // Table dispatch to one of the successor blocks.
      40             :     kDeoptimize,  // Return a value from this method.
      41             :     kTailCall,    // Tail call another method from this method.
      42             :     kReturn,      // Return a value from this method.
      43             :     kThrow        // Throw an exception.
      44             :   };
      45             : 
      46             :   class Id {
      47             :    public:
      48    10549045 :     int ToInt() const { return static_cast<int>(index_); }
      49    20851306 :     size_t ToSize() const { return index_; }
      50             :     static Id FromSize(size_t index) { return Id(index); }
      51    20848121 :     static Id FromInt(int index) { return Id(static_cast<size_t>(index)); }
      52             : 
      53             :    private:
      54             :     explicit Id(size_t index) : index_(index) {}
      55             :     size_t index_;
      56             :   };
      57             : 
      58             :   BasicBlock(Zone* zone, Id id);
      59             : 
      60             :   Id id() const { return id_; }
      61             : #if DEBUG
      62             :   void set_debug_info(AssemblerDebugInfo debug_info) {
      63             :     debug_info_ = debug_info;
      64             :   }
      65             :   AssemblerDebugInfo debug_info() const { return debug_info_; }
      66             : #endif  // DEBUG
      67             : 
      68             :   void Print();
      69             : 
      70             :   // Predecessors.
      71           7 :   BasicBlockVector& predecessors() { return predecessors_; }
      72             :   const BasicBlockVector& predecessors() const { return predecessors_; }
      73             :   size_t PredecessorCount() const { return predecessors_.size(); }
      74    30951815 :   BasicBlock* PredecessorAt(size_t index) { return predecessors_[index]; }
      75             :   void ClearPredecessors() { predecessors_.clear(); }
      76             :   void AddPredecessor(BasicBlock* predecessor);
      77             : 
      78             :   // Successors.
      79           6 :   BasicBlockVector& successors() { return successors_; }
      80             :   const BasicBlockVector& successors() const { return successors_; }
      81             :   size_t SuccessorCount() const { return successors_.size(); }
      82    63748317 :   BasicBlock* SuccessorAt(size_t index) { return successors_[index]; }
      83             :   void ClearSuccessors() { successors_.clear(); }
      84             :   void AddSuccessor(BasicBlock* successor);
      85             : 
      86             :   // Nodes in the basic block.
      87             :   using value_type = Node*;
      88             :   bool empty() const { return nodes_.empty(); }
      89             :   size_t size() const { return nodes_.size(); }
      90    93189886 :   Node* NodeAt(size_t index) { return nodes_[index]; }
      91             :   size_t NodeCount() const { return nodes_.size(); }
      92             : 
      93             :   value_type& front() { return nodes_.front(); }
      94             :   value_type const& front() const { return nodes_.front(); }
      95             : 
      96             :   using iterator = NodeVector::iterator;
      97             :   iterator begin() { return nodes_.begin(); }
      98             :   iterator end() { return nodes_.end(); }
      99             : 
     100     3966808 :   void RemoveNode(iterator it) { nodes_.erase(it); }
     101             : 
     102             :   using const_iterator = NodeVector::const_iterator;
     103             :   const_iterator begin() const { return nodes_.begin(); }
     104             :   const_iterator end() const { return nodes_.end(); }
     105             : 
     106             :   using reverse_iterator = NodeVector::reverse_iterator;
     107             :   reverse_iterator rbegin() { return nodes_.rbegin(); }
     108             :   reverse_iterator rend() { return nodes_.rend(); }
     109             : 
     110             :   void AddNode(Node* node);
     111             :   template <class InputIterator>
     112             :   void InsertNodes(iterator insertion_point, InputIterator insertion_start,
     113             :                    InputIterator insertion_end) {
     114          48 :     nodes_.insert(insertion_point, insertion_start, insertion_end);
     115             :   }
     116             : 
     117             :   // Accessors.
     118             :   Control control() const { return control_; }
     119             :   void set_control(Control control);
     120             : 
     121             :   Node* control_input() const { return control_input_; }
     122             :   void set_control_input(Node* control_input);
     123             : 
     124             :   bool deferred() const { return deferred_; }
     125    27660277 :   void set_deferred(bool deferred) { deferred_ = deferred; }
     126             : 
     127             :   int32_t dominator_depth() const { return dominator_depth_; }
     128    27086797 :   void set_dominator_depth(int32_t depth) { dominator_depth_ = depth; }
     129             : 
     130             :   BasicBlock* dominator() const { return dominator_; }
     131    24218639 :   void set_dominator(BasicBlock* dominator) { dominator_ = dominator; }
     132             : 
     133             :   BasicBlock* rpo_next() const { return rpo_next_; }
     134    40568556 :   void set_rpo_next(BasicBlock* rpo_next) { rpo_next_ = rpo_next; }
     135             : 
     136             :   BasicBlock* loop_header() const { return loop_header_; }
     137             :   void set_loop_header(BasicBlock* loop_header);
     138             : 
     139             :   BasicBlock* loop_end() const { return loop_end_; }
     140             :   void set_loop_end(BasicBlock* loop_end);
     141             : 
     142             :   int32_t loop_depth() const { return loop_depth_; }
     143             :   void set_loop_depth(int32_t loop_depth);
     144             : 
     145             :   int32_t loop_number() const { return loop_number_; }
     146      272485 :   void set_loop_number(int32_t loop_number) { loop_number_ = loop_number; }
     147             : 
     148             :   int32_t rpo_number() const { return rpo_number_; }
     149             :   void set_rpo_number(int32_t rpo_number);
     150             : 
     151             :   // Loop membership helpers.
     152             :   inline bool IsLoopHeader() const { return loop_end_ != nullptr; }
     153             :   bool LoopContains(BasicBlock* block) const;
     154             : 
     155             :   // Computes the immediate common dominator of {b1} and {b2}. The worst time
     156             :   // complexity is O(N) where N is the height of the dominator tree.
     157             :   static BasicBlock* GetCommonDominator(BasicBlock* b1, BasicBlock* b2);
     158             : 
     159             :  private:
     160             :   int32_t loop_number_;      // loop number of the block.
     161             :   int32_t rpo_number_;       // special RPO number of the block.
     162             :   bool deferred_;            // true if the block contains deferred code.
     163             :   int32_t dominator_depth_;  // Depth within the dominator tree.
     164             :   BasicBlock* dominator_;    // Immediate dominator of the block.
     165             :   BasicBlock* rpo_next_;     // Link to next block in special RPO order.
     166             :   BasicBlock* loop_header_;  // Pointer to dominating loop header basic block,
     167             :   // nullptr if none. For loop headers, this points to
     168             :   // enclosing loop header.
     169             :   BasicBlock* loop_end_;  // end of the loop, if this block is a loop header.
     170             :   int32_t loop_depth_;    // loop nesting, 0 is top-level
     171             : 
     172             :   Control control_;      // Control at the end of the block.
     173             :   Node* control_input_;  // Input value for control.
     174             :   NodeVector nodes_;     // nodes of this block in forward order.
     175             : 
     176             :   BasicBlockVector successors_;
     177             :   BasicBlockVector predecessors_;
     178             : #if DEBUG
     179             :   AssemblerDebugInfo debug_info_;
     180             : #endif
     181             :   Id id_;
     182             : 
     183             :   DISALLOW_COPY_AND_ASSIGN(BasicBlock);
     184             : };
     185             : 
     186             : std::ostream& operator<<(std::ostream&, const BasicBlock&);
     187             : std::ostream& operator<<(std::ostream&, const BasicBlock::Control&);
     188             : std::ostream& operator<<(std::ostream&, const BasicBlock::Id&);
     189             : 
     190             : // A schedule represents the result of assigning nodes to basic blocks
     191             : // and ordering them within basic blocks. Prior to computing a schedule,
     192             : // a graph has no notion of control flow ordering other than that induced
     193             : // by the graph's dependencies. A schedule is required to generate code.
     194         226 : class V8_EXPORT_PRIVATE Schedule final : public NON_EXPORTED_BASE(ZoneObject) {
     195             :  public:
     196             :   explicit Schedule(Zone* zone, size_t node_count_hint = 0);
     197             : 
     198             :   // Return the block which contains {node}, if any.
     199             :   BasicBlock* block(Node* node) const;
     200             : 
     201             :   bool IsScheduled(Node* node);
     202             :   BasicBlock* GetBlockById(BasicBlock::Id block_id);
     203             : 
     204             :   size_t BasicBlockCount() const { return all_blocks_.size(); }
     205             :   size_t RpoBlockCount() const { return rpo_order_.size(); }
     206             : 
     207             :   // Check if nodes {a} and {b} are in the same block.
     208             :   bool SameBasicBlock(Node* a, Node* b) const;
     209             : 
     210             :   // BasicBlock building: create a new block.
     211             :   BasicBlock* NewBasicBlock();
     212             : 
     213             :   // BasicBlock building: records that a node will later be added to a block but
     214             :   // doesn't actually add the node to the block.
     215             :   void PlanNode(BasicBlock* block, Node* node);
     216             : 
     217             :   // BasicBlock building: add a node to the end of the block.
     218             :   void AddNode(BasicBlock* block, Node* node);
     219             : 
     220             :   // BasicBlock building: add a goto to the end of {block}.
     221             :   void AddGoto(BasicBlock* block, BasicBlock* succ);
     222             : 
     223             :   // BasicBlock building: add a call at the end of {block}.
     224             :   void AddCall(BasicBlock* block, Node* call, BasicBlock* success_block,
     225             :                BasicBlock* exception_block);
     226             : 
     227             :   // BasicBlock building: add a branch at the end of {block}.
     228             :   void AddBranch(BasicBlock* block, Node* branch, BasicBlock* tblock,
     229             :                  BasicBlock* fblock);
     230             : 
     231             :   // BasicBlock building: add a switch at the end of {block}.
     232             :   void AddSwitch(BasicBlock* block, Node* sw, BasicBlock** succ_blocks,
     233             :                  size_t succ_count);
     234             : 
     235             :   // BasicBlock building: add a deoptimize at the end of {block}.
     236             :   void AddDeoptimize(BasicBlock* block, Node* input);
     237             : 
     238             :   // BasicBlock building: add a tailcall at the end of {block}.
     239             :   void AddTailCall(BasicBlock* block, Node* input);
     240             : 
     241             :   // BasicBlock building: add a return at the end of {block}.
     242             :   void AddReturn(BasicBlock* block, Node* input);
     243             : 
     244             :   // BasicBlock building: add a throw at the end of {block}.
     245             :   void AddThrow(BasicBlock* block, Node* input);
     246             : 
     247             :   // BasicBlock mutation: insert a branch into the end of {block}.
     248             :   void InsertBranch(BasicBlock* block, BasicBlock* end, Node* branch,
     249             :                     BasicBlock* tblock, BasicBlock* fblock);
     250             : 
     251             :   // BasicBlock mutation: insert a switch into the end of {block}.
     252             :   void InsertSwitch(BasicBlock* block, BasicBlock* end, Node* sw,
     253             :                     BasicBlock** succ_blocks, size_t succ_count);
     254             : 
     255             :   // Exposed publicly for testing only.
     256             :   void AddSuccessorForTesting(BasicBlock* block, BasicBlock* succ) {
     257        2159 :     return AddSuccessor(block, succ);
     258             :   }
     259             : 
     260           0 :   const BasicBlockVector* all_blocks() const { return &all_blocks_; }
     261      249018 :   BasicBlockVector* rpo_order() { return &rpo_order_; }
     262          28 :   const BasicBlockVector* rpo_order() const { return &rpo_order_; }
     263             : 
     264             :   BasicBlock* start() { return start_; }
     265             :   BasicBlock* end() { return end_; }
     266             : 
     267             :   Zone* zone() const { return zone_; }
     268             : 
     269             :  private:
     270             :   friend class Scheduler;
     271             :   friend class BasicBlockInstrumentor;
     272             :   friend class RawMachineAssembler;
     273             : 
     274             :   // For CSA/Torque: Ensure properties of the CFG assumed by further stages.
     275             :   void EnsureCFGWellFormedness();
     276             :   // For CSA/Torque: Eliminates unnecessary phi nodes, including phis with a
     277             :   // single input. The latter is necessary to ensure the property required for
     278             :   // SSA deconstruction that the target block of a control flow split has no
     279             :   // phis.
     280             :   void EliminateRedundantPhiNodes();
     281             :   // Ensure split-edge form for a hand-assembled schedule.
     282             :   void EnsureSplitEdgeForm(BasicBlock* block);
     283             :   // Ensure entry into a deferred block happens from a single hot block.
     284             :   void EnsureDeferredCodeSingleEntryPoint(BasicBlock* block);
     285             :   // Move Phi operands to newly created merger blocks
     286             :   void MovePhis(BasicBlock* from, BasicBlock* to);
     287             :   // Copy deferred block markers down as far as possible
     288             :   void PropagateDeferredMark();
     289             : 
     290             :   void AddSuccessor(BasicBlock* block, BasicBlock* succ);
     291             :   void MoveSuccessors(BasicBlock* from, BasicBlock* to);
     292             : 
     293             :   void SetControlInput(BasicBlock* block, Node* node);
     294             :   void SetBlockForNode(BasicBlock* block, Node* node);
     295             : 
     296             :   Zone* zone_;
     297             :   BasicBlockVector all_blocks_;       // All basic blocks in the schedule.
     298             :   BasicBlockVector nodeid_to_block_;  // Map from node to containing block.
     299             :   BasicBlockVector rpo_order_;        // Reverse-post-order block list.
     300             :   BasicBlock* start_;
     301             :   BasicBlock* end_;
     302             : 
     303             :   DISALLOW_COPY_AND_ASSIGN(Schedule);
     304             : };
     305             : 
     306             : V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream&, const Schedule&);
     307             : 
     308             : }  // namespace compiler
     309             : }  // namespace internal
     310             : }  // namespace v8
     311             : 
     312             : #endif  // V8_COMPILER_SCHEDULE_H_

Generated by: LCOV version 1.10