< prev index next >

src/hotspot/share/opto/escape.cpp

Print this page
rev 56101 : 8227745: Enable Escape Analysis for better performance when debugging
Reviewed-by: ???


 106   if (oop_null->outcnt() == 0)
 107     igvn->hash_delete(oop_null);
 108   if (noop_null->outcnt() == 0)
 109     igvn->hash_delete(noop_null);
 110 }
 111 
 112 bool ConnectionGraph::compute_escape() {
 113   Compile* C = _compile;
 114   PhaseGVN* igvn = _igvn;
 115 
 116   // Worklists used by EA.
 117   Unique_Node_List delayed_worklist;
 118   GrowableArray<Node*> alloc_worklist;
 119   GrowableArray<Node*> ptr_cmp_worklist;
 120   GrowableArray<Node*> storestore_worklist;
 121   GrowableArray<ArrayCopyNode*> arraycopy_worklist;
 122   GrowableArray<PointsToNode*>   ptnodes_worklist;
 123   GrowableArray<JavaObjectNode*> java_objects_worklist;
 124   GrowableArray<JavaObjectNode*> non_escaped_worklist;
 125   GrowableArray<FieldNode*>      oop_fields_worklist;

 126   DEBUG_ONLY( GrowableArray<Node*> addp_worklist; )
 127 
 128   { Compile::TracePhase tp("connectionGraph", &Phase::timers[Phase::_t_connectionGraph]);
 129 
 130   // 1. Populate Connection Graph (CG) with PointsTo nodes.
 131   ideal_nodes.map(C->live_nodes(), NULL);  // preallocate space
 132   // Initialize worklist
 133   if (C->root() != NULL) {
 134     ideal_nodes.push(C->root());
 135   }
 136   // Processed ideal nodes are unique on ideal_nodes list
 137   // but several ideal nodes are mapped to the phantom_obj.
 138   // To avoid duplicated entries on the following worklists
 139   // add the phantom_obj only once to them.
 140   ptnodes_worklist.append(phantom_obj);
 141   java_objects_worklist.append(phantom_obj);
 142   for( uint next = 0; next < ideal_nodes.size(); ++next ) {
 143     Node* n = ideal_nodes.at(next);
 144     // Create PointsTo nodes and add them to Connection Graph. Called
 145     // only once per ideal node since ideal_nodes is Unique_Node list.


 171       // escape status of the associated Allocate node some of them
 172       // may be eliminated.
 173       storestore_worklist.append(n);
 174     } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) &&
 175                (n->req() > MemBarNode::Precedent)) {
 176       record_for_optimizer(n);
 177 #ifdef ASSERT
 178     } else if (n->is_AddP()) {
 179       // Collect address nodes for graph verification.
 180       addp_worklist.append(n);
 181 #endif
 182     } else if (n->is_ArrayCopy()) {
 183       // Keep a list of ArrayCopy nodes so if one of its input is non
 184       // escaping, we can record a unique type
 185       arraycopy_worklist.append(n->as_ArrayCopy());
 186     }
 187     for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
 188       Node* m = n->fast_out(i);   // Get user
 189       ideal_nodes.push(m);
 190     }



 191   }
 192   if (non_escaped_worklist.length() == 0) {
 193     _collecting = false;
 194     return false; // Nothing to do.
 195   }
 196   // Add final simple edges to graph.
 197   while(delayed_worklist.size() > 0) {
 198     Node* n = delayed_worklist.pop();
 199     add_final_edges(n);
 200   }
 201   int ptnodes_length = ptnodes_worklist.length();
 202 
 203 #ifdef ASSERT
 204   if (VerifyConnectionGraph) {
 205     // Verify that no new simple edges could be created and all
 206     // local vars has edges.
 207     _verify = true;
 208     for (int next = 0; next < ptnodes_length; ++next) {
 209       PointsToNode* ptn = ptnodes_worklist.at(next);
 210       add_final_edges(ptn->ideal_node());


 300     // Now use the escape information to create unique types for
 301     // scalar replaceable objects.
 302     split_unique_types(alloc_worklist, arraycopy_worklist);
 303     if (C->failing())  return false;
 304     C->print_method(PHASE_AFTER_EA, 2);
 305 
 306 #ifdef ASSERT
 307   } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
 308     tty->print("=== No allocations eliminated for ");
 309     C->method()->print_short_name();
 310     if(!EliminateAllocations) {
 311       tty->print(" since EliminateAllocations is off ===");
 312     } else if(!has_scalar_replaceable_candidates) {
 313       tty->print(" since there are no scalar replaceable candidates ===");
 314     } else if(C->AliasLevel() < 3) {
 315       tty->print(" since AliasLevel < 3 ===");
 316     }
 317     tty->cr();
 318 #endif
 319   }































































 320   return has_non_escaping_obj;
 321 }
 322 
 323 // Utility function for nodes that load an object
 324 void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
 325   // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
 326   // ThreadLocal has RawPtr type.
 327   const Type* t = _igvn->type(n);
 328   if (t->make_ptr() != NULL) {
 329     Node* adr = n->in(MemNode::Address);
 330 #ifdef ASSERT
 331     if (!adr->is_AddP()) {
 332       assert(_igvn->type(adr)->isa_rawptr(), "sanity");
 333     } else {
 334       assert((ptnode_adr(adr->_idx) == NULL ||
 335               ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
 336     }
 337 #endif
 338     add_local_var_and_edge(n, PointsToNode::NoEscape,
 339                            adr, delayed_worklist);


2161     if (e->is_JavaObject()) {
2162       Node* n = e->ideal_node();
2163       if ((e->escape_state() != PointsToNode::NoEscape) ||
2164           !(n->is_Allocate() || n->is_CallStaticJava())) {
2165         return false;
2166       }
2167     }
2168   }
2169   return true;
2170 }
2171 
2172 // Return true if we know the node does not escape globally.
2173 bool ConnectionGraph::not_global_escape(Node *n) {
2174   assert(!_collecting, "should not call during graph construction");
2175   // If the node was created after the escape computation we can't answer.
2176   uint idx = n->_idx;
2177   if (idx >= nodes_size()) {
2178     return false;
2179   }
2180   PointsToNode* ptn = ptnode_adr(idx);



2181   PointsToNode::EscapeState es = ptn->escape_state();
2182   // If we have already computed a value, return it.
2183   if (es >= PointsToNode::GlobalEscape)
2184     return false;
2185   if (ptn->is_JavaObject()) {
2186     return true; // (es < PointsToNode::GlobalEscape);
2187   }
2188   assert(ptn->is_LocalVar(), "sanity");
2189   // Check all java objects it points to.
2190   for (EdgeIterator i(ptn); i.has_next(); i.next()) {
2191     if (i.get()->escape_state() >= PointsToNode::GlobalEscape)
2192       return false;
2193   }
2194   return true;
2195 }
2196 
2197 
2198 // Helper functions
2199 
2200 // Return true if this node points to specified node or nodes it points to.




 106   if (oop_null->outcnt() == 0)
 107     igvn->hash_delete(oop_null);
 108   if (noop_null->outcnt() == 0)
 109     igvn->hash_delete(noop_null);
 110 }
 111 
 112 bool ConnectionGraph::compute_escape() {
 113   Compile* C = _compile;
 114   PhaseGVN* igvn = _igvn;
 115 
 116   // Worklists used by EA.
 117   Unique_Node_List delayed_worklist;
 118   GrowableArray<Node*> alloc_worklist;
 119   GrowableArray<Node*> ptr_cmp_worklist;
 120   GrowableArray<Node*> storestore_worklist;
 121   GrowableArray<ArrayCopyNode*> arraycopy_worklist;
 122   GrowableArray<PointsToNode*>   ptnodes_worklist;
 123   GrowableArray<JavaObjectNode*> java_objects_worklist;
 124   GrowableArray<JavaObjectNode*> non_escaped_worklist;
 125   GrowableArray<FieldNode*>      oop_fields_worklist;
 126   GrowableArray<SafePointNode*>  sfn_worklist;
 127   DEBUG_ONLY( GrowableArray<Node*> addp_worklist; )
 128 
 129   { Compile::TracePhase tp("connectionGraph", &Phase::timers[Phase::_t_connectionGraph]);
 130 
 131   // 1. Populate Connection Graph (CG) with PointsTo nodes.
 132   ideal_nodes.map(C->live_nodes(), NULL);  // preallocate space
 133   // Initialize worklist
 134   if (C->root() != NULL) {
 135     ideal_nodes.push(C->root());
 136   }
 137   // Processed ideal nodes are unique on ideal_nodes list
 138   // but several ideal nodes are mapped to the phantom_obj.
 139   // To avoid duplicated entries on the following worklists
 140   // add the phantom_obj only once to them.
 141   ptnodes_worklist.append(phantom_obj);
 142   java_objects_worklist.append(phantom_obj);
 143   for( uint next = 0; next < ideal_nodes.size(); ++next ) {
 144     Node* n = ideal_nodes.at(next);
 145     // Create PointsTo nodes and add them to Connection Graph. Called
 146     // only once per ideal node since ideal_nodes is Unique_Node list.


 172       // escape status of the associated Allocate node some of them
 173       // may be eliminated.
 174       storestore_worklist.append(n);
 175     } else if (n->is_MemBar() && (n->Opcode() == Op_MemBarRelease) &&
 176                (n->req() > MemBarNode::Precedent)) {
 177       record_for_optimizer(n);
 178 #ifdef ASSERT
 179     } else if (n->is_AddP()) {
 180       // Collect address nodes for graph verification.
 181       addp_worklist.append(n);
 182 #endif
 183     } else if (n->is_ArrayCopy()) {
 184       // Keep a list of ArrayCopy nodes so if one of its input is non
 185       // escaping, we can record a unique type
 186       arraycopy_worklist.append(n->as_ArrayCopy());
 187     }
 188     for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
 189       Node* m = n->fast_out(i);   // Get user
 190       ideal_nodes.push(m);
 191     }
 192     if (n-> is_SafePoint()) {
 193       sfn_worklist.append(n->as_SafePoint());
 194     }
 195   }
 196   if (non_escaped_worklist.length() == 0) {
 197     _collecting = false;
 198     return false; // Nothing to do.
 199   }
 200   // Add final simple edges to graph.
 201   while(delayed_worklist.size() > 0) {
 202     Node* n = delayed_worklist.pop();
 203     add_final_edges(n);
 204   }
 205   int ptnodes_length = ptnodes_worklist.length();
 206 
 207 #ifdef ASSERT
 208   if (VerifyConnectionGraph) {
 209     // Verify that no new simple edges could be created and all
 210     // local vars has edges.
 211     _verify = true;
 212     for (int next = 0; next < ptnodes_length; ++next) {
 213       PointsToNode* ptn = ptnodes_worklist.at(next);
 214       add_final_edges(ptn->ideal_node());


 304     // Now use the escape information to create unique types for
 305     // scalar replaceable objects.
 306     split_unique_types(alloc_worklist, arraycopy_worklist);
 307     if (C->failing())  return false;
 308     C->print_method(PHASE_AFTER_EA, 2);
 309 
 310 #ifdef ASSERT
 311   } else if (Verbose && (PrintEscapeAnalysis || PrintEliminateAllocations)) {
 312     tty->print("=== No allocations eliminated for ");
 313     C->method()->print_short_name();
 314     if(!EliminateAllocations) {
 315       tty->print(" since EliminateAllocations is off ===");
 316     } else if(!has_scalar_replaceable_candidates) {
 317       tty->print(" since there are no scalar replaceable candidates ===");
 318     } else if(C->AliasLevel() < 3) {
 319       tty->print(" since AliasLevel < 3 ===");
 320     }
 321     tty->cr();
 322 #endif
 323   }
 324 
 325   // Annotate at safepoints if they have <= ArgEscape objects in their scope and at
 326   // java calls if they pass ArgEscape objects as parameters.
 327   if (has_non_escaping_obj &&
 328       (C->env()->should_retain_local_variables() ||
 329        C->env()->jvmti_can_get_owned_monitor_info() ||
 330        C->env()->jvmti_can_walk_any_space() ||
 331        DeoptimizeObjectsALot)) {
 332     int sfn_length = sfn_worklist.length();
 333     for (int next = 0; next < sfn_length; next++) {
 334       SafePointNode* sfn = sfn_worklist.at(next);
 335       bool found_not_global_escape = false;
 336       for (JVMState* jvms = sfn->jvms(); jvms && !found_not_global_escape; jvms = jvms->caller()) {
 337         if (C->env()->should_retain_local_variables() || C->env()->jvmti_can_walk_any_space() ||
 338             DeoptimizeObjectsALot) {
 339           // Jvmti agents can access locals. Must provide info about local objects at runtime.
 340           int num_locs = jvms->loc_size();
 341           for(int idx = 0; idx < num_locs && !found_not_global_escape; idx++ ) {
 342             Node* l = sfn->local(jvms, idx);
 343             found_not_global_escape = not_global_escape(l);
 344           }
 345         }
 346         if (C->env()->jvmti_can_get_owned_monitor_info() ||
 347             C->env()->jvmti_can_walk_any_space() || DeoptimizeObjectsALot) {
 348           // Jvmti agents can read monitors. Must provide info about locked objects at runtime.
 349           int num_mon = jvms->nof_monitors();
 350           for(int idx = 0; idx < num_mon && !found_not_global_escape; idx++ ) {
 351             Node* m = sfn->monitor_obj(jvms, idx);
 352             found_not_global_escape = m != NULL && not_global_escape(m);
 353           }
 354         }
 355       }
 356       sfn->set_not_global_escape_in_scope(found_not_global_escape);
 357 
 358       if (sfn->is_CallJava()) {
 359         CallJavaNode* call = sfn->as_CallJava();
 360         bool found_arg_escape_in_args = false;
 361         if (call->method() != NULL) {
 362           uint max_idx = TypeFunc::Parms + call->method()->arg_size();
 363           for(uint idx = TypeFunc::Parms; idx < max_idx && !found_arg_escape_in_args; idx++) {
 364             Node* p = call->in(idx);
 365             found_arg_escape_in_args = not_global_escape(p);
 366           }
 367         } else {
 368           const char* name = call->as_CallStaticJava()->_name;
 369           assert(name != NULL, "no name");
 370           // no arg escapes through uncommon traps
 371           if (strcmp(name, "uncommon_trap") != 0) {
 372             // process_call_arguments() assumes that all arguments escape globally
 373             const TypeTuple* d = call->tf()->domain();
 374             for (uint i = TypeFunc::Parms; i < d->cnt() && !found_arg_escape_in_args; i++) {
 375               const Type* at = d->field_at(i);
 376               if (at->isa_oopptr() != NULL) {
 377                 found_arg_escape_in_args = true;
 378               }
 379             }
 380           }
 381         }
 382         call->set_arg_escape(found_arg_escape_in_args);
 383       }
 384     }
 385   }
 386 
 387   return has_non_escaping_obj;
 388 }
 389 
 390 // Utility function for nodes that load an object
 391 void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) {
 392   // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because
 393   // ThreadLocal has RawPtr type.
 394   const Type* t = _igvn->type(n);
 395   if (t->make_ptr() != NULL) {
 396     Node* adr = n->in(MemNode::Address);
 397 #ifdef ASSERT
 398     if (!adr->is_AddP()) {
 399       assert(_igvn->type(adr)->isa_rawptr(), "sanity");
 400     } else {
 401       assert((ptnode_adr(adr->_idx) == NULL ||
 402               ptnode_adr(adr->_idx)->as_Field()->is_oop()), "sanity");
 403     }
 404 #endif
 405     add_local_var_and_edge(n, PointsToNode::NoEscape,
 406                            adr, delayed_worklist);


2228     if (e->is_JavaObject()) {
2229       Node* n = e->ideal_node();
2230       if ((e->escape_state() != PointsToNode::NoEscape) ||
2231           !(n->is_Allocate() || n->is_CallStaticJava())) {
2232         return false;
2233       }
2234     }
2235   }
2236   return true;
2237 }
2238 
2239 // Return true if we know the node does not escape globally.
2240 bool ConnectionGraph::not_global_escape(Node *n) {
2241   assert(!_collecting, "should not call during graph construction");
2242   // If the node was created after the escape computation we can't answer.
2243   uint idx = n->_idx;
2244   if (idx >= nodes_size()) {
2245     return false;
2246   }
2247   PointsToNode* ptn = ptnode_adr(idx);
2248   if (!ptn) {
2249     return false; // not in congraph (e.g. ConI)
2250   }
2251   PointsToNode::EscapeState es = ptn->escape_state();
2252   // If we have already computed a value, return it.
2253   if (es >= PointsToNode::GlobalEscape)
2254     return false;
2255   if (ptn->is_JavaObject()) {
2256     return true; // (es < PointsToNode::GlobalEscape);
2257   }
2258   assert(ptn->is_LocalVar(), "sanity");
2259   // Check all java objects it points to.
2260   for (EdgeIterator i(ptn); i.has_next(); i.next()) {
2261     if (i.get()->escape_state() >= PointsToNode::GlobalEscape)
2262       return false;
2263   }
2264   return true;
2265 }
2266 
2267 
2268 // Helper functions
2269 
2270 // Return true if this node points to specified node or nodes it points to.


< prev index next >