--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/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/hotspot/src/share/vm/opto/c2_globals.hpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/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/hotspot/src/share/vm/opto/compile.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/compile.cpp Mon Nov 24 07:29:03 2014 -0800
@@ -661,7 +661,8 @@
_print_inlining_stream(NULL),
_print_inlining_idx(0),
_print_inlining_output(NULL),
- _interpreter_frame_size(0) {
+ _interpreter_frame_size(0),
+ _max_node_limit(MaxNodeLimit) {
C = this;
CompileWrapper cw(this);
@@ -974,7 +975,8 @@
_print_inlining_idx(0),
_print_inlining_output(NULL),
_allowed_reasons(0),
- _interpreter_frame_size(0) {
+ _interpreter_frame_size(0),
+ _max_node_limit(MaxNodeLimit) {
C = this;
TraceTime t1(NULL, &_t_totalCompilation, CITime, false);
@@ -1087,6 +1089,7 @@
set_do_method_data_update(false);
set_age_code(has_method() && method()->profile_aging());
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/hotspot/src/share/vm/opto/compile.hpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/compile.hpp Mon Nov 24 07:29:03 2014 -0800
@@ -289,6 +289,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;
@@ -597,6 +598,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);
@@ -735,7 +739,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/hotspot/src/share/vm/opto/doCall.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/doCall.cpp Mon Nov 24 07:29:03 2014 -0800
@@ -418,6 +418,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/hotspot/src/share/vm/opto/escape.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/escape.cpp Mon Nov 24 07:29:03 2014 -0800
@@ -2417,7 +2417,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/hotspot/src/share/vm/opto/loopTransform.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/loopTransform.cpp Mon Nov 24 07:29:03 2014 -0800
@@ -272,10 +272,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
@@ -604,7 +603,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;
}
@@ -2281,8 +2280,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/hotspot/src/share/vm/opto/loopUnswitch.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/loopUnswitch.cpp Mon Nov 24 07:29:03 2014 -0800
@@ -61,8 +61,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/hotspot/src/share/vm/opto/loopopts.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/src/share/vm/opto/loopopts.cpp Mon Nov 24 07:29:03 2014 -0800
@@ -736,7 +736,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/hotspot/src/share/vm/opto/node.cpp Mon Nov 24 08:48:15 2014 +0100
+++ b/hotspot/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;
@@ -313,7 +313,7 @@
Node::Node(uint req)
: _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) {