src/share/vm/opto/escape.hpp

changeset 3651
ee138854b3a6
parent 3318
cc81b9c09bbb
child 3969
1d7922586cf6
     1.1 --- a/src/share/vm/opto/escape.hpp	Fri Mar 09 13:34:45 2012 -0800
     1.2 +++ b/src/share/vm/opto/escape.hpp	Mon Mar 12 10:46:47 2012 -0700
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -115,18 +115,36 @@
    1.11  class  CallNode;
    1.12  class  PhiNode;
    1.13  class  PhaseTransform;
    1.14 +class  PointsToNode;
    1.15  class  Type;
    1.16  class  TypePtr;
    1.17  class  VectorSet;
    1.18  
    1.19 -class PointsToNode {
    1.20 -friend class ConnectionGraph;
    1.21 +class JavaObjectNode;
    1.22 +class LocalVarNode;
    1.23 +class FieldNode;
    1.24 +class ArraycopyNode;
    1.25 +
    1.26 +// ConnectionGraph nodes
    1.27 +class PointsToNode : public ResourceObj {
    1.28 +  GrowableArray<PointsToNode*> _edges; // List of nodes this node points to
    1.29 +  GrowableArray<PointsToNode*> _uses;  // List of nodes which point to this node
    1.30 +
    1.31 +  const u1           _type;  // NodeType
    1.32 +  u1                _flags;  // NodeFlags
    1.33 +  u1               _escape;  // EscapeState of object
    1.34 +  u1        _fields_escape;  // EscapeState of object's fields
    1.35 +
    1.36 +  Node* const        _node;  // Ideal node corresponding to this PointsTo node.
    1.37 +  const int           _idx;  // Cached ideal node's _idx
    1.38 +
    1.39  public:
    1.40    typedef enum {
    1.41      UnknownType = 0,
    1.42      JavaObject  = 1,
    1.43      LocalVar    = 2,
    1.44 -    Field       = 3
    1.45 +    Field       = 3,
    1.46 +    Arraycopy   = 4
    1.47    } NodeType;
    1.48  
    1.49    typedef enum {
    1.50 @@ -140,178 +158,387 @@
    1.51    } EscapeState;
    1.52  
    1.53    typedef enum {
    1.54 -    UnknownEdge   = 0,
    1.55 -    PointsToEdge  = 1,
    1.56 -    DeferredEdge  = 2,
    1.57 -    FieldEdge     = 3
    1.58 -  } EdgeType;
    1.59 +    ScalarReplaceable = 1,  // Not escaped object could be replaced with scalar
    1.60 +    PointsToUnknown   = 2,  // Has edge to phantom_object
    1.61 +    ArraycopySrc      = 4,  // Has edge from Arraycopy node
    1.62 +    ArraycopyDst      = 8   // Has edge to Arraycopy node
    1.63 +  } NodeFlags;
    1.64  
    1.65 -private:
    1.66 -  enum {
    1.67 -    EdgeMask = 3,
    1.68 -    EdgeShift = 2,
    1.69  
    1.70 -    INITIAL_EDGE_COUNT = 4
    1.71 -  };
    1.72 -
    1.73 -  NodeType             _type;
    1.74 -  EscapeState          _escape;
    1.75 -  GrowableArray<uint>* _edges; // outgoing edges
    1.76 -  Node* _node;                 // Ideal node corresponding to this PointsTo node.
    1.77 -  int   _offset;               // Object fields offsets.
    1.78 -  bool  _scalar_replaceable;   // Not escaped object could be replaced with scalar
    1.79 -  bool  _has_unknown_ptr;      // Has edge to phantom_object
    1.80 -
    1.81 -public:
    1.82 -  PointsToNode():
    1.83 -    _type(UnknownType),
    1.84 -    _escape(UnknownEscape),
    1.85 -    _edges(NULL),
    1.86 -    _node(NULL),
    1.87 -    _offset(-1),
    1.88 -    _has_unknown_ptr(false),
    1.89 -    _scalar_replaceable(true) {}
    1.90 -
    1.91 -
    1.92 -  EscapeState escape_state() const { return _escape; }
    1.93 -  NodeType node_type() const { return _type;}
    1.94 -  int offset() { return _offset;}
    1.95 -  bool scalar_replaceable() { return _scalar_replaceable;}
    1.96 -  bool has_unknown_ptr()    { return _has_unknown_ptr;}
    1.97 -
    1.98 -  void set_offset(int offs) { _offset = offs;}
    1.99 -  void set_escape_state(EscapeState state) { _escape = state; }
   1.100 -  void set_node_type(NodeType ntype) {
   1.101 -    assert(_type == UnknownType || _type == ntype, "Can't change node type");
   1.102 -    _type = ntype;
   1.103 -  }
   1.104 -  void set_scalar_replaceable(bool v) { _scalar_replaceable = v; }
   1.105 -  void set_has_unknown_ptr()          { _has_unknown_ptr = true; }
   1.106 -
   1.107 -  // count of outgoing edges
   1.108 -  uint edge_count() const { return (_edges == NULL) ? 0 : _edges->length(); }
   1.109 -
   1.110 -  // node index of target of outgoing edge "e"
   1.111 -  uint edge_target(uint e) const {
   1.112 -    assert(_edges != NULL, "valid edge index");
   1.113 -    return (_edges->at(e) >> EdgeShift);
   1.114 -  }
   1.115 -  // type of outgoing edge "e"
   1.116 -  EdgeType edge_type(uint e) const {
   1.117 -    assert(_edges != NULL, "valid edge index");
   1.118 -    return (EdgeType) (_edges->at(e) & EdgeMask);
   1.119 +  PointsToNode(Compile *C, Node* n, EscapeState es, NodeType type):
   1.120 +    _edges(C->comp_arena(), 2, 0, NULL),
   1.121 +    _uses (C->comp_arena(), 2, 0, NULL),
   1.122 +    _node(n),
   1.123 +    _idx(n->_idx),
   1.124 +    _type((u1)type),
   1.125 +    _escape((u1)es),
   1.126 +    _fields_escape((u1)es),
   1.127 +    _flags(ScalarReplaceable) {
   1.128 +    assert(n != NULL && es != UnknownEscape, "sanity");
   1.129    }
   1.130  
   1.131 -  // add a edge of the specified type pointing to the specified target
   1.132 -  void add_edge(uint targIdx, EdgeType et);
   1.133 +  Node* ideal_node()   const { return _node; }
   1.134 +  int          idx()   const { return _idx; }
   1.135  
   1.136 -  // remove an edge of the specified type pointing to the specified target
   1.137 -  void remove_edge(uint targIdx, EdgeType et);
   1.138 +  bool is_JavaObject() const { return _type == (u1)JavaObject; }
   1.139 +  bool is_LocalVar()   const { return _type == (u1)LocalVar; }
   1.140 +  bool is_Field()      const { return _type == (u1)Field; }
   1.141 +  bool is_Arraycopy()  const { return _type == (u1)Arraycopy; }
   1.142 +
   1.143 +  JavaObjectNode* as_JavaObject() { assert(is_JavaObject(),""); return (JavaObjectNode*)this; }
   1.144 +  LocalVarNode*   as_LocalVar()   { assert(is_LocalVar(),"");   return (LocalVarNode*)this; }
   1.145 +  FieldNode*      as_Field()      { assert(is_Field(),"");      return (FieldNode*)this; }
   1.146 +  ArraycopyNode*  as_Arraycopy()  { assert(is_Arraycopy(),"");  return (ArraycopyNode*)this; }
   1.147 +
   1.148 +  EscapeState escape_state() const { return (EscapeState)_escape; }
   1.149 +  void    set_escape_state(EscapeState state) { _escape = (u1)state; }
   1.150 +
   1.151 +  EscapeState fields_escape_state() const { return (EscapeState)_fields_escape; }
   1.152 +  void    set_fields_escape_state(EscapeState state) { _fields_escape = (u1)state; }
   1.153 +
   1.154 +  bool     has_unknown_ptr() const { return (_flags & PointsToUnknown) != 0; }
   1.155 +  void set_has_unknown_ptr()       { _flags |= PointsToUnknown; }
   1.156 +
   1.157 +  bool     arraycopy_src() const { return (_flags & ArraycopySrc) != 0; }
   1.158 +  void set_arraycopy_src()       { _flags |= ArraycopySrc; }
   1.159 +  bool     arraycopy_dst() const { return (_flags & ArraycopyDst) != 0; }
   1.160 +  void set_arraycopy_dst()       { _flags |= ArraycopyDst; }
   1.161 +
   1.162 +  bool     scalar_replaceable() const { return (_flags & ScalarReplaceable) != 0;}
   1.163 +  void set_scalar_replaceable(bool v) {
   1.164 +    if (v)
   1.165 +      _flags |= ScalarReplaceable;
   1.166 +    else
   1.167 +      _flags &= ~ScalarReplaceable;
   1.168 +  }
   1.169 +
   1.170 +  int edge_count()              const { return _edges.length(); }
   1.171 +  PointsToNode* edge(int e)     const { return _edges.at(e); }
   1.172 +  bool add_edge(PointsToNode* edge)    { return _edges.append_if_missing(edge); }
   1.173 +
   1.174 +  int use_count()             const { return _uses.length(); }
   1.175 +  PointsToNode* use(int e)    const { return _uses.at(e); }
   1.176 +  bool add_use(PointsToNode* use)    { return _uses.append_if_missing(use); }
   1.177 +
   1.178 +  // Mark base edge use to distinguish from stored value edge.
   1.179 +  bool add_base_use(FieldNode* use) { return _uses.append_if_missing((PointsToNode*)((intptr_t)use + 1)); }
   1.180 +  static bool is_base_use(PointsToNode* use) { return (((intptr_t)use) & 1); }
   1.181 +  static PointsToNode* get_use_node(PointsToNode* use) { return (PointsToNode*)(((intptr_t)use) & ~1); }
   1.182 +
   1.183 +  // Return true if this node points to specified node or nodes it points to.
   1.184 +  bool points_to(JavaObjectNode* ptn) const;
   1.185 +
   1.186 +  // Return true if this node points only to non-escaping allocations.
   1.187 +  bool non_escaping_allocation();
   1.188 +
   1.189 +  // Return true if one node points to an other.
   1.190 +  bool meet(PointsToNode* ptn);
   1.191  
   1.192  #ifndef PRODUCT
   1.193 +  NodeType node_type() const { return (NodeType)_type;}
   1.194    void dump(bool print_state=true) const;
   1.195  #endif
   1.196  
   1.197  };
   1.198  
   1.199 +class LocalVarNode: public PointsToNode {
   1.200 +public:
   1.201 +  LocalVarNode(Compile *C, Node* n, EscapeState es):
   1.202 +    PointsToNode(C, n, es, LocalVar) {}
   1.203 +};
   1.204 +
   1.205 +class JavaObjectNode: public PointsToNode {
   1.206 +public:
   1.207 +  JavaObjectNode(Compile *C, Node* n, EscapeState es):
   1.208 +    PointsToNode(C, n, es, JavaObject) {
   1.209 +      if (es > NoEscape)
   1.210 +        set_scalar_replaceable(false);
   1.211 +    }
   1.212 +};
   1.213 +
   1.214 +class FieldNode: public PointsToNode {
   1.215 +  GrowableArray<PointsToNode*> _bases; // List of JavaObject nodes which point to this node
   1.216 +  const int   _offset; // Field's offset.
   1.217 +  const bool  _is_oop; // Field points to object
   1.218 +        bool  _has_unknown_base; // Has phantom_object base
   1.219 +public:
   1.220 +  FieldNode(Compile *C, Node* n, EscapeState es, int offs, bool is_oop):
   1.221 +    PointsToNode(C, n, es, Field),
   1.222 +    _offset(offs), _is_oop(is_oop),
   1.223 +    _has_unknown_base(false) {}
   1.224 +
   1.225 +  int      offset()              const { return _offset;}
   1.226 +  bool     is_oop()              const { return _is_oop;}
   1.227 +  bool     has_unknown_base()    const { return _has_unknown_base; }
   1.228 +  void set_has_unknown_base()          { _has_unknown_base = true; }
   1.229 +
   1.230 +  int base_count()              const { return _bases.length(); }
   1.231 +  PointsToNode* base(int e)     const { return _bases.at(e); }
   1.232 +  bool add_base(PointsToNode* base)    { return _bases.append_if_missing(base); }
   1.233 +#ifdef ASSERT
   1.234 +  // Return true if bases points to this java object.
   1.235 +  bool has_base(JavaObjectNode* ptn) const;
   1.236 +#endif
   1.237 +
   1.238 +};
   1.239 +
   1.240 +class ArraycopyNode: public PointsToNode {
   1.241 +public:
   1.242 +  ArraycopyNode(Compile *C, Node* n, EscapeState es):
   1.243 +    PointsToNode(C, n, es, Arraycopy) {}
   1.244 +};
   1.245 +
   1.246 +// Iterators for PointsTo node's edges:
   1.247 +//   for (EdgeIterator i(n); i.has_next(); i.next()) {
   1.248 +//     PointsToNode* u = i.get();
   1.249 +class PointsToIterator: public StackObj {
   1.250 +protected:
   1.251 +  const PointsToNode* node;
   1.252 +  const int cnt;
   1.253 +  int i;
   1.254 +public:
   1.255 +  inline PointsToIterator(const PointsToNode* n, int cnt) : node(n), cnt(cnt), i(0) { }
   1.256 +  inline bool has_next() const { return i < cnt; }
   1.257 +  inline void next() { i++; }
   1.258 +  PointsToNode* get() const { ShouldNotCallThis(); return NULL; }
   1.259 +};
   1.260 +
   1.261 +class EdgeIterator: public PointsToIterator {
   1.262 +public:
   1.263 +  inline EdgeIterator(const PointsToNode* n) : PointsToIterator(n, n->edge_count()) { }
   1.264 +  inline PointsToNode* get() const { return node->edge(i); }
   1.265 +};
   1.266 +
   1.267 +class UseIterator: public PointsToIterator {
   1.268 +public:
   1.269 +  inline UseIterator(const PointsToNode* n) : PointsToIterator(n, n->use_count()) { }
   1.270 +  inline PointsToNode* get() const { return node->use(i); }
   1.271 +};
   1.272 +
   1.273 +class BaseIterator: public PointsToIterator {
   1.274 +public:
   1.275 +  inline BaseIterator(const FieldNode* n) : PointsToIterator(n, n->base_count()) { }
   1.276 +  inline PointsToNode* get() const { return ((PointsToNode*)node)->as_Field()->base(i); }
   1.277 +};
   1.278 +
   1.279 +
   1.280  class ConnectionGraph: public ResourceObj {
   1.281  private:
   1.282 -  GrowableArray<PointsToNode>  _nodes; // Connection graph nodes indexed
   1.283 -                                       // by ideal node index.
   1.284 +  GrowableArray<PointsToNode*>  _nodes; // Map from ideal nodes to
   1.285 +                                        // ConnectionGraph nodes.
   1.286  
   1.287 -  Unique_Node_List  _delayed_worklist; // Nodes to be processed before
   1.288 -                                       // the call build_connection_graph().
   1.289 +  GrowableArray<PointsToNode*>  _worklist; // Nodes to be processed
   1.290  
   1.291 -  GrowableArray<MergeMemNode *>  _mergemem_worklist; // List of all MergeMem nodes
   1.292 +  bool            _collecting; // Indicates whether escape information
   1.293 +                               // is still being collected. If false,
   1.294 +                               // no new nodes will be processed.
   1.295  
   1.296 -  VectorSet                _processed; // Records which nodes have been
   1.297 -                                       // processed.
   1.298 +  bool               _verify;  // verify graph
   1.299  
   1.300 -  bool                    _collecting; // Indicates whether escape information
   1.301 -                                       // is still being collected. If false,
   1.302 -                                       // no new nodes will be processed.
   1.303 +  JavaObjectNode* phantom_obj; // Unknown object
   1.304 +  JavaObjectNode*    null_obj;
   1.305 +  Node*             _pcmp_neq; // ConI(#CC_GT)
   1.306 +  Node*              _pcmp_eq; // ConI(#CC_EQ)
   1.307  
   1.308 -  bool                    _progress;   // Indicates whether new Graph's edges
   1.309 -                                       // were created.
   1.310 +  Compile*           _compile; // Compile object for current compilation
   1.311 +  PhaseIterGVN*         _igvn; // Value numbering
   1.312  
   1.313 -  uint                _phantom_object; // Index of globally escaping object
   1.314 -                                       // that pointer values loaded from
   1.315 -                                       // a field which has not been set
   1.316 -                                       // are assumed to point to.
   1.317 -  uint                      _oop_null; // ConP(#NULL)->_idx
   1.318 -  uint                     _noop_null; // ConN(#NULL)->_idx
   1.319 -  Node*                     _pcmp_neq; // ConI(#CC_GT)
   1.320 -  Node*                      _pcmp_eq; // ConI(#CC_EQ)
   1.321 -
   1.322 -  Compile *                  _compile; // Compile object for current compilation
   1.323 -  PhaseIterGVN *                _igvn; // Value numbering
   1.324 +  Unique_Node_List ideal_nodes; // Used by CG construction and types splitting.
   1.325  
   1.326    // Address of an element in _nodes.  Used when the element is to be modified
   1.327 -  PointsToNode *ptnode_adr(uint idx) const {
   1.328 +  PointsToNode* ptnode_adr(int idx) const {
   1.329      // There should be no new ideal nodes during ConnectionGraph build,
   1.330 -    // growableArray::adr_at() will throw assert otherwise.
   1.331 -    return _nodes.adr_at(idx);
   1.332 +    // growableArray::at() will throw assert otherwise.
   1.333 +    return _nodes.at(idx);
   1.334    }
   1.335    uint nodes_size() const { return _nodes.length(); }
   1.336  
   1.337 -  bool is_null_ptr(uint idx) const { return (idx == _noop_null || idx == _oop_null); }
   1.338 +  // Add nodes to ConnectionGraph.
   1.339 +  void add_local_var(Node* n, PointsToNode::EscapeState es);
   1.340 +  void add_java_object(Node* n, PointsToNode::EscapeState es);
   1.341 +  void add_field(Node* n, PointsToNode::EscapeState es, int offset);
   1.342 +  void add_arraycopy(Node* n, PointsToNode::EscapeState es, PointsToNode* src, PointsToNode* dst);
   1.343  
   1.344 -  // Add node to ConnectionGraph.
   1.345 -  void add_node(Node *n, PointsToNode::NodeType nt, PointsToNode::EscapeState es, bool done);
   1.346 +  // Compute the escape state for arguments to a call.
   1.347 +  void process_call_arguments(CallNode *call);
   1.348 +
   1.349 +  // Add PointsToNode node corresponding to a call
   1.350 +  void add_call_node(CallNode* call);
   1.351 +
   1.352 +  // Map ideal node to existing PointsTo node (usually phantom_object).
   1.353 +  void map_ideal_node(Node *n, PointsToNode* ptn) {
   1.354 +    assert(ptn != NULL, "only existing PointsTo node");
   1.355 +    _nodes.at_put(n->_idx, ptn);
   1.356 +  }
   1.357 +
   1.358 +  // Create PointsToNode node and add it to Connection Graph.
   1.359 +  void add_node_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist);
   1.360 +
   1.361 +  // Add final simple edges to graph.
   1.362 +  void add_final_edges(Node *n);
   1.363 +
   1.364 +  // Finish Graph construction.
   1.365 +  bool complete_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
   1.366 +                                 GrowableArray<JavaObjectNode*>& non_escaped_worklist,
   1.367 +                                 GrowableArray<JavaObjectNode*>& java_objects_worklist,
   1.368 +                                 GrowableArray<FieldNode*>&      oop_fields_worklist);
   1.369 +
   1.370 +#ifdef ASSERT
   1.371 +  void verify_connection_graph(GrowableArray<PointsToNode*>&   ptnodes_worklist,
   1.372 +                               GrowableArray<JavaObjectNode*>& non_escaped_worklist,
   1.373 +                               GrowableArray<JavaObjectNode*>& java_objects_worklist,
   1.374 +                               GrowableArray<Node*>& addp_worklist);
   1.375 +#endif
   1.376 +
   1.377 +  // Add all references to this JavaObject node.
   1.378 +  int add_java_object_edges(JavaObjectNode* jobj, bool populate_worklist);
   1.379 +
   1.380 +  // Put node on worklist if it is (or was) not there.
   1.381 +  void add_to_worklist(PointsToNode* pt) {
   1.382 +    _worklist.push(pt);
   1.383 +    return;
   1.384 +  }
   1.385 +
   1.386 +  // Put on worklist all uses of this node.
   1.387 +  void add_uses_to_worklist(PointsToNode* pt) {
   1.388 +    for (UseIterator i(pt); i.has_next(); i.next())
   1.389 +      _worklist.push(i.get());
   1.390 +  }
   1.391 +
   1.392 +  // Put on worklist all field's uses and related field nodes.
   1.393 +  void add_field_uses_to_worklist(FieldNode* field);
   1.394 +
   1.395 +  // Put on worklist all related field nodes.
   1.396 +  void add_fields_to_worklist(FieldNode* field, PointsToNode* base);
   1.397 +
   1.398 +  // Find fields which have unknown value.
   1.399 +  int find_field_value(FieldNode* field);
   1.400 +
   1.401 +  // Find fields initializing values for allocations.
   1.402 +  int find_init_values(JavaObjectNode* ptn, PointsToNode* init_val, PhaseTransform* phase);
   1.403 +
   1.404 +  // Set the escape state of an object and its fields.
   1.405 +  void set_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) {
   1.406 +    // Don't change non-escaping state of NULL pointer.
   1.407 +    if (ptn != null_obj) {
   1.408 +      if (ptn->escape_state() < esc)
   1.409 +        ptn->set_escape_state(esc);
   1.410 +      if (ptn->fields_escape_state() < esc)
   1.411 +        ptn->set_fields_escape_state(esc);
   1.412 +    }
   1.413 +  }
   1.414 +  void set_fields_escape_state(PointsToNode* ptn, PointsToNode::EscapeState esc) {
   1.415 +    // Don't change non-escaping state of NULL pointer.
   1.416 +    if (ptn != null_obj) {
   1.417 +      if (ptn->fields_escape_state() < esc)
   1.418 +        ptn->set_fields_escape_state(esc);
   1.419 +    }
   1.420 +  }
   1.421 +
   1.422 +  // Propagate GlobalEscape and ArgEscape escape states to all nodes
   1.423 +  // and check that we still have non-escaping java objects.
   1.424 +  bool find_non_escaped_objects(GrowableArray<PointsToNode*>& ptnodes_worklist,
   1.425 +                                GrowableArray<JavaObjectNode*>& non_escaped_worklist);
   1.426 +
   1.427 +  // Adjust scalar_replaceable state after Connection Graph is built.
   1.428 +  void adjust_scalar_replaceable_state(JavaObjectNode* jobj);
   1.429 +
   1.430 +  // Optimize ideal graph.
   1.431 +  void optimize_ideal_graph(GrowableArray<Node*>& ptr_cmp_worklist,
   1.432 +                            GrowableArray<Node*>& storestore_worklist);
   1.433 +  // Optimize objects compare.
   1.434 +  Node* optimize_ptr_compare(Node* n);
   1.435 +
   1.436 +  // Returns unique corresponding java object or NULL.
   1.437 +  JavaObjectNode* unique_java_object(Node *n);
   1.438 +
   1.439 +  // Add an edge of the specified type pointing to the specified target.
   1.440 +  bool add_edge(PointsToNode* from, PointsToNode* to) {
   1.441 +    assert(!from->is_Field() || from->as_Field()->is_oop(), "sanity");
   1.442 +
   1.443 +    if (to == phantom_obj) {
   1.444 +      if (from->has_unknown_ptr()) {
   1.445 +        return false; // already points to phantom_obj
   1.446 +      }
   1.447 +      from->set_has_unknown_ptr();
   1.448 +    }
   1.449 +
   1.450 +    bool is_new = from->add_edge(to);
   1.451 +    assert(to != phantom_obj || is_new, "sanity");
   1.452 +    if (is_new) { // New edge?
   1.453 +      assert(!_verify, "graph is incomplete");
   1.454 +      is_new = to->add_use(from);
   1.455 +      assert(is_new, "use should be also new");
   1.456 +    }
   1.457 +    return is_new;
   1.458 +  }
   1.459 +
   1.460 +  // Add an edge from Field node to its base and back.
   1.461 +  bool add_base(FieldNode* from, PointsToNode* to) {
   1.462 +    assert(!to->is_Arraycopy(), "sanity");
   1.463 +    if (to == phantom_obj) {
   1.464 +      if (from->has_unknown_base()) {
   1.465 +        return false; // already has phantom_obj base
   1.466 +      }
   1.467 +      from->set_has_unknown_base();
   1.468 +    }
   1.469 +    bool is_new = from->add_base(to);
   1.470 +    assert(to != phantom_obj || is_new, "sanity");
   1.471 +    if (is_new) {      // New edge?
   1.472 +      assert(!_verify, "graph is incomplete");
   1.473 +      if (to == null_obj)
   1.474 +        return is_new; // Don't add fields to NULL pointer.
   1.475 +      if (to->is_JavaObject()) {
   1.476 +        is_new = to->add_edge(from);
   1.477 +      } else {
   1.478 +        is_new = to->add_base_use(from);
   1.479 +      }
   1.480 +      assert(is_new, "use should be also new");
   1.481 +    }
   1.482 +    return is_new;
   1.483 +  }
   1.484 +
   1.485 +  // Add LocalVar node and edge if possible
   1.486 +  void add_local_var_and_edge(Node* n, PointsToNode::EscapeState es, Node* to,
   1.487 +                              Unique_Node_List *delayed_worklist) {
   1.488 +    PointsToNode* ptn = ptnode_adr(to->_idx);
   1.489 +    if (delayed_worklist != NULL) { // First iteration of CG construction
   1.490 +      add_local_var(n, es);
   1.491 +      if (ptn == NULL) {
   1.492 +        delayed_worklist->push(n);
   1.493 +        return; // Process it later.
   1.494 +      }
   1.495 +    } else {
   1.496 +      assert(ptn != NULL, "node should be registered");
   1.497 +    }
   1.498 +    add_edge(ptnode_adr(n->_idx), ptn);
   1.499 +  }
   1.500 +
   1.501 +  // Helper functions
   1.502 +  bool   is_oop_field(Node* n, int offset);
   1.503 +  static Node* get_addp_base(Node *addp);
   1.504 +  static Node* find_second_addp(Node* addp, Node* n);
   1.505  
   1.506    // offset of a field reference
   1.507    int address_offset(Node* adr, PhaseTransform *phase);
   1.508  
   1.509 -  // compute the escape state for arguments to a call
   1.510 -  void process_call_arguments(CallNode *call, PhaseTransform *phase);
   1.511  
   1.512 -  // compute the escape state for the return value of a call
   1.513 -  void process_call_result(ProjNode *resproj, PhaseTransform *phase);
   1.514 +  // Propagate unique types created for unescaped allocated objects
   1.515 +  // through the graph
   1.516 +  void split_unique_types(GrowableArray<Node *>  &alloc_worklist);
   1.517  
   1.518 -  // Populate Connection Graph with Ideal nodes.
   1.519 -  void record_for_escape_analysis(Node *n, PhaseTransform *phase);
   1.520 +  // Helper methods for unique types split.
   1.521 +  bool split_AddP(Node *addp, Node *base);
   1.522  
   1.523 -  // Build Connection Graph and set nodes escape state.
   1.524 -  void build_connection_graph(Node *n, PhaseTransform *phase);
   1.525 +  PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, bool &new_created);
   1.526 +  PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist);
   1.527  
   1.528 -  // walk the connection graph starting at the node corresponding to "n" and
   1.529 -  // add the index of everything it could point to, to "ptset".  This may cause
   1.530 -  // Phi's encountered to get (re)processed  (which requires "phase".)
   1.531 -  VectorSet* PointsTo(Node * n);
   1.532 +  void  move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis);
   1.533 +  Node* find_inst_mem(Node* mem, int alias_idx,GrowableArray<PhiNode *>  &orig_phi_worklist);
   1.534 +  Node* step_through_mergemem(MergeMemNode *mmem, int alias_idx, const TypeOopPtr *toop);
   1.535  
   1.536 -  // Reused structures for PointsTo().
   1.537 -  VectorSet            pt_ptset;
   1.538 -  VectorSet            pt_visited;
   1.539 -  GrowableArray<uint>  pt_worklist;
   1.540  
   1.541 -  //  Edge manipulation.  The "from_i" and "to_i" arguments are the
   1.542 -  //  node indices of the source and destination of the edge
   1.543 -  void add_pointsto_edge(uint from_i, uint to_i);
   1.544 -  void add_deferred_edge(uint from_i, uint to_i);
   1.545 -  void add_field_edge(uint from_i, uint to_i, int offs);
   1.546 -
   1.547 -  // Add an edge of the specified type pointing to the specified target.
   1.548 -  // Set _progress if new edge is added.
   1.549 -  void add_edge(PointsToNode *f, uint to_i, PointsToNode::EdgeType et) {
   1.550 -    uint e_cnt = f->edge_count();
   1.551 -    f->add_edge(to_i, et);
   1.552 -    _progress |= (f->edge_count() != e_cnt);
   1.553 -  }
   1.554 -
   1.555 -  // Add an edge to node given by "to_i" from any field of adr_i whose offset
   1.556 -  // matches "offset"  A deferred edge is added if to_i is a LocalVar, and
   1.557 -  // a pointsto edge is added if it is a JavaObject
   1.558 -  void add_edge_from_fields(uint adr, uint to_i, int offs);
   1.559 -
   1.560 -  // Add a deferred  edge from node given by "from_i" to any field
   1.561 -  // of adr_i whose offset matches "offset"
   1.562 -  void add_deferred_edge_to_fields(uint from_i, uint adr, int offs);
   1.563 -
   1.564 -
   1.565 -  // Remove outgoing deferred edges from the node referenced by "ni".
   1.566 -  // Any outgoing edges from the target of the deferred edge are copied
   1.567 -  // to "ni".
   1.568 -  void remove_deferred(uint ni, GrowableArray<uint>* deferred_edges, VectorSet* visited);
   1.569 +  GrowableArray<MergeMemNode*>  _mergemem_worklist; // List of all MergeMem nodes
   1.570  
   1.571    Node_Array _node_map; // used for bookeeping during type splitting
   1.572                          // Used for the following purposes:
   1.573 @@ -320,21 +547,18 @@
   1.574                          // MemNode       - new memory input for this node
   1.575                          // ChecCastPP    - allocation that this is a cast of
   1.576                          // allocation    - CheckCastPP of the allocation
   1.577 -  bool split_AddP(Node *addp, Node *base,  PhaseGVN  *igvn);
   1.578 -  PhiNode *create_split_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn, bool &new_created);
   1.579 -  PhiNode *split_memory_phi(PhiNode *orig_phi, int alias_idx, GrowableArray<PhiNode *>  &orig_phi_worklist, PhaseGVN  *igvn);
   1.580 -  void  move_inst_mem(Node* n, GrowableArray<PhiNode *>  &orig_phis, PhaseGVN *igvn);
   1.581 -  Node *find_inst_mem(Node *mem, int alias_idx,GrowableArray<PhiNode *>  &orig_phi_worklist,  PhaseGVN  *igvn);
   1.582 -
   1.583 -  // Propagate unique types created for unescaped allocated objects
   1.584 -  // through the graph
   1.585 -  void split_unique_types(GrowableArray<Node *>  &alloc_worklist);
   1.586  
   1.587    // manage entries in _node_map
   1.588 -  void  set_map(int idx, Node *n)        { _node_map.map(idx, n); }
   1.589 -  Node *get_map(int idx)                 { return _node_map[idx]; }
   1.590 -  PhiNode *get_map_phi(int idx) {
   1.591 -    Node *phi = _node_map[idx];
   1.592 +
   1.593 +  void  set_map(Node* from, Node* to)  {
   1.594 +    ideal_nodes.push(from);
   1.595 +    _node_map.map(from->_idx, to);
   1.596 +  }
   1.597 +
   1.598 +  Node* get_map(int idx) { return _node_map[idx]; }
   1.599 +
   1.600 +  PhiNode* get_map_phi(int idx) {
   1.601 +    Node* phi = _node_map[idx];
   1.602      return (phi == NULL) ? NULL : phi->as_Phi();
   1.603    }
   1.604  
   1.605 @@ -344,23 +568,6 @@
   1.606      _igvn->add_users_to_worklist(n);
   1.607    }
   1.608  
   1.609 -  // Set the escape state of a node
   1.610 -  void set_escape_state(uint ni, PointsToNode::EscapeState es);
   1.611 -
   1.612 -  // Find fields initializing values for allocations.
   1.613 -  void find_init_values(Node* n, VectorSet* visited, PhaseTransform* phase);
   1.614 -
   1.615 -  // Adjust escape state after Connection Graph is built.
   1.616 -  void adjust_escape_state(Node* n);
   1.617 -
   1.618 -  // Propagate escape states to referenced nodes.
   1.619 -  bool propagate_escape_state(GrowableArray<int>* cg_worklist,
   1.620 -                              GrowableArray<uint>* worklist,
   1.621 -                              PointsToNode::EscapeState esc_state);
   1.622 -
   1.623 -  // Optimize objects compare.
   1.624 -  Node* optimize_ptr_compare(Node* n);
   1.625 -
   1.626    // Compute the escape information
   1.627    bool compute_escape();
   1.628  
   1.629 @@ -373,11 +580,10 @@
   1.630    // Perform escape analysis
   1.631    static void do_analysis(Compile *C, PhaseIterGVN *igvn);
   1.632  
   1.633 -  // escape state of a node
   1.634 -  PointsToNode::EscapeState escape_state(Node *n);
   1.635 +  bool not_global_escape(Node *n);
   1.636  
   1.637  #ifndef PRODUCT
   1.638 -  void dump();
   1.639 +  void dump(GrowableArray<PointsToNode*>& ptnodes_worklist);
   1.640  #endif
   1.641  };
   1.642  

mercurial