changeset 34:76567c910f2a

Support online deoptimization via WhiteBox API.
author shade
date Fri, 02 Aug 2013 02:26:51 +0400
parents 949417683eb0
children 7a152ea0e16a
files harness/src/main/java/org/openjdk/jcstress/ForkedMain.java harness/src/main/java/org/openjdk/jcstress/Main.java harness/src/main/java/org/openjdk/jcstress/Options.java harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor1_Runner.java harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor2_Arbiter1_Runner.java harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor2_Runner.java harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor3_Runner.java harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor4_Runner.java harness/src/main/java/org/openjdk/jcstress/infra/runners/Runner.java harness/src/main/java/org/openjdk/jcstress/infra/runners/TerminationRunner.java harness/src/main/java/org/openjdk/jcstress/util/VMSupport.java harness/src/main/java/sun/hotspot/WhiteBox.java harness/src/main/java/sun/hotspot/parser/DiagnosticCommand.java
diffstat 13 files changed, 294 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/harness/src/main/java/org/openjdk/jcstress/ForkedMain.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/ForkedMain.java	Fri Aug 02 02:26:51 2013 +0400
@@ -25,6 +25,7 @@
 package org.openjdk.jcstress;
 
 import org.openjdk.jcstress.infra.collectors.NetworkOutputCollector;
