src/share/vm/ci/ciTypeFlow.hpp

changeset 802
194b8e3a2fc4
parent 738
fa4d1d240383
child 815
eb28cf662f56
     1.1 --- a/src/share/vm/ci/ciTypeFlow.hpp	Wed Sep 17 08:29:17 2008 -0700
     1.2 +++ b/src/share/vm/ci/ciTypeFlow.hpp	Wed Sep 17 12:59:52 2008 -0700
     1.3 @@ -34,11 +34,13 @@
     1.4    int _max_locals;
     1.5    int _max_stack;
     1.6    int _code_size;
     1.7 +  bool      _has_irreducible_entry;
     1.8  
     1.9    const char* _failure_reason;
    1.10  
    1.11  public:
    1.12    class StateVector;
    1.13 +  class Loop;
    1.14    class Block;
    1.15  
    1.16    // Build a type flow analyzer
    1.17 @@ -55,6 +57,7 @@
    1.18    int       max_stack() const  { return _max_stack; }
    1.19    int       max_cells() const  { return _max_locals + _max_stack; }
    1.20    int       code_size() const  { return _code_size; }
    1.21 +  bool      has_irreducible_entry() const { return _has_irreducible_entry; }
    1.22  
    1.23    // Represents information about an "active" jsr call.  This
    1.24    // class represents a call to the routine at some entry address
    1.25 @@ -125,6 +128,19 @@
    1.26      void print_on(outputStream* st) const PRODUCT_RETURN;
    1.27    };
    1.28  
    1.29 +  class LocalSet VALUE_OBJ_CLASS_SPEC {
    1.30 +  private:
    1.31 +    enum Constants { max = 63 };
    1.32 +    uint64_t _bits;
    1.33 +  public:
    1.34 +    LocalSet() : _bits(0) {}
    1.35 +    void add(uint32_t i)        { if (i < (uint32_t)max) _bits |=  (1LL << i); }
    1.36 +    void add(LocalSet* ls)      { _bits |= ls->_bits; }
    1.37 +    bool test(uint32_t i) const { return i < (uint32_t)max ? (_bits>>i)&1U : true; }
    1.38 +    void clear()                { _bits = 0; }
    1.39 +    void print_on(outputStream* st, int limit) const  PRODUCT_RETURN;
    1.40 +  };
    1.41 +
    1.42    // Used as a combined index for locals and temps
    1.43    enum Cell {
    1.44      Cell_0, Cell_max = INT_MAX
    1.45 @@ -142,6 +158,8 @@
    1.46      int         _trap_bci;
    1.47      int         _trap_index;
    1.48  
    1.49 +    LocalSet    _def_locals;  // For entire block
    1.50 +
    1.51      static ciType* type_meet_internal(ciType* t1, ciType* t2, ciTypeFlow* analyzer);
    1.52  
    1.53    public:
    1.54 @@ -181,6 +199,9 @@
    1.55      int         monitor_count() const  { return _monitor_count; }
    1.56      void    set_monitor_count(int mc)  { _monitor_count = mc; }
    1.57  
    1.58 +    LocalSet* def_locals() { return &_def_locals; }
    1.59 +    const LocalSet* def_locals() const { return &_def_locals; }
    1.60 +
    1.61      static Cell start_cell()           { return (Cell)0; }
    1.62      static Cell next_cell(Cell c)      { return (Cell)(((int)c) + 1); }
    1.63      Cell        limit_cell() const {
    1.64 @@ -250,6 +271,10 @@
    1.65        return type->basic_type() == T_DOUBLE;
    1.66      }
    1.67  
    1.68 +    void store_to_local(int lnum) {
    1.69 +      _def_locals.add((uint) lnum);
    1.70 +    }
    1.71 +
    1.72      void      push_translate(ciType* type);
    1.73  
    1.74      void      push_int() {
    1.75 @@ -358,6 +383,7 @@
    1.76               "must be reference type or return address");
    1.77        overwrite_local_double_long(index);
    1.78        set_type_at(local(index), type);
    1.79 +      store_to_local(index);
    1.80      }
    1.81  
    1.82      void load_local_double(int index) {
    1.83 @@ -376,6 +402,8 @@
    1.84        overwrite_local_double_long(index);
    1.85        set_type_at(local(index), type);
    1.86        set_type_at(local(index+1), type2);
    1.87 +      store_to_local(index);
    1.88 +      store_to_local(index+1);
    1.89      }
    1.90  
    1.91      void load_local_float(int index) {
    1.92 @@ -388,6 +416,7 @@
    1.93        assert(is_float(type), "must be float type");
    1.94        overwrite_local_double_long(index);
    1.95        set_type_at(local(index), type);
    1.96 +      store_to_local(index);
    1.97      }
    1.98  
    1.99      void load_local_int(int index) {
   1.100 @@ -400,6 +429,7 @@
   1.101        assert(is_int(type), "must be int type");
   1.102        overwrite_local_double_long(index);
   1.103        set_type_at(local(index), type);
   1.104 +      store_to_local(index);
   1.105      }
   1.106  
   1.107      void load_local_long(int index) {
   1.108 @@ -418,6 +448,8 @@
   1.109        overwrite_local_double_long(index);
   1.110        set_type_at(local(index), type);
   1.111        set_type_at(local(index+1), type2);
   1.112 +      store_to_local(index);
   1.113 +      store_to_local(index+1);
   1.114      }
   1.115  
   1.116      // Stop interpretation of this path with a trap.
   1.117 @@ -450,13 +482,31 @@
   1.118    };
   1.119  
   1.120    // Parameter for "find_block" calls:
   1.121 -  // Describes the difference between a public and private copy.
   1.122 +  // Describes the difference between a public and backedge copy.
   1.123    enum CreateOption {
   1.124      create_public_copy,
   1.125 -    create_private_copy,
   1.126 +    create_backedge_copy,
   1.127      no_create
   1.128    };
   1.129  
   1.130 +  // Successor iterator
   1.131 +  class SuccIter : public StackObj {
   1.132 +  private:
   1.133 +    Block* _pred;
   1.134 +    int    _index;
   1.135 +    Block* _succ;
   1.136 +  public:
   1.137 +    SuccIter()                        : _pred(NULL), _index(-1), _succ(NULL) {}
   1.138 +    SuccIter(Block* pred)             : _pred(pred), _index(-1), _succ(NULL) { next(); }
   1.139 +    int    index()     { return _index; }
   1.140 +    Block* pred()      { return _pred; }           // Return predecessor
   1.141 +    bool   done()      { return _index < 0; }      // Finished?
   1.142 +    Block* succ()      { return _succ; }           // Return current successor
   1.143 +    void   next();                                 // Advance
   1.144 +    void   set_succ(Block* succ);                  // Update current successor
   1.145 +    bool   is_normal_ctrl() { return index() < _pred->successors()->length(); }
   1.146 +  };
   1.147 +
   1.148    // A basic block
   1.149    class Block : public ResourceObj {
   1.150    private:
   1.151 @@ -470,15 +520,24 @@
   1.152      int                              _trap_bci;
   1.153      int                              _trap_index;
   1.154  
   1.155 -    // A reasonable approximation to pre-order, provided.to the client.
   1.156 +    // pre_order, assigned at first visit. Used as block ID and "visited" tag
   1.157      int                              _pre_order;
   1.158  
   1.159 -    // Has this block been cloned for some special purpose?
   1.160 -    bool                             _private_copy;
   1.161 +    // A post-order, used to compute the reverse post order (RPO) provided to the client
   1.162 +    int                              _post_order;  // used to compute rpo
   1.163 +
   1.164 +    // Has this block been cloned for a loop backedge?
   1.165 +    bool                             _backedge_copy;
   1.166  
   1.167      // A pointer used for our internal work list
   1.168 -    Block*                 _next;
   1.169 -    bool                   _on_work_list;
   1.170 +    Block*                           _next;
   1.171 +    bool                             _on_work_list;      // on the work list
   1.172 +    Block*                           _rpo_next;          // Reverse post order list
   1.173 +
   1.174 +    // Loop info
   1.175 +    Loop*                            _loop;              // nearest loop
   1.176 +    bool                             _irreducible_entry; // entry to irreducible loop
   1.177 +    bool                             _exception_entry;   // entry to exception handler
   1.178  
   1.179      ciBlock*     ciblock() const     { return _ciblock; }
   1.180      StateVector* state() const     { return _state; }
   1.181 @@ -504,10 +563,11 @@
   1.182      int start() const         { return _ciblock->start_bci(); }
   1.183      int limit() const         { return _ciblock->limit_bci(); }
   1.184      int control() const       { return _ciblock->control_bci(); }
   1.185 +    JsrSet* jsrs() const      { return _jsrs; }
   1.186  
   1.187 -    bool    is_private_copy() const       { return _private_copy; }
   1.188 -    void   set_private_copy(bool z);
   1.189 -    int        private_copy_count() const { return outer()->private_copy_count(ciblock()->index(), _jsrs); }
   1.190 +    bool    is_backedge_copy() const       { return _backedge_copy; }
   1.191 +    void   set_backedge_copy(bool z);
   1.192 +    int        backedge_copy_count() const { return outer()->backedge_copy_count(ciblock()->index(), _jsrs); }
   1.193  
   1.194      // access to entry state
   1.195      int     stack_size() const         { return _state->stack_size(); }
   1.196 @@ -515,6 +575,20 @@
   1.197      ciType* local_type_at(int i) const { return _state->local_type_at(i); }
   1.198      ciType* stack_type_at(int i) const { return _state->stack_type_at(i); }
   1.199  
   1.200 +    // Data flow on locals
   1.201 +    bool is_invariant_local(uint v) const {
   1.202 +      assert(is_loop_head(), "only loop heads");
   1.203 +      // Find outermost loop with same loop head
   1.204 +      Loop* lp = loop();
   1.205 +      while (lp->parent() != NULL) {
   1.206 +        if (lp->parent()->head() != lp->head()) break;
   1.207 +        lp = lp->parent();
   1.208 +      }
   1.209 +      return !lp->def_locals()->test(v);
   1.210 +    }
   1.211 +    LocalSet* def_locals() { return _state->def_locals(); }
   1.212 +    const LocalSet* def_locals() const { return _state->def_locals(); }
   1.213 +
   1.214      // Get the successors for this Block.
   1.215      GrowableArray<Block*>* successors(ciBytecodeStream* str,
   1.216                                        StateVector* state,
   1.217 @@ -524,13 +598,6 @@
   1.218        return _successors;
   1.219      }
   1.220  
   1.221 -    // Helper function for "successors" when making private copies of
   1.222 -    // loop heads for C2.
   1.223 -    Block * clone_loop_head(ciTypeFlow* analyzer,
   1.224 -                            int branch_bci,
   1.225 -                            Block* target,
   1.226 -                            JsrSet* jsrs);
   1.227 -
   1.228      // Get the exceptional successors for this Block.
   1.229      GrowableArray<Block*>* exceptions() {
   1.230        if (_exceptions == NULL) {
   1.231 @@ -584,17 +651,126 @@
   1.232      bool   is_on_work_list() const  { return _on_work_list; }
   1.233  
   1.234      bool   has_pre_order() const  { return _pre_order >= 0; }
   1.235 -    void   set_pre_order(int po)  { assert(!has_pre_order() && po >= 0, ""); _pre_order = po; }
   1.236 +    void   set_pre_order(int po)  { assert(!has_pre_order(), ""); _pre_order = po; }
   1.237      int    pre_order() const      { assert(has_pre_order(), ""); return _pre_order; }
   1.238 +    void   set_next_pre_order()   { set_pre_order(outer()->inc_next_pre_order()); }
   1.239      bool   is_start() const       { return _pre_order == outer()->start_block_num(); }
   1.240  
   1.241 -    // A ranking used in determining order within the work list.
   1.242 -    bool   is_simpler_than(Block* other);
   1.243 +    // Reverse post order
   1.244 +    void   df_init();
   1.245 +    bool   has_post_order() const { return _post_order >= 0; }
   1.246 +    void   set_post_order(int po) { assert(!has_post_order() && po >= 0, ""); _post_order = po; }
   1.247 +    void   reset_post_order(int o){ _post_order = o; }
   1.248 +    int    post_order() const     { assert(has_post_order(), ""); return _post_order; }
   1.249 +
   1.250 +    bool   has_rpo() const        { return has_post_order() && outer()->have_block_count(); }
   1.251 +    int    rpo() const            { assert(has_rpo(), ""); return outer()->block_count() - post_order() - 1; }
   1.252 +    void   set_rpo_next(Block* b) { _rpo_next = b; }
   1.253 +    Block* rpo_next()             { return _rpo_next; }
   1.254 +
   1.255 +    // Loops
   1.256 +    Loop*  loop() const                  { return _loop; }
   1.257 +    void   set_loop(Loop* lp)            { _loop = lp; }
   1.258 +    bool   is_loop_head() const          { return _loop && _loop->head() == this; }
   1.259 +    void   set_irreducible_entry(bool c) { _irreducible_entry = c; }
   1.260 +    bool   is_irreducible_entry() const  { return _irreducible_entry; }
   1.261 +    bool   is_visited() const            { return has_pre_order(); }
   1.262 +    bool   is_post_visited() const       { return has_post_order(); }
   1.263 +    bool   is_clonable_exit(Loop* lp);
   1.264 +    Block* looping_succ(Loop* lp);       // Successor inside of loop
   1.265 +    bool   is_single_entry_loop_head() const {
   1.266 +      if (!is_loop_head()) return false;
   1.267 +      for (Loop* lp = loop(); lp != NULL && lp->head() == this; lp = lp->parent())
   1.268 +        if (lp->is_irreducible()) return false;
   1.269 +      return true;
   1.270 +    }
   1.271  
   1.272      void   print_value_on(outputStream* st) const PRODUCT_RETURN;
   1.273      void   print_on(outputStream* st) const       PRODUCT_RETURN;
   1.274    };
   1.275  
   1.276 +  // Loop
   1.277 +  class Loop : public ResourceObj {
   1.278 +  private:
   1.279 +    Loop* _parent;
   1.280 +    Loop* _sibling;  // List of siblings, null terminated
   1.281 +    Loop* _child;    // Head of child list threaded thru sibling pointer
   1.282 +    Block* _head;    // Head of loop
   1.283 +    Block* _tail;    // Tail of loop
   1.284 +    bool   _irreducible;
   1.285 +    LocalSet _def_locals;
   1.286 +
   1.287 +  public:
   1.288 +    Loop(Block* head, Block* tail) :
   1.289 +      _head(head),   _tail(tail),
   1.290 +      _parent(NULL), _sibling(NULL), _child(NULL),
   1.291 +      _irreducible(false), _def_locals() {}
   1.292 +
   1.293 +    Loop* parent()  const { return _parent; }
   1.294 +    Loop* sibling() const { return _sibling; }
   1.295 +    Loop* child()   const { return _child; }
   1.296 +    Block* head()   const { return _head; }
   1.297 +    Block* tail()   const { return _tail; }
   1.298 +    void set_parent(Loop* p)  { _parent = p; }
   1.299 +    void set_sibling(Loop* s) { _sibling = s; }
   1.300 +    void set_child(Loop* c)   { _child = c; }
   1.301 +    void set_head(Block* hd)  { _head = hd; }
   1.302 +    void set_tail(Block* tl)  { _tail = tl; }
   1.303 +
   1.304 +    int depth() const;              // nesting depth
   1.305 +
   1.306 +    // Returns true if lp is a nested loop or us.
   1.307 +    bool contains(Loop* lp) const;
   1.308 +    bool contains(Block* blk) const { return contains(blk->loop()); }
   1.309 +
   1.310 +    // Data flow on locals
   1.311 +    LocalSet* def_locals() { return &_def_locals; }
   1.312 +    const LocalSet* def_locals() const { return &_def_locals; }
   1.313 +
   1.314 +    // Merge the branch lp into this branch, sorting on the loop head
   1.315 +    // pre_orders. Returns the new branch.
   1.316 +    Loop* sorted_merge(Loop* lp);
   1.317 +
   1.318 +    // Mark non-single entry to loop
   1.319 +    void set_irreducible(Block* entry) {
   1.320 +      _irreducible = true;
   1.321 +      entry->set_irreducible_entry(true);
   1.322 +    }
   1.323 +    bool is_irreducible() const { return _irreducible; }
   1.324 +
   1.325 +    bool is_root() const { return _tail->pre_order() == max_jint; }
   1.326 +
   1.327 +    void print(outputStream* st = tty, int indent = 0) const PRODUCT_RETURN;
   1.328 +  };
   1.329 +
   1.330 +  // Postorder iteration over the loop tree.
   1.331 +  class PostorderLoops : public StackObj {
   1.332 +  private:
   1.333 +    Loop* _root;
   1.334 +    Loop* _current;
   1.335 +  public:
   1.336 +    PostorderLoops(Loop* root) : _root(root), _current(root) {
   1.337 +      while (_current->child() != NULL) {
   1.338 +        _current = _current->child();
   1.339 +      }
   1.340 +    }
   1.341 +    bool done() { return _current == NULL; }  // Finished iterating?
   1.342 +    void next();                            // Advance to next loop
   1.343 +    Loop* current() { return _current; }      // Return current loop.
   1.344 +  };
   1.345 +
   1.346 +  // Preorder iteration over the loop tree.
   1.347 +  class PreorderLoops : public StackObj {
   1.348 +  private:
   1.349 +    Loop* _root;
   1.350 +    Loop* _current;
   1.351 +  public:
   1.352 +    PreorderLoops(Loop* root) : _root(root), _current(root) {}
   1.353 +    bool done() { return _current == NULL; }  // Finished iterating?
   1.354 +    void next();                            // Advance to next loop
   1.355 +    Loop* current() { return _current; }      // Return current loop.
   1.356 +  };
   1.357 +
   1.358    // Standard indexes of successors, for various bytecodes.
   1.359    enum {
   1.360      FALL_THROUGH   = 0,  // normal control
   1.361 @@ -619,6 +795,12 @@
   1.362    // Tells if a given instruction is able to generate an exception edge.
   1.363    bool can_trap(ciBytecodeStream& str);
   1.364  
   1.365 +  // Clone the loop heads. Returns true if any cloning occurred.
   1.366 +  bool clone_loop_heads(Loop* lp, StateVector* temp_vector, JsrSet* temp_set);
   1.367 +
   1.368 +  // Clone lp's head and replace tail's successors with clone.
   1.369 +  Block* clone_loop_head(Loop* lp, StateVector* temp_vector, JsrSet* temp_set);
   1.370 +
   1.371  public:
   1.372    // Return the block beginning at bci which has a JsrSet compatible
   1.373    // with jsrs.
   1.374 @@ -627,8 +809,8 @@
   1.375    // block factory
   1.376    Block* get_block_for(int ciBlockIndex, JsrSet* jsrs, CreateOption option = create_public_copy);
   1.377  
   1.378 -  // How many of the blocks have the private_copy bit set?
   1.379 -  int private_copy_count(int ciBlockIndex, JsrSet* jsrs) const;
   1.380 +  // How many of the blocks have the backedge_copy bit set?
   1.381 +  int backedge_copy_count(int ciBlockIndex, JsrSet* jsrs) const;
   1.382  
   1.383    // Return an existing block containing bci which has a JsrSet compatible
   1.384    // with jsrs, or NULL if there is none.
   1.385 @@ -651,11 +833,18 @@
   1.386                                        return _block_map[po]; }
   1.387    Block* start_block() const        { return pre_order_at(start_block_num()); }
   1.388    int start_block_num() const       { return 0; }
   1.389 +  Block* rpo_at(int rpo) const      { assert(0 <= rpo && rpo < block_count(), "out of bounds");
   1.390 +                                      return _block_map[rpo]; }
   1.391 +  int next_pre_order()              { return _next_pre_order; }
   1.392 +  int inc_next_pre_order()          { return _next_pre_order++; }
   1.393  
   1.394  private:
   1.395    // A work list used during flow analysis.
   1.396    Block* _work_list;
   1.397  
   1.398 +  // List of blocks in reverse post order
   1.399 +  Block* _rpo_list;
   1.400 +
   1.401    // Next Block::_pre_order.  After mapping, doubles as block_count.
   1.402    int _next_pre_order;
   1.403  
   1.404 @@ -668,6 +857,15 @@
   1.405    // Add a basic block to our work list.
   1.406    void add_to_work_list(Block* block);
   1.407  
   1.408 +  // Prepend a basic block to rpo list.
   1.409 +  void prepend_to_rpo_list(Block* blk) {
   1.410 +    blk->set_rpo_next(_rpo_list);
   1.411 +    _rpo_list = blk;
   1.412 +  }
   1.413 +
   1.414 +  // Root of the loop tree
   1.415 +  Loop* _loop_tree_root;
   1.416 +
   1.417    // State used for make_jsr_record
   1.418    int _jsr_count;
   1.419    GrowableArray<JsrRecord*>* _jsr_records;
   1.420 @@ -677,6 +875,9 @@
   1.421    // does not already exist.
   1.422    JsrRecord* make_jsr_record(int entry_address, int return_address);
   1.423  
   1.424 +  void  set_loop_tree_root(Loop* ltr) { _loop_tree_root = ltr; }
   1.425 +  Loop* loop_tree_root()              { return _loop_tree_root; }
   1.426 +
   1.427  private:
   1.428    // Get the initial state for start_bci:
   1.429    const StateVector* get_start_state();
   1.430 @@ -703,6 +904,15 @@
   1.431    // necessary.
   1.432    void flow_types();
   1.433  
   1.434 +  // Perform the depth first type flow analysis. Helper for flow_types.
   1.435 +  void df_flow_types(Block* start,
   1.436 +                     bool do_flow,
   1.437 +                     StateVector* temp_vector,
   1.438 +                     JsrSet* temp_set);
   1.439 +
   1.440 +  // Incrementally build loop tree.
   1.441 +  void build_loop_tree(Block* blk);
   1.442 +
   1.443    // Create the block map, which indexes blocks in pre_order.
   1.444    void map_blocks();
   1.445  
   1.446 @@ -711,4 +921,6 @@
   1.447    void do_flow();
   1.448  
   1.449    void print_on(outputStream* st) const PRODUCT_RETURN;
   1.450 +
   1.451 +  void rpo_print_on(outputStream* st) const PRODUCT_RETURN;
   1.452  };

mercurial