8061443: Whitebox get*VMFlag() methods fail with develop flags in product builds
authorthartmann
Fri, 24 Oct 2014 08:22:33 +0200
changeset 27417 576e2b527e1c
parent 27416 862162c5a8e0
child 27418 a13fdcbaa345
8061443: Whitebox get*VMFlag() methods fail with develop flags in product builds Summary: Changed 'get*VMFlag' to return all flags. Added methods 'isLockedVMFlag' and 'isConstantVMFlag' and adapted tests. Reviewed-by: kvn, dholmes, sla
hotspot/src/share/vm/prims/whitebox.cpp
hotspot/src/share/vm/runtime/globals.cpp
hotspot/src/share/vm/runtime/globals.hpp
hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java
hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java
hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java
hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java
hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java
--- a/hotspot/src/share/vm/prims/whitebox.cpp	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/src/share/vm/prims/whitebox.cpp	Fri Oct 24 08:22:33 2014 +0200
@@ -566,13 +566,13 @@
 WB_END
 
 template <typename T>
-static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*)) {
+static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*, bool, bool)) {
   if (name == NULL) {
     return false;
   }
   ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
   const char* flag_name = env->GetStringUTFChars(name, NULL);
-  bool result = (*TAt)(flag_name, value);
+  bool result = (*TAt)(flag_name, value, true, true);
   env->ReleaseStringUTFChars(name, flag_name);
   return result;
 }
@@ -619,6 +619,24 @@
   return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
 }
 
+static Flag* getVMFlag(JavaThread* thread, JNIEnv* env, jstring name) {
+  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+  const char* flag_name = env->GetStringUTFChars(name, NULL);
+  Flag* result = Flag::find_flag(flag_name, strlen(flag_name), true, true);
+  env->ReleaseStringUTFChars(name, flag_name);
+  return result;
+}
+
+WB_ENTRY(jboolean, WB_IsConstantVMFlag(JNIEnv* env, jobject o, jstring name))
+  Flag* flag = getVMFlag(thread, env, name);
+  return (flag != NULL) && flag->is_constant_in_binary();
+WB_END
+
+WB_ENTRY(jboolean, WB_IsLockedVMFlag(JNIEnv* env, jobject o, jstring name))
+  Flag* flag = getVMFlag(thread, env, name);
+  return (flag != NULL) && !(flag->is_unlocked() || flag->is_unlocker());
+WB_END
+
 WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
   bool result;
   if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
@@ -1018,6 +1036,8 @@
       CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
   {CC"clearMethodState",
       CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
+  {CC"isConstantVMFlag",   CC"(Ljava/lang/String;)Z", (void*)&WB_IsConstantVMFlag},
+  {CC"isLockedVMFlag",     CC"(Ljava/lang/String;)Z", (void*)&WB_IsLockedVMFlag},
   {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
   {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
   {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
--- a/hotspot/src/share/vm/runtime/globals.cpp	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/src/share/vm/runtime/globals.cpp	Fri Oct 24 08:22:33 2014 +0200
@@ -634,8 +634,8 @@
   e.commit();
 }
 
-bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_bool()) return false;
   *value = result->get_bool();
@@ -662,8 +662,8 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_intx()) return false;
   *value = result->get_intx();
@@ -690,8 +690,8 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_uintx()) return false;
   *value = result->get_uintx();
@@ -718,8 +718,8 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_uint64_t()) return false;
   *value = result->get_uint64_t();
@@ -746,8 +746,8 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_size_t()) return false;
   *value = result->get_size_t();
@@ -774,8 +774,8 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_double()) return false;
   *value = result->get_double();
