changeset 1920:5ddfcf4b079e

7003554: (tiered) assert(is_null_object() || handle() != NULL) failed: cannot embed null pointer Summary: C1 with profiling doesn't check whether the MDO has been really allocated, which can silently fail if the perm gen is full. The solution is to check if the allocation failed and bailout out of inlining or compilation. Reviewed-by: kvn, never
author iveresov
date Thu, 02 Dec 2010 17:21:12 -0800
parents bbefa3ca1543
children 2f644f85485d
files src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp src/cpu/x86/vm/c1_LIRAssembler_x86.cpp src/share/vm/c1/c1_Compilation.cpp src/share/vm/c1/c1_GraphBuilder.cpp src/share/vm/c1/c1_IR.cpp src/share/vm/c1/c1_LIRGenerator.cpp src/share/vm/ci/ciMethod.cpp src/share/vm/ci/ciMethod.hpp src/share/vm/opto/compile.cpp src/share/vm/opto/graphKit.cpp
diffstat 10 files changed, 55 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -2419,11 +2419,8 @@
 
 void LIR_Assembler::setup_md_access(ciMethod* method, int bci,
                                     ciMethodData*& md, ciProfileData*& data, int& mdo_offset_bias) {
-  md = method->method_data();
-  if (md == NULL) {
-    bailout("out of memory building methodDataOop");
-    return;
-  }
+  md = method->method_data_or_null();
+  assert(md != NULL, "Sanity");
   data = md->bci_to_data(bci);
   assert(data != NULL,       "need data for checkcast");
   assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -2821,11 +2818,8 @@
   int bci          = op->profiled_bci();
 
   // Update counter for all call types
-  ciMethodData* md = method->method_data();
-  if (md == NULL) {
-    bailout("out of memory building methodDataOop");
-    return;
-  }
+  ciMethodData* md = method->method_data_or_null();
+  assert(md != NULL, "Sanity");
   ciProfileData* data = md->bci_to_data(bci);
   assert(data->is_CounterData(), "need CounterData for calls");
   assert(op->mdo()->is_single_cpu(),  "mdo must be allocated");
--- a/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -1716,11 +1716,8 @@
     ciMethod* method = op->profiled_method();
     assert(method != NULL, "Should have method");
     int bci = op->profiled_bci();
-    md = method->method_data();
-    if (md == NULL) {
-      bailout("out of memory building methodDataOop");
-      return;
-    }
+    md = method->method_data_or_null();
+    assert(md != NULL, "Sanity");
     data = md->bci_to_data(bci);
     assert(data != NULL,                "need data for type check");
     assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -1879,11 +1876,8 @@
       ciMethod* method = op->profiled_method();
       assert(method != NULL, "Should have method");
       int bci = op->profiled_bci();
-      md = method->method_data();
-      if (md == NULL) {
-        bailout("out of memory building methodDataOop");
-        return;
-      }
+      md = method->method_data_or_null();
+      assert(md != NULL, "Sanity");
       data = md->bci_to_data(bci);
       assert(data != NULL,                "need data for type check");
       assert(data->is_ReceiverTypeData(), "need ReceiverTypeData for type check");
@@ -3373,11 +3367,8 @@
   int bci          = op->profiled_bci();
 
   // Update counter for all call types
-  ciMethodData* md = method->method_data();
-  if (md == NULL) {
-    bailout("out of memory building methodDataOop");
-    return;
-  }
+  ciMethodData* md = method->method_data_or_null();
+  assert(md != NULL, "Sanity");
   ciProfileData* data = md->bci_to_data(bci);
   assert(data->is_CounterData(), "need CounterData for calls");
   assert(op->mdo()->is_single_cpu(),  "mdo must be allocated");
--- a/src/share/vm/c1/c1_Compilation.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/c1/c1_Compilation.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -298,8 +298,8 @@
 
   CHECK_BAILOUT_(no_frame_size);
 
-  if (is_profiling()) {
-    method()->build_method_data();
+  if (is_profiling() && !method()->ensure_method_data()) {
+    BAILOUT_("mdo allocation failed", no_frame_size);
   }
 
   {
@@ -484,11 +484,11 @@
     if (is_profiling()) {
       // Compilation failed, create MDO, which would signal the interpreter
       // to start profiling on its own.
-      _method->build_method_data();
+      _method->ensure_method_data();
     }
   } else if (is_profiling() && _would_profile) {
-    ciMethodData *md = method->method_data();
-    assert (md != NULL, "Should have MDO");
+    ciMethodData *md = method->method_data_or_null();
+    assert(md != NULL, "Sanity");
     md->set_would_profile(_would_profile);
   }
 }
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -3377,6 +3377,9 @@
     INLINE_BAILOUT("total inlining greater than DesiredMethodLimit");
   }
 
