mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-11 14:11:36 +00:00
8058148: MaxNodeLimit and LiveNodeCountInliningCutoff
Reviewed-by: kvn, roland
This commit is contained in:
parent
9adb455ba8
commit
5a00d5f6b5
@ -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 @@ void ciTypeFlow::df_flow_types(Block* start,
|
||||
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!
|
||||
|
||||
@ -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, \
|
||||
|
||||
@ -661,7 +661,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
_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 @@ Compile::Compile( ciEnv* ci_env,
|
||||
_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 @@ void Compile::Init(int aliaslevel) {
|
||||
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();
|
||||
|
||||
@ -289,6 +289,7 @@ class Compile : public Phase {
|
||||
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 @@ class Compile : public Phase {
|
||||
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 @@ class Compile : public Phase {
|
||||
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 {
|
||||
|
||||
@ -418,6 +418,11 @@ void Parse::do_call() {
|
||||
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)) {
|
||||
|
||||
@ -2417,7 +2417,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()) {
|
||||
// Retry compilation without escape analysis.
|
||||
// If this is the first failure, the sentinel string will "stick"
|
||||
|
||||
@ -272,10 +272,9 @@ void IdealLoopTree::reassociate_invariants(PhaseIdealLoop *phase) {
|
||||
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 @@ bool IdealLoopTree::policy_maximally_unroll( PhaseIdealLoop *phase ) const {
|
||||
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 @@ bool IdealLoopTree::iteration_split_impl( PhaseIdealLoop *phase, Node_List &old_
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@ -61,8 +61,8 @@ bool IdealLoopTree::policy_unswitching( PhaseIdealLoop *phase ) const {
|
||||
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();
|
||||
|
||||
@ -736,7 +736,7 @@ static bool merge_point_too_heavy(Compile* C, Node* region) {
|
||||
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)
|
||||
|
||||
@ -69,7 +69,7 @@ void Node::verify_construction() {
|
||||
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 @@ inline int Node::Init(int req) {
|
||||
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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user