提交 cd04ba90 编写于 作者: V vlivanov

8058148: MaxNodeLimit and LiveNodeCountInliningCutoff

Reviewed-by: kvn, roland
上级 14e7429d
......@@ -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, \
......
......@@ -679,7 +679,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_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 @@ Compile::Compile( ciEnv* ci_env,
_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 @@ void Compile::Init(int aliaslevel) {
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();
......
......@@ -290,6 +290,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;
......@@ -594,6 +595,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);
......@@ -723,7 +727,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 {
......
......@@ -410,6 +410,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)) {
......
......@@ -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()) {
// Retry compilation without escape analysis.
// If this is the first failure, the sentinel string will "stick"
......
......@@ -269,10 +269,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
......@@ -601,7 +600,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;
}
......@@ -2287,8 +2286,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;
}
......
......@@ -59,8 +59,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();
......
......@@ -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++) {
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;
......@@ -326,7 +326,7 @@ inline int Node::Init(int req, Compile* C) {
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) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册