Merge
authorjwilhelm
Wed, 06 Feb 2019 00:20:37 +0100
changeset 53652 262afafdb266
parent 53649 0b959dfdf0d9 (current diff)
parent 53651 0331b08811ad (diff)
child 53653 868611f0adc3
Merge
src/hotspot/share/code/compiledIC.cpp
src/hotspot/share/code/compiledIC.hpp
src/hotspot/share/code/compiledMethod.hpp
src/hotspot/share/code/nmethod.cpp
src/hotspot/share/runtime/sweeper.hpp
--- a/src/hotspot/share/code/compiledIC.cpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/code/compiledIC.cpp	Wed Feb 06 00:20:37 2019 +0100
@@ -51,7 +51,8 @@
 CompiledICLocker::CompiledICLocker(CompiledMethod* method)
   : _method(method),
     _behaviour(CompiledICProtectionBehaviour::current()),
-    _locked(_behaviour->lock(_method)){
+    _locked(_behaviour->lock(_method)),
+    _nsv(true, !SafepointSynchronize::is_at_safepoint()) {
 }
 
 CompiledICLocker::~CompiledICLocker() {
@@ -583,17 +584,6 @@
   return is_icholder_entry(dest);
 }
 
-// Release the CompiledICHolder* associated with this call site is there is one.
-void CompiledIC::cleanup_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm) {
-  assert(cm->is_nmethod(), "must be nmethod");
-  // This call site might have become stale so inspect it carefully.
-  NativeCall* call = nativeCall_at(call_site->addr());
-  if (is_icholder_entry(call->destination())) {
-    NativeMovConstReg* value = nativeMovConstReg_at(call_site->cached_value());
-    InlineCacheBuffer::queue_for_release((CompiledICHolder*)value->data());
-  }
-}
-
 // ----------------------------------------------------------------------------
 
 bool CompiledStaticCall::set_to_clean(bool in_use) {
--- a/src/hotspot/share/code/compiledIC.hpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/code/compiledIC.hpp	Wed Feb 06 00:20:37 2019 +0100
@@ -226,10 +226,6 @@
   friend CompiledIC* CompiledIC_at(Relocation* call_site);
   friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
 
-  // This is used to release CompiledICHolder*s from nmethods that
-  // are about to be freed.  The callsite might contain other stale
-  // values of other kinds so it must be careful.
-  static void cleanup_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm);
   static bool is_icholder_call_site(virtual_call_Relocation* call_site, const CompiledMethod* cm);
 
   // Return the cached_metadata/destination associated with this inline cache. If the cache currently points
--- a/src/hotspot/share/code/compiledMethod.cpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/code/compiledMethod.cpp	Wed Feb 06 00:20:37 2019 +0100
@@ -399,15 +399,16 @@
   }
 }
 
-// Clear ICStubs of all compiled ICs
-void CompiledMethod::clear_ic_stubs() {
+// Clear IC callsites, releasing ICStubs of all compiled ICs
+// as well as any associated CompiledICHolders.
+void CompiledMethod::clear_ic_callsites() {
   assert(CompiledICLocker::is_safe(this), "mt unsafe call");
   ResourceMark rm;
   RelocIterator iter(this);
   while(iter.next()) {
     if (iter.type() == relocInfo::virtual_call_type) {
       CompiledIC* ic = CompiledIC_at(&iter);
-      ic->clear_ic_stub();
+      ic->set_to_clean(false);
     }
   }
 }
--- a/src/hotspot/share/code/compiledMethod.hpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/code/compiledMethod.hpp	Wed Feb 06 00:20:37 2019 +0100
@@ -361,7 +361,7 @@
   void cleanup_inline_caches(bool clean_all);
 
   virtual void clear_inline_caches();
-  void clear_ic_stubs();
+  void clear_ic_callsites();
 
   // Verify and count cached icholder relocations.
   int  verify_icholder_relocations();
--- a/src/hotspot/share/code/nmethod.cpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/code/nmethod.cpp	Wed Feb 06 00:20:37 2019 +0100
@@ -1099,6 +1099,12 @@
   assert(SafepointSynchronize::is_at_safepoint() || Thread::current()->is_ConcurrentGC_thread(),
          "must be at safepoint");
 
+  {
+    // Clear ICStubs and release any CompiledICHolders.
+    CompiledICLocker ml(this);
+    clear_ic_callsites();
+  }
+
   // Unregister must be done before the state change
   {
     MutexLockerEx ml(SafepointSynchronize::is_at_safepoint() ? NULL : CodeCache_lock,
@@ -1291,10 +1297,11 @@
     }
 
     // Clear ICStubs to prevent back patching stubs of zombie or flushed
-    // nmethods during the next safepoint (see ICStub::finalize).
+    // nmethods during the next safepoint (see ICStub::finalize), as well
+    // as to free up CompiledICHolder resources.
     {
       CompiledICLocker ml(this);
-      clear_ic_stubs();
+      clear_ic_callsites();
     }
 
     // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload
@@ -1326,6 +1333,7 @@
 }
 
 void nmethod::flush() {
+  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   // Note that there are no valid oops in the nmethod anymore.
   assert(!is_osr_method() || is_unloaded() || is_zombie(),
          "osr nmethod must be unloaded or zombie before flushing");
--- a/src/hotspot/share/runtime/sweeper.cpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/runtime/sweeper.cpp	Wed Feb 06 00:20:37 2019 +0100
@@ -663,27 +663,6 @@
   }
 };
 
