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
--- a/hotspot/src/share/vm/includeDB_compiler2 Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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
--- a/hotspot/src/share/vm/opto/c2compiler.cpp Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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().
--- a/hotspot/src/share/vm/opto/c2compiler.hpp Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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();
--- a/hotspot/src/share/vm/opto/compile.cpp Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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;
--- a/hotspot/src/share/vm/opto/compile.hpp Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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
--- a/hotspot/src/share/vm/opto/escape.cpp Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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) {
--- a/hotspot/src/share/vm/opto/parse1.cpp Wed Mar 05 11:33:31 2008 -0800
+++ b/hotspot/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;
}