+  if (is_profiling() && !callee->ensure_method_data()) {
+    INLINE_BAILOUT("mdo allocation failed");
+  }
 #ifndef PRODUCT
       // printing
   if (PrintInlining) {
--- a/src/share/vm/c1/c1_IR.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/c1/c1_IR.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -504,7 +504,12 @@
   count_edges(start_block, NULL);
 
   if (compilation()->is_profiling()) {
-    compilation()->method()->method_data()->set_compilation_stats(_num_loops, _num_blocks);
+    ciMethod *method = compilation()->method();
+    if (!method->is_accessor()) {
+      ciMethodData* md = method->method_data_or_null();
+      assert(md != NULL, "Sanity");
+      md->set_compilation_stats(_num_loops, _num_blocks);
+    }
   }
 
   if (_num_loops > 0) {
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -836,11 +836,8 @@
   if (if_instr->should_profile()) {
     ciMethod* method = if_instr->profiled_method();
     assert(method != NULL, "method should be set if branch is profiled");
-    ciMethodData* md = method->method_data();
-    if (md == NULL) {
-      bailout("out of memory building methodDataOop");
-      return;
-    }
+    ciMethodData* md = method->method_data_or_null();
+    assert(md != NULL, "Sanity");
     ciProfileData* data = md->bci_to_data(if_instr->profiled_bci());
     assert(data != NULL, "must have profiling data");
     assert(data->is_BranchData(), "need BranchData for two-way branches");
@@ -2219,11 +2216,8 @@
   if (x->should_profile()) {
     ciMethod* method = x->profiled_method();
     assert(method != NULL, "method should be set if branch is profiled");
-    ciMethodData* md = method->method_data();
-    if (md == NULL) {
-      bailout("out of memory building methodDataOop");
-      return;
-    }
+    ciMethodData* md = method->method_data_or_null();
+    assert(md != NULL, "Sanity");
     ciProfileData* data = md->bci_to_data(x->profiled_bci());
     assert(data != NULL, "must have profiling data");
     int offset;
@@ -2723,7 +2717,9 @@
   } else if (level == CompLevel_full_profile) {
     offset = in_bytes(backedge ? methodDataOopDesc::backedge_counter_offset() :
                                  methodDataOopDesc::invocation_counter_offset());
-    __ oop2reg(method->method_data()->constant_encoding(), counter_holder);
+    ciMethodData* md = method->method_data_or_null();
+    assert(md != NULL, "Sanity");
+    __ oop2reg(md->constant_encoding(), counter_holder);
     meth = new_register(T_OBJECT);
     __ oop2reg(method->constant_encoding(), meth);
   } else {
--- a/src/share/vm/ci/ciMethod.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/ci/ciMethod.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -797,12 +797,13 @@
 
 
 // ------------------------------------------------------------------
-// ciMethod::build_method_data
+// ciMethod::ensure_method_data
 //
 // Generate new methodDataOop objects at compile time.
-void ciMethod::build_method_data(methodHandle h_m) {
+// Return true if allocation was successful or no MDO is required.
+bool ciMethod::ensure_method_data(methodHandle h_m) {
   EXCEPTION_CONTEXT;
-  if (is_native() || is_abstract() || h_m()->is_accessor()) return;
+  if (is_native() || is_abstract() || h_m()->is_accessor()) return true;
   if (h_m()->method_data() == NULL) {
     methodOopDesc::build_interpreter_method_data(h_m, THREAD);
     if (HAS_PENDING_EXCEPTION) {
@@ -812,18 +813,22 @@
   if (h_m()->method_data() != NULL) {
     _method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data();
     _method_data->load_data();
+    return true;
   } else {
     _method_data = CURRENT_ENV->get_empty_methodData();
+    return false;
   }
 }
 
 // public, retroactive version
-void ciMethod::build_method_data() {
+bool ciMethod::ensure_method_data() {
+  bool result = true;
   if (_method_data == NULL || _method_data->is_empty()) {
     GUARDED_VM_ENTRY({
-      build_method_data(get_methodOop());
+      result = ensure_method_data(get_methodOop());
     });
   }
+  return result;
 }
 
 
@@ -839,11 +844,6 @@
   Thread* my_thread = JavaThread::current();
   methodHandle h_m(my_thread, get_methodOop());
 
-  // Create an MDO for the inlinee
-  if (TieredCompilation && is_c1_compile(env->comp_level())) {
-    build_method_data(h_m);
-  }
-
   if (h_m()->method_data() != NULL) {
     _method_data = CURRENT_ENV->get_object(h_m()->method_data())->as_method_data();
     _method_data->load_data();
@@ -854,6 +854,15 @@
 
 }
 
+// ------------------------------------------------------------------
+// ciMethod::method_data_or_null
+// Returns a pointer to ciMethodData if MDO exists on the VM side,
+// NULL otherwise.
+ciMethodData* ciMethod::method_data_or_null() {
+  ciMethodData *md = method_data();
+  if (md->is_empty()) return NULL;
+  return md;
+}
 
 // ------------------------------------------------------------------
 // ciMethod::will_link
--- a/src/share/vm/ci/ciMethod.hpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/ci/ciMethod.hpp	Thu Dec 02 17:21:12 2010 -0800
@@ -106,7 +106,7 @@
 
   void check_is_loaded() const                   { assert(is_loaded(), "not loaded"); }
 
-  void build_method_data(methodHandle h_m);
+  bool ensure_method_data(methodHandle h_m);
 
   void code_at_put(int bci, Bytecodes::Code code) {
     Bytecodes::check(code);
@@ -121,6 +121,7 @@
   ciSymbol* name() const                         { return _name; }
   ciInstanceKlass* holder() const                { return _holder; }
   ciMethodData* method_data();
+  ciMethodData* method_data_or_null();
 
   // Signature information.
   ciSignature* signature() const                 { return _signature; }
@@ -230,7 +231,7 @@
   bool has_unloaded_classes_in_signature();
   bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const;
   bool check_call(int refinfo_index, bool is_static) const;
-  void build_method_data();  // make sure it exists in the VM also
+  bool ensure_method_data();  // make sure it exists in the VM also
   int scale_count(int count, float prof_factor = 1.);  // make MDO count commensurate with IIC
 
   // JSR 292 support
--- a/src/share/vm/opto/compile.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/opto/compile.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -553,7 +553,7 @@
   if (ProfileTraps) {
     // Make sure the method being compiled gets its own MDO,
     // so we can at least track the decompile_count().
-    method()->build_method_data();
+    method()->ensure_method_data();
   }
 
   Init(::AliasLevel);
--- a/src/share/vm/opto/graphKit.cpp	Thu Dec 02 01:02:55 2010 -0800
+++ b/src/share/vm/opto/graphKit.cpp	Thu Dec 02 17:21:12 2010 -0800
@@ -1841,7 +1841,7 @@
 
   // Note:  If ProfileTraps is true, and if a deopt. actually
   // occurs here, the runtime will make sure an MDO exists.  There is
-  // no need to call method()->build_method_data() at this point.
+  // no need to call method()->ensure_method_data() at this point.
 
 #ifdef ASSERT
   if (!must_throw) {