src/share/vm/opto/escape.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File
8041984 Cdiff src/share/vm/opto/escape.cpp
src/share/vm/opto/escape.cpp
Print this page
*** 36,45 ****
--- 36,47 ----
#include "opto/movenode.hpp"
#include "opto/rootnode.hpp"
ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
_nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
+ _in_worklist(C->comp_arena()),
+ _next_pidx(0),
_collecting(true),
_verify(false),
_compile(C),
_igvn(igvn),
_node_map(C->comp_arena()) {
*** 123,139 ****
ideal_nodes.map(C->live_nodes(), NULL); // preallocate space
// Initialize worklist
if (C->root() != NULL) {
ideal_nodes.push(C->root());
}
for( uint next = 0; next < ideal_nodes.size(); ++next ) {
Node* n = ideal_nodes.at(next);
// Create PointsTo nodes and add them to Connection Graph. Called
// only once per ideal node since ideal_nodes is Unique_Node list.
add_node_to_connection_graph(n, &delayed_worklist);
PointsToNode* ptn = ptnode_adr(n->_idx);
! if (ptn != NULL) {
ptnodes_worklist.append(ptn);
if (ptn->is_JavaObject()) {
java_objects_worklist.append(ptn->as_JavaObject());
if ((n->is_Allocate() || n->is_CallStaticJava()) &&
(ptn->escape_state() < PointsToNode::GlobalEscape)) {
--- 125,143 ----
ideal_nodes.map(C->live_nodes(), NULL); // preallocate space
// Initialize worklist
if (C->root() != NULL) {
ideal_nodes.push(C->root());
}
+ ptnodes_worklist.append(phantom_obj);
+ java_objects_worklist.append(phantom_obj);
for( uint next = 0; next < ideal_nodes.size(); ++next ) {
Node* n = ideal_nodes.at(next);
// Create PointsTo nodes and add them to Connection Graph. Called
// only once per ideal node since ideal_nodes is Unique_Node list.
add_node_to_connection_graph(n, &delayed_worklist);
PointsToNode* ptn = ptnode_adr(n->_idx);
! if (ptn != NULL && ptn != phantom_obj) {
ptnodes_worklist.append(ptn);
if (ptn->is_JavaObject()) {
java_objects_worklist.append(ptn->as_JavaObject());
if ((n->is_Allocate() || n->is_CallStaticJava()) &&
(ptn->escape_state() < PointsToNode::GlobalEscape)) {
*** 413,423 ****
add_java_object(n, es);
break;
}
case Op_CreateEx: {
// assume that all exception objects globally escape
! add_java_object(n, PointsToNode::GlobalEscape);
break;
}
case Op_LoadKlass:
case Op_LoadNKlass: {
// Unknown class is loaded
--- 417,427 ----
add_java_object(n, es);
break;
}
case Op_CreateEx: {
// assume that all exception objects globally escape
! map_ideal_node(n, phantom_obj);
break;
}
case Op_LoadKlass:
case Op_LoadNKlass: {
// Unknown class is loaded
*** 1089,1123 ****
return false; // Nothing to do.
}
// Now propagate references to all JavaObject nodes.
int java_objects_length = java_objects_worklist.length();
elapsedTimer time;
int new_edges = 1;
int iterations = 0;
do {
while ((new_edges > 0) &&
! (iterations++ < CG_BUILD_ITER_LIMIT) &&
! (time.seconds() < CG_BUILD_TIME_LIMIT)) {
time.start();
new_edges = 0;
// Propagate references to phantom_object for nodes pushed on _worklist
// by find_non_escaped_objects() and find_field_value().
new_edges += add_java_object_edges(phantom_obj, false);
for (int next = 0; next < java_objects_length; ++next) {
JavaObjectNode* ptn = java_objects_worklist.at(next);
new_edges += add_java_object_edges(ptn, true);
}
if (new_edges > 0) {
// Update escape states on each iteration if graph was updated.
if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
return false; // Nothing to do.
}
}
time.stop();
}
! if ((iterations < CG_BUILD_ITER_LIMIT) &&
! (time.seconds() < CG_BUILD_TIME_LIMIT)) {
time.start();
// Find fields which have unknown value.
int fields_length = oop_fields_worklist.length();
for (int next = 0; next < fields_length; next++) {
FieldNode* field = oop_fields_worklist.at(next);
--- 1093,1146 ----
return false; // Nothing to do.
}
// Now propagate references to all JavaObject nodes.
int java_objects_length = java_objects_worklist.length();
elapsedTimer time;
+ bool timeout = false;
int new_edges = 1;
int iterations = 0;
do {
while ((new_edges > 0) &&
! (iterations++ < CG_BUILD_ITER_LIMIT)) {
! double start_time = time.seconds();
time.start();
new_edges = 0;
// Propagate references to phantom_object for nodes pushed on _worklist
// by find_non_escaped_objects() and find_field_value().
new_edges += add_java_object_edges(phantom_obj, false);
for (int next = 0; next < java_objects_length; ++next) {
JavaObjectNode* ptn = java_objects_worklist.at(next);
new_edges += add_java_object_edges(ptn, true);
+ if ((next & 3) == 0) {
+ // Each 4 iterations calculate how much time it will take
+ // to complete graph construction.
+ time.stop();
+ double stop_time = time.seconds();
+ double time_per_iter = (stop_time - start_time) * 0.25;
+ double time_until_end = time_per_iter * (double)(java_objects_length - next);
+ if ((start_time + time_until_end) >= CG_BUILD_TIME_LIMIT) {
+ timeout = true;
+ break; // Timeout
+ }
+ start_time = stop_time;
+ time.start();
+ }
}
+ if (timeout) break;
if (new_edges > 0) {
// Update escape states on each iteration if graph was updated.
if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) {
return false; // Nothing to do.
}
}
time.stop();
+ if (time.seconds() >= CG_BUILD_TIME_LIMIT) {
+ timeout = true;
+ break;
+ }
}
! if ((iterations < CG_BUILD_ITER_LIMIT) && !timeout) {
time.start();
// Find fields which have unknown value.
int fields_length = oop_fields_worklist.length();
for (int next = 0; next < fields_length; next++) {
FieldNode* field = oop_fields_worklist.at(next);
*** 1126,1147 ****
// This code may added new edges to phantom_object.
// Need an other cycle to propagate references to phantom_object.
}
}
time.stop();
} else {
new_edges = 0; // Bailout
}
} while (new_edges > 0);
// Bailout if passed limits.
! if ((iterations >= CG_BUILD_ITER_LIMIT) ||
! (time.seconds() >= CG_BUILD_TIME_LIMIT)) {
Compile* C = _compile;
if (C->log() != NULL) {
C->log()->begin_elem("connectionGraph_bailout reason='reached ");
! C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time");
C->log()->end_elem(" limit'");
}
assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
time.seconds(), iterations, nodes_size(), ptnodes_worklist.length()));
// Possible infinite build_connection_graph loop,
--- 1149,1173 ----
// This code may added new edges to phantom_object.
// Need an other cycle to propagate references to phantom_object.
}
}
time.stop();
+ if (time.seconds() >= CG_BUILD_TIME_LIMIT) {
+ timeout = true;
+ break;
+ }
} else {
new_edges = 0; // Bailout
}
} while (new_edges > 0);
// Bailout if passed limits.
! if ((iterations >= CG_BUILD_ITER_LIMIT) || timeout) {
Compile* C = _compile;
if (C->log() != NULL) {
C->log()->begin_elem("connectionGraph_bailout reason='reached ");
! C->log()->text("%s", timeout ? "time" : "iterations");
C->log()->end_elem(" limit'");
}
assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d",
time.seconds(), iterations, nodes_size(), ptnodes_worklist.length()));
// Possible infinite build_connection_graph loop,
*** 1278,1289 ****
// related field nodes (same base and offset).
add_field_uses_to_worklist(use->as_Field());
}
}
}
! while(_worklist.length() > 0) {
! PointsToNode* use = _worklist.pop();
if (PointsToNode::is_base_use(use)) {
// Add reference from jobj to field and from field to jobj (field's base).
use = PointsToNode::get_use_node(use)->as_Field();
if (add_base(use->as_Field(), jobj)) {
new_edges++;
--- 1304,1315 ----
// related field nodes (same base and offset).
add_field_uses_to_worklist(use->as_Field());
}
}
}
! for (int l = 0; l < _worklist.length(); l++) {
! PointsToNode* use = _worklist.at(l);
if (PointsToNode::is_base_use(use)) {
// Add reference from jobj to field and from field to jobj (field's base).
use = PointsToNode::get_use_node(use)->as_Field();
if (add_base(use->as_Field(), jobj)) {
new_edges++;
*** 1326,1335 ****
--- 1352,1363 ----
// Put on worklist all field's uses (loads) and
// related field nodes (same base and offset).
add_field_uses_to_worklist(use->as_Field());
}
}
+ _worklist.clear();
+ _in_worklist.Reset();
return new_edges;
}
// Put on worklist all related field nodes.
void ConnectionGraph::add_field_uses_to_worklist(FieldNode* field) {
*** 1904,1925 ****
if (ptadr != NULL) {
assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity");
return;
}
Compile* C = _compile;
! ptadr = new (C->comp_arena()) LocalVarNode(C, n, es);
_nodes.at_put(n->_idx, ptadr);
}
void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) {
PointsToNode* ptadr = _nodes.at(n->_idx);
if (ptadr != NULL) {
assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity");
return;
}
Compile* C = _compile;
! ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es);
_nodes.at_put(n->_idx, ptadr);
}
void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) {
PointsToNode* ptadr = _nodes.at(n->_idx);
--- 1932,1953 ----
if (ptadr != NULL) {
assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity");
return;
}
Compile* C = _compile;
! ptadr = new (C->comp_arena()) LocalVarNode(this, n, es);
_nodes.at_put(n->_idx, ptadr);
}
void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) {
PointsToNode* ptadr = _nodes.at(n->_idx);
if (ptadr != NULL) {
assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity");
return;
}
Compile* C = _compile;
! ptadr = new (C->comp_arena()) JavaObjectNode(this, n, es);
_nodes.at_put(n->_idx, ptadr);
}
void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) {
PointsToNode* ptadr = _nodes.at(n->_idx);
*** 1931,1941 ****
bool is_oop = is_oop_field(n, offset, &unsafe);
if (unsafe) {
es = PointsToNode::GlobalEscape;
}
Compile* C = _compile;
! FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop);
_nodes.at_put(n->_idx, field);
}
void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es,
PointsToNode* src, PointsToNode* dst) {
--- 1959,1969 ----
bool is_oop = is_oop_field(n, offset, &unsafe);
if (unsafe) {
es = PointsToNode::GlobalEscape;
}
Compile* C = _compile;
! FieldNode* field = new (C->comp_arena()) FieldNode(this, n, es, offset, is_oop);
_nodes.at_put(n->_idx, field);
}
void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es,
PointsToNode* src, PointsToNode* dst) {
*** 1945,1955 ****
if (ptadr != NULL) {
assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity");
return;
}
Compile* C = _compile;
! ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es);
_nodes.at_put(n->_idx, ptadr);
// Add edge from arraycopy node to source object.
(void)add_edge(ptadr, src);
src->set_arraycopy_src();
// Add edge from destination object to arraycopy node.
--- 1973,1983 ----
if (ptadr != NULL) {
assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity");
return;
}
Compile* C = _compile;
! ptadr = new (C->comp_arena()) ArraycopyNode(this, n, es);
_nodes.at_put(n->_idx, ptadr);
// Add edge from arraycopy node to source object.
(void)add_edge(ptadr, src);
src->set_arraycopy_src();
// Add edge from destination object to arraycopy node.
src/share/vm/opto/escape.cpp
Index
Unified diffs
Context diffs
Sdiffs
Wdiffs
Patch
New
Old
Previous File
Next File