Mercurial > hg > graal-jvmci-8
comparison src/share/vm/opto/escape.cpp @ 20585:90297adbda9d
8041984: CompilerThread seems to occupy all CPU in a very rare situation
Summary: Add new timeout checks to EA.
Reviewed-by: iveresov, drchase
author | kvn |
---|---|
date | Fri, 24 Oct 2014 10:28:19 -0700 |
parents | 87f199a9c1b1 |
children | 9e69e8d1c900 |
comparison
equal
deleted
inserted
replaced
20584:ef9eda2c1abe | 20585:90297adbda9d |
---|---|
35 #include "opto/phaseX.hpp" | 35 #include "opto/phaseX.hpp" |
36 #include "opto/rootnode.hpp" | 36 #include "opto/rootnode.hpp" |
37 | 37 |
38 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : | 38 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) : |
39 _nodes(C->comp_arena(), C->unique(), C->unique(), NULL), | 39 _nodes(C->comp_arena(), C->unique(), C->unique(), NULL), |
40 _in_worklist(C->comp_arena()), | |
41 _next_pidx(0), | |
40 _collecting(true), | 42 _collecting(true), |
41 _verify(false), | 43 _verify(false), |
42 _compile(C), | 44 _compile(C), |
43 _igvn(igvn), | 45 _igvn(igvn), |
44 _node_map(C->comp_arena()) { | 46 _node_map(C->comp_arena()) { |
122 ideal_nodes.map(C->live_nodes(), NULL); // preallocate space | 124 ideal_nodes.map(C->live_nodes(), NULL); // preallocate space |
123 // Initialize worklist | 125 // Initialize worklist |
124 if (C->root() != NULL) { | 126 if (C->root() != NULL) { |
125 ideal_nodes.push(C->root()); | 127 ideal_nodes.push(C->root()); |
126 } | 128 } |
129 // Processed ideal nodes are unique on ideal_nodes list | |
130 // but several ideal nodes are mapped to the phantom_obj. | |
131 // To avoid duplicated entries on the following worklists | |
132 // add the phantom_obj only once to them. | |
133 ptnodes_worklist.append(phantom_obj); | |
134 java_objects_worklist.append(phantom_obj); | |
127 for( uint next = 0; next < ideal_nodes.size(); ++next ) { | 135 for( uint next = 0; next < ideal_nodes.size(); ++next ) { |
128 Node* n = ideal_nodes.at(next); | 136 Node* n = ideal_nodes.at(next); |
129 // Create PointsTo nodes and add them to Connection Graph. Called | 137 // Create PointsTo nodes and add them to Connection Graph. Called |
130 // only once per ideal node since ideal_nodes is Unique_Node list. | 138 // only once per ideal node since ideal_nodes is Unique_Node list. |
131 add_node_to_connection_graph(n, &delayed_worklist); | 139 add_node_to_connection_graph(n, &delayed_worklist); |
132 PointsToNode* ptn = ptnode_adr(n->_idx); | 140 PointsToNode* ptn = ptnode_adr(n->_idx); |
133 if (ptn != NULL) { | 141 if (ptn != NULL && ptn != phantom_obj) { |
134 ptnodes_worklist.append(ptn); | 142 ptnodes_worklist.append(ptn); |
135 if (ptn->is_JavaObject()) { | 143 if (ptn->is_JavaObject()) { |
136 java_objects_worklist.append(ptn->as_JavaObject()); | 144 java_objects_worklist.append(ptn->as_JavaObject()); |
137 if ((n->is_Allocate() || n->is_CallStaticJava()) && | 145 if ((n->is_Allocate() || n->is_CallStaticJava()) && |
138 (ptn->escape_state() < PointsToNode::GlobalEscape)) { | 146 (ptn->escape_state() < PointsToNode::GlobalEscape)) { |
412 add_java_object(n, es); | 420 add_java_object(n, es); |
413 break; | 421 break; |
414 } | 422 } |
415 case Op_CreateEx: { | 423 case Op_CreateEx: { |
416 // assume that all exception objects globally escape | 424 // assume that all exception objects globally escape |
417 add_java_object(n, PointsToNode::GlobalEscape); | 425 map_ideal_node(n, phantom_obj); |
418 break; | 426 break; |
419 } | 427 } |
420 case Op_LoadKlass: | 428 case Op_LoadKlass: |
421 case Op_LoadNKlass: { | 429 case Op_LoadNKlass: { |
422 // Unknown class is loaded | 430 // Unknown class is loaded |
1063 GrowableArray<FieldNode*>& oop_fields_worklist) { | 1071 GrowableArray<FieldNode*>& oop_fields_worklist) { |
1064 // Normally only 1-3 passes needed to build Connection Graph depending | 1072 // Normally only 1-3 passes needed to build Connection Graph depending |
1065 // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler. | 1073 // on graph complexity. Observed 8 passes in jvm2008 compiler.compiler. |
1066 // Set limit to 20 to catch situation when something did go wrong and | 1074 // Set limit to 20 to catch situation when something did go wrong and |
1067 // bailout Escape Analysis. | 1075 // bailout Escape Analysis. |
1068 // Also limit build time to 30 sec (60 in debug VM). | 1076 // Also limit build time to 20 sec (60 in debug VM), EscapeAnalysisTimeout flag. |
1069 #define CG_BUILD_ITER_LIMIT 20 | 1077 #define CG_BUILD_ITER_LIMIT 20 |
1070 #ifdef ASSERT | |
1071 #define CG_BUILD_TIME_LIMIT 60.0 | |
1072 #else | |
1073 #define CG_BUILD_TIME_LIMIT 30.0 | |
1074 #endif | |
1075 | 1078 |
1076 // Propagate GlobalEscape and ArgEscape escape states and check that | 1079 // Propagate GlobalEscape and ArgEscape escape states and check that |
1077 // we still have non-escaping objects. The method pushs on _worklist | 1080 // we still have non-escaping objects. The method pushs on _worklist |
1078 // Field nodes which reference phantom_object. | 1081 // Field nodes which reference phantom_object. |
1079 if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) { | 1082 if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) { |
1080 return false; // Nothing to do. | 1083 return false; // Nothing to do. |
1081 } | 1084 } |
1082 // Now propagate references to all JavaObject nodes. | 1085 // Now propagate references to all JavaObject nodes. |
1083 int java_objects_length = java_objects_worklist.length(); | 1086 int java_objects_length = java_objects_worklist.length(); |
1084 elapsedTimer time; | 1087 elapsedTimer time; |
1088 bool timeout = false; | |
1085 int new_edges = 1; | 1089 int new_edges = 1; |
1086 int iterations = 0; | 1090 int iterations = 0; |
1087 do { | 1091 do { |
1088 while ((new_edges > 0) && | 1092 while ((new_edges > 0) && |
1089 (iterations++ < CG_BUILD_ITER_LIMIT) && | 1093 (iterations++ < CG_BUILD_ITER_LIMIT)) { |
1090 (time.seconds() < CG_BUILD_TIME_LIMIT)) { | 1094 double start_time = time.seconds(); |
1091 time.start(); | 1095 time.start(); |
1092 new_edges = 0; | 1096 new_edges = 0; |
1093 // Propagate references to phantom_object for nodes pushed on _worklist | 1097 // Propagate references to phantom_object for nodes pushed on _worklist |
1094 // by find_non_escaped_objects() and find_field_value(). | 1098 // by find_non_escaped_objects() and find_field_value(). |
1095 new_edges += add_java_object_edges(phantom_obj, false); | 1099 new_edges += add_java_object_edges(phantom_obj, false); |
1096 for (int next = 0; next < java_objects_length; ++next) { | 1100 for (int next = 0; next < java_objects_length; ++next) { |
1097 JavaObjectNode* ptn = java_objects_worklist.at(next); | 1101 JavaObjectNode* ptn = java_objects_worklist.at(next); |
1098 new_edges += add_java_object_edges(ptn, true); | 1102 new_edges += add_java_object_edges(ptn, true); |
1099 } | 1103 |
1104 #define SAMPLE_SIZE 4 | |
1105 if ((next % SAMPLE_SIZE) == 0) { | |
1106 // Each 4 iterations calculate how much time it will take | |
1107 // to complete graph construction. | |
1108 time.stop(); | |
1109 double stop_time = time.seconds(); | |
1110 double time_per_iter = (stop_time - start_time) / (double)SAMPLE_SIZE; | |
1111 double time_until_end = time_per_iter * (double)(java_objects_length - next); | |
1112 if ((start_time + time_until_end) >= EscapeAnalysisTimeout) { | |
1113 timeout = true; | |
1114 break; // Timeout | |
1115 } | |
1116 start_time = stop_time; | |
1117 time.start(); | |
1118 } | |
1119 #undef SAMPLE_SIZE | |
1120 | |
1121 } | |
1122 if (timeout) break; | |
1100 if (new_edges > 0) { | 1123 if (new_edges > 0) { |
1101 // Update escape states on each iteration if graph was updated. | 1124 // Update escape states on each iteration if graph was updated. |
1102 if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) { | 1125 if (!find_non_escaped_objects(ptnodes_worklist, non_escaped_worklist)) { |
1103 return false; // Nothing to do. | 1126 return false; // Nothing to do. |
1104 } | 1127 } |
1105 } | 1128 } |
1106 time.stop(); | 1129 time.stop(); |
1107 } | 1130 if (time.seconds() >= EscapeAnalysisTimeout) { |
1108 if ((iterations < CG_BUILD_ITER_LIMIT) && | 1131 timeout = true; |
1109 (time.seconds() < CG_BUILD_TIME_LIMIT)) { | 1132 break; |
1133 } | |
1134 } | |
1135 if ((iterations < CG_BUILD_ITER_LIMIT) && !timeout) { | |
1110 time.start(); | 1136 time.start(); |
1111 // Find fields which have unknown value. | 1137 // Find fields which have unknown value. |
1112 int fields_length = oop_fields_worklist.length(); | 1138 int fields_length = oop_fields_worklist.length(); |
1113 for (int next = 0; next < fields_length; next++) { | 1139 for (int next = 0; next < fields_length; next++) { |
1114 FieldNode* field = oop_fields_worklist.at(next); | 1140 FieldNode* field = oop_fields_worklist.at(next); |
1117 // This code may added new edges to phantom_object. | 1143 // This code may added new edges to phantom_object. |
1118 // Need an other cycle to propagate references to phantom_object. | 1144 // Need an other cycle to propagate references to phantom_object. |
1119 } | 1145 } |
1120 } | 1146 } |
1121 time.stop(); | 1147 time.stop(); |
1148 if (time.seconds() >= EscapeAnalysisTimeout) { | |
1149 timeout = true; | |
1150 break; | |
1151 } | |
1122 } else { | 1152 } else { |
1123 new_edges = 0; // Bailout | 1153 new_edges = 0; // Bailout |
1124 } | 1154 } |
1125 } while (new_edges > 0); | 1155 } while (new_edges > 0); |
1126 | 1156 |
1127 // Bailout if passed limits. | 1157 // Bailout if passed limits. |
1128 if ((iterations >= CG_BUILD_ITER_LIMIT) || | 1158 if ((iterations >= CG_BUILD_ITER_LIMIT) || timeout) { |
1129 (time.seconds() >= CG_BUILD_TIME_LIMIT)) { | |
1130 Compile* C = _compile; | 1159 Compile* C = _compile; |
1131 if (C->log() != NULL) { | 1160 if (C->log() != NULL) { |
1132 C->log()->begin_elem("connectionGraph_bailout reason='reached "); | 1161 C->log()->begin_elem("connectionGraph_bailout reason='reached "); |
1133 C->log()->text("%s", (iterations >= CG_BUILD_ITER_LIMIT) ? "iterations" : "time"); | 1162 C->log()->text("%s", timeout ? "time" : "iterations"); |
1134 C->log()->end_elem(" limit'"); | 1163 C->log()->end_elem(" limit'"); |
1135 } | 1164 } |
1136 assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d", | 1165 assert(ExitEscapeAnalysisOnTimeout, err_msg_res("infinite EA connection graph build (%f sec, %d iterations) with %d nodes and worklist size %d", |
1137 time.seconds(), iterations, nodes_size(), ptnodes_worklist.length())); | 1166 time.seconds(), iterations, nodes_size(), ptnodes_worklist.length())); |
1138 // Possible infinite build_connection_graph loop, | 1167 // Possible infinite build_connection_graph loop, |
1145 iterations, nodes_size(), ptnodes_worklist.length()); | 1174 iterations, nodes_size(), ptnodes_worklist.length()); |
1146 } | 1175 } |
1147 #endif | 1176 #endif |
1148 | 1177 |
1149 #undef CG_BUILD_ITER_LIMIT | 1178 #undef CG_BUILD_ITER_LIMIT |
1150 #undef CG_BUILD_TIME_LIMIT | |
1151 | 1179 |
1152 // Find fields initialized by NULL for non-escaping Allocations. | 1180 // Find fields initialized by NULL for non-escaping Allocations. |
1153 int non_escaped_length = non_escaped_worklist.length(); | 1181 int non_escaped_length = non_escaped_worklist.length(); |
1154 for (int next = 0; next < non_escaped_length; next++) { | 1182 for (int next = 0; next < non_escaped_length; next++) { |
1155 JavaObjectNode* ptn = non_escaped_worklist.at(next); | 1183 JavaObjectNode* ptn = non_escaped_worklist.at(next); |
1269 // related field nodes (same base and offset). | 1297 // related field nodes (same base and offset). |
1270 add_field_uses_to_worklist(use->as_Field()); | 1298 add_field_uses_to_worklist(use->as_Field()); |
1271 } | 1299 } |
1272 } | 1300 } |
1273 } | 1301 } |
1274 while(_worklist.length() > 0) { | 1302 for (int l = 0; l < _worklist.length(); l++) { |
1275 PointsToNode* use = _worklist.pop(); | 1303 PointsToNode* use = _worklist.at(l); |
1276 if (PointsToNode::is_base_use(use)) { | 1304 if (PointsToNode::is_base_use(use)) { |
1277 // Add reference from jobj to field and from field to jobj (field's base). | 1305 // Add reference from jobj to field and from field to jobj (field's base). |
1278 use = PointsToNode::get_use_node(use)->as_Field(); | 1306 use = PointsToNode::get_use_node(use)->as_Field(); |
1279 if (add_base(use->as_Field(), jobj)) { | 1307 if (add_base(use->as_Field(), jobj)) { |
1280 new_edges++; | 1308 new_edges++; |
1317 // Put on worklist all field's uses (loads) and | 1345 // Put on worklist all field's uses (loads) and |
1318 // related field nodes (same base and offset). | 1346 // related field nodes (same base and offset). |
1319 add_field_uses_to_worklist(use->as_Field()); | 1347 add_field_uses_to_worklist(use->as_Field()); |
1320 } | 1348 } |
1321 } | 1349 } |
1350 _worklist.clear(); | |
1351 _in_worklist.Reset(); | |
1322 return new_edges; | 1352 return new_edges; |
1323 } | 1353 } |
1324 | 1354 |
1325 // Put on worklist all related field nodes. | 1355 // Put on worklist all related field nodes. |
1326 void ConnectionGraph::add_field_uses_to_worklist(FieldNode* field) { | 1356 void ConnectionGraph::add_field_uses_to_worklist(FieldNode* field) { |
1896 if (ptadr != NULL) { | 1926 if (ptadr != NULL) { |
1897 assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity"); | 1927 assert(ptadr->is_LocalVar() && ptadr->ideal_node() == n, "sanity"); |
1898 return; | 1928 return; |
1899 } | 1929 } |
1900 Compile* C = _compile; | 1930 Compile* C = _compile; |
1901 ptadr = new (C->comp_arena()) LocalVarNode(C, n, es); | 1931 ptadr = new (C->comp_arena()) LocalVarNode(this, n, es); |
1902 _nodes.at_put(n->_idx, ptadr); | 1932 _nodes.at_put(n->_idx, ptadr); |
1903 } | 1933 } |
1904 | 1934 |
1905 void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) { | 1935 void ConnectionGraph::add_java_object(Node *n, PointsToNode::EscapeState es) { |
1906 PointsToNode* ptadr = _nodes.at(n->_idx); | 1936 PointsToNode* ptadr = _nodes.at(n->_idx); |
1907 if (ptadr != NULL) { | 1937 if (ptadr != NULL) { |
1908 assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity"); | 1938 assert(ptadr->is_JavaObject() && ptadr->ideal_node() == n, "sanity"); |
1909 return; | 1939 return; |
1910 } | 1940 } |
1911 Compile* C = _compile; | 1941 Compile* C = _compile; |
1912 ptadr = new (C->comp_arena()) JavaObjectNode(C, n, es); | 1942 ptadr = new (C->comp_arena()) JavaObjectNode(this, n, es); |
1913 _nodes.at_put(n->_idx, ptadr); | 1943 _nodes.at_put(n->_idx, ptadr); |
1914 } | 1944 } |
1915 | 1945 |
1916 void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) { | 1946 void ConnectionGraph::add_field(Node *n, PointsToNode::EscapeState es, int offset) { |
1917 PointsToNode* ptadr = _nodes.at(n->_idx); | 1947 PointsToNode* ptadr = _nodes.at(n->_idx); |
1923 bool is_oop = is_oop_field(n, offset, &unsafe); | 1953 bool is_oop = is_oop_field(n, offset, &unsafe); |
1924 if (unsafe) { | 1954 if (unsafe) { |
1925 es = PointsToNode::GlobalEscape; | 1955 es = PointsToNode::GlobalEscape; |
1926 } | 1956 } |
1927 Compile* C = _compile; | 1957 Compile* C = _compile; |
1928 FieldNode* field = new (C->comp_arena()) FieldNode(C, n, es, offset, is_oop); | 1958 FieldNode* field = new (C->comp_arena()) FieldNode(this, n, es, offset, is_oop); |
1929 _nodes.at_put(n->_idx, field); | 1959 _nodes.at_put(n->_idx, field); |
1930 } | 1960 } |
1931 | 1961 |
1932 void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es, | 1962 void ConnectionGraph::add_arraycopy(Node *n, PointsToNode::EscapeState es, |
1933 PointsToNode* src, PointsToNode* dst) { | 1963 PointsToNode* src, PointsToNode* dst) { |
1937 if (ptadr != NULL) { | 1967 if (ptadr != NULL) { |
1938 assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity"); | 1968 assert(ptadr->is_Arraycopy() && ptadr->ideal_node() == n, "sanity"); |
1939 return; | 1969 return; |
1940 } | 1970 } |
1941 Compile* C = _compile; | 1971 Compile* C = _compile; |
1942 ptadr = new (C->comp_arena()) ArraycopyNode(C, n, es); | 1972 ptadr = new (C->comp_arena()) ArraycopyNode(this, n, es); |
1943 _nodes.at_put(n->_idx, ptadr); | 1973 _nodes.at_put(n->_idx, ptadr); |
1944 // Add edge from arraycopy node to source object. | 1974 // Add edge from arraycopy node to source object. |
1945 (void)add_edge(ptadr, src); | 1975 (void)add_edge(ptadr, src); |
1946 src->set_arraycopy_src(); | 1976 src->set_arraycopy_src(); |
1947 // Add edge from destination object to arraycopy node. | 1977 // Add edge from destination object to arraycopy node. |