< prev index next >

src/hotspot/share/opto/parse.hpp

Print this page
*** 29,10 ***
--- 29,11 ---
  #include "ci/ciTypeFlow.hpp"
  #include "compiler/methodLiveness.hpp"
  #include "libadt/vectset.hpp"
  #include "oops/generateOopMap.hpp"
  #include "opto/graphKit.hpp"
+ #include "opto/partialEscape.hpp"
  #include "opto/subnode.hpp"
  
  class BytecodeParseHistogram;
  class InlineTree;
  class Parse;

*** 159,17 ***
      uint               _count;          // how many times executed?  Currently only set by _goto's
      bool               _is_parsed;      // has this block been parsed yet?
      bool               _is_handler;     // is this block an exception handler?
      bool               _has_merged_backedge; // does this block have merged backedge?
      SafePointNode*     _start_map;      // all values flowing into this block
!     MethodLivenessResult _live_locals;  // lazily initialized liveness bitmap
      bool               _has_predicates; // Were predicates added before parsing of the loop head?
  
      int                _num_successors; // Includes only normal control flow.
      int                _all_successors; // Include exception paths also.
      Block**            _successors;
  
     public:
  
      // Set up the block data structure itself.
      Block(Parse* outer, int rpo);
  
--- 160,27 ---
      uint               _count;          // how many times executed?  Currently only set by _goto's
      bool               _is_parsed;      // has this block been parsed yet?
      bool               _is_handler;     // is this block an exception handler?
      bool               _has_merged_backedge; // does this block have merged backedge?
      SafePointNode*     _start_map;      // all values flowing into this block
!     mutable MethodLivenessResult _live_locals;  // lazily initialized liveness bitmap
      bool               _has_predicates; // Were predicates added before parsing of the loop head?
  
      int                _num_successors; // Includes only normal control flow.
      int                _all_successors; // Include exception paths also.
      Block**            _successors;
+     Block**            _predecessors;
+     Block*             _from_block;
+     int                _init_pnum;      // the pnum of Block where _state is copied from.
  
+     const MethodLivenessResult& liveness() const {
+       if (!_live_locals.is_valid()) {
+         _live_locals = flow()->outer()->method()->liveness_at_bci(start());
+       }
+       assert(_live_locals.is_valid(), "sanity check");
+       return _live_locals;
+     }
     public:
  
      // Set up the block data structure itself.
      Block(Parse* outer, int rpo);
  

*** 187,10 ***
--- 198,16 ---
      SafePointNode* start_map() const       { assert(is_merged(),"");   return _start_map; }
      void set_start_map(SafePointNode* m)   { assert(!is_merged(), ""); _start_map = m; }
  
      // True after any predecessor flows control into this block
      bool is_merged() const                 { return _start_map != nullptr; }
+     Block* from_block() const              { return _from_block; }
+     int init_pnum() const                  { return _init_pnum; }
+     PEAState& state()                      {
+       assert(is_merged(), "sanity check");
+       return _start_map->jvms()->alloc_state();
+     }
  
  #ifdef ASSERT
      // True after backedge predecessor flows control into this block
      bool has_merged_backedge() const       { return _has_merged_backedge; }
      void mark_merged_backedge(Block* pred) {

*** 214,10 ***
--- 231,16 ---
        assert((uint)i < (uint)all_successors(), "");
        return _successors[i];
      }
      Block* successor_for_bci(int bci);
  
+     Block* predecessor_at(int i) const {
+       assert(DoPartialEscapeAnalysis, "_predecessors is only available when DoPartialEscapeAnalysis is ON");
+       assert(i < _pred_count, "");
+       return _predecessors[i];
+     }
+ 
      int start() const                      { return flow()->start(); }
      int limit() const                      { return flow()->limit(); }
      int rpo() const                        { return flow()->rpo(); }
      int start_sp() const                   { return flow()->stack_size(); }
  

*** 284,11 ***
      // and all its phi nodes (if any).  The value returned is a
      // path number ("pnum").
      int add_new_path();
  
      // Initialize me by recording the parser's map.  My own map must be null.