@@ -802,8 +802,8 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value) {
-  Flag* result = Flag::find_flag(name, len);
+bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked, bool return_flag) {
+  Flag* result = Flag::find_flag(name, len, allow_locked, return_flag);
   if (result == NULL) return false;
   if (!result->is_ccstr()) return false;
   *value = result->get_ccstr();
--- a/hotspot/src/share/vm/runtime/globals.hpp	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/src/share/vm/runtime/globals.hpp	Fri Oct 24 08:22:33 2014 +0200
@@ -379,38 +379,38 @@
 
 class CommandLineFlags {
  public:
-  static bool boolAt(const char* name, size_t len, bool* value);
-  static bool boolAt(const char* name, bool* value)      { return boolAt(name, strlen(name), value); }
+  static bool boolAt(const char* name, size_t len, bool* value, bool allow_locked = false, bool return_flag = false);
+  static bool boolAt(const char* name, bool* value, bool allow_locked = false, bool return_flag = false)      { return boolAt(name, strlen(name), value, allow_locked, return_flag); }
   static bool boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin);
   static bool boolAtPut(const char* name, bool* value, Flag::Flags origin)   { return boolAtPut(name, strlen(name), value, origin); }
 
-  static bool intxAt(const char* name, size_t len, intx* value);
-  static bool intxAt(const char* name, intx* value)      { return intxAt(name, strlen(name), value); }
+  static bool intxAt(const char* name, size_t len, intx* value, bool allow_locked = false, bool return_flag = false);
+  static bool intxAt(const char* name, intx* value, bool allow_locked = false, bool return_flag = false)      { return intxAt(name, strlen(name), value, allow_locked, return_flag); }
   static bool intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin);
   static bool intxAtPut(const char* name, intx* value, Flag::Flags origin)   { return intxAtPut(name, strlen(name), value, origin); }
 
-  static bool uintxAt(const char* name, size_t len, uintx* value);
-  static bool uintxAt(const char* name, uintx* value)    { return uintxAt(name, strlen(name), value); }
+  static bool uintxAt(const char* name, size_t len, uintx* value, bool allow_locked = false, bool return_flag = false);
+  static bool uintxAt(const char* name, uintx* value, bool allow_locked = false, bool return_flag = false)    { return uintxAt(name, strlen(name), value, allow_locked, return_flag); }
   static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
   static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
 
-  static bool size_tAt(const char* name, size_t len, size_t* value);
-  static bool size_tAt(const char* name, size_t* value)    { return size_tAt(name, strlen(name), value); }
+  static bool size_tAt(const char* name, size_t len, size_t* value, bool allow_locked = false, bool return_flag = false);
+  static bool size_tAt(const char* name, size_t* value, bool allow_locked = false, bool return_flag = false)    { return size_tAt(name, strlen(name), value, allow_locked, return_flag); }
   static bool size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin);
   static bool size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
 
-  static bool uint64_tAt(const char* name, size_t len, uint64_t* value);
-  static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
+  static bool uint64_tAt(const char* name, size_t len, uint64_t* value, bool allow_locked = false, bool return_flag = false);
+  static bool uint64_tAt(const char* name, uint64_t* value, bool allow_locked = false, bool return_flag = false) { return uint64_tAt(name, strlen(name), value, allow_locked, return_flag); }
   static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
   static bool uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
 
-  static bool doubleAt(const char* name, size_t len, double* value);
-  static bool doubleAt(const char* name, double* value)    { return doubleAt(name, strlen(name), value); }
+  static bool doubleAt(const char* name, size_t len, double* value, bool allow_locked = false, bool return_flag = false);
+  static bool doubleAt(const char* name, double* value, bool allow_locked = false, bool return_flag = false)    { return doubleAt(name, strlen(name), value, allow_locked, return_flag); }
   static bool doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin);
   static bool doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
 
-  static bool ccstrAt(const char* name, size_t len, ccstr* value);
-  static bool ccstrAt(const char* name, ccstr* value)    { return ccstrAt(name, strlen(name), value); }
+  static bool ccstrAt(const char* name, size_t len, ccstr* value, bool allow_locked = false, bool return_flag = false);
+  static bool ccstrAt(const char* name, ccstr* value, bool allow_locked = false, bool return_flag = false)    { return ccstrAt(name, strlen(name), value, allow_locked, return_flag); }
   // Contract:  Flag will make private copy of the incoming value.
   // Outgoing value is always malloc-ed, and caller MUST call free.
   static bool ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin);
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java	Fri Oct 24 08:22:33 2014 +0200
@@ -179,6 +179,8 @@
   public native void printRegionInfo(int context);
 
   // VM flags
