< 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 >