提交 cd04ba90 编写于 作者: V vlivanov

8058148: MaxNodeLimit and LiveNodeCountInliningCutoff

Reviewed-by: kvn, roland
上级 14e7429d
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "interpreter/bytecode.hpp" #include "interpreter/bytecode.hpp"
#include "interpreter/bytecodes.hpp" #include "interpreter/bytecodes.hpp"
#include "memory/allocation.inline.hpp" #include "memory/allocation.inline.hpp"
#include "opto/compile.hpp"
#include "runtime/deoptimization.hpp" #include "runtime/deoptimization.hpp"
#include "utilities/growableArray.hpp" #include "utilities/growableArray.hpp"
...@@ -2646,7 +2647,7 @@ void ciTypeFlow::df_flow_types(Block* start, ...@@ -2646,7 +2647,7 @@ void ciTypeFlow::df_flow_types(Block* start,
assert (!blk->has_pre_order(), ""); assert (!blk->has_pre_order(), "");
blk->set_next_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. // Too many basic blocks. Bail out.
// This can happen when try/finally constructs are nested to depth N, // 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! // and there is O(2**N) cloning of jsr bodies. See bug 4697245!
......
...@@ -647,7 +647,7 @@ ...@@ -647,7 +647,7 @@
develop(bool, AlwaysIncrementalInline, false, \ develop(bool, AlwaysIncrementalInline, false, \
"do all inlining incrementally") \ "do all inlining incrementally") \
\ \
product(intx, LiveNodeCountInliningCutoff, 20000, \ product(intx, LiveNodeCountInliningCutoff, 40000, \
"max number of live nodes in a method") \ "max number of live nodes in a method") \
\ \
diagnostic(bool, OptimizeExpensiveOps, true, \ diagnostic(bool, OptimizeExpensiveOps, true, \
......
...@@ -679,7 +679,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -679,7 +679,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_inlining_incrementally(false), _inlining_incrementally(false),
_print_inlining_list(NULL), _print_inlining_list(NULL),
_print_inlining_idx(0), _print_inlining_idx(0),
_interpreter_frame_size(0) { _interpreter_frame_size(0),
_max_node_limit(MaxNodeLimit) {
C = this; C = this;
CompileWrapper cw(this); CompileWrapper cw(this);
...@@ -990,7 +991,8 @@ Compile::Compile( ciEnv* ci_env, ...@@ -990,7 +991,8 @@ Compile::Compile( ciEnv* ci_env,
_print_inlining_list(NULL), _print_inlining_list(NULL),
_print_inlining_idx(0), _print_inlining_idx(0),
_allowed_reasons(0), _allowed_reasons(0),
_interpreter_frame_size(0) { _interpreter_frame_size(0),
_max_node_limit(MaxNodeLimit) {
C = this; C = this;
#ifndef PRODUCT #ifndef PRODUCT
...@@ -1100,6 +1102,7 @@ void Compile::Init(int aliaslevel) { ...@@ -1100,6 +1102,7 @@ void Compile::Init(int aliaslevel) {
set_do_count_invocations(false); set_do_count_invocations(false);
set_do_method_data_update(false); set_do_method_data_update(false);
set_rtm_state(NoRTM); // No RTM lock eliding by default set_rtm_state(NoRTM); // No RTM lock eliding by default
method_has_option_value("MaxNodeLimit", _max_node_limit);
#if INCLUDE_RTM_OPT #if INCLUDE_RTM_OPT
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) { if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
int rtm_state = method()->method_data()->rtm_state(); int rtm_state = method()->method_data()->rtm_state();
......
...@@ -290,6 +290,7 @@ class Compile : public Phase { ...@@ -290,6 +290,7 @@ class Compile : public Phase {
int _freq_inline_size; // Max hot method inline size for this compilation int _freq_inline_size; // Max hot method inline size for this compilation
int _fixed_slots; // count of frame slots not allocated by the register int _fixed_slots; // count of frame slots not allocated by the register
// allocator i.e. locks, original deopt pc, etc. // allocator i.e. locks, original deopt pc, etc.
uintx _max_node_limit; // Max unique node count during a single compilation.
// For deopt // For deopt
int _orig_pc_slot; int _orig_pc_slot;
int _orig_pc_slot_offset_in_bytes; int _orig_pc_slot_offset_in_bytes;
...@@ -594,6 +595,9 @@ class Compile : public Phase { ...@@ -594,6 +595,9 @@ class Compile : public Phase {
void set_rtm_state(RTMState s) { _rtm_state = s; } void set_rtm_state(RTMState s) { _rtm_state = s; }
bool use_rtm() const { return (_rtm_state & NoRTM) == 0; } bool use_rtm() const { return (_rtm_state & NoRTM) == 0; }
bool profile_rtm() const { return _rtm_state == ProfileRTM; } 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 // check the CompilerOracle for special behaviours for this compile
bool method_has_option(const char * option) { bool method_has_option(const char * option) {
return method() != NULL && method()->has_option(option); return method() != NULL && method()->has_option(option);
...@@ -723,7 +727,7 @@ class Compile : public Phase { ...@@ -723,7 +727,7 @@ class Compile : public Phase {
record_method_not_compilable(reason, true); record_method_not_compilable(reason, true);
} }
bool check_node_count(uint margin, const char* reason) { 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); record_method_not_compilable(reason);
return true; return true;
} else { } else {
......
...@@ -410,6 +410,11 @@ void Parse::do_call() { ...@@ -410,6 +410,11 @@ void Parse::do_call() {
ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
assert(declared_signature != NULL, "cannot be null"); 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 // uncommon-trap when callee is unloaded, uninitialized or will not link
// bailout when too many arguments for register representation // bailout when too many arguments for register representation
if (!will_link || can_not_compile_call_site(orig_callee, klass)) { if (!will_link || can_not_compile_call_site(orig_callee, klass)) {
......
...@@ -2409,7 +2409,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro ...@@ -2409,7 +2409,7 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
} }
} }
} }
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()) { if (C->do_escape_analysis() == true && !C->failing()) {
// Retry compilation without escape analysis. // Retry compilation without escape analysis.
// If this is the first failure, the sentinel string will "stick" // If this is the first failure, the sentinel string will "stick"
......
...@@ -269,10 +269,9 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) { ...@@ -269,10 +269,9 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const { bool IdealLoopTree::policy_peeling( PhaseIdealLoop *phase ) const {
Node *test = ((IdealLoopTree*)this)->tail(); Node *test = ((IdealLoopTree*)this)->tail();
int body_size = ((IdealLoopTree*)this)->_body.size(); 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 // Peeling does loop cloning which can result in O(N^2) node construction
if( body_size > 255 /* Prevent overflow for large body_size */ 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 return false; // too large to safely clone
} }
while( test != _head ) { // Scan till run off top of loop while( test != _head ) { // Scan till run off top of loop
...@@ -601,7 +600,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const { ...@@ -601,7 +600,7 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
return false; return false;
if (new_body_size > unroll_limit || if (new_body_size > unroll_limit ||
// Unrolling can result in a large amount of node construction // 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; return false;
} }
...@@ -2287,8 +2286,8 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_ ...@@ -2287,8 +2286,8 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
// Skip next optimizations if running low on nodes. Note that // Skip next optimizations if running low on nodes. Note that
// policy_unswitching and policy_maximally_unroll have this check. // policy_unswitching and policy_maximally_unroll have this check.
uint nodes_left = MaxNodeLimit - (uint) phase->C->live_nodes(); int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
if ((2 * _body.size()) > nodes_left) { if ((int)(2 * _body.size()) > nodes_left) {
return true; return true;
} }
......
...@@ -59,8 +59,8 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const { ...@@ -59,8 +59,8 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
if (!_head->is_Loop()) { if (!_head->is_Loop()) {
return false; return false;
} }
uint nodes_left = MaxNodeLimit - phase->C->live_nodes(); int nodes_left = phase->C->max_node_limit() - phase->C->live_nodes();
if (2 * _body.size() > nodes_left) { if ((int)(2 * _body.size()) > nodes_left) {
return false; // Too speculative if running low on nodes. return false; // Too speculative if running low on nodes.
} }
LoopNode* head = _head->as_Loop(); LoopNode* head = _head->as_Loop();
......
...@@ -734,7 +734,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) { ...@@ -734,7 +734,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) {
for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) { for (DUIterator_Fast imax, i = region->fast_outs(imax); i < imax; i++) {
weight += region->fast_out(i)->outcnt(); 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) { if (weight * 8 > nodes_left) {
#ifndef PRODUCT #ifndef PRODUCT
if (PrintOpto) if (PrintOpto)
......
...@@ -69,7 +69,7 @@ void Node::verify_construction() { ...@@ -69,7 +69,7 @@ void Node::verify_construction() {
Compile::set_debug_idx(new_debug_idx); Compile::set_debug_idx(new_debug_idx);
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()->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)) { if (BreakAtNode != 0 && (_debug_idx == BreakAtNode || (int)_idx == BreakAtNode)) {
tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx); tty->print_cr("BreakAtNode: _idx=%d _debug_idx=%d", _idx, _debug_idx);
BREAKPOINT; BREAKPOINT;
...@@ -326,7 +326,7 @@ inline int Node::Init(int req, Compile* C) { ...@@ -326,7 +326,7 @@ inline int Node::Init(int req, Compile* C) {
Node::Node(uint req) Node::Node(uint req)
: _idx(IDX_INIT(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() ); debug_only( verify_construction() );
NOT_PRODUCT(nodes_created++); NOT_PRODUCT(nodes_created++);
if (req == 0) { if (req == 0) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册