src/hotspot/share/code/codeCache.cpp
changeset 53641 c572eb605087
parent 52908 449a2ce77784
child 54122 4b1426ed1c44
--- a/src/hotspot/share/code/codeCache.cpp	Thu Jan 31 23:56:37 2019 +0800
+++ b/src/hotspot/share/code/codeCache.cpp	Tue Feb 05 10:40:25 2019 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -1200,9 +1200,9 @@
 #endif
 }
 
-int CodeCache::mark_for_evol_deoptimization(InstanceKlass* dependee) {
+// Just marks the methods in this class as needing deoptimization
+void CodeCache::mark_for_evol_deoptimization(InstanceKlass* dependee) {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-  int number_of_marked_CodeBlobs = 0;
 
   // Deoptimize all methods of the evolving class itself
   Array<Method*>* old_methods = dependee->methods();
@@ -1212,16 +1212,24 @@
     CompiledMethod* nm = old_method->code();
     if (nm != NULL) {
       nm->mark_for_deoptimization();
-      number_of_marked_CodeBlobs++;
     }
   }
 
+  // Mark dependent AOT nmethods, which are only found via the class redefined.
+  AOTLoader::mark_evol_dependent_methods(dependee);
+}
+
+// Walk compiled methods and mark dependent methods for deoptimization.
+int CodeCache::mark_dependents_for_evol_deoptimization() {
+  int number_of_marked_CodeBlobs = 0;
   CompiledMethodIterator iter(CompiledMethodIterator::only_alive_and_not_unloading);
   while(iter.next()) {
     CompiledMethod* nm = iter.method();
     if (nm->is_marked_for_deoptimization()) {
-      // ...Already marked in the previous pass; don't count it again.
-    } else if (nm->is_evol_dependent_on(dependee)) {
+      // ...Already marked in the previous pass; count it here.
+      // Also counts AOT compiled methods, already marked.
+      number_of_marked_CodeBlobs++;
+    } else if (nm->is_evol_dependent()) {
       ResourceMark rm;
       nm->mark_for_deoptimization();
       number_of_marked_CodeBlobs++;
@@ -1231,6 +1239,8 @@
     }
   }
 
+  // return total count of nmethods marked for deoptimization, if zero the caller
+  // can skip deoptimization
   return number_of_marked_CodeBlobs;
 }
 
@@ -1294,34 +1304,30 @@
   }
 }
 
-// Flushes compiled methods dependent on dependee when the dependee is redefined
-// via RedefineClasses
-void CodeCache::flush_evol_dependents_on(InstanceKlass* ev_k) {
+// Flushes compiled methods dependent on redefined classes, that have already been
+// marked for deoptimization.
+void CodeCache::flush_evol_dependents() {
   // --- Compile_lock is not held. However we are at a safepoint.
   assert_locked_or_safepoint(Compile_lock);
-  if (number_of_nmethods_with_dependencies() == 0 && !UseAOT) return;
 
   // CodeCache can only be updated by a thread_in_VM and they will all be
   // stopped during the safepoint so CodeCache will be safe to update without
   // holding the CodeCache_lock.
 
-  // Compute the dependent nmethods
-  if (mark_for_evol_deoptimization(ev_k) > 0) {
-    // At least one nmethod has been marked for deoptimization
+  // At least one nmethod has been marked for deoptimization
 
-    // All this already happens inside a VM_Operation, so we'll do all the work here.
-    // Stuff copied from VM_Deoptimize and modified slightly.
+  // All this already happens inside a VM_Operation, so we'll do all the work here.
+  // Stuff copied from VM_Deoptimize and modified slightly.
 
-    // We do not want any GCs to happen while we are in the middle of this VM operation
-    ResourceMark rm;
-    DeoptimizationMarker dm;
+  // We do not want any GCs to happen while we are in the middle of this VM operation
+  ResourceMark rm;
+  DeoptimizationMarker dm;
 
-    // Deoptimize all activations depending on marked nmethods
-    Deoptimization::deoptimize_dependents();
+  // Deoptimize all activations depending on marked nmethods
+  Deoptimization::deoptimize_dependents();
 
-    // Make the dependent methods not entrant
-    make_marked_nmethods_not_entrant();
-  }
+  // Make the dependent methods not entrant
+  make_marked_nmethods_not_entrant();
 }
 
 // Flushes compiled methods dependent on dependee