1.1 --- a/src/share/vm/opto/escape.cpp Thu Oct 30 10:51:06 2014 +0100 1.2 +++ b/src/share/vm/opto/escape.cpp Fri Oct 24 10:28:19 2014 -0700 1.3 @@ -37,6 +37,8 @@ 1.4 1.5 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : 1.6 _nodes(C->comp_arena(), C->unique(), C->unique(), NULL), 1.7 + _in_worklist(C->comp_arena()), 1.8 + _next_pidx(0), 1.9 _collecting(true), 1.10 _verify(false), 1.11 _compile(C), 1.12 @@ -124,13 +126,19 @@ 1.13 if (C->root() != NULL) { 1.14 ideal_nodes.push(C->root()); 1.15 } 1.16 + // Processed ideal nodes are unique on ideal_nodes list 1.17 + // but several ideal nodes are mapped to the phantom_obj. 1.18 + // To avoid duplicated entries on the following worklists 1.19 + // add the phantom_obj only once to them. 1.20 + ptnodes_worklist.append(phantom_obj); 1.21 + java_objects_worklist.append(phantom_obj); 1.22 for( uint next = 0; next < ideal_nodes.size(); ++next ) { 1.23 Node* n = ideal_nodes.at(next); 1.24 // Create PointsTo nodes and add them to Connection Graph. Called 1.25 // only once per ideal node since ideal_nodes is Unique_Node list. 1.26 add_node_to_connection_graph(n, &delayed_worklist); 1.27 PointsToNode* ptn = ptnode_adr(n->_idx); 1.28 - if (ptn != NULL) { 1.29 + if (ptn != NULL && ptn != phantom_obj) { 1.30 ptnodes_worklist.append(ptn); 1.31 if (ptn->is_JavaObject()) { 1.32 java_objects_worklist.append(ptn->as_JavaObject()); 1.33 @@ -414,7 +422,7 @@ 1.34 } 1.35 case Op_CreateEx: { 1.36 // assume that all exception objects globally escape 1.37 - add_java_object(n, PointsToNode::GlobalEscape); 1.38 + map_ideal_node(n, phantom_obj); 1.39 break; 1.40 } 1.41 case Op_LoadKlass: 1.42 @@ -1065,13 +1073,8 @@ 1.43 // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler. 1.44 // Set limit to 20 to catch situation when something did go wrong and 1.45 // bailout Escape Analysis. 1.46 - // Also limit build time to 30 sec (60 in debug VM). 1.47 + // Also limit build time to 20 sec (60 in debug VM), EscapeAnalysisTimeout flag. 1.48 #define CG_BUILD_ITER_LIMIT 20 1.49 -#ifdef ASSERT 1.50 -#define CG_BUILD_TIME_LIMIT 60.0 1.51 -#else 1.52 -#define CG_BUILD_TIME_LIMIT 30.0 1.53 -#endif 1.54 1.55 // Propagate GlobalEscape and ArgEscape escape states and check that 1.56 // we still have non-escaping objects. The method pushs on _worklist 1.57 @@ -1082,12 +1085,13 @@ 1.58 // Now propagate references to all JavaObject nodes. 1.59 int java_objects_length = java_objects_worklist.length(); 1.60 elapsedTimer time; 1.61 + bool timeout = false; 1.62 int new_edges = 1; 1.63 int iterations = 0; 1.64 do { 1.65 while ((new_edges > 0) && 1.66 - (iterations++ < CG_BUILD_ITER_LIMIT) && 1.67 - (time.seconds() < CG_BUILD_TIME_LIMIT)) { 1.68 + (iterations++ < CG_BUILD_ITER_LIMIT)) { 1.69 + double start_time = time.seconds(); 1.70 time.start(); 1.71 new_edges = 0; 1.72 // Propagate references to phantom_object for nodes pushed on _worklist 1.73 @@ -1096,7 +1100,26 @@ 1.74 for (int next = 0; next < java_objects_length; ++next) { 1.75 JavaObjectNode* ptn = java_objects_worklist.at(next); 1.76 new_edges += add_java_object_edges(ptn, true); 1.77 + 1.78 +#define SAMPLE_SIZE 4 1.79 + if ((next % SAMPLE_SIZE) == 0) { 1.80 + // Each 4 iterations calculate how much time it will take 1.81 + // to complete graph construction. 1.82 + time.stop(); 1.83 + double stop_time = time.seconds(); 1.84 + double time_per_iter = (stop_time - start_time) / (double)SAMPLE_SIZE; 1.85 + double time_until_end = time_per_iter * (double)(java_objects_length - next); 1.86 + if ((start_time + time_until_end) >= EscapeAnalysisTimeout) { 1.87 + timeout = true; 1.88 + break; // Timeout 1.89 + } 1.90 + start_time = stop_time; 1.91 + time.start(); 1.92 + } 1.93 +#undef SAMPLE_SIZE 1.94 + 1.95 } 1.96 + if (timeout) break; 1.97 if (new_edges > 0) { 1.98 // Update escape states on each iteration if graph was updated. 1.99 if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) { 1.100 @@ -1104,9 +1127,12 @@ 1.101 } 1.102 } 1.103 time.stop(); 1.104 + if (time.seconds() >= EscapeAnalysisTimeout) { 1.105 + timeout = true; 1.106 + break; 1.107 + } 1.108 } 1.109 - if ((iterations < CG_BUILD_ITER_LIMIT) && 1.110 - (time.seconds() < CG_BUILD_TIME_LIMIT)) { 1.111 + if ((iterations < CG_BUILD_ITER_LIMIT) && !timeout) { 1.112 time.start(); 1.113 // Find fields which have unknown value. 1.114 int fields_length = oop_fields_worklist.length(); 1.115 @@ -1119,18 +1145,21 @@ 1.116 } 1.117 } 1.118 time.stop(); 1.119 + if (time.seconds() >= EscapeAnalysisTimeout) { 1.120 + timeout = true; 1.121 + break; 1.122 + } 1.123 } else { 1.124 new_edges = 0; // Bailout 1.125 } 1.126 } while (new_edges > 0); 1.127 1.128 // Bailout if passed limits. 1.129 - if ((iterations >= CG_BUILD_ITER_LIMIT) || 1.130 - (time.seconds() >= CG_BUILD_TIME_LIMIT)) { 1.131 + if ((iterations >= CG_BUILD_ITER_LIMIT) || timeout) { 1.132 Compile* C = _compile; 1.133 if (C->log() != NULL) { 1.134 C->log()->begin_elem("connectionGraph_bailout reason='reached "); 1.135 - C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time"); 1.136 + C->log()->text("%s", timeout ? "time" : "iterations"); 1.137 C->log()->end_elem(" limit'"); 1.138 } 1.139 assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d", 1.140 @@ -1147,7 +1176,6 @@ 1.141 #endif 1.142 1.143 #undef CG_BUILD_ITER_LIMIT 1.144 -#undef CG_BUILD_TIME_LIMIT 1.145 1.146 // Find fields initialized by NULL for non-escaping Allocations. 1.147 int non_escaped_length = non_escaped_worklist.length(); 1.148 @@ -1271,8 +1299,8 @@ 1.149 } 1.150 } 1.151 } 1.152 - while(_worklist.length() > 0) { 1.153 - PointsToNode* use = _worklist.pop(); 1.154 + for (int l = 0; l < _worklist.length(); l++) { 1.155 + PointsToNode* use = _worklist.at(l); 1.156 if (PointsToNode::is_base_use(use)) { 1.157 // Add reference from jobj to field and from field to jobj (field's base). 1.158 use = PointsToNode::get_use_node(use)->as_Field(); 1.159 @@ -1319,6 +1347,8 @@ 1.160 add_field_uses_to_worklist(use->as_Field()); 1.161 } 1.162 } 1.163 + _worklist.clear(); 1.164 + _in_worklist.Reset(); 1.165 return new_edges; 1.166 } 1.167 1.168 @@ -1898,7 +1928,7 @@ 1.169 return; 1.170 } 1.171 Compile* C = _compile; 1.172 - ptadr = new (C->comp_arena()) LocalVarNode(C, n, es); 1.173 + ptadr = new (C->comp_arena()) LocalVarNode(this, n, es); 1.174 _nodes.at_put(n->_idx, ptadr); 1.175 } 1.176 1.177 @@ -1909,7 +1939,7 @@ 1.178 return; 1.179 } 1.180 Compile* C = _compile; 1.181 - ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es); 1.182 + ptadr = new (C->comp_arena()) JavaObjectNode(this, n, es); 1.183 _nodes.at_put(n->_idx, ptadr); 1.184 } 1.185 1.186 @@ -1925,7 +1955,7 @@ 1.187 es = PointsToNode::GlobalEscape; 1.188 } 1.189 Compile* C = _compile; 1.190 - FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop); 1.191 + FieldNode* field = new (C->comp_arena()) FieldNode(this, n, es, offset, is_oop); 1.192 _nodes.at_put(n->_idx, field); 1.193 } 1.194 1.195 @@ -1939,7 +1969,7 @@ 1.196 return; 1.197 } 1.198 Compile* C = _compile; 1.199 - ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es); 1.200 + ptadr = new (C->comp_arena()) ArraycopyNode(this, n, es); 1.201 _nodes.at_put(n->_idx, ptadr); 1.202 // Add edge from arraycopy node to source object. 1.203 (void)add_edge(ptadr, src);