8021775: compiler/8009761/Test8009761.java "Failed: init recursive calls: 51. After deopt 50"
authorthartmann
Fri, 30 May 2014 09:26:48 +0200
changeset 24919 080f9a6da70a
parent 24678 9bb217f7f313
child 24920 3748d954e5fe
8021775: compiler/8009761/Test8009761.java "Failed: init recursive calls: 51. After deopt 50" Summary: Reimplemented the test using the Whitebox API to deterministically trigger compilation and deoptimization. Now allowing number of recursive calls to vary by 1. Reviewed-by: twisti, roland, iignatyev
hotspot/test/TEST.groups
hotspot/test/compiler/8009761/Test8009761.java
--- a/hotspot/test/TEST.groups	Thu May 29 09:41:07 2014 +0000
+++ b/hotspot/test/TEST.groups	Fri May 30 09:26:48 2014 +0200
@@ -115,6 +115,7 @@
 # Tests that require compact3 API's
 #
 needs_compact3 = \
+  compiler/8009761/Test8009761.java \
   compiler/whitebox/DeoptimizeMethodTest.java \
   compiler/whitebox/SetForceInlineMethodTest.java \
   compiler/whitebox/SetDontInlineMethodTest.java \
--- a/hotspot/test/compiler/8009761/Test8009761.java	Thu May 29 09:41:07 2014 +0000
+++ b/hotspot/test/compiler/8009761/Test8009761.java	Fri May 30 09:26:48 2014 +0200
@@ -21,19 +21,27 @@
  * questions.
  */
 
+import com.sun.management.HotSpotDiagnosticMXBean;
+import com.sun.management.VMOption;
+import sun.hotspot.WhiteBox;
+import sun.management.ManagementFactoryHelper;
+
+import java.lang.reflect.Method;
+
 /*
  * @test
  * @bug 8009761
+ * @library /testlibrary /testlibrary/whitebox
  * @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates
- * @run main/othervm -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761
- *
+ * @build Test8009761
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761
  */
-
 public class Test8009761 {
 
-    static class UnloadedClass {
-        volatile int i;
-    }
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+    private static Method m3 = null;
 
     static Object m1(boolean deopt) {
         // When running interpreted, on sparc, the caller's stack is
@@ -142,9 +150,11 @@
         ll508, ll509, ll510, ll511;
 
         if (deopt) {
-            UnloadedClass res = new UnloadedClass(); // sufficient to force deopt with c2 but not c1
-            res.i = 0; // forces deopt with c1
-            return res;
+            // Force deoptimization of m3
+            WHITE_BOX.deoptimizeMethod(m3);
+            if(WHITE_BOX.isMethodCompiled(m3)) {
+                throw new RuntimeException(m3 + " not deoptimized");
+            }
         }
         return null;
     }
@@ -225,6 +235,18 @@
     }
 
     static public void main(String[] args) {
+        // Make sure background compilation is disabled
+        if (backgroundCompilationEnabled()) {
+            throw new RuntimeException("Background compilation enabled");
+        }
+
+        try {
+            // Get Method object for m3
+            m3 = Test8009761.class.getDeclaredMethod("m3", boolean.class, boolean.class);
+        } catch (NoSuchMethodException | SecurityException ex) {
+            throw new RuntimeException("Failed to retrieve method m3");
+        }
+
         int c1;
         // Call m2 from m3 recursively until stack overflow. Count the number of recursive calls.
         try {
@@ -232,10 +254,14 @@
         } catch(StackOverflowError soe) {
         }
         c1 = count;
+
         // Force the compilation of m3() that will inline m1()
-        for (int i = 0; i < 20000; i++) {
-            m3(false, false);
+        WHITE_BOX.enqueueMethodForCompilation(m3, COMP_LEVEL_FULL_OPTIMIZATION);
+        // Because background compilation is disabled, method should now be compiled
+        if(!WHITE_BOX.isMethodCompiled(m3)) {
+            throw new RuntimeException(m3 + " not compiled");
         }
+
         count = 0;
         // Force deoptimization of m3() in m1(), then return from m1()
         // to m3(), call recursively m2(). If deoptimization correctly
@@ -245,11 +271,26 @@
             m3(false, true);
         } catch(StackOverflowError soe) {
         }
-        if (c1 != count) {
-            System.out.println("Failed: init recursive calls: " + c1 + ". After deopt " + count);
-            System.exit(97);
+        // Allow number of recursive calls to vary by 1
+        if ((c1 < (count - 1)) || (c1 > (count + 1))) {
+            throw new RuntimeException("Failed: init recursive calls: " + c1 + ". After deopt " + count);
         } else {
             System.out.println("PASSED " + c1);
         }
     }
+
+    /**
+     * Checks if background compilation (-XX:+BackgroundCompilation) is enabled.
+     * @return True if background compilation is enabled, false otherwise
+     */
+    private static boolean backgroundCompilationEnabled() {
+      HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean();
+      VMOption backgroundCompilation;
+      try {
+          backgroundCompilation = diagnostic.getVMOption("BackgroundCompilation");
+      } catch (IllegalArgumentException e) {
+          return false;
+      }
+      return Boolean.valueOf(backgroundCompilation.getValue());
+    }
 }