< prev index next >

src/hotspot/share/opto/escape.cpp

Print this page
rev 60137 : 8227745: Enable Escape Analysis for Better Performance in the Presence of JVMTI Agents
Reviewed-by: mdoerr, goetz

*** 1,7 **** /* ! * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. --- 1,7 ---- /* ! * Copyright (c) 2005, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.
*** 121,130 **** --- 121,131 ---- GrowableArray<ArrayCopyNode*> arraycopy_worklist; GrowableArray<PointsToNode*> ptnodes_worklist; GrowableArray<JavaObjectNode*> java_objects_worklist; GrowableArray<JavaObjectNode*> non_escaped_worklist; GrowableArray<FieldNode*> oop_fields_worklist; + GrowableArray<SafePointNode*> sfn_worklist; DEBUG_ONLY( GrowableArray<Node*> addp_worklist; ) { Compile::TracePhase tp("connectionGraph", &Phase::timers[Phase::_t_connectionGraph]); // 1. Populate Connection Graph (CG) with PointsTo nodes.
*** 186,195 **** --- 187,199 ---- } for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node* m = n->fast_out(i); // Get user ideal_nodes.push(m); } + if (n-> is_SafePoint()) { + sfn_worklist.append(n->as_SafePoint()); + } } if (non_escaped_worklist.length() == 0) { _collecting = false; return false; // Nothing to do. }
*** 315,327 **** --- 319,411 ---- tty->print(" since AliasLevel < 3 ==="); } tty->cr(); #endif } + + // Annotate at safepoints if they have <= ArgEscape objects in their scope and at + // java calls if they pass ArgEscape objects as parameters. + if (has_non_escaping_obj && + (C->env()->should_retain_local_variables() || + C->env()->jvmti_can_get_owned_monitor_info() || + C->env()->jvmti_can_walk_any_space() || + DeoptimizeObjectsALot)) { + int sfn_length = sfn_worklist.length(); + for (int next = 0; next < sfn_length; next++) { + SafePointNode* sfn = sfn_worklist.at(next); + sfn->set_not_global_escape_in_scope(has_not_global_escape_in_scope(sfn)); + if (sfn->is_CallJava()) { + CallJavaNode* call = sfn->as_CallJava(); + call->set_arg_escape(has_arg_escape(call)); + } + } + } + return has_non_escaping_obj; } + // Returns true if an object in the scope of sfn does not escape globally. + bool ConnectionGraph::has_not_global_escape_in_scope(SafePointNode* sfn) { + Compile* C = _compile; + for (JVMState* jvms = sfn->jvms(); jvms != NULL; jvms = jvms->caller()) { + if (C->env()->should_retain_local_variables() || C->env()->jvmti_can_walk_any_space() || + DeoptimizeObjectsALot) { + // Jvmti agents can access locals. Must provide info about local objects at runtime. + int num_locs = jvms->loc_size(); + for (int idx = 0; idx < num_locs; idx++) { + Node* l = sfn->local(jvms, idx); + if (not_global_escape(l)) { + return true; + } + } + } + if (C->env()->jvmti_can_get_owned_monitor_info() || + C->env()->jvmti_can_walk_any_space() || DeoptimizeObjectsALot) { + // Jvmti agents can read monitors. Must provide info about locked objects at runtime. + int num_mon = jvms->nof_monitors(); + for (int idx = 0; idx < num_mon; idx++) { + Node* m = sfn->monitor_obj(jvms, idx); + if (m != NULL && not_global_escape(m)) { + return true; + } + } + } + } + return false; + } + + // Returns true if at least one of the arguments to the call is an object + // that does not escape globally. + bool ConnectionGraph::has_arg_escape(CallJavaNode* call) { + if (call->method() != NULL) { + uint max_idx = TypeFunc::Parms + call->method()->arg_size(); + for (uint idx = TypeFunc::Parms; idx < max_idx; idx++) { + Node* p = call->in(idx); + if (not_global_escape(p)) { + return true; + } + } + } else { + const char* name = call->as_CallStaticJava()->_name; + assert(name != NULL, "no name"); + // no arg escapes through uncommon traps + if (strcmp(name, "uncommon_trap") != 0) { + // process_call_arguments() assumes that all arguments escape globally + const TypeTuple* d = call->tf()->domain(); + for (uint i = TypeFunc::Parms; i < d->cnt(); i++) { + const Type* at = d->field_at(i); + if (at->isa_oopptr() != NULL) { + return true; + } + } + } + } + return false; + } + + + // Utility function for nodes that load an object void ConnectionGraph::add_objload_to_connection_graph(Node *n, Unique_Node_List *delayed_worklist) { // Using isa_ptr() instead of isa_oopptr() for LoadP and Phi because // ThreadLocal has RawPtr type. const Type* t = _igvn->type(n);
< prev index next >