# HG changeset patch # User jwilhelm # Date 1549408837 -3600 # Node ID 262afafdb26637d600d3823f0f64b05e5aafd90e # Parent 0b959dfdf0d9f07122a2ebb04b33b697d948883e# Parent 0331b08811ad1121eb175f6fe0845faafbdc8c7e Merge diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/code/compiledIC.cpp --- 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) { diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/code/compiledIC.hpp --- 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 diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/code/compiledMethod.cpp --- 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); } } } diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/code/compiledMethod.hpp --- 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(); diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/code/nmethod.cpp --- 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"); diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/runtime/sweeper.cpp --- 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 { diff -r 0b959dfdf0d9 -r 262afafdb266 src/hotspot/share/runtime/sweeper.hpp --- 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(); diff -r 0b959dfdf0d9 -r 262afafdb266 test/failure_handler/src/share/classes/jdk/test/failurehandler/HtmlSection.java --- 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) { diff -r 0b959dfdf0d9 -r 262afafdb266 test/failure_handler/src/share/classes/jdk/test/failurehandler/ToolKit.java --- 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 actions = new ArrayList<>(); @@ -52,20 +53,27 @@ @Override public void gatherProcessInfo(HtmlSection section, long pid) { - Queue pids = new LinkedList<>(); - pids.add(pid); - for (Long p = pids.poll(); p != null; p = pids.poll()) { - HtmlSection pidSection = section.createChildren("" + p); - List 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 orderedPids = new LinkedList<>(); + Queue 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 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); } } } diff -r 0b959dfdf0d9 -r 262afafdb266 test/failure_handler/src/share/classes/jdk/test/failurehandler/action/ActionHelper.java --- 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); diff -r 0b959dfdf0d9 -r 262afafdb266 test/failure_handler/src/share/classes/jdk/test/failurehandler/action/PatternAction.java --- 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(); }