# HG changeset patch # User iignatyev # Date 1376509823 -14400 # Node ID f99558245e5c95245c28c466c611837db3013ea6 # Parent 6c72125a2f40199031590cd5409ccb6a1fc892f2 8022832: Add WB APIs for OSR compilation Reviewed-by: kvn diff -r 6c72125a2f40 -r f99558245e5c src/share/vm/oops/method.cpp --- a/src/share/vm/oops/method.cpp Fri Aug 16 17:34:37 2013 +0400 +++ b/src/share/vm/oops/method.cpp Wed Aug 14 23:50:23 2013 +0400 @@ -747,6 +747,7 @@ set_not_c2_compilable(); } CompilationPolicy::policy()->disable_compilation(this); + assert(!CompilationPolicy::can_be_compiled(this, comp_level), "sanity check"); } bool Method::is_not_osr_compilable(int comp_level) const { @@ -773,6 +774,7 @@ set_not_c2_osr_compilable(); } CompilationPolicy::policy()->disable_compilation(this); + assert(!CompilationPolicy::can_be_osr_compiled(this, comp_level), "sanity check"); } // Revert to using the interpreter and clear out the nmethod diff -r 6c72125a2f40 -r f99558245e5c src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp Fri Aug 16 17:34:37 2013 +0400 +++ b/src/share/vm/prims/whitebox.cpp Wed Aug 14 23:50:23 2013 +0400 @@ -196,12 +196,22 @@ VMThread::execute(&op); WB_END -WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method)) +WB_ENTRY(jint, WB_DeoptimizeMethod(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); int result = 0; - nmethod* code = mh->code(); + nmethod* code; + if (is_osr) { + int bci = InvocationEntryBci; + while ((code = mh->lookup_osr_nmethod_for(bci, CompLevel_none, false)) != NULL) { + code->mark_for_deoptimization(); + ++result; + bci = code->osr_entry_bci() + 1; + } + } else { + code = mh->code(); + } if (code != NULL) { code->mark_for_deoptimization(); ++result; @@ -214,22 +224,26 @@ return result; WB_END -WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method)) +WB_ENTRY(jboolean, WB_IsMethodCompiled(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - nmethod* code = mh->code(); + nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); if (code == NULL) { return JNI_FALSE; } return (code->is_alive() && !code->is_marked_for_deoptimization()); WB_END -WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level)) +WB_ENTRY(jboolean, WB_IsMethodCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); MutexLockerEx mu(Compile_lock); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - return CompilationPolicy::can_be_compiled(mh, comp_level); + if (is_osr) { + return CompilationPolicy::can_be_osr_compiled(mh, comp_level); + } else { + return CompilationPolicy::can_be_compiled(mh, comp_level); + } WB_END WB_ENTRY(jboolean, WB_IsMethodQueuedForCompilation(JNIEnv* env, jobject o, jobject method)) @@ -239,18 +253,28 @@ return mh->queued_for_compilation(); WB_END -WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method)) +WB_ENTRY(jint, WB_GetMethodCompilationLevel(JNIEnv* env, jobject o, jobject method, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - nmethod* code = mh->code(); + nmethod* code = is_osr ? mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false) : mh->code(); return (code != NULL ? code->comp_level() : CompLevel_none); WB_END - -WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level)) +WB_ENTRY(void, WB_MakeMethodNotCompilable(JNIEnv* env, jobject o, jobject method, jint comp_level, jboolean is_osr)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - mh->set_not_compilable(comp_level, true /* report */, "WhiteBox"); + if (is_osr) { + mh->set_not_osr_compilable(comp_level, true /* report */, "WhiteBox"); + } else { + mh->set_not_compilable(comp_level, true /* report */, "WhiteBox"); + } +WB_END + +WB_ENTRY(jint, WB_GetMethodEntryBci(JNIEnv* env, jobject o, jobject method)) + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* code = mh->lookup_osr_nmethod_for(InvocationEntryBci, CompLevel_none, false); + return (code != NULL && code->is_osr_method() ? code->osr_entry_bci() : InvocationEntryBci); WB_END WB_ENTRY(jboolean, WB_TestSetDontInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) @@ -261,12 +285,15 @@ return result; WB_END -WB_ENTRY(jint, WB_GetCompileQueuesSize(JNIEnv* env, jobject o)) - return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ + - CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; +WB_ENTRY(jint, WB_GetCompileQueueSize(JNIEnv* env, jobject o, jint comp_level)) + if (comp_level == CompLevel_any) { + return CompileBroker::queue_size(CompLevel_full_optimization) /* C2 */ + + CompileBroker::queue_size(CompLevel_full_profile) /* C1 */; + } else { + return CompileBroker::queue_size(comp_level); + } WB_END - WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject method, jboolean value)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); @@ -275,10 +302,10 @@ return result; WB_END -WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level)) +WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci)) jmethodID jmid = reflected_method_to_jmid(thread, env, method); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); - nmethod* nm = CompileBroker::compile_method(mh, InvocationEntryBci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); + nmethod* nm = CompileBroker::compile_method(mh, bci, comp_level, mh, mh->invocation_count(), "WhiteBox", THREAD); MutexLockerEx mu(Compile_lock); return (mh->queued_for_compilation() || nm != NULL); WB_END @@ -324,7 +351,6 @@ return (StringTable::lookup(name, len) != NULL); WB_END - WB_ENTRY(void, WB_FullGC(JNIEnv* env, jobject o)) Universe::heap()->collector_policy()->set_should_clear_all_soft_refs(true); Universe::heap()->collect(GCCause::_last_ditch_collection); @@ -423,31 +449,32 @@ {CC"NMTWaitForDataMerge", CC"()Z", (void*)&WB_NMTWaitForDataMerge}, #endif // INCLUDE_NMT {CC"deoptimizeAll", CC"()V", (void*)&WB_DeoptimizeAll }, - {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;)I", + {CC"deoptimizeMethod", CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_DeoptimizeMethod }, - {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;)Z", + {CC"isMethodCompiled", CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_IsMethodCompiled }, - {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;I)Z", + {CC"isMethodCompilable", CC"(Ljava/lang/reflect/Executable;IZ)Z", (void*)&WB_IsMethodCompilable}, {CC"isMethodQueuedForCompilation", CC"(Ljava/lang/reflect/Executable;)Z", (void*)&WB_IsMethodQueuedForCompilation}, {CC"makeMethodNotCompilable", - CC"(Ljava/lang/reflect/Executable;I)V", (void*)&WB_MakeMethodNotCompilable}, + CC"(Ljava/lang/reflect/Executable;IZ)V", (void*)&WB_MakeMethodNotCompilable}, {CC"testSetDontInlineMethod", CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetDontInlineMethod}, {CC"getMethodCompilationLevel", - CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodCompilationLevel}, - {CC"getCompileQueuesSize", - CC"()I", (void*)&WB_GetCompileQueuesSize}, + CC"(Ljava/lang/reflect/Executable;Z)I", (void*)&WB_GetMethodCompilationLevel}, + {CC"getMethodEntryBci", + CC"(Ljava/lang/reflect/Executable;)I", (void*)&WB_GetMethodEntryBci}, + {CC"getCompileQueueSize", + CC"(I)I", (void*)&WB_GetCompileQueueSize}, {CC"testSetForceInlineMethod", CC"(Ljava/lang/reflect/Executable;Z)Z", (void*)&WB_TestSetForceInlineMethod}, {CC"enqueueMethodForCompilation", - CC"(Ljava/lang/reflect/Executable;I)Z", (void*)&WB_EnqueueMethodForCompilation}, + CC"(Ljava/lang/reflect/Executable;II)Z", (void*)&WB_EnqueueMethodForCompilation}, {CC"clearMethodState", CC"(Ljava/lang/reflect/Executable;)V", (void*)&WB_ClearMethodState}, {CC"isInStringTable", CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable }, {CC"fullGC", CC"()V", (void*)&WB_FullGC }, - {CC"readReservedMemory", CC"()V", (void*)&WB_ReadReservedMemory }, }; diff -r 6c72125a2f40 -r f99558245e5c src/share/vm/runtime/compilationPolicy.cpp --- a/src/share/vm/runtime/compilationPolicy.cpp Fri Aug 16 17:34:37 2013 +0400 +++ b/src/share/vm/runtime/compilationPolicy.cpp Wed Aug 14 23:50:23 2013 +0400 @@ -138,6 +138,23 @@ return false; } +// Returns true if m is allowed to be osr compiled +bool CompilationPolicy::can_be_osr_compiled(methodHandle m, int comp_level) { + bool result = false; + if (comp_level == CompLevel_all) { + if (TieredCompilation) { + // enough to be osr compilable at any level for tiered + result = !m->is_not_osr_compilable(CompLevel_simple) || !m->is_not_osr_compilable(CompLevel_full_optimization); + } else { + // must be osr compilable at available level for non-tiered + result = !m->is_not_osr_compilable(CompLevel_highest_tier); + } + } else if (is_compile(comp_level)) { + result = !m->is_not_osr_compilable(comp_level); + } + return (result && can_be_compiled(m, comp_level)); +} + bool CompilationPolicy::is_compilation_enabled() { // NOTE: CompileBroker::should_compile_new_jobs() checks for UseCompiler return !delay_compilation_during_startup() && CompileBroker::should_compile_new_jobs(); @@ -458,7 +475,7 @@ const int hot_count = m->backedge_count(); const char* comment = "backedge_count"; - if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m, comp_level)) { + if (is_compilation_enabled() && can_be_osr_compiled(m, comp_level)) { CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } @@ -514,7 +531,7 @@ const int hot_count = m->backedge_count(); const char* comment = "backedge_count"; - if (is_compilation_enabled() && !m->is_not_osr_compilable(comp_level) && can_be_compiled(m, comp_level)) { + if (is_compilation_enabled() && can_be_osr_compiled(m, comp_level)) { CompileBroker::compile_method(m, bci, comp_level, m, hot_count, comment, thread); NOT_PRODUCT(trace_osr_completion(m->lookup_osr_nmethod_for(bci, comp_level, true));) } diff -r 6c72125a2f40 -r f99558245e5c src/share/vm/runtime/compilationPolicy.hpp --- a/src/share/vm/runtime/compilationPolicy.hpp Fri Aug 16 17:34:37 2013 +0400 +++ b/src/share/vm/runtime/compilationPolicy.hpp Wed Aug 14 23:50:23 2013 +0400 @@ -52,6 +52,8 @@ static bool must_be_compiled(methodHandle m, int comp_level = CompLevel_all); // m is allowed to be compiled static bool can_be_compiled(methodHandle m, int comp_level = CompLevel_all); + // m is allowed to be osr compiled + static bool can_be_osr_compiled(methodHandle m, int comp_level = CompLevel_all); static bool is_compilation_enabled(); static void set_policy(CompilationPolicy* policy) { _policy = policy; } static CompilationPolicy* policy() { return _policy; } diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/ClearMethodStateTest.java --- a/test/compiler/whitebox/ClearMethodStateTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/ClearMethodStateTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,6 +23,7 @@ /* * @test ClearMethodStateTest + * @bug 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build ClearMethodStateTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -59,16 +60,19 @@ WHITE_BOX.clearMethodState(method); checkCompiled(); WHITE_BOX.clearMethodState(method); - WHITE_BOX.deoptimizeMethod(method); + deoptimize(); checkNotCompiled(); - + if (testCase.isOsr) { + // part test isn't applicable for OSR test case + return; + } if (!TIERED_COMPILATION) { WHITE_BOX.clearMethodState(method); compile(COMPILE_THRESHOLD); checkCompiled(); - WHITE_BOX.deoptimizeMethod(method); + deoptimize(); checkNotCompiled(); WHITE_BOX.clearMethodState(method); diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/CompilerWhiteBoxTest.java --- a/test/compiler/whitebox/CompilerWhiteBoxTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/CompilerWhiteBoxTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -44,8 +44,14 @@ protected static int COMP_LEVEL_ANY = -1; /** {@code CompLevel::CompLevel_simple} -- C1 */ protected static int COMP_LEVEL_SIMPLE = 1; + /** {@code CompLevel::CompLevel_limited_profile} -- C1, invocation & backedge counters */ + protected static int COMP_LEVEL_LIMITED_PROFILE = 2; + /** {@code CompLevel::CompLevel_full_profile} -- C1, invocation & backedge counters + mdo */ + protected static int COMP_LEVEL_FULL_PROFILE = 3; /** {@code CompLevel::CompLevel_full_optimization} -- C2 or Shark */ protected static int COMP_LEVEL_FULL_OPTIMIZATION = 4; + /** Maximal value for CompLeveL */ + protected static int COMP_LEVEL_MAX = COMP_LEVEL_FULL_OPTIMIZATION; /** Instance of WhiteBox */ protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); @@ -64,6 +70,21 @@ /** Flag for verbose output, true if {@code -Dverbose} specified */ protected static final boolean IS_VERBOSE = System.getProperty("verbose") != null; + /** count of invocation to triger compilation */ + protected static final int THRESHOLD; + /** count of invocation to triger OSR compilation */ + protected static final long BACKEDGE_THRESHOLD; + + static { + if (TIERED_COMPILATION) { + THRESHOLD = 150000; + BACKEDGE_THRESHOLD = 0xFFFFFFFFL; + } else { + THRESHOLD = COMPILE_THRESHOLD; + BACKEDGE_THRESHOLD = COMPILE_THRESHOLD * Long.parseLong(getVMOption( + "OnStackReplacePercentage")); + } + } /** * Returns value of VM option. @@ -112,7 +133,7 @@ /** tested method */ protected final Executable method; - private final Callable callable; + protected final TestCase testCase; /** * Constructor. @@ -123,7 +144,7 @@ Objects.requireNonNull(testCase); System.out.println("TEST CASE:" + testCase.name()); method = testCase.executable; - callable = testCase.callable; + this.testCase = testCase; } /** @@ -169,12 +190,18 @@ if (WHITE_BOX.isMethodQueuedForCompilation(method)) { throw new RuntimeException(method + " must not be in queue"); } - if (WHITE_BOX.isMethodCompiled(method)) { + if (WHITE_BOX.isMethodCompiled(method, false)) { throw new RuntimeException(method + " must be not compiled"); } - if (WHITE_BOX.getMethodCompilationLevel(method) != 0) { + if (WHITE_BOX.getMethodCompilationLevel(method, false) != 0) { throw new RuntimeException(method + " comp_level must be == 0"); } + if (WHITE_BOX.isMethodCompiled(method, true)) { + throw new RuntimeException(method + " must be not osr_compiled"); + } + if (WHITE_BOX.getMethodCompilationLevel(method, true) != 0) { + throw new RuntimeException(method + " osr_comp_level must be == 0"); + } } /** @@ -192,12 +219,44 @@ method, System.currentTimeMillis() - start); return; } - if (!WHITE_BOX.isMethodCompiled(method)) { - throw new RuntimeException(method + " must be compiled"); + if (!WHITE_BOX.isMethodCompiled(method, testCase.isOsr)) { + throw new RuntimeException(method + " must be " + + (testCase.isOsr ? "osr_" : "") + "compiled"); + } + if (WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr) == 0) { + throw new RuntimeException(method + + (testCase.isOsr ? " osr_" : " ") + + "comp_level must be != 0"); + } + } + + protected final void deoptimize() { + WHITE_BOX.deoptimizeMethod(method, testCase.isOsr); + if (testCase.isOsr) { + WHITE_BOX.deoptimizeMethod(method, false); } - if (WHITE_BOX.getMethodCompilationLevel(method) == 0) { - throw new RuntimeException(method + " comp_level must be != 0"); - } + } + + protected final int getCompLevel() { + return WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr); + } + + protected final boolean isCompilable() { + return WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, + testCase.isOsr); + } + + protected final boolean isCompilable(int compLevel) { + return WHITE_BOX.isMethodCompilable(method, compLevel, testCase.isOsr); + } + + protected final void makeNotCompilable() { + WHITE_BOX.makeMethodNotCompilable(method, COMP_LEVEL_ANY, + testCase.isOsr); + } + + protected final void makeNotCompilable(int compLevel) { + WHITE_BOX.makeMethodNotCompilable(method, compLevel, testCase.isOsr); } /** @@ -226,12 +285,18 @@ protected final void printInfo() { System.out.printf("%n%s:%n", method); System.out.printf("\tcompilable:\t%b%n", - WHITE_BOX.isMethodCompilable(method)); + WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, false)); System.out.printf("\tcompiled:\t%b%n", - WHITE_BOX.isMethodCompiled(method)); + WHITE_BOX.isMethodCompiled(method, false)); System.out.printf("\tcomp_level:\t%d%n", - WHITE_BOX.getMethodCompilationLevel(method)); - System.out.printf("\tin_queue:\t%b%n", + WHITE_BOX.getMethodCompilationLevel(method, false)); + System.out.printf("\tosr_compilable:\t%b%n", + WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY, true)); + System.out.printf("\tosr_compiled:\t%b%n", + WHITE_BOX.isMethodCompiled(method, true)); + System.out.printf("\tosr_comp_level:\t%d%n", + WHITE_BOX.getMethodCompilationLevel(method, true)); + System.out.printf("\tin_queue:\t%b%n", WHITE_BOX.isMethodQueuedForCompilation(method)); System.out.printf("compile_queues_size:\t%d%n%n", WHITE_BOX.getCompileQueuesSize()); @@ -244,18 +309,22 @@ /** * Tries to trigger compilation of {@linkplain #method} by call - * {@linkplain #callable} enough times. + * {@linkplain #testCase.callable} enough times. * * @return accumulated result * @see #compile(int) */ protected final int compile() { - return compile(Math.max(COMPILE_THRESHOLD, 150000)); + if (testCase.isOsr) { + return compile(1); + } else { + return compile(THRESHOLD); + } } /** * Tries to trigger compilation of {@linkplain #method} by call - * {@linkplain #callable} specified times. + * {@linkplain #testCase.callable} specified times. * * @param count invocation count * @return accumulated result @@ -265,7 +334,7 @@ Integer tmp; for (int i = 0; i < count; ++i) { try { - tmp = callable.call(); + tmp = testCase.callable.call(); } catch (Exception e) { tmp = null; } @@ -283,23 +352,36 @@ */ enum TestCase { /** constructor test case */ - CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE), + CONSTRUCTOR_TEST(Helper.CONSTRUCTOR, Helper.CONSTRUCTOR_CALLABLE, false), /** method test case */ - METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE), + METOD_TEST(Helper.METHOD, Helper.METHOD_CALLABLE, false), /** static method test case */ - STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE); + STATIC_TEST(Helper.STATIC, Helper.STATIC_CALLABLE, false), + + /** OSR constructor test case */ + OSR_CONSTRUCTOR_TEST(Helper.OSR_CONSTRUCTOR, + Helper.OSR_CONSTRUCTOR_CALLABLE, true), + /** OSR method test case */ + OSR_METOD_TEST(Helper.OSR_METHOD, Helper.OSR_METHOD_CALLABLE, true), + /** OSR static method test case */ + OSR_STATIC_TEST(Helper.OSR_STATIC, Helper.OSR_STATIC_CALLABLE, true); /** tested method */ final Executable executable; /** object to invoke {@linkplain #executable} */ final Callable callable; + /** flag for OSR test case */ + final boolean isOsr; - private TestCase(Executable executable, Callable callable) { + private TestCase(Executable executable, Callable callable, + boolean isOsr) { this.executable = executable; this.callable = callable; + this.isOsr = isOsr; } private static class Helper { + private static final Callable CONSTRUCTOR_CALLABLE = new Callable() { @Override @@ -326,9 +408,39 @@ } }; + private static final Callable OSR_CONSTRUCTOR_CALLABLE + = new Callable() { + @Override + public Integer call() throws Exception { + return new Helper(null).hashCode(); + } + }; + + private static final Callable OSR_METHOD_CALLABLE + = new Callable() { + private final Helper helper = new Helper(); + + @Override + public Integer call() throws Exception { + return helper.osrMethod(); + } + }; + + private static final Callable OSR_STATIC_CALLABLE + = new Callable() { + @Override + public Integer call() throws Exception { + return osrStaticMethod(); + } + }; + + private static final Constructor CONSTRUCTOR; + private static final Constructor OSR_CONSTRUCTOR; private static final Method METHOD; private static final Method STATIC; + private static final Method OSR_METHOD; + private static final Method OSR_STATIC; static { try { @@ -338,17 +450,26 @@ "exception on getting method Helper.(int)", e); } try { - METHOD = Helper.class.getDeclaredMethod("method"); + OSR_CONSTRUCTOR = Helper.class.getDeclaredConstructor( + Object.class); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException( - "exception on getting method Helper.method()", e); + "exception on getting method Helper.(Object)", e); } + METHOD = getMethod("method"); + STATIC = getMethod("staticMethod"); + OSR_METHOD = getMethod("osrMethod"); + OSR_STATIC = getMethod("osrStaticMethod"); + } + + private static Method getMethod(String name) { try { - STATIC = Helper.class.getDeclaredMethod("staticMethod"); + return Helper.class.getDeclaredMethod(name); } catch (NoSuchMethodException | SecurityException e) { throw new RuntimeException( - "exception on getting method Helper.staticMethod()", e); + "exception on getting method Helper." + name, e); } + } private static int staticMethod() { @@ -359,12 +480,39 @@ return 42; } + private static int osrStaticMethod() { + int result = 0; + for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) { + result += staticMethod(); + } + return result; + } + + private int osrMethod() { + int result = 0; + for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) { + result += method(); + } + return result; + } + private final int x; + // for method and OSR method test case public Helper() { x = 0; } + // for OSR constructor test case + private Helper(Object o) { + int result = 0; + for (long i = 0; i < CompilerWhiteBoxTest.BACKEDGE_THRESHOLD; ++i) { + result += method(); + } + x = result; + } + + // for constructor test case private Helper(int x) { this.x = x; } diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/DeoptimizeAllTest.java --- a/test/compiler/whitebox/DeoptimizeAllTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/DeoptimizeAllTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,6 +23,7 @@ /* * @test DeoptimizeAllTest + * @bug 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build DeoptimizeAllTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/DeoptimizeMethodTest.java --- a/test/compiler/whitebox/DeoptimizeMethodTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/DeoptimizeMethodTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,6 +23,7 @@ /* * @test DeoptimizeMethodTest + * @bug 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build DeoptimizeMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox @@ -54,7 +55,7 @@ protected void test() throws Exception { compile(); checkCompiled(); - WHITE_BOX.deoptimizeMethod(method); + deoptimize(); checkNotCompiled(); } } diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/EnqueueMethodForCompilationTest.java --- a/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/EnqueueMethodForCompilationTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,10 +23,11 @@ /* * @test EnqueueMethodForCompilationTest + * @bug 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build EnqueueMethodForCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,TestCase$Helper::* EnqueueMethodForCompilationTest + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,TestCase$Helper::* EnqueueMethodForCompilationTest * @summary testing of WB::enqueueMethodForCompilation() * @author igor.ignatyev@oracle.com */ @@ -50,7 +51,7 @@ // method can not be compiled on level 'none' WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_NONE); - if (WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_NONE)) { + if (isCompilable(COMP_LEVEL_NONE)) { throw new RuntimeException(method + " is compilable at level COMP_LEVEL_NONE"); } @@ -60,27 +61,29 @@ WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_ANY); checkNotCompiled(); - WHITE_BOX.enqueueMethodForCompilation(method, 5); - if (!WHITE_BOX.isMethodCompilable(method, 5)) { - checkNotCompiled(); - compile(); - checkCompiled(); - } else { - checkCompiled(); - } - - int compLevel = WHITE_BOX.getMethodCompilationLevel(method); - WHITE_BOX.deoptimizeMethod(method); - checkNotCompiled(); - - WHITE_BOX.enqueueMethodForCompilation(method, compLevel); - checkCompiled(); - WHITE_BOX.deoptimizeMethod(method); + // not existing comp level + WHITE_BOX.enqueueMethodForCompilation(method, 42); checkNotCompiled(); compile(); checkCompiled(); - WHITE_BOX.deoptimizeMethod(method); + + int compLevel = getCompLevel(); + int bci = WHITE_BOX.getMethodEntryBci(method); + System.out.println("bci = " + bci); + printInfo(); + deoptimize(); + printInfo(); + checkNotCompiled(); + printInfo(); + WHITE_BOX.enqueueMethodForCompilation(method, compLevel, bci); + checkCompiled(); + deoptimize(); + checkNotCompiled(); + + compile(); + checkCompiled(); + deoptimize(); checkNotCompiled(); } } diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/IsMethodCompilableTest.java --- a/test/compiler/whitebox/IsMethodCompilableTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/IsMethodCompilableTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,11 +23,11 @@ /* * @test IsMethodCompilableTest - * @bug 8007270 + * @bug 8007270 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build IsMethodCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,TestCase$Helper::* IsMethodCompilableTest + * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,TestCase$Helper::* IsMethodCompilableTest * @summary testing of WB::isMethodCompilable() * @author igor.ignatyev@oracle.com */ @@ -68,7 +68,7 @@ */ @Override protected void test() throws Exception { - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!isCompilable()) { throw new RuntimeException(method + " must be compilable"); } System.out.println("PerMethodRecompilationCutoff = " @@ -83,7 +83,8 @@ for (long i = 0L, n = PER_METHOD_RECOMPILATION_CUTOFF - 1; i < n; ++i) { compileAndDeoptimize(); } - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!testCase.isOsr && !isCompilable()) { + // in osr test case count of deopt maybe more than iterations throw new RuntimeException(method + " is not compilable after " + (PER_METHOD_RECOMPILATION_CUTOFF - 1) + " iterations"); } @@ -92,15 +93,16 @@ // deoptimize 'PerMethodRecompilationCutoff' + 1 times long i; for (i = 0L; i < PER_METHOD_RECOMPILATION_CUTOFF - && WHITE_BOX.isMethodCompilable(method); ++i) { + && isCompilable(); ++i) { compileAndDeoptimize(); } - if (i != PER_METHOD_RECOMPILATION_CUTOFF) { + if (!testCase.isOsr && i != PER_METHOD_RECOMPILATION_CUTOFF) { + // in osr test case count of deopt maybe more than iterations throw new RuntimeException(method + " is not compilable after " + i + " iterations, but must only after " + PER_METHOD_RECOMPILATION_CUTOFF); } - if (WHITE_BOX.isMethodCompilable(method)) { + if (isCompilable()) { throw new RuntimeException(method + " is still compilable after " + PER_METHOD_RECOMPILATION_CUTOFF + " iterations"); } @@ -109,7 +111,7 @@ // WB.clearMethodState() must reset no-compilable flags WHITE_BOX.clearMethodState(method); - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!isCompilable()) { throw new RuntimeException(method + " is not compilable after clearMethodState()"); } @@ -120,6 +122,6 @@ private void compileAndDeoptimize() throws Exception { compile(); waitBackgroundCompilation(); - WHITE_BOX.deoptimizeMethod(method); + deoptimize(); } } diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/MakeMethodNotCompilableTest.java --- a/test/compiler/whitebox/MakeMethodNotCompilableTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/MakeMethodNotCompilableTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,16 +23,16 @@ /* * @test MakeMethodNotCompilableTest - * @bug 8012322 + * @bug 8012322 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,TestCase$Helper::* MakeMethodNotCompilableTest + * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,TestCase$Helper::* MakeMethodNotCompilableTest * @summary testing of WB::makeMethodNotCompilable() * @author igor.ignatyev@oracle.com */ public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest { - + private int bci; public static void main(String[] args) throws Exception { if (args.length == 0) { for (TestCase test : TestCase.values()) { @@ -63,25 +63,27 @@ @Override protected void test() throws Exception { checkNotCompiled(); - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!isCompilable()) { throw new RuntimeException(method + " must be compilable"); } + bci = getBci(); + if (TIERED_COMPILATION) { final int tierLimit = TIERED_STOP_AT_LEVEL + 1; for (int testedTier = 1; testedTier < tierLimit; ++testedTier) { testTier(testedTier); } for (int testedTier = 1; testedTier < tierLimit; ++testedTier) { - WHITE_BOX.makeMethodNotCompilable(method, testedTier); - if (WHITE_BOX.isMethodCompilable(method, testedTier)) { + makeNotCompilable(testedTier); + if (isCompilable(testedTier)) { throw new RuntimeException(method + " must be not compilable at level" + testedTier); } - WHITE_BOX.enqueueMethodForCompilation(method, testedTier); + WHITE_BOX.enqueueMethodForCompilation(method, testedTier, bci); checkNotCompiled(); - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!isCompilable()) { System.out.println(method + " is not compilable after level " + testedTier); } @@ -89,15 +91,20 @@ } else { compile(); checkCompiled(); - int compLevel = WHITE_BOX.getMethodCompilationLevel(method); - WHITE_BOX.deoptimizeMethod(method); - WHITE_BOX.makeMethodNotCompilable(method, compLevel); - if (WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { + int compLevel = getCompLevel(); + deoptimize(); + makeNotCompilable(compLevel); + if (isCompilable(COMP_LEVEL_ANY)) { throw new RuntimeException(method + " must be not compilable at CompLevel::CompLevel_any," + " after it is not compilable at " + compLevel); } + WHITE_BOX.clearMethodState(method); + if (!isCompilable()) { + throw new RuntimeException(method + + " is not compilable after clearMethodState()"); + } // nocompilable at opposite level must make no sense int oppositeLevel; @@ -106,16 +113,16 @@ } else { oppositeLevel = COMP_LEVEL_SIMPLE; } - WHITE_BOX.makeMethodNotCompilable(method, oppositeLevel); + makeNotCompilable(oppositeLevel); - if (!WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { + if (!isCompilable(COMP_LEVEL_ANY)) { throw new RuntimeException(method + " must be compilable at CompLevel::CompLevel_any," + " even it is not compilable at opposite level [" + compLevel + "]"); } - if (!WHITE_BOX.isMethodCompilable(method, compLevel)) { + if (!isCompilable(compLevel)) { throw new RuntimeException(method + " must be compilable at level " + compLevel + ", even it is not compilable at opposite level [" @@ -126,24 +133,24 @@ // clearing after tiered/non-tiered tests // WB.clearMethodState() must reset no-compilable flags WHITE_BOX.clearMethodState(method); - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!isCompilable()) { throw new RuntimeException(method + " is not compilable after clearMethodState()"); } - WHITE_BOX.makeMethodNotCompilable(method); - if (WHITE_BOX.isMethodCompilable(method)) { + makeNotCompilable(); + if (isCompilable()) { throw new RuntimeException(method + " must be not compilable"); } compile(); checkNotCompiled(); - if (WHITE_BOX.isMethodCompilable(method)) { + if (isCompilable()) { throw new RuntimeException(method + " must be not compilable"); } // WB.clearMethodState() must reset no-compilable flags WHITE_BOX.clearMethodState(method); - if (!WHITE_BOX.isMethodCompilable(method)) { + if (!isCompilable()) { throw new RuntimeException(method + " is not compilable after clearMethodState()"); } @@ -153,24 +160,23 @@ // separately tests each tier private void testTier(int testedTier) { - if (!WHITE_BOX.isMethodCompilable(method, testedTier)) { + if (!isCompilable(testedTier)) { throw new RuntimeException(method + " is not compilable on start"); } - WHITE_BOX.makeMethodNotCompilable(method, testedTier); + makeNotCompilable(testedTier); // tests for all other tiers for (int anotherTier = 1, tierLimit = TIERED_STOP_AT_LEVEL + 1; anotherTier < tierLimit; ++anotherTier) { - boolean isCompilable = WHITE_BOX.isMethodCompilable(method, - anotherTier); + boolean isCompilable = isCompilable(anotherTier); if (sameCompile(testedTier, anotherTier)) { if (isCompilable) { throw new RuntimeException(method + " must be not compilable at level " + anotherTier + ", if it is not compilable at " + testedTier); } - WHITE_BOX.enqueueMethodForCompilation(method, anotherTier); + WHITE_BOX.enqueueMethodForCompilation(method, anotherTier, bci); checkNotCompiled(); } else { if (!isCompilable) { @@ -179,12 +185,12 @@ + ", even if it is not compilable at " + testedTier); } - WHITE_BOX.enqueueMethodForCompilation(method, anotherTier); + WHITE_BOX.enqueueMethodForCompilation(method, anotherTier, bci); checkCompiled(); - WHITE_BOX.deoptimizeMethod(method); + deoptimize(); } - if (!WHITE_BOX.isMethodCompilable(method, COMP_LEVEL_ANY)) { + if (!isCompilable(COMP_LEVEL_ANY)) { throw new RuntimeException(method + " must be compilable at 'CompLevel::CompLevel_any'" + ", if it is not compilable only at " + testedTier); @@ -193,7 +199,7 @@ // clear state after test WHITE_BOX.clearMethodState(method); - if (!WHITE_BOX.isMethodCompilable(method, testedTier)) { + if (!isCompilable(testedTier)) { throw new RuntimeException(method + " is not compilable after clearMethodState()"); } @@ -211,4 +217,13 @@ } return false; } + + private int getBci() { + compile(); + checkCompiled(); + int result = WHITE_BOX.getMethodEntryBci(method); + deoptimize(); + WHITE_BOX.clearMethodState(method); + return result; + } } diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/SetDontInlineMethodTest.java --- a/test/compiler/whitebox/SetDontInlineMethodTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/SetDontInlineMethodTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,6 +23,7 @@ /* * @test SetDontInlineMethodTest + * @bug 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build SetDontInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff -r 6c72125a2f40 -r f99558245e5c test/compiler/whitebox/SetForceInlineMethodTest.java --- a/test/compiler/whitebox/SetForceInlineMethodTest.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/compiler/whitebox/SetForceInlineMethodTest.java Wed Aug 14 23:50:23 2013 +0400 @@ -23,6 +23,7 @@ /* * @test SetForceInlineMethodTest + * @bug 8006683 8007288 8022832 * @library /testlibrary /testlibrary/whitebox * @build SetForceInlineMethodTest * @run main ClassFileInstaller sun.hotspot.WhiteBox diff -r 6c72125a2f40 -r f99558245e5c test/testlibrary/whitebox/sun/hotspot/WhiteBox.java --- a/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Fri Aug 16 17:34:37 2013 +0400 +++ b/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java Wed Aug 14 23:50:23 2013 +0400 @@ -93,23 +93,45 @@ // Compiler public native void deoptimizeAll(); - public native boolean isMethodCompiled(Executable method); - public boolean isMethodCompilable(Executable method) { - return isMethodCompilable(method, -1 /*any*/); + public boolean isMethodCompiled(Executable method) { + return isMethodCompiled(method, false /*not osr*/); } - public native boolean isMethodCompilable(Executable method, int compLevel); + public native boolean isMethodCompiled(Executable method, boolean isOsr); + public boolean isMethodCompilable(Executable method) { + return isMethodCompilable(method, -1 /*any*/); + } + public boolean isMethodCompilable(Executable method, int compLevel) { + return isMethodCompilable(method, compLevel, false /*not osr*/); + } + public native boolean isMethodCompilable(Executable method, int compLevel, boolean isOsr); public native boolean isMethodQueuedForCompilation(Executable method); - public native int deoptimizeMethod(Executable method); - public void makeMethodNotCompilable(Executable method) { - makeMethodNotCompilable(method, -1 /*any*/); + public int deoptimizeMethod(Executable method) { + return deoptimizeMethod(method, false /*not osr*/); + } + public native int deoptimizeMethod(Executable method, boolean isOsr); + public void makeMethodNotCompilable(Executable method) { + makeMethodNotCompilable(method, -1 /*any*/); + } + public void makeMethodNotCompilable(Executable method, int compLevel) { + makeMethodNotCompilable(method, compLevel, false /*not osr*/); + } + public native void makeMethodNotCompilable(Executable method, int compLevel, boolean isOsr); + public int getMethodCompilationLevel(Executable method) { + return getMethodCompilationLevel(method, false /*not ost*/); } - public native void makeMethodNotCompilable(Executable method, int compLevel); - public native int getMethodCompilationLevel(Executable method); + public native int getMethodCompilationLevel(Executable method, boolean isOsr); public native boolean testSetDontInlineMethod(Executable method, boolean value); - public native int getCompileQueuesSize(); + public int getCompileQueuesSize() { + return getCompileQueueSize(-1 /*any*/); + } + public native int getCompileQueueSize(int compLevel); public native boolean testSetForceInlineMethod(Executable method, boolean value); - public native boolean enqueueMethodForCompilation(Executable method, int compLevel); + public boolean enqueueMethodForCompilation(Executable method, int compLevel) { + return enqueueMethodForCompilation(method, compLevel, -1 /*InvocationEntryBci*/); + } + public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci); public native void clearMethodState(Executable method); + public native int getMethodEntryBci(Executable method); // Intered strings public native boolean isInStringTable(String str);