changeset 38:b789bcaf2dd9

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
author kvn
date Thu, 06 Mar 2008 10:30:17 -0800
parents 73970d8c0b27
children 76256d272075
files src/share/vm/includeDB_compiler2 src/share/vm/opto/c2compiler.cpp src/share/vm/opto/c2compiler.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/compile.hpp src/share/vm/opto/escape.cpp src/share/vm/opto/parse1.cpp
diffstat 7 files changed, 57 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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().
--- 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();
--- 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;
--- 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
--- 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) {
--- 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;
 }