--- old/src/share/vm/oops/instanceKlass.hpp 2014-10-24 13:42:10.050562020 +0200 +++ new/src/share/vm/oops/instanceKlass.hpp 2014-10-24 13:42:09.906562024 +0200 @@ -742,7 +742,7 @@ void set_osr_nmethods_head(nmethod* h) { _osr_nmethods_head = h; }; void add_osr_nmethod(nmethod* n); void remove_osr_nmethod(nmethod* n); - nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level) const; + nmethod* lookup_osr_nmethod(const Method* m, int bci, int level, bool match_level, bool skip_marked = false) const; // Breakpoint support (see methods on Method* for details) BreakpointInfo* breakpoints() const { return _breakpoints; }; --- old/src/share/vm/oops/instanceKlass.cpp 2014-10-24 13:42:10.054562019 +0200 +++ new/src/share/vm/oops/instanceKlass.cpp 2014-10-24 13:42:09.902562025 +0200 @@ -2845,7 +2845,8 @@ } } -nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, bool match_level) const { +nmethod* InstanceKlass::lookup_osr_nmethod(const Method* m, int bci, int comp_level, + bool match_level, bool skip_marked) const { // This is a short non-blocking critical region, so the no safepoint check is ok. MutexLockerEx ml(OsrList_lock, Mutex::_no_safepoint_check_flag); nmethod* osr = osr_nmethods_head(); @@ -2858,7 +2859,7 @@ // while we overflow in the c1 code at back branches we don't want to // try and switch to the same code as we are already running - if (osr->method() == m && + if (osr->method() == m && !(skip_marked && osr->is_marked_for_deoptimization()) && (bci == InvocationEntryBci || osr->osr_entry_bci() == bci)) { if (match_level) { if (osr->comp_level() == comp_level) { --- old/src/share/vm/prims/whitebox.cpp 2014-10-24 13:42:10.070562019 +0200 +++ new/src/share/vm/prims/whitebox.cpp 2014-10-24 13:42:09.934562024 +0200 @@ -388,11 +388,10 @@ methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); nmethod* code; if (is_osr) { - int bci = InvocationEntryBci; - while ((code = mh->lookup_osr_nmethod_for(bci, CompLevel_none, false)) != NULL) { + // Mark all OSR compiled versions for deoptimization + while ((code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false, true)) != NULL) { code->mark_for_deoptimization(); ++result; - bci = code->osr_entry_bci() + 1; } } else { code = mh->code(); --- old/src/share/vm/oops/method.hpp 2014-10-24 13:42:10.122562017 +0200 +++ new/src/share/vm/oops/method.hpp 2014-10-24 13:42:09.978562022 +0200 @@ -813,8 +813,8 @@ return method_holder()->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL; } - nmethod* lookup_osr_nmethod_for(int bci, int level, bool match_level) { - return method_holder()->lookup_osr_nmethod(this, bci, level, match_level); + nmethod* lookup_osr_nmethod_for(int bci, int level, bool match_level, bool skip_marked = false) { + return method_holder()->lookup_osr_nmethod(this, bci, level, match_level, skip_marked); } // Inline cache support --- /dev/null 2014-10-24 08:04:40.031555971 +0200 +++ new/test/compiler/whitebox/DeoptimizeMultipleOSRTest.java 2014-10-24 13:42:10.054562019 +0200 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, 2014, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import sun.hotspot.WhiteBox; +import java.lang.reflect.Executable; +import java.lang.reflect.Method; + +/* + * @test DeoptimizeMultipleOSRTest + * @bug 8061817 + * @library /testlibrary /testlibrary/whitebox + * @build DeoptimizeMultipleOSRTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,DeoptimizeMultipleOSRTest::triggerOSR DeoptimizeMultipleOSRTest + * @summary testing of WB::deoptimizeMethod() + */ +public class DeoptimizeMultipleOSRTest { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final long BACKEDGE_THRESHOLD = 150000; + private static Method method; + private static int counter = 0; + + public static void main(String[] args) throws Exception { + method = DeoptimizeMultipleOSRTest.class.getDeclaredMethod("triggerOSR", boolean.class, long.class); + // Trigger two OSR compiled versions + triggerOSR(true, BACKEDGE_THRESHOLD); + triggerOSR(false, BACKEDGE_THRESHOLD); + // Wait for compilation + CompilerWhiteBoxTest.waitBackgroundCompilation(method); + // Deoptimize + WHITE_BOX.deoptimizeMethod(method, true); + if (WHITE_BOX.isMethodCompiled(method, true)) { + throw new RuntimeException("Not all OSR compiled versions were deoptimized"); + } + } + + /** + * Triggers OSR compilations by executing loops. + * + * @param first Determines which loop to execute + * @param limit The number of loop iterations + */ + public static void triggerOSR(boolean first, long limit) { + if (limit != 1) { + // Warmup method to avoid uncommon traps + for (int i = 0; i < limit; ++i) { + triggerOSR(first, 1); + } + CompilerWhiteBoxTest.waitBackgroundCompilation(method); + } + if (first) { + // Trigger OSR compilation 1 + for (int i = 0; i < limit; ++i) { + counter++; + } + } else { + // Trigger OSR compilation 2 + for (int i = 0; i < limit; ++i) { + counter++; + } + } + } +}