hotspot/src/share/vm/opto/escape.hpp
changeset 27424 77a7f4a2463b
parent 13886 8d82c4dfa722
child 30629 b6e5ad2f18d5
equal deleted inserted replaced
27423:a52be21f172a 27424:77a7f4a2463b
   123 class JavaObjectNode;
   123 class JavaObjectNode;
   124 class LocalVarNode;
   124 class LocalVarNode;
   125 class FieldNode;
   125 class FieldNode;
   126 class ArraycopyNode;
   126 class ArraycopyNode;
   127 
   127 
       
   128 class ConnectionGraph;
       
   129 
   128 // ConnectionGraph nodes
   130 // ConnectionGraph nodes
   129 class PointsToNode : public ResourceObj {
   131 class PointsToNode : public ResourceObj {
   130   GrowableArray<PointsToNode*> _edges; // List of nodes this node points to
   132   GrowableArray<PointsToNode*> _edges; // List of nodes this node points to
   131   GrowableArray<PointsToNode*> _uses;  // List of nodes which point to this node
   133   GrowableArray<PointsToNode*> _uses;  // List of nodes which point to this node
   132 
   134 
   135   u1               _escape;  // EscapeState of object
   137   u1               _escape;  // EscapeState of object
   136   u1        _fields_escape;  // EscapeState of object's fields
   138   u1        _fields_escape;  // EscapeState of object's fields
   137 
   139 
   138   Node* const        _node;  // Ideal node corresponding to this PointsTo node.
   140   Node* const        _node;  // Ideal node corresponding to this PointsTo node.
   139   const int           _idx;  // Cached ideal node's _idx
   141   const int           _idx;  // Cached ideal node's _idx
       
   142   const uint         _pidx;  // Index of this node
   140 
   143 
   141 public:
   144 public:
   142   typedef enum {
   145   typedef enum {
   143     UnknownType = 0,
   146     UnknownType = 0,
   144     JavaObject  = 1,
   147     JavaObject  = 1,
   163     ArraycopySrc      = 4,  // Has edge from Arraycopy node
   166     ArraycopySrc      = 4,  // Has edge from Arraycopy node
   164     ArraycopyDst      = 8   // Has edge to Arraycopy node
   167     ArraycopyDst      = 8   // Has edge to Arraycopy node
   165   } NodeFlags;
   168   } NodeFlags;
   166 
   169 
   167 
   170 
   168   PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type):
   171   inline PointsToNode(ConnectionGraph* CG, Node* n, EscapeState es, NodeType type);
   169     _edges(C->comp_arena(), 2, 0, NULL),
   172 
   170     _uses (C->comp_arena(), 2, 0, NULL),
   173   uint        pidx()   const { return _pidx; }
   171     _node(n),
       
   172     _idx(n->_idx),
       
   173     _type((u1)type),
       
   174     _escape((u1)es),
       
   175     _fields_escape((u1)es),
       
   176     _flags(ScalarReplaceable) {
       
   177     assert(n != NULL && es != UnknownEscape, "sanity");
       
   178   }
       
   179 
   174 
   180   Node* ideal_node()   const { return _node; }
   175   Node* ideal_node()   const { return _node; }
   181   int          idx()   const { return _idx; }
   176   int          idx()   const { return _idx; }
   182 
   177 
   183   bool is_JavaObject() const { return _type == (u1)JavaObject; }
   178   bool is_JavaObject() const { return _type == (u1)JavaObject; }
   241 
   236 
   242 };
   237 };
   243 
   238 
   244 class LocalVarNode: public PointsToNode {
   239 class LocalVarNode: public PointsToNode {
   245 public:
   240 public:
   246   LocalVarNode(Compile *C, Node* n, EscapeState es):
   241   LocalVarNode(ConnectionGraph *CG, Node* n, EscapeState es):
   247     PointsToNode(C, n, es, LocalVar) {}
   242     PointsToNode(CG, n, es, LocalVar) {}
   248 };
   243 };
   249 
   244 
   250 class JavaObjectNode: public PointsToNode {
   245 class JavaObjectNode: public PointsToNode {
   251 public:
   246 public:
   252   JavaObjectNode(Compile *C, Node* n, EscapeState es):
   247   JavaObjectNode(ConnectionGraph *CG, Node* n, EscapeState es):
   253     PointsToNode(C, n, es, JavaObject) {
   248     PointsToNode(CG, n, es, JavaObject) {
   254       if (es > NoEscape)
   249       if (es > NoEscape)
   255         set_scalar_replaceable(false);
   250         set_scalar_replaceable(false);
   256     }
   251     }
   257 };
   252 };
   258 
   253 
   260   GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node
   255   GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node
   261   const int   _offset; // Field's offset.
   256   const int   _offset; // Field's offset.
   262   const bool  _is_oop; // Field points to object
   257   const bool  _is_oop; // Field points to object
   263         bool  _has_unknown_base; // Has phantom_object base
   258         bool  _has_unknown_base; // Has phantom_object base
   264 public:
   259 public:
   265   FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop):
   260   FieldNode(ConnectionGraph *CG, Node* n, EscapeState es, int offs, bool is_oop):
   266     PointsToNode(C, n, es, Field),
   261     PointsToNode(CG, n, es, Field),
   267     _offset(offs), _is_oop(is_oop),
   262     _offset(offs), _is_oop(is_oop),
   268     _has_unknown_base(false) {}
   263     _has_unknown_base(false) {}
   269 
   264 
   270   int      offset()              const { return _offset;}
   265   int      offset()              const { return _offset;}
   271   bool     is_oop()              const { return _is_oop;}
   266   bool     is_oop()              const { return _is_oop;}
   282 
   277 
   283 };
   278 };
   284 
   279 
   285 class ArraycopyNode: public PointsToNode {
   280 class ArraycopyNode: public PointsToNode {
   286 public:
   281 public:
   287   ArraycopyNode(Compile *C, Node* n, EscapeState es):
   282   ArraycopyNode(ConnectionGraph *CG, Node* n, EscapeState es):
   288     PointsToNode(C, n, es, Arraycopy) {}
   283     PointsToNode(CG, n, es, Arraycopy) {}
   289 };
   284 };
   290 
   285 
   291 // Iterators for PointsTo node's edges:
   286 // Iterators for PointsTo node's edges:
   292 //   for (EdgeIterator i(n); i.has_next(); i.next()) {
   287 //   for (EdgeIterator i(n); i.has_next(); i.next()) {
   293 //     PointsToNode* u = i.get();
   288 //     PointsToNode* u = i.get();
   321   inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); }
   316   inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); }
   322 };
   317 };
   323 
   318 
   324 
   319 
   325 class ConnectionGraph: public ResourceObj {
   320 class ConnectionGraph: public ResourceObj {
       
   321   friend class PointsToNode;
   326 private:
   322 private:
   327   GrowableArray<PointsToNode*>  _nodes; // Map from ideal nodes to
   323   GrowableArray<PointsToNode*>  _nodes; // Map from ideal nodes to
   328                                         // ConnectionGraph nodes.
   324                                         // ConnectionGraph nodes.
   329 
   325 
   330   GrowableArray<PointsToNode*>  _worklist; // Nodes to be processed
   326   GrowableArray<PointsToNode*>  _worklist; // Nodes to be processed
       
   327   VectorSet                  _in_worklist;
       
   328   uint                         _next_pidx;
   331 
   329 
   332   bool            _collecting; // Indicates whether escape information
   330   bool            _collecting; // Indicates whether escape information
   333                                // is still being collected. If false,
   331                                // is still being collected. If false,
   334                                // no new nodes will be processed.
   332                                // no new nodes will be processed.
   335 
   333 
   350     // There should be no new ideal nodes during ConnectionGraph build,
   348     // There should be no new ideal nodes during ConnectionGraph build,
   351     // growableArray::at() will throw assert otherwise.
   349     // growableArray::at() will throw assert otherwise.
   352     return _nodes.at(idx);
   350     return _nodes.at(idx);
   353   }
   351   }
   354   uint nodes_size() const { return _nodes.length(); }
   352   uint nodes_size() const { return _nodes.length(); }
       
   353 
       
   354   uint next_pidx() { return _next_pidx++; }
   355 
   355 
   356   // Add nodes to ConnectionGraph.
   356   // Add nodes to ConnectionGraph.
   357   void add_local_var(Node* n, PointsToNode::EscapeState es);
   357   void add_local_var(Node* n, PointsToNode::EscapeState es);
   358   void add_java_object(Node* n, PointsToNode::EscapeState es);
   358   void add_java_object(Node* n, PointsToNode::EscapeState es);
   359   void add_field(Node* n, PointsToNode::EscapeState es, int offset);
   359   void add_field(Node* n, PointsToNode::EscapeState es, int offset);
   394 
   394 
   395   // Add all references to this JavaObject node.
   395   // Add all references to this JavaObject node.
   396   int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist);
   396   int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist);
   397 
   397 
   398   // Put node on worklist if it is (or was) not there.
   398   // Put node on worklist if it is (or was) not there.
   399   void add_to_worklist(PointsToNode* pt) {
   399   inline void add_to_worklist(PointsToNode* pt) {
   400     _worklist.push(pt);
   400     PointsToNode* ptf = pt;
   401     return;
   401     uint pidx_bias = 0;
       
   402     if (PointsToNode::is_base_use(pt)) {
       
   403       // Create a separate entry in _in_worklist for a marked base edge
       
   404       // because _worklist may have an entry for a normal edge pointing
       
   405       // to the same node. To separate them use _next_pidx as bias.
       
   406       ptf = PointsToNode::get_use_node(pt)->as_Field();
       
   407       pidx_bias = _next_pidx;
       
   408     }
       
   409     if (!_in_worklist.test_set(ptf->pidx() + pidx_bias)) {
       
   410       _worklist.append(pt);
       
   411     }
   402   }
   412   }
   403 
   413 
   404   // Put on worklist all uses of this node.
   414   // Put on worklist all uses of this node.
   405   void add_uses_to_worklist(PointsToNode* pt) {
   415   inline void add_uses_to_worklist(PointsToNode* pt) {
   406     for (UseIterator i(pt); i.has_next(); i.next())
   416     for (UseIterator i(pt); i.has_next(); i.next()) {
   407       _worklist.push(i.get());
   417       add_to_worklist(i.get());
       
   418     }
   408   }
   419   }
   409 
   420 
   410   // Put on worklist all field's uses and related field nodes.
   421   // Put on worklist all field's uses and related field nodes.
   411   void add_field_uses_to_worklist(FieldNode* field);
   422   void add_field_uses_to_worklist(FieldNode* field);
   412 
   423 
   515     }
   526     }
   516     add_edge(ptnode_adr(n->_idx), ptn);
   527     add_edge(ptnode_adr(n->_idx), ptn);
   517  }
   528  }
   518   // Helper functions
   529   // Helper functions
   519   bool   is_oop_field(Node* n, int offset, bool* unsafe);
   530   bool   is_oop_field(Node* n, int offset, bool* unsafe);
   520  static Node* get_addp_base(Node *addp);
   531   static Node* get_addp_base(Node *addp);
   521  static Node* find_second_addp(Node* addp, Node* n);
   532   static Node* find_second_addp(Node* addp, Node* n);
   522   // offset of a field reference
   533   // offset of a field reference
   523   int address_offset(Node* adr, PhaseTransform *phase);
   534   int address_offset(Node* adr, PhaseTransform *phase);
   524 
   535 
   525 
   536 
   526   // Propagate unique types created for unescaped allocated objects
   537   // Propagate unique types created for unescaped allocated objects
   585 #ifndef PRODUCT
   596 #ifndef PRODUCT
   586   void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
   597   void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
   587 #endif
   598 #endif
   588 };
   599 };
   589 
   600 
       
   601 inline PointsToNode::PointsToNode(ConnectionGraph *CG, Node* n, EscapeState es, NodeType type):
       
   602   _edges(CG->_compile->comp_arena(), 2, 0, NULL),
       
   603   _uses (CG->_compile->comp_arena(), 2, 0, NULL),
       
   604   _node(n),
       
   605   _idx(n->_idx),
       
   606   _pidx(CG->next_pidx()),
       
   607   _type((u1)type),
       
   608   _escape((u1)es),
       
   609   _fields_escape((u1)es),
       
   610   _flags(ScalarReplaceable) {
       
   611   assert(n != NULL && es != UnknownEscape, "sanity");
       
   612 }
       
   613 
   590 #endif // SHARE_VM_OPTO_ESCAPE_HPP
   614 #endif // SHARE_VM_OPTO_ESCAPE_HPP