+  public native boolean isConstantVMFlag(String name);
+  public native boolean isLockedVMFlag(String name);
   public native void    setBooleanVMFlag(String name, boolean value);
   public native void    setIntxVMFlag(String name, long value);
   public native void    setUintxVMFlag(String name, long value);
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java	Fri Oct 24 08:22:33 2014 +0200
@@ -43,6 +43,7 @@
     private static final Boolean[] TESTS = {true, false, true, true, false};
     private static final String TEST_NAME = "BooleanTest";
     private static final String FLAG_NAME = "PrintCompilation";
+    private static final String FLAG_DEBUG_NAME = "SafepointALot";
     private static final String METHOD = TEST_NAME + "::method";
     private static final String METHOD1 = METHOD + "1";
     private static final String METHOD2 = METHOD + "2";
@@ -54,6 +55,7 @@
                 VmFlagTest.WHITE_BOX::getBooleanVMFlag);
             testFunctional(false);
             testFunctional(true);
+            VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getBooleanVMFlag);
         } else {
             boolean value = Boolean.valueOf(args[0]);
             method1();
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java	Fri Oct 24 08:22:33 2014 +0200
@@ -35,6 +35,7 @@
 
 public class IntxTest {
     private static final String FLAG_NAME = "OnStackReplacePercentage";
+    private static final String FLAG_DEBUG_NAME = "InlineFrequencyCount";
     private static final Long[] TESTS = {0L, 100L, -1L,
             (long) Integer.MAX_VALUE, (long) Integer.MIN_VALUE};
 
@@ -42,6 +43,7 @@
         VmFlagTest.runTest(FLAG_NAME, TESTS,
             VmFlagTest.WHITE_BOX::setIntxVMFlag,
             VmFlagTest.WHITE_BOX::getIntxVMFlag);
+        VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getIntxVMFlag);
     }
 }
 
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java	Fri Oct 24 08:22:33 2014 +0200
@@ -35,12 +35,14 @@
 
 public class StringTest {
     private static final String FLAG_NAME = "CompileOnly";
+    private static final String FLAG_DEBUG_NAME = "SuppressErrorAt";
     private static final String[] TESTS = {"StringTest::*", ""};
 
     public static void main(String[] args) throws Exception {
         VmFlagTest.runTest(FLAG_NAME, TESTS,
             VmFlagTest.WHITE_BOX::setStringVMFlag,
             VmFlagTest.WHITE_BOX::getStringVMFlag);
+        VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getStringVMFlag);
     }
 }
 
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java	Fri Oct 24 08:22:33 2014 +0200
@@ -36,6 +36,7 @@
 
 public class UintxTest {
     private static final String FLAG_NAME = "VerifyGCStartAt";
+    private static final String FLAG_DEBUG_NAME = "CodeCacheMinimumUseSpace";
     private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
         (1L << 32L) - 1L, 1L << 32L};
     private static final Long[] EXPECTED_64 = TESTS;
@@ -47,6 +48,7 @@
             Platform.is64bit() ? EXPECTED_64 : EXPECTED_32,
             VmFlagTest.WHITE_BOX::setUintxVMFlag,
             VmFlagTest.WHITE_BOX::getUintxVMFlag);
+        VmFlagTest.runTest(FLAG_DEBUG_NAME, VmFlagTest.WHITE_BOX::getUintxVMFlag);
     }
 }
 
--- a/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java	Thu Oct 23 09:41:59 2014 -1000
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java	Fri Oct 24 08:22:33 2014 +0200
@@ -37,16 +37,18 @@
     private final BiConsumer<T, T> test;
     private final BiConsumer<String, T> set;
     private final Function<String, T> get;
