# HG changeset patch # User iignatyev # Date 1426171613 -10800 # Thu Mar 12 17:46:53 2015 +0300 # Node ID a3d605fa0ad004798c9268e69a40c315f65e635e # Parent de7ca28f8b7d6a913967a002b4458d3bdb768a53 8074980: add WhiteBox API to get a flag value for a method Reviewed-by: diff --git a/src/share/vm/prims/whitebox.cpp b/src/share/vm/prims/whitebox.cpp --- a/src/share/vm/prims/whitebox.cpp +++ b/src/share/vm/prims/whitebox.cpp @@ -1133,6 +1133,75 @@ VMThread::execute(&force_safepoint_op); WB_END +template +static bool GetMethodOption(JavaThread* thread, JNIEnv* env, jobject method, jstring name, T* value) { + assert(value != NULL, "sanity"); + if (method == NULL || name == NULL) { + return false; + } + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION_(env, false); + methodHandle mh(thread, Method::checked_resolve_jmethod_id(jmid)); + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + const char* flag_name = env->GetStringUTFChars(name, NULL); + bool result = CompilerOracle::has_option_value(mh, flag_name, *value); + env->ReleaseStringUTFChars(name, flag_name); + return result; +} + +WB_ENTRY(jobject, WB_GetMethodBooleaneOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + bool result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return booleanBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodIntxOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + intx result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return longBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodUintxOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + uintx result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return longBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodDoubleOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + double result; + if (GetMethodOption (thread, env, method, name, &result)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + return doubleBox(thread, env, result); + } + return NULL; +WB_END + +WB_ENTRY(jobject, WB_GetMethodStringOption(JNIEnv* env, jobject wb, jobject method, jstring name)) + ccstr ccstrResult; + if (GetMethodOption (thread, env, method, name, &ccstrResult)) { + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + jstring result = env->NewStringUTF(ccstrResult); + CHECK_JNI_EXCEPTION_(env, NULL); + return result; + } + return NULL; +WB_END + //Some convenience methods to deal with objects from java int WhiteBox::offset_for_field(const char* field_name, oop object, Symbol* signature_symbol) { @@ -1333,6 +1402,21 @@ {CC"assertMatchingSafepointCalls", CC"(ZZ)V", (void*)&WB_AssertMatchingSafepointCalls }, {CC"isMonitorInflated", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, {CC"forceSafepoint", CC"()V", (void*)&WB_ForceSafepoint }, + {CC"getMethodBooleanOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Boolean;", + (void*)&WB_GetMethodBooleaneOption}, + {CC"getMethodIntxOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetMethodIntxOption}, + {CC"getMethodUintxOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Long;", + (void*)&WB_GetMethodUintxOption}, + {CC"getMethodDoubleOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/Double;", + (void*)&WB_GetMethodDoubleOption}, + {CC"getMethodStringOption", + CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;", + (void*)&WB_GetMethodStringOption}, }; #undef CC diff --git a/test/compiler/oracle/GetMethodOptionTest.java b/test/compiler/oracle/GetMethodOptionTest.java new file mode 100644 --- /dev/null +++ b/test/compiler/oracle/GetMethodOptionTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 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 java.lang.reflect.Executable; +import java.util.function.BiFunction; + +import com.oracle.java.testlibrary.Asserts; +import sun.hotspot.WhiteBox; + +/* + * @test + * @bug 8074980 + * @library /testlibrary /../../test/lib + * @build sun.hotspot.WhiteBox com.oracle.java.testlibrary.Asserts GetMethodOptionTest + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=option,GetMethodOptionTest::test,ccstrlist,MyListOption,_foo,_bar + * -XX:CompileCommand=option,GetMethodOptionTest::test,ccstr,MyStrOption,_foo + * -XX:CompileCommand=option,GetMethodOptionTest::test,bool,MyBoolOption,false + * -XX:CompileCommand=option,GetMethodOptionTest::test,intx,MyIntxOption,-1 + * -XX:CompileCommand=option,GetMethodOptionTest::test,uintx,MyUintxOption,1 + * -XX:CompileCommand=option,GetMethodOptionTest::test,MyFlag + * -XX:CompileCommand=option,GetMethodOptionTest::test,double,MyDoubleOption1,1.123 + * -XX:CompileCommand=option,GetMethodOptionTest.test,double,MyDoubleOption2,1.123 + * -XX:CompileCommand=option,GetMethodOptionTest::test,bool,MyBoolOptionX,false,intx,MyIntxOptionX,-1,uintx,MyUintxOptionX,1,MyFlagX,double,MyDoubleOptionX,1.123 + * GetMethodOptionTest + */ + +public class GetMethodOptionTest { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + public static void main(String[] args) { + Executable test = getMethod("test"); + Executable test2 = getMethod("test2"); + BiFunction getter = WB::getMethodOption; + for (TestCase testCase : TestCase.values()) { + Object expected = testCase.value; + String name = testCase.name(); + Asserts.assertEQ(expected, getter.apply(test, name), + testCase + ": universal getter returns wrong value"); + Asserts.assertEQ(expected, testCase.getter.apply(test, name), + testCase + ": specific getter returns wrong value"); + Asserts.assertEQ(null, getter.apply(test2, name), + testCase + ": universal getter returns value for unused method"); + Asserts.assertEQ(null, testCase.getter.apply(test2, name), + testCase + ": type specific getter returns value for unused method"); + } + } + private static void test() { } + private static void test2() { } + + private static enum TestCase { + MyListOption("_foo _bar", WB::getMethodStringOption), + MyStrOption("_foo", WB::getMethodStringOption), + MyBoolOption(false, WB::getMethodBooleanOption), + MyIntxOption(-1L, WB::getMethodIntxOption), + MyUintxOption(1L, WB::getMethodUintxOption), + MyFlag(true, WB::getMethodBooleanOption), + MyDoubleOption1(1.123d, WB::getMethodDoubleOption), + MyDoubleOption2(1.123d, WB::getMethodDoubleOption), + MyBoolOptionX(false, WB::getMethodBooleanOption), + MyIntxOptionX(-1L, WB::getMethodIntxOption), + MyUintxOptionX(1L, WB::getMethodUintxOption), + MyFlagX(true, WB::getMethodBooleanOption), + MyDoubleOptionX(1.123d, WB::getMethodDoubleOption); + + public final Object value; + public final BiFunction getter; + private TestCase(Object value, BiFunction getter) { + this.value = value; + this.getter = getter; + } + } + + private static Executable getMethod(String name) { + Executable result; + try { + result = GetMethodOptionTest.class.getDeclaredMethod(name); + } catch (NoSuchMethodException | SecurityException e) { + throw new Error("TESTBUG : can't get method " + name, e); + } + return result; + } +}