+import org.openjdk.jcstress.util.VMSupport;
 
 /**
  * Entry point for the forked VM run.
@@ -39,6 +40,8 @@
             System.exit(1);
         }
 
+        VMSupport.tryInit();
+
         NetworkOutputCollector collector = new NetworkOutputCollector(opts.getHostName(), opts.getHostPort());
         new JCStress().run(opts, true, collector);
         collector.close();
--- a/harness/src/main/java/org/openjdk/jcstress/Main.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/Main.java	Fri Aug 02 02:26:51 2013 +0400
@@ -25,6 +25,7 @@
 package org.openjdk.jcstress;
 
 import org.openjdk.jcstress.tests.ConcurrencyTest;
+import org.openjdk.jcstress.util.VMSupport;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -56,6 +57,15 @@
                 System.out.println(test.getName());
             }
         } else {
+            if (!VMSupport.tryInit()) {
+                System.out.println("Non-fatal: VM support is not enabled. Possible reasons are:\n" +
+                        "  1) unsupported JDK, only JDK 8+ is supported; \n" +
+                        "  2) -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI VM options are missing; \n" +
+                        "  3) the jcstress JAR is not added to -Xbootclasspath/a\n");
+            } else {
+                System.out.println("VM support is initialized.\n");
+            }
+
             new JCStress().run(opts);
         }
     }
--- a/harness/src/main/java/org/openjdk/jcstress/Options.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/Options.java	Fri Aug 02 02:26:51 2013 +0400
@@ -300,6 +300,10 @@
         out.println();
     }
 
+    public int getDeoptEachIter() {
+        return 5;
+    }
+
     public static class BurningTask implements Runnable {
 
         @Override
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor1_Runner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor1_Runner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jcstress.tests.Actor1_Test;
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.util.Counters;
+import org.openjdk.jcstress.util.VMSupport;
 
 import javax.xml.bind.JAXBException;
 import java.io.FileNotFoundException;
@@ -74,6 +75,10 @@
 
         testLog.print("Iterations ");
         for (int c = 0; c < iters; c++) {
+            if (c % deoptEachIter == 0) {
+                VMSupport.tryDeoptimizeAll();
+            }
+
             testLog.print(".");
             testLog.flush();
             Counter<R> runResult = run(time);
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor2_Arbiter1_Runner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor2_Arbiter1_Runner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jcstress.tests.Actor2_Arbiter1_Test;
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.util.Counters;
+import org.openjdk.jcstress.util.VMSupport;
 
 import javax.xml.bind.JAXBException;
 import java.io.FileNotFoundException;
@@ -66,6 +67,10 @@
 
         testLog.print("Iterations ");
         for (int c = 0; c < iters; c++) {
+            if (c % deoptEachIter == 0) {
+                VMSupport.tryDeoptimizeAll();
+            }
+
             testLog.print(".");
             testLog.flush();
             Counter<R> runResult = run(time);
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor2_Runner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor2_Runner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jcstress.tests.Actor2_Test;
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.util.Counters;
+import org.openjdk.jcstress.util.VMSupport;
 
 import javax.xml.bind.JAXBException;
 import java.io.FileNotFoundException;
@@ -74,6 +75,10 @@
 
         testLog.print("Iterations ");
         for (int c = 0; c < iters; c++) {
+            if (c % deoptEachIter == 0) {
+                VMSupport.tryDeoptimizeAll();
+            }
+
             testLog.print(".");
             testLog.flush();
             Counter<R> runResult = run(time);
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor3_Runner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor3_Runner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jcstress.tests.Actor3_Test;
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.util.Counters;
+import org.openjdk.jcstress.util.VMSupport;
 
 import javax.xml.bind.JAXBException;
 import java.io.FileNotFoundException;
@@ -74,6 +75,10 @@
 
         testLog.print("Iterations ");
         for (int c = 0; c < iters; c++) {
+            if (c % deoptEachIter == 0) {
+                VMSupport.tryDeoptimizeAll();
+            }
+
             testLog.print(".");
             testLog.flush();
             Counter<R> runResult = run(time);
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor4_Runner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/Actor4_Runner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -30,6 +30,7 @@
 import org.openjdk.jcstress.tests.Actor4_Test;
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.util.Counters;
+import org.openjdk.jcstress.util.VMSupport;
 
 import javax.xml.bind.JAXBException;
 import java.io.FileNotFoundException;
@@ -74,6 +75,10 @@
 
         testLog.print("Iterations ");
         for (int c = 0; c < iters; c++) {
+            if (c % deoptEachIter == 0) {
+                VMSupport.tryDeoptimizeAll();
+            }
+
             testLog.print(".");
             testLog.flush();
             Counter<R> runResult = run(time);
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/Runner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/Runner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -52,6 +52,7 @@
     protected final int time;
     protected final int iters;
     protected final int minStride, maxStride;
+    protected final int deoptEachIter;
     protected final boolean verbose;
     protected final TestResultCollector collector;
     protected final ExecutorService pool;
@@ -71,6 +72,7 @@
         iters = opts.getIterations();
         shouldYield = opts.shouldYield();
         verbose = opts.isVerbose();
+        deoptEachIter = opts.getDeoptEachIter();
 
         if (verbose) {
             testLog = new PrintWriter(System.out, true);
--- a/harness/src/main/java/org/openjdk/jcstress/infra/runners/TerminationRunner.java	Fri Aug 02 00:38:08 2013 +0400
+++ b/harness/src/main/java/org/openjdk/jcstress/infra/runners/TerminationRunner.java	Fri Aug 02 02:26:51 2013 +0400
@@ -29,6 +29,7 @@
 import org.openjdk.jcstress.tests.TerminationTest;
 import org.openjdk.jcstress.util.Counter;
 import org.openjdk.jcstress.util.HashCounter;
+import org.openjdk.jcstress.util.VMSupport;
 
 import javax.xml.bind.JAXBException;
 import java.io.FileNotFoundException;
@@ -62,6 +63,10 @@
 
         testLog.print("Iterations ");
         for (int c = 0; c < iters; c++) {
+            if (c % deoptEachIter == 0) {
+                VMSupport.tryDeoptimizeAll();
+            }
+
             testLog.print(".");
             testLog.flush();
             run(time, results);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harness/src/main/java/org/openjdk/jcstress/util/VMSupport.java	Fri Aug 02 02:26:51 2013 +0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2005, 2013, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package org.openjdk.jcstress.util;
+
+import sun.hotspot.WhiteBox;
+
+public class VMSupport {
+
+    private static WhiteBox whiteBox;
+    private static volatile boolean inited;
+
+    public static boolean tryInit() {
+        if (inited) return true;
+        try {
+            WhiteBox w = WhiteBox.getWhiteBox();
+            w.deoptimizeAll();
+            whiteBox = w;
+            return true;
+        } catch (UnsatisfiedLinkError e) {
+            // expected
+            return false;
+        } finally {
+            inited = true;
+        }
+    }
+
+    public static void tryDeoptimizeAll() {
+        WhiteBox w = whiteBox;
+        if (w != null) {
+            w.deoptimizeAll();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harness/src/main/java/sun/hotspot/WhiteBox.java	Fri Aug 02 02:26:51 2013 +0400
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2005, 2013, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package sun.hotspot;
+
+import java.lang.reflect.Executable;
+import java.security.BasicPermission;
+import sun.hotspot.parser.DiagnosticCommand;
+
+public class WhiteBox {
+
+  @SuppressWarnings("serial")
+  public static class WhiteBoxPermission extends BasicPermission {
+    public WhiteBoxPermission(String s) {
+      super(s);
+    }
+  }
+
+  private WhiteBox() {}
+  private static final WhiteBox instance = new WhiteBox();
+  private static native void registerNatives();
+
+  /**
+   * Returns the singleton WhiteBox instance.
+   *
+   * The returned WhiteBox object should be carefully guarded
+   * by the caller, since it can be used to read and write data
+   * at arbitrary memory addresses. It must never be passed to
+   * untrusted code.
+   */
+  public synchronized static WhiteBox getWhiteBox() {
+    SecurityManager sm = System.getSecurityManager();
+    if (sm != null) {
+      sm.checkPermission(new WhiteBoxPermission("getInstance"));
+    }
+    return instance;
+  }
+
+  static {
+    registerNatives();
+  }
+
+  // Arguments
+  public native void printHeapSizes();
+
+  // Memory
+  public native long getObjectAddress(Object o);
+  public native int  getHeapOopSize();
+
+  // Runtime
+  // Make sure class name is in the correct format
+  public boolean isClassAlive(String name) {
+    return isClassAlive0(name.replace('.', '/'));
+  }
+  private native boolean isClassAlive0(String name);
+
+  // G1
+  public native boolean g1InConcurrentMark();
+  public native boolean g1IsHumongous(Object o);
+  public native long    g1NumFreeRegions();
+  public native int     g1RegionSize();
+  public native Object[]    parseCommandLine(String commandline, DiagnosticCommand[] args);
+
+  // NMT
+  public native long NMTMalloc(long size);
+  public native void NMTFree(long mem);
+  public native long NMTReserveMemory(long size);
+  public native void NMTCommitMemory(long addr, long size);
+  public native void NMTUncommitMemory(long addr, long size);
+  public native void NMTReleaseMemory(long addr, long size);
+  public native boolean NMTWaitForDataMerge();
+
+  // Compiler
+  public native void    deoptimizeAll();
+  public native boolean isMethodCompiled(Executable method);
+  public boolean isMethodCompilable(Executable method) {
+      return isMethodCompilable(method, -1 /*any*/);
+  }
+  public native boolean isMethodCompilable(Executable method, int compLevel);
+  public native boolean isMethodQueuedForCompilation(Executable method);
+  public native int     deoptimizeMethod(Executable method);
+  public void makeMethodNotCompilable(Executable method) {
+      makeMethodNotCompilable(method, -1 /*any*/);
+  }
+  public native void    makeMethodNotCompilable(Executable method, int compLevel);
+  public native int     getMethodCompilationLevel(Executable method);
+  public native boolean testSetDontInlineMethod(Executable method, boolean value);
+  public native int     getCompileQueuesSize();
+  public native boolean testSetForceInlineMethod(Executable method, boolean value);
+  public native boolean enqueueMethodForCompilation(Executable method, int compLevel);
+  public native void    clearMethodState(Executable method);
+
+  // Intered strings
+  public native boolean isInStringTable(String str);
+
+  // Memory
+  public native void readReservedMemory();
+
+  // force Full GC
+  public native void fullGC();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/harness/src/main/java/sun/hotspot/parser/DiagnosticCommand.java	Fri Aug 02 02:26:51 2013 +0400
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2005, 2013, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package sun.hotspot.parser;
+
+public class DiagnosticCommand {
+
+    public enum DiagnosticArgumentType {
+        JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE
+    }
+
+    private String name;
+    private String desc;
+    private DiagnosticArgumentType type;
+    private boolean mandatory;
+    private String defaultValue;
+
+    public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type,
+            boolean mandatory, String defaultValue) {
+        this.name = name;
+        this.desc = desc;
+        this.type = type;
+        this.mandatory = mandatory;
+        this.defaultValue = defaultValue;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getDesc() {
+        return desc;
+    }
+
+    public DiagnosticArgumentType getType() {
+        return type;
+    }
+
+    public boolean isMandatory() {
+        return mandatory;
+    }
+
+    public String getDefaultValue() {
+        return defaultValue;
+    }
+}