+    private final boolean isPositive;
 
     protected VmFlagTest(String flagName, BiConsumer<String, T> set,
             Function<String, T> get, boolean isPositive) {
         this.flagName = flagName;
         this.set = set;
         this.get = get;
+        this.isPositive = isPositive;
         if (isPositive) {
-            test = this::testPositive;
+            test = this::testWritePositive;
         } else {
-            test = this::testNegative;
+            test = this::testWriteNegative;
         }
     }
 
@@ -63,6 +65,10 @@
         runTest(existentFlag, tests, tests, set, get);
     }
 
+    protected static <T> void runTest(String existentFlag, Function<String, T> get) {
+        runTest(existentFlag, null, null, null, get);
+    }
+
     protected static <T> void runTest(String existentFlag, T[] tests,
             T[] results, BiConsumer<String, T> set, Function<String, T> get) {
         if (existentFlag != null) {
@@ -72,13 +78,23 @@
     }
 
     public final void test(T[] tests, T[] results) {
-        Asserts.assertEQ(tests.length, results.length, "[TESTBUG] tests.length != results.length");
-        for (int i = 0, n = tests.length ; i < n; ++i) {
-            test.accept(tests[i], results[i]);
+        if (isPositive) {
+            testRead();
+        }
+        if (tests != null) {
+            Asserts.assertEQ(tests.length, results.length, "[TESTBUG] tests.length != results.length");
+            for (int i = 0, n = tests.length ; i < n; ++i) {
+                test.accept(tests[i], results[i]);
+            }
         }
     }
 
     protected String getVMOptionAsString() {
+        if (WHITE_BOX.isConstantVMFlag(flagName) || WHITE_BOX.isLockedVMFlag(flagName)) {
+          // JMM cannot access debug flags in product builds or locked flags,
+          // use whitebox methods to get such flags value.
+          return asString(getValue());
+        }
         HotSpotDiagnosticMXBean diagnostic
                 = ManagementFactoryHelper.getDiagnosticMXBean();
         VMOption tmp;
@@ -90,18 +106,24 @@
         return tmp == null ? null : tmp.getValue();
     }
 
-    private void testPositive(T value, T expected) {
-        String oldValue = getVMOptionAsString();
-        Asserts.assertEQ(oldValue, asString(getValue()));
-        Asserts.assertEQ(oldValue, asString(WHITE_BOX.getVMFlag(flagName)));
-        setNewValue(value);
-        String newValue = getVMOptionAsString();
-        Asserts.assertEQ(newValue, asString(expected));
-        Asserts.assertEQ(newValue, asString(getValue()));
-        Asserts.assertEQ(newValue, asString(WHITE_BOX.getVMFlag(flagName)));
+    private String testRead() {
+        String value = getVMOptionAsString();
+        Asserts.assertNotNull(value);
+        Asserts.assertEQ(value, asString(getValue()));
+        Asserts.assertEQ(value, asString(WHITE_BOX.getVMFlag(flagName)));
+        return value;
     }
 
-    private void testNegative(T value, T expected) {
+    private void testWritePositive(T value, T expected) {
+        setNewValue(value);
+        String newValue = testRead();
+        Asserts.assertEQ(newValue, asString(expected));
+    }
+
+    private void testWriteNegative(T value, T expected) {
+        // Should always return false for non-existing flags
+        Asserts.assertFalse(WHITE_BOX.isConstantVMFlag(flagName));
+        Asserts.assertFalse(WHITE_BOX.isLockedVMFlag(flagName));
         String oldValue = getVMOptionAsString();
         Asserts.assertEQ(oldValue, asString(getValue()));
         Asserts.assertEQ(oldValue, asString(WHITE_BOX.getVMFlag(flagName)));
@@ -114,4 +136,3 @@
         return value == null ? null : "" + value;
     }
 }
-