!     void record_state(Parse* outer);
    };
  
  #ifndef PRODUCT
    // BytecodeParseHistogram collects number of bytecodes parsed, nodes constructed, and transformations.
    class BytecodeParseHistogram : public ArenaObj {
--- 307,11 ---
      // and all its phi nodes (if any).  The value returned is a
      // path number ("pnum").
      int add_new_path();
  
      // Initialize me by recording the parser's map.  My own map must be null.
!     void record_state(Parse* outer, int pnum);
    };
  
  #ifndef PRODUCT
    // BytecodeParseHistogram collects number of bytecodes parsed, nodes constructed, and transformations.
    class BytecodeParseHistogram : public ArenaObj {

*** 341,10 ***
--- 364,11 ---
    friend class Block;
  
    // Variables which characterize this compilation as a whole:
  
    JVMState*     _caller;        // JVMS which carries incoming args & state.
+   PEAState*     _caller_state;  // current PEA state of caller
    float         _expected_uses; // expected number of calls to this code
    float         _prof_factor;   // discount applied to my profile counts
    int           _depth;         // Inline tree depth, for debug printouts
    const TypeFunc*_tf;           // My kind of function type
    int           _entry_bci;     // the osr bci or InvocationEntryBci

*** 370,18 ***
  #ifndef PRODUCT
    int _max_switch_depth;        // Debugging SwitchRanges.
    int _est_switch_depth;        // Debugging SwitchRanges.
  #endif
  
!   bool         _first_return;                  // true if return is the first to be parsed
    bool         _replaced_nodes_for_exceptions; // needs processing of replaced nodes in exception paths?
    uint         _new_idx;                       // any node with _idx above were new during this parsing. Used to trim the replaced nodes list.
  
   public:
    // Constructor
!   Parse(JVMState* caller, ciMethod* parse_method, float expected_uses);
  
    virtual Parse* is_Parse() const { return (Parse*)this; }
  
    // Accessors.
    JVMState*     caller()        const { return _caller; }
    float         expected_uses() const { return _expected_uses; }
--- 394,21 ---
  #ifndef PRODUCT
    int _max_switch_depth;        // Debugging SwitchRanges.
    int _est_switch_depth;        // Debugging SwitchRanges.
  #endif
  
!   int          _first_return;                  // true if return is the first to be parsed
    bool         _replaced_nodes_for_exceptions; // needs processing of replaced nodes in exception paths?
    uint         _new_idx;                       // any node with _idx above were new during this parsing. Used to trim the replaced nodes list.
  
   public:
    // Constructor
!   Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, PEAState* caller_state = nullptr);
  
+ #ifndef PRODUCT
+   ~Parse();
+ #endif
    virtual Parse* is_Parse() const { return (Parse*)this; }
  
    // Accessors.
    JVMState*     caller()        const { return _caller; }
    float         expected_uses() const { return _expected_uses; }

*** 403,12 ***
    void      set_wrote_stable(bool z)  { _wrote_stable = z; }
    bool         wrote_fields() const   { return _wrote_fields; }
    void     set_wrote_fields(bool z)   { _wrote_fields = z; }
    Node*    alloc_with_final() const   { return _alloc_with_final; }
    void set_alloc_with_final(Node* n)  {
!     assert((_alloc_with_final == nullptr) || (_alloc_with_final == n), "different init objects?");
!     _alloc_with_final = n;
    }
  
    Block*             block()    const { return _block; }
    ciBytecodeStream&  iter()           { return _iter; }
    Bytecodes::Code    bc()       const { return _iter.cur_bc(); }
--- 430,18 ---
    void      set_wrote_stable(bool z)  { _wrote_stable = z; }
    bool         wrote_fields() const   { return _wrote_fields; }
    void     set_wrote_fields(bool z)   { _wrote_fields = z; }
    Node*    alloc_with_final() const   { return _alloc_with_final; }
    void set_alloc_with_final(Node* n)  {
!     if (DoPartialEscapeAnalysis) {
!       assert((_alloc_with_final == nullptr) || (_alloc_with_final == PEA()->is_alias(n)), 
+              "different init objects?");
+       _alloc_with_final = PEA()->is_alias(n);
+     } else {
+       assert((_alloc_with_final == nullptr) || (_alloc_with_final == n), "different init objects?");
+       _alloc_with_final = n;
+     }
    }
  
    Block*             block()    const { return _block; }
    ciBytecodeStream&  iter()           { return _iter; }
    Bytecodes::Code    bc()       const { return _iter.cur_bc(); }

*** 450,11 ***
    void  load_interpreter_state(Node* osr_buf);
  
    // Functions for managing basic blocks:
    void init_blocks();
    void load_state_from(Block* b);
!   void store_state_to(Block* b) { b->record_state(this); }
  
    // Parse all the basic blocks.
    void do_all_blocks();
  
    // Parse the current basic block
--- 483,11 ---
    void  load_interpreter_state(Node* osr_buf);
  
    // Functions for managing basic blocks:
    void init_blocks();
    void load_state_from(Block* b);
!   void store_state_to(Block* b, int pnum) { b->record_state(this, pnum); }
  
    // Parse all the basic blocks.
    void do_all_blocks();
  
    // Parse the current basic block

*** 482,10 ***
--- 515,11 ---
    // Helper: Merge the current mapping into the given basic block
    void merge_common(Block* target, int pnum);
    // Helper functions for merging individual cells.
    PhiNode *ensure_phi(       int idx, bool nocreate = false);
    PhiNode *ensure_memory_phi(int idx, bool nocreate = false);
+ 
    // Helper to merge the current memory state into the given basic block
    void merge_memory_edges(MergeMemNode* n, int pnum, bool nophi);
  
    // Parse this bytecode, and alter the Parsers JVM->Node mapping
    void do_one_bytecode();
< prev index next >