changeset 7421:9e69e8d1c900

8058148: MaxNodeLimit and LiveNodeCountInliningCutoff Reviewed-by: kvn, roland
author vlivanov
date Mon, 24 Nov 2014 07:29:03 -0800
parents 6a528388c7da
children 6bf89bfe8185
files src/share/vm/ci/ciTypeFlow.cpp src/share/vm/opto/c2_globals.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/compile.hpp src/share/vm/opto/doCall.cpp src/share/vm/opto/escape.cpp src/share/vm/opto/loopTransform.cpp src/share/vm/opto/loopUnswitch.cpp src/share/vm/opto/loopopts.cpp src/share/vm/opto/node.cpp
diffstat 10 files changed, 28 insertions(+), 16 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/ci/ciTypeFlow.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/ci/ciTypeFlow.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -35,6 +35,7 @@
 #include "interpreter/bytecode.hpp"
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.inline.hpp"
+#include "opto/compile.hpp"
 #include "runtime/deoptimization.hpp"
 #include "utilities/growableArray.hpp"
 
@@ -2646,7 +2647,7 @@
       assert (!blk->has_pre_order(), "");
       blk->set_next_pre_order();
 
-      if (_next_pre_order >= MaxNodeLimit / 2) {
+      if (_next_pre_order >= (int)Compile::current()->max_node_limit() / 2) {
         // Too many basic blocks.  Bail out.
         // This can happen when try/finally constructs are nested to depth N,
         // and there is O(2**N) cloning of jsr bodies.  See bug 4697245!
--- a/src/share/vm/opto/c2_globals.hpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/c2_globals.hpp	Mon Nov 24 07:29:03 2014 -0800
@@ -647,7 +647,7 @@
   develop(bool, AlwaysIncrementalInline, false,                             \
           "do all inlining incrementally")                                  \
                                                                             \
-  product(intx, LiveNodeCountInliningCutoff, 20000,                         \
+  product(intx, LiveNodeCountInliningCutoff, 40000,                         \
           "max number of live nodes in a method")                           \
                                                                             \
   diagnostic(bool, OptimizeExpensiveOps, true,                              \
--- a/src/share/vm/opto/compile.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/compile.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -679,7 +679,8 @@
                   _inlining_incrementally(false),
                   _print_inlining_list(NULL),
                   _print_inlining_idx(0),
-                  _interpreter_frame_size(0) {
+                  _interpreter_frame_size(0),
+                  _max_node_limit(MaxNodeLimit) {
   C = this;
 
   CompileWrapper cw(this);
@@ -990,7 +991,8 @@
     _print_inlining_list(NULL),
     _print_inlining_idx(0),
     _allowed_reasons(0),
-    _interpreter_frame_size(0) {
+    _interpreter_frame_size(0),
+    _max_node_limit(MaxNodeLimit) {
   C = this;
 
 #ifndef PRODUCT
@@ -1100,6 +1102,7 @@
   set_do_count_invocations(false);
   set_do_method_data_update(false);
   set_rtm_state(NoRTM); // No RTM lock eliding by default
+  method_has_option_value("MaxNodeLimit", _max_node_limit);
 #if INCLUDE_RTM_OPT
   if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
     int rtm_state = method()->method_data()->rtm_state();
--- a/src/share/vm/opto/compile.hpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/compile.hpp	Mon Nov 24 07:29:03 2014 -0800
@@ -290,6 +290,7 @@
   int                   _freq_inline_size;      // Max hot method inline size for this compilation
   int                   _fixed_slots;           // count of frame slots not allocated by the register
                                                 // allocator i.e. locks, original deopt pc, etc.
+  uintx                 _max_node_limit;        // Max unique node count during a single compilation.
   // For deopt
   int                   _orig_pc_slot;
   int                   _orig_pc_slot_offset_in_bytes;
@@ -594,6 +595,9 @@
   void          set_rtm_state(RTMState s)        { _rtm_state = s; }
   bool              use_rtm() const              { return (_rtm_state & NoRTM) == 0; }
   bool          profile_rtm() const              { return _rtm_state == ProfileRTM; }
+  uint              max_node_limit() const       { return (uint)_max_node_limit; }
+  void          set_max_node_limit(uint n)       { _max_node_limit = n; }
+
   // check the CompilerOracle for special behaviours for this compile
   bool          method_has_option(const char * option) {
     return method() != NULL && method()->has_option(option);
@@ -723,7 +727,7 @@
     record_method_not_compilable(reason, true);
   }
   bool check_node_count(uint margin, const char* reason) {
-    if (live_nodes() + margin > (uint)MaxNodeLimit) {
+    if (live_nodes() + margin > max_node_limit()) {
       record_method_not_compilable(reason);
       return true;
     } else {
--- a/src/share/vm/opto/doCall.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/doCall.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -410,6 +410,11 @@
   ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
   assert(declared_signature != NULL, "cannot be null");
 
+  // Bump max node limit for JSR292 users
+  if (bc() == Bytecodes::_invokedynamic || orig_callee->is_method_handle_intrinsic()) {
+    C->set_max_node_limit(3*MaxNodeLimit);
+  }
+
   // uncommon-trap when callee is unloaded, uninitialized or will not link
   // bailout when too many arguments for register representation
   if (!will_link || can_not_compile_call_site(orig_callee, klass)) {
--- a/src/share/vm/opto/escape.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/escape.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -2409,7 +2409,7 @@
       }
     }
   }
-  if ((int) (C->live_nodes() + 2*NodeLimitFudgeFactor) > MaxNodeLimit) {
+  if (C->live_nodes() + 2*NodeLimitFudgeFactor > C->max_node_limit()) {
     if (C->do_escape_analysis() == true && !C->failing()) {
       // Retry compilation without escape analysis.
       // If this is the first failure, the sentinel string will "stick"
--- a/src/share/vm/opto/loopTransform.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/loopTransform.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -269,10 +269,9 @@
 bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
   Node *test = ((IdealLoopTree*)this)->tail();
   int  body_size = ((IdealLoopTree*)this)->_body.size();
-  int  live_node_count = phase->C->live_nodes();
   // Peeling does loop cloning which can result in O(N^2) node construction
   if( body_size > 255 /* Prevent overflow for large body_size */
-      || (body_size * body_size + live_node_count > MaxNodeLimit) ) {
+      || (body_size * body_size + phase->C->live_nodes()) > phase->C->max_node_limit() ) {
     return false;           // too large to safely clone
   }
   while( test != _head ) {      // Scan till run off top of loop
@@ -601,7 +600,7 @@
     return false;
   if (new_body_size > unroll_limit ||
       // Unrolling can result in a large amount of node construction
-      new_body_size >= MaxNodeLimit - (uint) phase->C->live_nodes()) {
+      new_body_size >= phase->C->max_node_limit() - phase->C->live_nodes()) {
     return false;
   }
 
@@ -2287,8 +2286,8 @@
 
   // Skip next optimizations if running low on nodes. Note that
   // policy_unswitching and policy_maximally_unroll have this check.
-  uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes();
-  if ((2 * _body.size()) > nodes_left) {
+  int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
+  if ((int)(2 * _body.size()) > nodes_left) {
     return true;
   }
 
--- a/src/share/vm/opto/loopUnswitch.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/loopUnswitch.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -59,8 +59,8 @@
   if (!_head->is_Loop()) {
     return false;
   }
-  uint nodes_left = MaxNodeLimit - phase->C->live_nodes();
-  if (2 * _body.size() > nodes_left) {
+  int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
+  if ((int)(2 * _body.size()) > nodes_left) {
     return false; // Too speculative if running low on nodes.
   }
   LoopNode* head = _head->as_Loop();
--- a/src/share/vm/opto/loopopts.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/loopopts.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -734,7 +734,7 @@
   for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
     weight += region->fast_out(i)->outcnt();
   }
-  int nodes_left = MaxNodeLimit - C->live_nodes();
+  int nodes_left = C->max_node_limit() - C->live_nodes();
   if (weight * 8 > nodes_left) {
 #ifndef PRODUCT
     if (PrintOpto)
--- a/src/share/vm/opto/node.cpp	Tue Nov 11 04:46:13 2014 -0800
+++ b/src/share/vm/opto/node.cpp	Mon Nov 24 07:29:03 2014 -0800
@@ -69,7 +69,7 @@
   Compile::set_debug_idx(new_debug_idx);
   set_debug_idx( new_debug_idx );
   assert(Compile::current()->unique() < (INT_MAX - 1), "Node limit exceeded INT_MAX");
-  assert(Compile::current()->live_nodes() < (uint)MaxNodeLimit, "Live Node limit exceeded limit");
+  assert(Compile::current()->live_nodes() < Compile::current()->max_node_limit(), "Live Node limit exceeded limit");
   if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) {
     tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx);
     BREAKPOINT;
@@ -326,7 +326,7 @@
 Node::Node(uint req)
   : _idx(IDX_INIT(req))
 {
-  assert( req < (uint)(MaxNodeLimit - NodeLimitFudgeFactor), "Input limit exceeded" );
+  assert( req < Compile::current()->max_node_limit() - NodeLimitFudgeFactor, "Input limit exceeded" );
   debug_only( verify_construction() );
   NOT_PRODUCT(nodes_created++);
   if (req == 0) {