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