-void NMethodSweeper::release_compiled_method(CompiledMethod* nm) {
-  // Make sure the released nmethod is no longer referenced by the sweeper thread
-  CodeCacheSweeperThread* thread = (CodeCacheSweeperThread*)JavaThread::current();
-  thread->set_scanned_compiled_method(NULL);
-
-  // Clean up any CompiledICHolders
-  {
-    ResourceMark rm;
-    RelocIterator iter(nm);
-    CompiledICLocker ml(nm);
-    while (iter.next()) {
-      if (iter.type() == relocInfo::virtual_call_type) {
-        CompiledIC::cleanup_call_site(iter.virtual_call_reloc(), nm);
-      }
-    }
-  }
-
-  MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
-  nm->flush();
-}
-
 NMethodSweeper::MethodStateChange NMethodSweeper::process_compiled_method(CompiledMethod* cm) {
   assert(cm != NULL, "sanity");
   assert(!CodeCache_lock->owned_by_self(), "just checking");
@@ -697,7 +676,7 @@
   // Skip methods that are currently referenced by the VM
   if (cm->is_locked_by_vm()) {
     // But still remember to clean-up inline caches for alive nmethods
-    if (cm->is_alive() && !cm->is_unloading()) {
+    if (cm->is_alive()) {
       // Clean inline caches that point to zombie/non-entrant/unloaded nmethods
       cm->cleanup_inline_caches(false);
       SWEEP(cm);
@@ -709,7 +688,7 @@
     // All inline caches that referred to this nmethod were cleaned in the
     // previous sweeper cycle. Now flush the nmethod from the code cache.
     assert(!cm->is_locked_by_vm(), "must not flush locked Compiled Methods");
-    release_compiled_method(cm);
+    cm->flush();
     assert(result == None, "sanity");
     result = Flushed;
   } else if (cm->is_not_entrant()) {
@@ -728,7 +707,7 @@
         // Make sure that we unregistered the nmethod with the heap and flushed all
         // dependencies before removing the nmethod (done in make_zombie()).
         assert(cm->is_zombie(), "nmethod must be unregistered");
-        release_compiled_method(cm);
+        cm->flush();
         assert(result == None, "sanity");
         result = Flushed;
       } else {
@@ -744,14 +723,10 @@
   } else if (cm->is_unloaded()) {
     // Code is unloaded, so there are no activations on the stack.
     // Convert the nmethod to zombie or flush it directly in the OSR case.
-
-    // Clean ICs of unloaded nmethods as well because they may reference other
-    // unloaded nmethods that may be flushed earlier in the sweeper cycle.
-    cm->cleanup_inline_caches(false);
     if (cm->is_osr_method()) {
       SWEEP(cm);
       // No inline caches will ever point to osr methods, so we can just remove it
-      release_compiled_method(cm);
+      cm->flush();
       assert(result == None, "sanity");
       result = Flushed;
     } else {
--- a/src/hotspot/share/runtime/sweeper.hpp	Tue Feb 05 15:06:08 2019 -0800
+++ b/src/hotspot/share/runtime/sweeper.hpp	Wed Feb 06 00:20:37 2019 +0100
@@ -89,7 +89,6 @@
   static Tickspan  _peak_sweep_fraction_time;     // Peak time sweeping one fraction
 
   static MethodStateChange process_compiled_method(CompiledMethod *nm);
-  static void              release_compiled_method(CompiledMethod* nm);
 
   static void init_sweeper_log() NOT_DEBUG_RETURN;
   static bool wait_for_stack_scanning();
--- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/HtmlSection.java	Tue Feb 05 15:06:08 2019 -0800
+++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/HtmlSection.java	Wed Feb 06 00:20:37 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 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
@@ -153,13 +153,11 @@
     public HtmlSection createChildren(String[] sections) {
         int i = 0;
         int n = sections.length;
-        HtmlSection current = rootSection;
-        if (current != null) {
-            for (; i < n && current.child != null;
-                    ++i, current = current.child) {
-                if (!sections[i].equals(current.child.name)) {
-                    break;
-                }
+        HtmlSection current = this;
+        for (; i < n && current.child != null;
+                ++i, current = current.child) {
+            if (!sections[i].equals(current.child.name)) {
+                break;
             }
         }
         for (; i < n; ++i) {
--- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/ToolKit.java	Tue Feb 05 15:06:08 2019 -0800
+++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/ToolKit.java	Wed Feb 06 00:20:37 2019 +0100
@@ -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
@@ -31,6 +31,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Queue;
+import java.util.Deque;
 
 public class ToolKit implements EnvironmentInfoGatherer, ProcessInfoGatherer {
     private final List<ActionSet> actions = new ArrayList<>();
@@ -52,20 +53,27 @@
 
     @Override
     public void gatherProcessInfo(HtmlSection section, long pid) {
-        Queue<Long> pids = new LinkedList<>();
-        pids.add(pid);
-        for (Long p = pids.poll(); p != null; p = pids.poll()) {
-            HtmlSection pidSection = section.createChildren("" + p);
-            List<Long> children = helper.getChildren(pidSection, p);
+        // as some of actions can kill a process, we need to get children of all
+        // test process first, and run the actions starting from the leaves
+        // and going up by the process tree
+        Deque<Long> orderedPids = new LinkedList<>();
+        Queue<Long> testPids = new LinkedList<>();
+        testPids.add(pid);
+        HtmlSection ptreeSection = section.createChildren("test_processes");
+        for (Long p = testPids.poll(); p != null; p = testPids.poll()) {
+            orderedPids.addFirst(p);
+            List<Long> children = helper.getChildren(ptreeSection, p);
             if (!children.isEmpty()) {
-                HtmlSection s = pidSection.createChildren("children");
+                HtmlSection s = ptreeSection.createChildren("" + p);
                 for (Long c : children) {
                     s.link(section, c.toString(), c.toString());
                 }
-                pids.addAll(children);
+                testPids.addAll(children);
             }
+        }
+        for (Long p : orderedPids) {
             for (ActionSet set : actions) {
-                set.gatherProcessInfo(pidSection, p);
+                set.gatherProcessInfo(section, p);
             }
         }
     }
--- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/action/ActionHelper.java	Tue Feb 05 15:06:08 2019 -0800
+++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/action/ActionHelper.java	Wed Feb 06 00:20:37 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 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
@@ -64,7 +64,7 @@
     public ActionHelper(Path workDir, String prefix, Properties properties,
                         Path... jdks) throws InvalidValueException {
         this.workDir = workDir.toAbsolutePath();
-        getChildren = new PatternAction("children",
+        getChildren = new PatternAction(null,
                 Utils.prependPrefix(prefix, "getChildren"), properties);
         ValueHandler.apply(this, properties, prefix);
         String[] pathStrings = System.getenv("PATH").split(File.pathSeparator);
--- a/test/failure_handler/src/share/classes/jdk/test/failurehandler/action/PatternAction.java	Tue Feb 05 15:06:08 2019 -0800
+++ b/test/failure_handler/src/share/classes/jdk/test/failurehandler/action/PatternAction.java	Wed Feb 06 00:20:37 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 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
@@ -44,7 +44,7 @@
 
     public PatternAction(String name, String id, Properties properties)
             throws InvalidValueException {
-        action = new SimpleAction(("pattern." + name), id, properties);
+        action = new SimpleAction(name != null ? ("pattern." + name) : "pattern", id, properties);
         ValueHandler.apply(this, properties, id);
         originalArgs = action.args.clone();
     }