提交 b7457039 编写于 作者: K kvn

6667610: (Escape Analysis) retry compilation without EA if it fails

Summary: During split unique types EA could exceed nodes limit and fail the method compilation.
Reviewed-by: rasbold
上级 74c7267b
...@@ -410,6 +410,7 @@ domgraph.cpp vectset.hpp ...@@ -410,6 +410,7 @@ domgraph.cpp vectset.hpp
escape.cpp allocation.hpp escape.cpp allocation.hpp
escape.cpp bcEscapeAnalyzer.hpp escape.cpp bcEscapeAnalyzer.hpp
escape.cpp c2compiler.hpp
escape.cpp callnode.hpp escape.cpp callnode.hpp
escape.cpp cfgnode.hpp escape.cpp cfgnode.hpp
escape.cpp compile.hpp escape.cpp compile.hpp
......
...@@ -35,6 +35,9 @@ extern const int register_save_type[]; ...@@ -35,6 +35,9 @@ extern const int register_save_type[];
const char* C2Compiler::retry_no_subsuming_loads() { const char* C2Compiler::retry_no_subsuming_loads() {
return "retry without subsuming loads"; return "retry without subsuming loads";
} }
const char* C2Compiler::retry_no_escape_analysis() {
return "retry without escape analysis";
}
void C2Compiler::initialize_runtime() { void C2Compiler::initialize_runtime() {
// Check assumptions used while running ADLC // Check assumptions used while running ADLC
...@@ -101,9 +104,10 @@ void C2Compiler::compile_method(ciEnv* env, ...@@ -101,9 +104,10 @@ void C2Compiler::compile_method(ciEnv* env,
initialize(); initialize();
} }
bool subsume_loads = true; bool subsume_loads = true;
bool do_escape_analysis = DoEscapeAnalysis;
while (!env->failing()) { while (!env->failing()) {
// Attempt to compile while subsuming loads into machine instructions. // Attempt to compile while subsuming loads into machine instructions.
Compile C(env, this, target, entry_bci, subsume_loads); Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis);
// Check result and retry if appropriate. // Check result and retry if appropriate.
if (C.failure_reason() != NULL) { if (C.failure_reason() != NULL) {
...@@ -112,6 +116,11 @@ void C2Compiler::compile_method(ciEnv* env, ...@@ -112,6 +116,11 @@ void C2Compiler::compile_method(ciEnv* env,
subsume_loads = false; subsume_loads = false;
continue; // retry continue; // retry
} }
if (C.failure_reason_is(retry_no_escape_analysis())) {
assert(do_escape_analysis, "must make progress");
do_escape_analysis = false;
continue; // retry
}
// Pass any other failure reason up to the ciEnv. // Pass any other failure reason up to the ciEnv.
// Note that serious, irreversible failures are already logged // Note that serious, irreversible failures are already logged
// on the ciEnv via env->record_method_not_compilable(). // on the ciEnv via env->record_method_not_compilable().
......
...@@ -50,6 +50,7 @@ public: ...@@ -50,6 +50,7 @@ public:
// sentinel value used to trigger backtracking in compile_method(). // sentinel value used to trigger backtracking in compile_method().
static const char* retry_no_subsuming_loads(); static const char* retry_no_subsuming_loads();
static const char* retry_no_escape_analysis();
// Print compilation timers and statistics // Print compilation timers and statistics
void print_timers(); void print_timers();
......
...@@ -333,6 +333,12 @@ void Compile::print_compile_messages() { ...@@ -333,6 +333,12 @@ void Compile::print_compile_messages() {
tty->print_cr("** Bailout: Recompile without subsuming loads **"); tty->print_cr("** Bailout: Recompile without subsuming loads **");
tty->print_cr("*********************************************************"); tty->print_cr("*********************************************************");
} }
if (_do_escape_analysis != DoEscapeAnalysis && PrintOpto) {
// Recompiling without escape analysis
tty->print_cr("*********************************************************");
tty->print_cr("** Bailout: Recompile without escape analysis **");
tty->print_cr("*********************************************************");
}
if (env()->break_at_compile()) { if (env()->break_at_compile()) {
// Open the debugger when compiing this method. // Open the debugger when compiing this method.
tty->print("### Breaking when compiling: "); tty->print("### Breaking when compiling: ");
...@@ -415,7 +421,7 @@ debug_only( int Compile::_debug_idx = 100000; ) ...@@ -415,7 +421,7 @@ debug_only( int Compile::_debug_idx = 100000; )
// the continuation bci for on stack replacement. // the continuation bci for on stack replacement.
Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, bool subsume_loads ) Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci, bool subsume_loads, bool do_escape_analysis )
: Phase(Compiler), : Phase(Compiler),
_env(ci_env), _env(ci_env),
_log(ci_env->log()), _log(ci_env->log()),
...@@ -430,6 +436,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -430,6 +436,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
_for_igvn(NULL), _for_igvn(NULL),
_warm_calls(NULL), _warm_calls(NULL),
_subsume_loads(subsume_loads), _subsume_loads(subsume_loads),
_do_escape_analysis(do_escape_analysis),
_failure_reason(NULL), _failure_reason(NULL),
_code_buffer("Compile::Fill_buffer"), _code_buffer("Compile::Fill_buffer"),
_orig_pc_slot(0), _orig_pc_slot(0),
...@@ -487,7 +494,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -487,7 +494,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
PhaseGVN gvn(node_arena(), estimated_size); PhaseGVN gvn(node_arena(), estimated_size);
set_initial_gvn(&gvn); set_initial_gvn(&gvn);
if (DoEscapeAnalysis) if (_do_escape_analysis)
_congraph = new ConnectionGraph(this); _congraph = new ConnectionGraph(this);
{ // Scope for timing the parser { // Scope for timing the parser
...@@ -577,6 +584,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr ...@@ -577,6 +584,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
if (_congraph != NULL) { if (_congraph != NULL) {
NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); ) NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); )
_congraph->compute_escape(); _congraph->compute_escape();
if (failing()) return;
#ifndef PRODUCT #ifndef PRODUCT
if (PrintEscapeAnalysis) { if (PrintEscapeAnalysis) {
_congraph->dump(); _congraph->dump();
...@@ -675,6 +684,7 @@ Compile::Compile( ciEnv* ci_env, ...@@ -675,6 +684,7 @@ Compile::Compile( ciEnv* ci_env,
_orig_pc_slot(0), _orig_pc_slot(0),
_orig_pc_slot_offset_in_bytes(0), _orig_pc_slot_offset_in_bytes(0),
_subsume_loads(true), _subsume_loads(true),
_do_escape_analysis(false),
_failure_reason(NULL), _failure_reason(NULL),
_code_buffer("Compile::Fill_buffer"), _code_buffer("Compile::Fill_buffer"),
_node_bundling_limit(0), _node_bundling_limit(0),
...@@ -822,7 +832,7 @@ void Compile::Init(int aliaslevel) { ...@@ -822,7 +832,7 @@ void Compile::Init(int aliaslevel) {
// Type::update_loaded_types(_method, _method->constants()); // Type::update_loaded_types(_method, _method->constants());
// Init alias_type map. // Init alias_type map.
if (!DoEscapeAnalysis && aliaslevel == 3) if (!_do_escape_analysis && aliaslevel == 3)
aliaslevel = 2; // No unique types without escape analysis aliaslevel = 2; // No unique types without escape analysis
_AliasLevel = aliaslevel; _AliasLevel = aliaslevel;
const int grow_ats = 16; const int grow_ats = 16;
......
...@@ -31,6 +31,7 @@ class InlineTree; ...@@ -31,6 +31,7 @@ class InlineTree;
class Int_Array; class Int_Array;
class Matcher; class Matcher;
class MachNode; class MachNode;
class MachSafePointNode;
class Node; class Node;
class Node_Array; class Node_Array;
class Node_Notes; class Node_Notes;
...@@ -52,9 +53,6 @@ class TypeFunc; ...@@ -52,9 +53,6 @@ class TypeFunc;
class Unique_Node_List; class Unique_Node_List;
class nmethod; class nmethod;
class WarmCallInfo; class WarmCallInfo;
#ifdef ENABLE_ZAP_DEAD_LOCALS
class MachSafePointNode;
#endif
//------------------------------Compile---------------------------------------- //------------------------------Compile----------------------------------------
// This class defines a top-level Compiler invocation. // This class defines a top-level Compiler invocation.
...@@ -127,6 +125,7 @@ class Compile : public Phase { ...@@ -127,6 +125,7 @@ class Compile : public Phase {
const int _compile_id; const int _compile_id;
const bool _save_argument_registers; // save/restore arg regs for trampolines const bool _save_argument_registers; // save/restore arg regs for trampolines
const bool _subsume_loads; // Load can be matched as part of a larger op. const bool _subsume_loads; // Load can be matched as part of a larger op.
const bool _do_escape_analysis; // Do escape analysis.
ciMethod* _method; // The method being compiled. ciMethod* _method; // The method being compiled.
int _entry_bci; // entry bci for osr methods. int _entry_bci; // entry bci for osr methods.
const TypeFunc* _tf; // My kind of signature const TypeFunc* _tf; // My kind of signature
...@@ -260,6 +259,8 @@ class Compile : public Phase { ...@@ -260,6 +259,8 @@ class Compile : public Phase {
// instructions that subsume a load may result in an unschedulable // instructions that subsume a load may result in an unschedulable
// instruction sequence. // instruction sequence.
bool subsume_loads() const { return _subsume_loads; } bool subsume_loads() const { return _subsume_loads; }
// Do escape analysis.
bool do_escape_analysis() const { return _do_escape_analysis; }
bool save_argument_registers() const { return _save_argument_registers; } bool save_argument_registers() const { return _save_argument_registers; }
...@@ -560,7 +561,7 @@ class Compile : public Phase { ...@@ -560,7 +561,7 @@ class Compile : public Phase {
// replacement, entry_bci indicates the bytecode for which to compile a // replacement, entry_bci indicates the bytecode for which to compile a
// continuation. // continuation.
Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
int entry_bci, bool subsume_loads); int entry_bci, bool subsume_loads, bool do_escape_analysis);
// Second major entry point. From the TypeFunc signature, generate code // Second major entry point. From the TypeFunc signature, generate code
// to pass arguments from the Java calling convention to the C calling // to pass arguments from the Java calling convention to the C calling
......
...@@ -395,6 +395,15 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro ...@@ -395,6 +395,15 @@ PhiNode *ConnectionGraph::create_split_phi(PhiNode *orig_phi, int alias_idx, Gro
if (result != NULL && C->get_alias_index(result->adr_type()) == alias_idx) { if (result != NULL && C->get_alias_index(result->adr_type()) == alias_idx) {
return result; return result;
} }
if ((int)C->unique() + 2*NodeLimitFudgeFactor > MaxNodeLimit) {
if (C->do_escape_analysis() == true && !C->failing()) {
// Retry compilation without escape analysis.
// If this is the first failure, the sentinel string will "stick"
// to the Compile object, and the C2Compiler will see it and retry.
C->record_failure(C2Compiler::retry_no_escape_analysis());
}
return NULL;
}
orig_phi_worklist.append_if_missing(orig_phi); orig_phi_worklist.append_if_missing(orig_phi);
result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype); result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype);
...@@ -443,6 +452,9 @@ PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, Gro ...@@ -443,6 +452,9 @@ PhiNode *ConnectionGraph::split_memory_phi(PhiNode *orig_phi, int alias_idx, Gro
mem = nphi; mem = nphi;
} }
} }
if (C->failing()) {
return NULL;
}
result->set_req(idx++, mem); result->set_req(idx++, mem);
} }
#ifdef ASSERT #ifdef ASSERT
...@@ -672,6 +684,9 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) ...@@ -672,6 +684,9 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
if (mem->is_Phi()) { if (mem->is_Phi()) {
mem = split_memory_phi(mem->as_Phi(), alias_idx, orig_phis, igvn); mem = split_memory_phi(mem->as_Phi(), alias_idx, orig_phis, igvn);
} }
if (_compile->failing()) {
return;
}
if (mem != n->in(MemNode::Memory)) if (mem != n->in(MemNode::Memory))
set_map(n->_idx, mem); set_map(n->_idx, mem);
if (n->is_Load()) { if (n->is_Load()) {
...@@ -742,7 +757,11 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist) ...@@ -742,7 +757,11 @@ void ConnectionGraph::split_unique_types(GrowableArray<Node *> &alloc_worklist)
if((uint)_compile->get_general_index(ni) == i) { if((uint)_compile->get_general_index(ni) == i) {
Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni); Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni);
if (nmm->is_empty_memory(m)) { if (nmm->is_empty_memory(m)) {
nmm->set_memory_at(ni, split_memory_phi(mem->as_Phi(), ni, orig_phis, igvn)); m = split_memory_phi(mem->as_Phi(), ni, orig_phis, igvn);
if (_compile->failing()) {
return;
}
nmm->set_memory_at(ni, m);
} }
} }
} }
...@@ -881,6 +900,11 @@ void ConnectionGraph::compute_escape() { ...@@ -881,6 +900,11 @@ void ConnectionGraph::compute_escape() {
// Now use the escape information to create unique types for // Now use the escape information to create unique types for
// unescaped objects // unescaped objects
split_unique_types(alloc_worklist); split_unique_types(alloc_worklist);
if (_compile->failing()) return;
// Clean up after split unique types.
ResourceMark rm;
PhaseRemoveUseless pru(_compile->initial_gvn(), _compile->for_igvn());
} }
Node * ConnectionGraph::skip_casts(Node *n) { Node * ConnectionGraph::skip_casts(Node *n) {
......
...@@ -1836,7 +1836,7 @@ PhiNode *Parse::ensure_phi(int idx, bool nocreate) { ...@@ -1836,7 +1836,7 @@ PhiNode *Parse::ensure_phi(int idx, bool nocreate) {
PhiNode* phi = PhiNode::make(region, o, t); PhiNode* phi = PhiNode::make(region, o, t);
gvn().set_type(phi, t); gvn().set_type(phi, t);
if (DoEscapeAnalysis) record_for_igvn(phi); if (C->do_escape_analysis()) record_for_igvn(phi);
map->set_req(idx, phi); map->set_req(idx, phi);
return phi; return phi;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册