8082782: vm crash on StressRedefineWithoutBytecodeCorruption fails with assert(((Metadata*)obj)->is_valid()) failed: obj is valid
authorcoleenp
Thu, 23 Jul 2015 15:17:58 -0400
changeset 31981 9caa094a485f
parent 31856 614d6786ba55
child 31982 ebe371c6926a
8082782: vm crash on StressRedefineWithoutBytecodeCorruption fails with assert(((Metadata*)obj)->is_valid()) failed: obj is valid Summary: Walk compile task for Method* to not deallocate, store methods in methodHandle while compile task is being taken off compile queue Reviewed-by: dcubed, sspitsyn
hotspot/src/share/vm/compiler/compileBroker.cpp
hotspot/src/share/vm/compiler/compileBroker.hpp
hotspot/src/share/vm/runtime/thread.cpp
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp	Thu Jul 23 15:17:58 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -345,6 +345,14 @@
   }
 }
 
+// RedefineClasses support
+void CompileTask::metadata_do(void f(Metadata*)) {
+  f(method());
+  if (hot_method() != NULL && hot_method() != method()) {
+    f(hot_method());
+  }
+}
+
 // ------------------------------------------------------------------
 // CompileTask::print_line_on_error
 //
@@ -660,6 +668,11 @@
  * Get the next CompileTask from a CompileQueue
  */
 CompileTask* CompileQueue::get() {
+  // save methods from RedefineClasses across safepoint
+  // across MethodCompileQueue_lock below.
+  methodHandle save_method;
+  methodHandle save_hot_method;
+
   MutexLocker locker(MethodCompileQueue_lock);
   // If _first is NULL we have no more compile jobs. There are two reasons for
   // having no compile jobs: First, we compiled everything we wanted. Second,
@@ -693,6 +706,12 @@
     No_Safepoint_Verifier nsv;
     task = CompilationPolicy::policy()->select_task(this);
   }
+
+  // Save method pointers across unlock safepoint.  The task is removed from
+  // the compilation queue, which is walked during RedefineClasses.
+  save_method = methodHandle(task->method());
+  save_hot_method = methodHandle(task->hot_method());
+
   remove(task);
   purge_stale_tasks(); // may temporarily release MCQ lock
   return task;
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp	Thu Jul 23 15:17:58 2015 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -80,6 +80,7 @@
 
   int          compile_id() const                { return _compile_id; }
   Method*      method() const                    { return _method; }
+  Method*      hot_method() const                { return _hot_method; }
   int          osr_bci() const                   { return _osr_bci; }
   bool         is_complete() const               { return _is_complete; }
   bool         is_blocking() const               { return _is_blocking; }
@@ -108,6 +109,9 @@
   bool         is_free() const                   { return _is_free; }
   void         set_is_free(bool val)             { _is_free = val; }
 
+  // RedefineClasses support
+  void         metadata_do(void f(Metadata*));
+
 private:
   static void  print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level,
                                       bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false,
--- a/hotspot/src/share/vm/runtime/thread.cpp	Tue Jul 21 07:28:37 2015 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp	Thu Jul 23 15:17:58 2015 -0400
@@ -2739,6 +2739,9 @@
     if (ct->env() != NULL) {
       ct->env()->metadata_do(f);
     }
+    if (ct->task() != NULL) {
+      ct->task()->metadata_do(f);
+    }
   }
 }