changeset 58645:cf319f17c647

8239072: subtype check macro node causes node budget to be exhausted Reviewed-by: vlivanov, kvn
author roland
date Tue, 31 Mar 2020 10:40:17 +0200
parents 289aa2a0e819
children 117b5f22ad28
files src/hotspot/share/opto/compile.cpp src/hotspot/share/opto/compile.hpp src/hotspot/share/opto/macro.cpp
diffstat 3 files changed, 71 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/share/opto/compile.cpp	Tue Mar 24 17:56:15 2020 +0100
+++ b/src/hotspot/share/opto/compile.cpp	Tue Mar 31 10:40:17 2020 +0200
@@ -4224,3 +4224,20 @@
     ni.dump();
   }
 }
+
+// Move Allocate nodes to the start of the list
+void Compile::sort_macro_nodes() {
+  int count = macro_count();
+  int allocates = 0;
+  for (int i = 0; i < count; i++) {
+    Node* n = macro_node(i);
+    if (n->is_Allocate()) {
+      if (i != allocates) {
+        Node* tmp = macro_node(allocates);
+        _macro_nodes->at_put(allocates, n);
+        _macro_nodes->at_put(i, tmp);
+      }
+      allocates++;
+    }
+  }
+}
--- a/src/hotspot/share/opto/compile.hpp	Tue Mar 24 17:56:15 2020 +0100
+++ b/src/hotspot/share/opto/compile.hpp	Tue Mar 31 10:40:17 2020 +0200
@@ -718,6 +718,8 @@
   int   opaque4_count()       const { return _opaque4_nodes->length(); }
   void  remove_opaque4_nodes(PhaseIterGVN &igvn);
 
+  void sort_macro_nodes();
+
   // remove the opaque nodes that protect the predicates so that the unused checks and
   // uncommon traps will be eliminated from the graph.
   void cleanup_loop_predicates(PhaseIterGVN &igvn);
--- a/src/hotspot/share/opto/macro.cpp	Tue Mar 24 17:56:15 2020 +0100
+++ b/src/hotspot/share/opto/macro.cpp	Tue Mar 31 10:40:17 2020 +0200
@@ -2658,12 +2658,6 @@
   // Last attempt to eliminate macro nodes.
   eliminate_macro_nodes();
 
-  // Make sure expansion will not cause node limit to be exceeded.
-  // Worst case is a macro node gets expanded into about 200 nodes.
-  // Allow 50% more for optimization.
-  if (C->check_node_count(C->macro_count() * 300, "out of nodes before macro expansion" ) )
-    return true;
-
   // Eliminate Opaque and LoopLimit nodes. Do it after all loop optimizations.
   bool progress = true;
   while (progress) {
@@ -2719,17 +2713,44 @@
     }
   }
 
+  // Clean up the graph so we're less likely to hit the maximum node
+  // limit
+  _igvn.set_delay_transform(false);
+  _igvn.optimize();
+  if (C->failing())  return true;
+  _igvn.set_delay_transform(true);
+
+
+  // Because we run IGVN after each expansion, some macro nodes may go
+  // dead and be removed from the list as we iterate over it. Move
+  // Allocate nodes (processed in a second pass) at the beginning of
+  // the list and then iterate from the last element of the list until
+  // an Allocate node is seen. This is robust to random deletion in
+  // the list due to nodes going dead.
+  C->sort_macro_nodes();
+
   // expand arraycopy "macro" nodes first
   // For ReduceBulkZeroing, we must first process all arraycopy nodes
   // before the allocate nodes are expanded.
-  for (int i = C->macro_count(); i > 0; i--) {
-    Node* n = C->macro_node(i-1);
+  while (C->macro_count() > 0) {
+    int macro_count = C->macro_count();
+    Node * n = C->macro_node(macro_count-1);
     assert(n->is_macro(), "only macro nodes expected here");
     if (_igvn.type(n) == Type::TOP || (n->in(0) != NULL && n->in(0)->is_top())) {
       // node is unreachable, so don't try to expand it
       C->remove_macro_node(n);
       continue;
     }
+    if (n->is_Allocate()) {
+      break;
+    }
+    // Make sure expansion will not cause node limit to be exceeded.
+    // Worst case is a macro node gets expanded into about 200 nodes.
+    // Allow 50% more for optimization.
+    if (C->check_node_count(300, "out of nodes before macro expansion")) {
+      return true;
+    }
+
     debug_only(int old_macro_count = C->macro_count(););
     switch (n->class_id()) {
     case Node::Class_Lock:
@@ -2748,18 +2769,23 @@
       expand_subtypecheck_node(n->as_SubTypeCheck());
       assert(C->macro_count() == (old_macro_count - 1), "expansion must have deleted one node from macro list");
       break;
+    default:
+      assert(false, "unknown node type in macro list");
     }
+    assert(C->macro_count() < macro_count, "must have deleted a node from macro list");
     if (C->failing())  return true;
+
+    // Clean up the graph so we're less likely to hit the maximum node
+    // limit
+    _igvn.set_delay_transform(false);
+    _igvn.optimize();
+    if (C->failing())  return true;
+    _igvn.set_delay_transform(true);
   }
 
   // All nodes except Allocate nodes are expanded now. There could be
   // new optimization opportunities (such as folding newly created
   // load from a just allocated object). Run IGVN.
-  _igvn.set_delay_transform(false);
-  _igvn.optimize();
-  if (C->failing())  return true;
-
-  _igvn.set_delay_transform(true);
 
   // expand "macro" nodes
   // nodes are removed from the macro list as they are processed
@@ -2772,6 +2798,12 @@
       C->remove_macro_node(n);
       continue;
     }
+    // Make sure expansion will not cause node limit to be exceeded.
+    // Worst case is a macro node gets expanded into about 200 nodes.
+    // Allow 50% more for optimization.
+    if (C->check_node_count(300, "out of nodes before macro expansion")) {
+      return true;
+    }
     switch (n->class_id()) {
     case Node::Class_Allocate:
       expand_allocate(n->as_Allocate());
@@ -2784,10 +2816,15 @@
     }
     assert(C->macro_count() < macro_count, "must have deleted a node from macro list");
     if (C->failing())  return true;
+
+    // Clean up the graph so we're less likely to hit the maximum node
+    // limit
+    _igvn.set_delay_transform(false);
+    _igvn.optimize();
+    if (C->failing())  return true;
+    _igvn.set_delay_transform(true);
   }
 
   _igvn.set_delay_transform(false);
-  _igvn.optimize();
-  if (C->failing())  return true;
   return false;
 }