src/hotspot/share/code/compiledMethod.cpp
changeset 54150 5529640c5f67
parent 53651 0331b08811ad
child 54839 e9db10a375d9
--- a/src/hotspot/share/code/compiledMethod.cpp	Fri Mar 15 18:59:21 2019 +0100
+++ b/src/hotspot/share/code/compiledMethod.cpp	Fri Mar 15 16:00:18 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2019, 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
@@ -415,20 +415,22 @@
 
 #ifdef ASSERT
 // Check class_loader is alive for this bit of metadata.
-static void check_class(Metadata* md) {
-   Klass* klass = NULL;
-   if (md->is_klass()) {
-     klass = ((Klass*)md);
-   } else if (md->is_method()) {
-     klass = ((Method*)md)->method_holder();
-   } else if (md->is_methodData()) {
-     klass = ((MethodData*)md)->method()->method_holder();
-   } else {
-     md->print();
-     ShouldNotReachHere();
-   }
-   assert(klass->is_loader_alive(), "must be alive");
-}
+class CheckClass : public MetadataClosure {
+  void do_metadata(Metadata* md) {
+    Klass* klass = NULL;
+    if (md->is_klass()) {
+      klass = ((Klass*)md);
+    } else if (md->is_method()) {
+      klass = ((Method*)md)->method_holder();
+    } else if (md->is_methodData()) {
+      klass = ((MethodData*)md)->method()->method_holder();
+    } else {
+      md->print();
+      ShouldNotReachHere();
+    }
+    assert(klass->is_loader_alive(), "must be alive");
+  }
+};
 #endif // ASSERT
 
 
@@ -550,8 +552,11 @@
   // All static stubs need to be cleaned.
   clean_ic_stubs();
 
+#ifdef ASSERT
   // Check that the metadata embedded in the nmethod is alive
-  DEBUG_ONLY(metadata_do(check_class));
+  CheckClass check_class;
+  metadata_do(&check_class);
+#endif
   return true;
 }
 
@@ -628,3 +633,35 @@
          os::is_readable_pointer(method->constants()) &&
          os::is_readable_pointer(method->signature());
 }
+
+class HasEvolDependency : public MetadataClosure {
+  bool _has_evol_dependency;
+ public:
+  HasEvolDependency() : _has_evol_dependency(false) {}
+  void do_metadata(Metadata* md) {
+    if (md->is_method()) {
+      Method* method = (Method*)md;
+      if (method->is_old()) {
+        _has_evol_dependency = true;
+      }
+    }
+  }
+  bool has_evol_dependency() const { return _has_evol_dependency; }
+};
+
+bool CompiledMethod::has_evol_metadata() {
+  // Check the metadata in relocIter and CompiledIC and also deoptimize
+  // any nmethod that has reference to old methods.
+  HasEvolDependency check_evol;
+  metadata_do(&check_evol);
+  if (check_evol.has_evol_dependency() && log_is_enabled(Debug, redefine, class, nmethod)) {
+    ResourceMark rm;
+    log_debug(redefine, class, nmethod)
+            ("Found evol dependency of nmethod %s.%s(%s) compile_id=%d on in nmethod metadata",
+             _method->method_holder()->external_name(),
+             _method->name()->as_C_string(),
+             _method->signature()->as_C_string(),
+             compile_id());
+  }
+  return check_evol.has_evol_dependency();
+}