src/share/vm/opto/escape.cpp

changeset 2276
e4fcbeb5a698
parent 2170
5867d89c129b
child 2314
f95d63e2154a
     1.1 --- a/src/share/vm/opto/escape.cpp	Sat Nov 06 18:52:07 2010 -0700
     1.2 +++ b/src/share/vm/opto/escape.cpp	Sat Nov 06 20:35:36 2010 -0700
     1.3 @@ -85,6 +85,7 @@
     1.4    _nodes(C->comp_arena(), C->unique(), C->unique(), PointsToNode()),
     1.5    _processed(C->comp_arena()),
     1.6    _collecting(true),
     1.7 +  _progress(false),
     1.8    _compile(C),
     1.9    _igvn(igvn),
    1.10    _node_map(C->comp_arena()) {
    1.11 @@ -113,7 +114,7 @@
    1.12    assert(f->node_type() != PointsToNode::UnknownType && t->node_type() != PointsToNode::UnknownType, "node types must be set");
    1.13    assert(f->node_type() == PointsToNode::LocalVar || f->node_type() == PointsToNode::Field, "invalid source of PointsTo edge");
    1.14    assert(t->node_type() == PointsToNode::JavaObject, "invalid destination of PointsTo edge");
    1.15 -  f->add_edge(to_i, PointsToNode::PointsToEdge);
    1.16 +  add_edge(f, to_i, PointsToNode::PointsToEdge);
    1.17  }
    1.18  
    1.19  void ConnectionGraph::add_deferred_edge(uint from_i, uint to_i) {
    1.20 @@ -126,7 +127,7 @@
    1.21    // don't add a self-referential edge, this can occur during removal of
    1.22    // deferred edges
    1.23    if (from_i != to_i)
    1.24 -    f->add_edge(to_i, PointsToNode::DeferredEdge);
    1.25 +    add_edge(f, to_i, PointsToNode::DeferredEdge);
    1.26  }
    1.27  
    1.28  int ConnectionGraph::address_offset(Node* adr, PhaseTransform *phase) {
    1.29 @@ -157,7 +158,7 @@
    1.30    assert (t->offset() == -1 || t->offset() == offset, "conflicting field offsets");
    1.31    t->set_offset(offset);
    1.32  
    1.33 -  f->add_edge(to_i, PointsToNode::FieldEdge);
    1.34 +  add_edge(f, to_i, PointsToNode::FieldEdge);
    1.35  }
    1.36  
    1.37  void ConnectionGraph::set_escape_state(uint ni, PointsToNode::EscapeState es) {
    1.38 @@ -995,7 +996,7 @@
    1.39    GrowableArray<Node *>  memnode_worklist;
    1.40    GrowableArray<PhiNode *>  orig_phis;
    1.41  
    1.42 -  PhaseGVN  *igvn = _igvn;
    1.43 +  PhaseIterGVN  *igvn = _igvn;
    1.44    uint new_index_start = (uint) _compile->num_alias_types();
    1.45    Arena* arena = Thread::current()->resource_area();
    1.46    VectorSet visited(arena);
    1.47 @@ -1531,14 +1532,9 @@
    1.48        has_allocations = true;
    1.49      }
    1.50      if(n->is_AddP()) {
    1.51 -      // Collect address nodes which directly reference an allocation.
    1.52 -      // Use them during stage 3 below to build initial connection graph
    1.53 -      // field edges. Other field edges could be added after StoreP/LoadP
    1.54 -      // nodes are processed during stage 4 below.
    1.55 -      Node* base = get_addp_base(n);
    1.56 -      if(base->is_Proj() && base->in(0)->is_Allocate()) {
    1.57 -        cg_worklist.append(n->_idx);
    1.58 -      }
    1.59 +      // Collect address nodes. Use them during stage 3 below
    1.60 +      // to build initial connection graph field edges.
    1.61 +      cg_worklist.append(n->_idx);
    1.62      } else if (n->is_MergeMem()) {
    1.63        // Collect all MergeMem nodes to add memory slices for
    1.64        // scalar replaceable objects in split_unique_types().
    1.65 @@ -1562,18 +1558,28 @@
    1.66      build_connection_graph(n, igvn);
    1.67    }
    1.68  
    1.69 -  // 3. Pass to create fields edges (Allocate -F-> AddP).
    1.70 +  // 3. Pass to create initial fields edges (JavaObject -F-> AddP)
    1.71 +  //    to reduce number of iterations during stage 4 below.
    1.72    uint cg_length = cg_worklist.length();
    1.73    for( uint next = 0; next < cg_length; ++next ) {
    1.74      int ni = cg_worklist.at(next);
    1.75 -    build_connection_graph(ptnode_adr(ni)->_node, igvn);
    1.76 +    Node* n = ptnode_adr(ni)->_node;
    1.77 +    Node* base = get_addp_base(n);
    1.78 +    if (base->is_Proj())
    1.79 +      base = base->in(0);
    1.80 +    PointsToNode::NodeType nt = ptnode_adr(base->_idx)->node_type();
    1.81 +    if (nt == PointsToNode::JavaObject) {
    1.82 +      build_connection_graph(n, igvn);
    1.83 +    }
    1.84    }
    1.85  
    1.86    cg_worklist.clear();
    1.87    cg_worklist.append(_phantom_object);
    1.88 +  GrowableArray<uint>  worklist;
    1.89  
    1.90    // 4. Build Connection Graph which need
    1.91    //    to walk the connection graph.
    1.92 +  _progress = false;
    1.93    for (uint ni = 0; ni < nodes_size(); ni++) {
    1.94      PointsToNode* ptn = ptnode_adr(ni);
    1.95      Node *n = ptn->_node;
    1.96 @@ -1581,13 +1587,52 @@
    1.97        build_connection_graph(n, igvn);
    1.98        if (ptn->node_type() != PointsToNode::UnknownType)
    1.99          cg_worklist.append(n->_idx); // Collect CG nodes
   1.100 +      if (!_processed.test(n->_idx))
   1.101 +        worklist.append(n->_idx); // Collect C/A/L/S nodes
   1.102      }
   1.103    }
   1.104  
   1.105 +  // After IGVN user nodes may have smaller _idx than
   1.106 +  // their inputs so they will be processed first in
   1.107 +  // previous loop. Because of that not all Graph
   1.108 +  // edges will be created. Walk over interesting
   1.109 +  // nodes again until no new edges are created.
   1.110 +  //
   1.111 +  // Normally only 1-3 passes needed to build
   1.112 +  // Connection Graph depending on graph complexity.
   1.113 +  // Set limit to 10 to catch situation when something
   1.114 +  // did go wrong and recompile the method without EA.
   1.115 +
   1.116 +#define CG_BUILD_ITER_LIMIT 10
   1.117 +
   1.118 +  uint length = worklist.length();
   1.119 +  int iterations = 0;
   1.120 +  while(_progress && (iterations++ < CG_BUILD_ITER_LIMIT)) {
   1.121 +    _progress = false;
   1.122 +    for( uint next = 0; next < length; ++next ) {
   1.123 +      int ni = worklist.at(next);
   1.124 +      PointsToNode* ptn = ptnode_adr(ni);
   1.125 +      Node* n = ptn->_node;
   1.126 +      assert(n != NULL, "should be known node");
   1.127 +      build_connection_graph(n, igvn);
   1.128 +    }
   1.129 +  }
   1.130 +  if (iterations >= CG_BUILD_ITER_LIMIT) {
   1.131 +    assert(iterations < CG_BUILD_ITER_LIMIT,
   1.132 +           err_msg("infinite EA connection graph build with %d nodes and worklist size %d",
   1.133 +           nodes_size(), length));
   1.134 +    // Possible infinite build_connection_graph loop,
   1.135 +    // retry compilation without escape analysis.
   1.136 +    C->record_failure(C2Compiler::retry_no_escape_analysis());
   1.137 +    _collecting = false;
   1.138 +    return false;
   1.139 +  }
   1.140 +#undef CG_BUILD_ITER_LIMIT
   1.141 +
   1.142    Arena* arena = Thread::current()->resource_area();
   1.143    VectorSet ptset(arena);
   1.144 -  GrowableArray<uint>  deferred_edges;
   1.145    VectorSet visited(arena);
   1.146 +  worklist.clear();
   1.147  
   1.148    // 5. Remove deferred edges from the graph and adjust
   1.149    //    escape state of nonescaping objects.
   1.150 @@ -1597,7 +1642,7 @@
   1.151      PointsToNode* ptn = ptnode_adr(ni);
   1.152      PointsToNode::NodeType nt = ptn->node_type();
   1.153      if (nt == PointsToNode::LocalVar || nt == PointsToNode::Field) {
   1.154 -      remove_deferred(ni, &deferred_edges, &visited);
   1.155 +      remove_deferred(ni, &worklist, &visited);
   1.156        Node *n = ptn->_node;
   1.157        if (n->is_AddP()) {
   1.158          // Search for objects which are not scalar replaceable
   1.159 @@ -1608,7 +1653,7 @@
   1.160    }
   1.161  
   1.162    // 6. Propagate escape states.
   1.163 -  GrowableArray<int>  worklist;
   1.164 +  worklist.clear();
   1.165    bool has_non_escaping_obj = false;
   1.166  
   1.167    // push all GlobalEscape nodes on the worklist
   1.168 @@ -2444,13 +2489,14 @@
   1.169  
   1.170    // Don't set processed bit for AddP, LoadP, StoreP since
   1.171    // they may need more then one pass to process.
   1.172 +  // Also don't mark as processed Call nodes since their
   1.173 +  // arguments may need more then one pass to process.
   1.174    if (_processed.test(n_idx))
   1.175      return; // No need to redefine node's state.
   1.176  
   1.177    if (n->is_Call()) {
   1.178      CallNode *call = n->as_Call();
   1.179      process_call_arguments(call, phase);
   1.180 -    _processed.set(n_idx);
   1.181      return;
   1.182    }
   1.183  

mercurial