# HG changeset patch # User kvn # Date 1204828217 28800 # Node ID b789bcaf2dd9f0ab4457f0938630ec07f279b828 # Parent 73970d8c0b275f8b24db8f9966db56404bb70ea5 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 diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/includeDB_compiler2 --- a/src/share/vm/includeDB_compiler2 Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/includeDB_compiler2 Thu Mar 06 10:30:17 2008 -0800 @@ -410,6 +410,7 @@ escape.cpp allocation.hpp escape.cpp bcEscapeAnalyzer.hpp +escape.cpp c2compiler.hpp escape.cpp callnode.hpp escape.cpp cfgnode.hpp escape.cpp compile.hpp diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/opto/c2compiler.cpp --- a/src/share/vm/opto/c2compiler.cpp Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/opto/c2compiler.cpp Thu Mar 06 10:30:17 2008 -0800 @@ -35,6 +35,9 @@ const char* C2Compiler::retry_no_subsuming_loads() { return "retry without subsuming loads"; } +const char* C2Compiler::retry_no_escape_analysis() { + return "retry without escape analysis"; +} void C2Compiler::initialize_runtime() { // Check assumptions used while running ADLC @@ -101,17 +104,23 @@ initialize(); } bool subsume_loads = true; + bool do_escape_analysis = DoEscapeAnalysis; while (!env->failing()) { // 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. if (C.failure_reason() != NULL) { - if (C.failure_reason_is(retry_no_subsuming_loads())) { + if (C.failure_reason_is(retry_no_subsuming_loads())) { assert(subsume_loads, "must make progress"); subsume_loads = false; 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. // Note that serious, irreversible failures are already logged // on the ciEnv via env->record_method_not_compilable(). diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/opto/c2compiler.hpp --- a/src/share/vm/opto/c2compiler.hpp Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/opto/c2compiler.hpp Thu Mar 06 10:30:17 2008 -0800 @@ -50,6 +50,7 @@ // sentinel value used to trigger backtracking in compile_method(). static const char* retry_no_subsuming_loads(); + static const char* retry_no_escape_analysis(); // Print compilation timers and statistics void print_timers(); diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/opto/compile.cpp --- a/src/share/vm/opto/compile.cpp Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/opto/compile.cpp Thu Mar 06 10:30:17 2008 -0800 @@ -333,6 +333,12 @@ tty->print_cr("** Bailout: Recompile without subsuming loads **"); 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()) { // Open the debugger when compiing this method. tty->print("### Breaking when compiling: "); @@ -415,7 +421,7 @@ // 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), _env(ci_env), _log(ci_env->log()), @@ -430,6 +436,7 @@ _for_igvn(NULL), _warm_calls(NULL), _subsume_loads(subsume_loads), + _do_escape_analysis(do_escape_analysis), _failure_reason(NULL), _code_buffer("Compile::Fill_buffer"), _orig_pc_slot(0), @@ -487,7 +494,7 @@ PhaseGVN gvn(node_arena(), estimated_size); set_initial_gvn(&gvn); - if (DoEscapeAnalysis) + if (_do_escape_analysis) _congraph = new ConnectionGraph(this); { // Scope for timing the parser @@ -577,6 +584,8 @@ if (_congraph != NULL) { NOT_PRODUCT( TracePhase t2("escapeAnalysis", &_t_escapeAnalysis, TimeCompiler); ) _congraph->compute_escape(); + if (failing()) return; + #ifndef PRODUCT if (PrintEscapeAnalysis) { _congraph->dump(); @@ -675,6 +684,7 @@ _orig_pc_slot(0), _orig_pc_slot_offset_in_bytes(0), _subsume_loads(true), + _do_escape_analysis(false), _failure_reason(NULL), _code_buffer("Compile::Fill_buffer"), _node_bundling_limit(0), @@ -822,7 +832,7 @@ // Type::update_loaded_types(_method, _method->constants()); // Init alias_type map. - if (!DoEscapeAnalysis && aliaslevel == 3) + if (!_do_escape_analysis && aliaslevel == 3) aliaslevel = 2; // No unique types without escape analysis _AliasLevel = aliaslevel; const int grow_ats = 16; diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/opto/compile.hpp --- a/src/share/vm/opto/compile.hpp Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/opto/compile.hpp Thu Mar 06 10:30:17 2008 -0800 @@ -31,6 +31,7 @@ class Int_Array; class Matcher; class MachNode; +class MachSafePointNode; class Node; class Node_Array; class Node_Notes; @@ -52,9 +53,6 @@ class Unique_Node_List; class nmethod; class WarmCallInfo; -#ifdef ENABLE_ZAP_DEAD_LOCALS -class MachSafePointNode; -#endif //------------------------------Compile---------------------------------------- // This class defines a top-level Compiler invocation. @@ -127,6 +125,7 @@ const int _compile_id; 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 _do_escape_analysis; // Do escape analysis. ciMethod* _method; // The method being compiled. int _entry_bci; // entry bci for osr methods. const TypeFunc* _tf; // My kind of signature @@ -260,6 +259,8 @@ // instructions that subsume a load may result in an unschedulable // instruction sequence. 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; } @@ -560,7 +561,7 @@ // replacement, entry_bci indicates the bytecode for which to compile a // continuation. 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 // to pass arguments from the Java calling convention to the C calling diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/opto/escape.cpp --- a/src/share/vm/opto/escape.cpp Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/opto/escape.cpp Thu Mar 06 10:30:17 2008 -0800 @@ -395,6 +395,15 @@ if (result != NULL && C->get_alias_index(result->adr_type()) == alias_idx) { 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); result = PhiNode::make(orig_phi->in(0), NULL, Type::MEMORY, atype); @@ -443,6 +452,9 @@ mem = nphi; } } + if (C->failing()) { + return NULL; + } result->set_req(idx++, mem); } #ifdef ASSERT @@ -672,6 +684,9 @@ if (mem->is_Phi()) { mem = split_memory_phi(mem->as_Phi(), alias_idx, orig_phis, igvn); } + if (_compile->failing()) { + return; + } if (mem != n->in(MemNode::Memory)) set_map(n->_idx, mem); if (n->is_Load()) { @@ -742,7 +757,11 @@ if((uint)_compile->get_general_index(ni) == i) { Node *m = (ni >= nmm->req()) ? nmm->empty_memory() : nmm->in(ni); 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 @@ // Now use the escape information to create unique types for // unescaped objects 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) { diff -r 73970d8c0b27 -r b789bcaf2dd9 src/share/vm/opto/parse1.cpp --- a/src/share/vm/opto/parse1.cpp Wed Mar 05 11:33:31 2008 -0800 +++ b/src/share/vm/opto/parse1.cpp Thu Mar 06 10:30:17 2008 -0800 @@ -1836,7 +1836,7 @@ PhiNode* phi = PhiNode::make(region, o, 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); return phi; }