# HG changeset patch # User iveresov # Date 1502500881 0 # Node ID 76fb4ae9fd2f7d6315e6affc2b04ded8834b9d30 # Parent 22196b3c7dfdff9c44b5dfaed3624c277c3d8eaf# Parent 8b2c620d7092c75403a09276acf24a16726f57ec Merge diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/AllocSpy.java Sat Aug 12 01:21:21 2017 +0000 @@ -71,6 +71,7 @@ field.setAccessible(true); enabled = field.get(null) != null; } catch (Exception e) { + } catch (LinkageError e) { } ENABLED = enabled; if (ENABLED) { diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java Sat Aug 12 01:21:21 2017 +0000 @@ -101,6 +101,14 @@ */ public class CheckGraalInvariants extends GraalCompilerTest { + public CheckGraalInvariants() { + try { + Class.forName("java.lang.management.ManagementFactory"); + } catch (ClassNotFoundException ex) { + Assume.assumeNoException("cannot run without java.management JDK9 module", ex); + } + } + private static boolean shouldVerifyEquals(ResolvedJavaMethod m) { if (m.getName().equals("identityEquals")) { ResolvedJavaType c = m.getDeclaringClass(); diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java Sat Aug 12 01:21:21 2017 +0000 @@ -946,6 +946,7 @@ InstalledCode installedCode = null; StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph; DebugContext debug = graphToCompile.getDebug(); + try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) { CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI); CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options); diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java Sat Aug 12 01:21:21 2017 +0000 @@ -26,6 +26,7 @@ import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction; import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction; import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException; +import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction; import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL; import static org.graalvm.compiler.debug.DebugOptions.Dump; import static org.graalvm.compiler.debug.DebugOptions.DumpPath; @@ -36,6 +37,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; +import java.util.Map; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.debug.DiagnosticsOutputDirectory; @@ -59,6 +61,8 @@ * {@link CompilationWrapper}. The actions are with respect to what the user sees on the * console. The compilation requester determines what ultimate action is taken in * {@link CompilationWrapper#handleException(Throwable)}. + * + * The actions are in ascending order of verbosity. */ public enum ExceptionAction { /** @@ -97,16 +101,32 @@ return null; } } + + /** + * Gets the action that is one level less verbose than this action, bottoming out at the + * least verbose action. + */ + ExceptionAction quieter() { + assert ExceptionAction.Silent.ordinal() == 0; + int index = Math.max(ordinal() - 1, 0); + return values()[index]; + } } private final DiagnosticsOutputDirectory outputDirectory; + private final Map problemsHandledPerAction; + /** * @param outputDirectory object used to access a directory for dumping if the compilation is * re-executed + * @param problemsHandledPerAction map used to count the number of compilation failures or + * bailouts handled by each action. This is provided by the caller as it is expected + * to be shared between instances of {@link CompilationWrapper}. */ - public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory) { + public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory, Map problemsHandledPerAction) { this.outputDirectory = outputDirectory; + this.problemsHandledPerAction = problemsHandledPerAction; } /** @@ -177,9 +197,12 @@ } ExceptionAction action = lookupAction(initialOptions, actionKey); + action = adjustAction(initialOptions, actionKey, action); + if (action == ExceptionAction.Silent) { return handleException(cause); } + if (action == ExceptionAction.Print) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (PrintStream ps = new PrintStream(baos)) { @@ -214,7 +237,7 @@ String dir = this.outputDirectory.getPath(); if (dir == null) { - return null; + return handleException(cause); } String dumpName = PathUtilities.sanitizeFileName(toString()); File dumpPath = new File(dir, dumpName); @@ -274,4 +297,31 @@ } } } + + /** + * Adjusts {@code initialAction} if necessary based on + * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}. + */ + private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey actionKey, ExceptionAction initialAction) { + ExceptionAction action = initialAction; + int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions); + synchronized (problemsHandledPerAction) { + while (action != ExceptionAction.Silent) { + int problems = problemsHandledPerAction.getOrDefault(action, 0); + if (problems >= maxProblems) { + if (problems == maxProblems) { + TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", actionKey, action, action.quieter(), + MaxCompilationProblemsPerAction, maxProblems); + // Ensure that the message above is only printed once + problemsHandledPerAction.put(action, problems + 1); + } + action = action.quieter(); + } else { + break; + } + } + problemsHandledPerAction.put(action, problemsHandledPerAction.getOrDefault(action, 0) + 1); + } + return action; + } } diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java Sat Aug 12 01:21:21 2017 +0000 @@ -39,11 +39,14 @@ @Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " + "This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug) public static final OptionKey CrashAt = new OptionKey<>(null); - @Option(help = "Specifies the action to take when compilation fails with a non-bailout exception.", type = OptionType.User) + @Option(help = "The action to take when compilation fails with a non-bailout exception.", type = OptionType.User) public static final EnumOptionKey CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose, ExceptionAction.HELP); - @Option(help = "Specifies the action to take when compilation fails with a bailout exception.", type = OptionType.User) + @Option(help = "The action to take when compilation fails with a bailout exception.", type = OptionType.User) public static final EnumOptionKey CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent, ExceptionAction.HELP); - @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.Debug) + @Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " + + "by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User) + public static final OptionKey MaxCompilationProblemsPerAction = new OptionKey<>(5); + @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User) public static final OptionKey ExitVMOnException = new OptionKey<>(false); // @formatter:on } diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java Sat Aug 12 01:21:21 2017 +0000 @@ -45,11 +45,14 @@ @SuppressWarnings("try") public class TimerKeyTest { - private static final ThreadMXBean threadMXBean = Management.getThreadMXBean(); - @Before public void checkCapabilities() { - Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported()); + try { + ThreadMXBean threadMXBean = Management.getThreadMXBean(); + Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported()); + } catch (LinkageError err) { + Assume.assumeNoException("Cannot run without java.management JDK9 module", err); + } } /** @@ -60,6 +63,7 @@ * {@code ms} */ private static long spin(long ms) { + ThreadMXBean threadMXBean = Management.getThreadMXBean(); long start = threadMXBean.getCurrentThreadCpuTime(); do { long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000; diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java --- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java Sat Aug 12 02:13:29 2017 +0200 +++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugMemUseTracker.java Sat Aug 12 01:21:21 2017 +0000 @@ -22,11 +22,9 @@ */ package org.graalvm.compiler.debug; -import com.sun.management.ThreadMXBean; - /** - * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed - * using the try-with-resources pattern: + * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility + * should be employed using the try-with-resources pattern: * *
  * try (DebugMemUseTracker.Closeable a = memUseTracker.start()) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,7 +25,6 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
-import java.lang.management.ManagementFactory;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
@@ -74,16 +73,20 @@
      * Gets a unique identifier for this execution such as a process ID.
      */
     protected String getExecutionID() {
-        String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
         try {
-            int index = runtimeName.indexOf('@');
-            if (index != -1) {
-                long pid = Long.parseLong(runtimeName.substring(0, index));
-                return Long.toString(pid);
+            String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
+            try {
+                int index = runtimeName.indexOf('@');
+                if (index != -1) {
+                    long pid = Long.parseLong(runtimeName.substring(0, index));
+                    return Long.toString(pid);
+                }
+            } catch (NumberFormatException e) {
             }
-        } catch (NumberFormatException e) {
+            return runtimeName;
+        } catch (LinkageError err) {
+            return String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
         }
-        return runtimeName;
     }
 
     private synchronized String getPath(boolean createIfNull) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java	Sat Aug 12 01:21:21 2017 +0000
@@ -24,12 +24,6 @@
 
 import static java.lang.Thread.currentThread;
 
-import java.lang.management.ManagementFactory;
-import java.lang.management.ThreadInfo;
-import java.lang.management.ThreadMXBean;
-
-import javax.management.ObjectName;
-
 public class Management {
 
     private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean();
@@ -46,20 +40,20 @@
 
     private static com.sun.management.ThreadMXBean initThreadMXBean() {
         try {
-            return (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
+            return (com.sun.management.ThreadMXBean) java.lang.management.ManagementFactory.getThreadMXBean();
         } catch (Error err) {
             return new UnimplementedBean();
         }
     }
 
-    public static ThreadMXBean getThreadMXBean() {
+    public static java.lang.management.ThreadMXBean getThreadMXBean() {
         return threadMXBean;
     }
 
-    private static class UnimplementedBean implements ThreadMXBean, com.sun.management.ThreadMXBean {
+    private static class UnimplementedBean implements java.lang.management.ThreadMXBean, com.sun.management.ThreadMXBean {
 
         @Override
-        public ObjectName getObjectName() {
+        public javax.management.ObjectName getObjectName() {
             return null;
         }
 
@@ -123,22 +117,22 @@
         }
 
         @Override
-        public ThreadInfo getThreadInfo(long id) {
+        public java.lang.management.ThreadInfo getThreadInfo(long id) {
             return null;
         }
 
         @Override
-        public ThreadInfo[] getThreadInfo(long[] ids) {
+        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids) {
             return null;
         }
 
         @Override
-        public ThreadInfo getThreadInfo(long id, int maxDepth) {
+        public java.lang.management.ThreadInfo getThreadInfo(long id, int maxDepth) {
             return null;
         }
 
         @Override
-        public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
+        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
             return null;
         }
 
@@ -220,12 +214,12 @@
         }
 
         @Override
-        public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
+        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
             return null;
         }
 
         @Override
-        public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
+        public java.lang.management.ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
             return null;
         }
     }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java	Sat Aug 12 01:21:21 2017 +0000
@@ -22,11 +22,9 @@
  */
 package org.graalvm.compiler.debug;
 
-import com.sun.management.ThreadMXBean;
-
 /**
- * Tracks memory usage within a scope using {@link ThreadMXBean}. This facility should be employed
- * using the try-with-resources pattern:
+ * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
+ * should be employed using the try-with-resources pattern:
  *
  * 
  * try (DebugCloseable a = memUseTracker.start()) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java	Sat Aug 12 01:21:21 2017 +0000
@@ -22,14 +22,12 @@
  */
 package org.graalvm.compiler.debug;
 
-import java.lang.management.ThreadMXBean;
-
 /**
  * A consistent source of timing data that should be used by all facilities in the debug package.
  */
 public class TimeSource {
     private static final boolean USING_BEAN;
-    private static final ThreadMXBean threadMXBean;
+    private static final java.lang.management.ThreadMXBean threadMXBean;
 
     static {
         threadMXBean = Management.getThreadMXBean();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Sat Aug 12 01:21:21 2017 +0000
@@ -88,7 +88,19 @@
     }
 
     public static ResolvedJavaMethod resolveIntrinsic(MetaAccessProvider metaAccess, VMIntrinsicMethod intrinsic) throws ClassNotFoundException {
-        Class c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
+        Class c;
+        try {
+            c = Class.forName(intrinsic.declaringClass.replace('/', '.'), false, CheckGraalIntrinsics.class.getClassLoader());
+        } catch (ClassNotFoundException ex) {
+            try {
+                Class.forName("javax.naming.Reference");
+            } catch (ClassNotFoundException coreNamingMissing) {
+                // if core JDK classes aren't found, we are probably running in a
+                // JDK9 java.base environment and then missing class is OK
+                return null;
+            }
+            throw ex;
+        }
         for (Method javaMethod : c.getDeclaredMethods()) {
             if (javaMethod.getName().equals(intrinsic.name)) {
                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(javaMethod);
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Sat Aug 12 01:21:21 2017 +0000
@@ -29,28 +29,38 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipFile;
 
+import org.graalvm.compiler.core.GraalCompilerOptions;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.test.SubprocessUtil;
 import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 
 /**
  * Tests support for dumping graphs and other info useful for debugging a compiler crash.
  */
 public class CompilationWrapperTest extends GraalCompilerTest {
+    public CompilationWrapperTest() {
+        try {
+            Class.forName("java.lang.management.ManagementFactory");
+        } catch (ClassNotFoundException ex) {
+            Assume.assumeNoException("skip this test if there is no java.management JDK9 module around", ex);
+        }
+    }
 
     /**
      * Tests compilation requested by the VM.
      */
     @Test
     public void testVMCompilation1() throws IOException, InterruptedException {
-        testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
+        testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
                         "-XX:+UseJVMCICompiler",
                         "-Dgraal.CompilationFailureAction=ExitVM",
                         "-Dgraal.CrashAt=Object.*,String.*",
@@ -63,31 +73,79 @@
      */
     @Test
     public void testVMCompilation2() throws IOException, InterruptedException {
-        testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
+        testHelper(Collections.emptyList(), Arrays.asList("-XX:+BootstrapJVMCI",
                         "-XX:+UseJVMCICompiler",
                         "-Dgraal.ExitVMOnException=true",
                         "-Dgraal.CrashAt=Object.*,String.*",
                         "-version"));
     }
 
+    static class Probe {
+        final String substring;
+        final int expectedOccurrences;
+        int actualOccurrences;
+        String lastMatchingLine;
+
+        Probe(String substring, int expectedOccurrences) {
+            this.substring = substring;
+            this.expectedOccurrences = expectedOccurrences;
+        }
+
+        boolean matches(String line) {
+            if (line.contains(substring)) {
+                actualOccurrences++;
+                lastMatchingLine = line;
+                return true;
+            }
+            return false;
+        }
+
+        String test() {
+            return expectedOccurrences == actualOccurrences ? null : String.format("expected %d, got %d occurrences", expectedOccurrences, actualOccurrences);
+        }
+    }
+
+    /**
+     * Tests {@link GraalCompilerOptions#MaxCompilationProblemsPerAction} in context of a
+     * compilation requested by the VM.
+     */
+    @Test
+    public void testVMCompilation3() throws IOException, InterruptedException {
+        final int maxProblems = 4;
+        Probe[] probes = {
+                        new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems),
+                        new Probe("Retrying compilation of", maxProblems),
+                        new Probe("adjusting CompilationFailureAction from Diagnose to Print", 1),
+                        new Probe("adjusting CompilationFailureAction from Print to Silent", 1),
+        };
+        testHelper(Arrays.asList(probes), Arrays.asList("-XX:+BootstrapJVMCI",
+                        "-XX:+UseJVMCICompiler",
+                        "-Dgraal.CompilationFailureAction=Diagnose",
+                        "-Dgraal.MaxCompilationProblemsPerAction=" + maxProblems,
+                        "-Dgraal.CrashAt=Object.*,String.*",
+                        "-version"));
+    }
+
     /**
      * Tests compilation requested by Truffle.
      */
     @Test
     public void testTruffleCompilation() throws IOException, InterruptedException {
-        testHelper(Arrays.asList(
-                        "-Dgraal.CompilationFailureAction=ExitVM",
-                        "-Dgraal.CrashAt=root test1"),
-                        "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite",
-                        "test");
+        testHelper(Collections.emptyList(),
+                        Arrays.asList(
+                                        "-Dgraal.CompilationFailureAction=ExitVM",
+                                        "-Dgraal.CrashAt=root test1"),
+                        "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
     }
 
     private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose");
 
-    private static void testHelper(List extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
+    private static void testHelper(List initialProbes, List extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
         final File dumpPath = new File(CompilationWrapperTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
         List vmArgs = withoutDebuggerArguments(getVMCommandLine());
         vmArgs.removeIf(a -> a.startsWith("-Dgraal."));
+        vmArgs.remove("-esa");
+        vmArgs.remove("-ea");
         vmArgs.add("-Dgraal.DumpPath=" + dumpPath);
         // Force output to a file even if there's a running IGV instance available.
         vmArgs.add("-Dgraal.PrintGraphFile=true");
@@ -98,35 +156,37 @@
             System.out.println(proc);
         }
 
-        String forcedCrashString = "Forced crash after compiling";
-        String diagnosticOutputFilePrefix = "Graal diagnostic output saved in ";
-
-        boolean seenForcedCrashString = false;
-        String diagnosticOutputZip = null;
+        List probes = new ArrayList<>(initialProbes);
+        Probe diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
+        probes.add(diagnosticProbe);
+        probes.add(new Probe("Forced crash after compiling", Integer.MAX_VALUE) {
+            @Override
+            String test() {
+                return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
+            }
+        });
 
         for (String line : proc.output) {
-            if (line.contains(forcedCrashString)) {
-                seenForcedCrashString = true;
-            } else if (diagnosticOutputZip == null) {
-                int index = line.indexOf(diagnosticOutputFilePrefix);
-                if (index != -1) {
-                    diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim();
+            for (Probe probe : probes) {
+                if (probe.matches(line)) {
+                    break;
                 }
             }
         }
-
-        if (!seenForcedCrashString) {
-            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc));
-        }
-        if (diagnosticOutputZip == null) {
-            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc));
+        for (Probe probe : probes) {
+            String error = probe.test();
+            if (error != null) {
+                Assert.fail(String.format("Did not find expected occurences of '%s' in output of command: %s%n%s", probe.substring, error, proc));
+            }
         }
 
-        String[] dumpPathEntries = dumpPath.list();
+        String diagnosticOutputZip = diagnosticProbe.lastMatchingLine.substring(diagnosticProbe.substring.length()).trim();
+
+        List dumpPathEntries = Arrays.asList(dumpPath.list());
 
         File zip = new File(diagnosticOutputZip).getAbsoluteFile();
         Assert.assertTrue(zip.toString(), zip.exists());
-        Assert.assertArrayEquals(dumpPathEntries, new String[]{zip.getName()});
+        Assert.assertTrue(zip + " not in " + dumpPathEntries, dumpPathEntries.contains(zip.getName()));
         try {
             int bgv = 0;
             int cfg = 0;
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java	Sat Aug 12 01:21:21 2017 +0000
@@ -43,6 +43,7 @@
 import org.junit.Test;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.junit.Assume;
 
 /**
  * Test on-stack-replacement with locks.
@@ -51,6 +52,14 @@
 
     private static boolean TestInSeparateThread = false;
 
+    public GraalOSRLockTest() {
+        try {
+            Class.forName("java.lang.management.ManagementFactory");
+        } catch (ClassNotFoundException ex) {
+            Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex);
+        }
+    }
+
     // testing only
     public static boolean isMonitorLockHeld(Object o) {
         return isMonitorLockHeldByThread(o, null);
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Sat Aug 12 01:21:21 2017 +0000
@@ -110,7 +110,7 @@
         MBeanInfo info = server.getMBeanInfo(name);
         assertNotNull("Info is found", info);
 
-        MBeanAttributeInfo printCompilation = findAttributeInfo("PrintCompilation", info);
+        MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info);
         assertNotNull("PrintCompilation found", printCompilation);
         assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
 
@@ -124,9 +124,9 @@
         assertEquals("Changed to on", Boolean.TRUE, after);
     }
 
-    private static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
+    private static Object findAttributeInfo(String attrName, Object info) {
         MBeanAttributeInfo printCompilation = null;
-        for (MBeanAttributeInfo attr : info.getAttributes()) {
+        for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) {
             if (attr.getName().equals(attrName)) {
                 assertTrue("Readable", attr.isReadable());
                 assertTrue("Writable", attr.isWritable());
@@ -157,7 +157,7 @@
         MBeanInfo info = server.getMBeanInfo(name);
         assertNotNull("Info is found", info);
 
-        MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
+        MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
 
         Attribute dumpTo1 = new Attribute(dump.getName(), 1);
 
@@ -215,7 +215,7 @@
                         "java.util.Arrays", "asList", ":3"
         }, null);
 
-        MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
+        MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
         Attribute dumpTo1 = new Attribute(dump.getName(), "");
         server.setAttribute(name, dumpTo1);
         Object after = server.getAttribute(name, dump.getName());
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java	Sat Aug 12 01:21:21 2017 +0000
@@ -46,7 +46,6 @@
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
-import com.sun.management.ThreadMXBean;
 
 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -88,7 +87,7 @@
     private static long zeroTime = System.nanoTime();
 
     private static long getThreadAllocatedBytes() {
-        ThreadMXBean thread = (ThreadMXBean) Management.getThreadMXBean();
+        com.sun.management.ThreadMXBean thread = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
         return thread.getThreadAllocatedBytes(currentThread().getId());
     }
 
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Sat Aug 12 01:21:21 2017 +0000
@@ -96,7 +96,7 @@
         CompilationResult result;
 
         HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) {
-            super(compiler.getGraalRuntime().getOutputDirectory());
+            super(compiler.getGraalRuntime().getOutputDirectory(), compiler.getGraalRuntime().getCompilationProblemsPerAction());
             this.compilationEvent = compilationEvent;
         }
 
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Sat Aug 12 01:21:21 2017 +0000
@@ -146,7 +146,7 @@
         }
     }
 
-    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
+    public StructuredGraph createGraph(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
         HotSpotBackend backend = graalRuntime.getHostBackend();
         HotSpotProviders providers = backend.getProviders();
         final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
@@ -160,6 +160,15 @@
             graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.ifTrue(OptAssumptions.getValue(options))).method(method).entryBCI(entryBCI).speculationLog(
                             speculationLog).useProfilingInfo(useProfilingInfo).compilationId(compilationId).build();
         }
+        return graph;
+    }
+
+    public CompilationResult compileHelper(CompilationResultBuilderFactory crbf, CompilationResult result, StructuredGraph graph, ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo,
+                    OptionValues options) {
+
+        HotSpotBackend backend = graalRuntime.getHostBackend();
+        HotSpotProviders providers = backend.getProviders();
+        final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
 
         Suites suites = getSuites(providers, options);
         LIRSuites lirSuites = getLIRSuites(providers, options);
@@ -173,11 +182,11 @@
         if (isOSR && !OnStackReplacementPhase.Options.DeoptAfterOSR.getValue(options)) {
             optimisticOpts.remove(Optimization.RemoveNeverExecutedCode);
         }
-        CompilationResult result = new CompilationResult();
+
         result.setEntryBCI(entryBCI);
         boolean shouldDebugNonSafepoints = providers.getCodeCache().shouldDebugNonSafepoints();
         PhaseSuite graphBuilderSuite = configGraphBuilderSuite(providers.getSuites().getDefaultGraphBuilderSuite(), shouldDebugNonSafepoints, isOSR);
-        GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, CompilationResultBuilderFactory.Default);
+        GraalCompiler.compileGraph(graph, method, providers, backend, graphBuilderSuite, optimisticOpts, profilingInfo, suites, lirSuites, result, crbf);
 
         if (!isOSR && useProfilingInfo) {
             ProfilingInfo profile = profilingInfo;
@@ -187,6 +196,12 @@
         return result;
     }
 
+    public CompilationResult compile(ResolvedJavaMethod method, int entryBCI, boolean useProfilingInfo, CompilationIdentifier compilationId, OptionValues options, DebugContext debug) {
+        StructuredGraph graph = createGraph(method, entryBCI, useProfilingInfo, compilationId, options, debug);
+        CompilationResult result = new CompilationResult();
+        return compileHelper(CompilationResultBuilderFactory.Default, result, graph, method, entryBCI, useProfilingInfo, options);
+    }
+
     /**
      * Gets a graph produced from the intrinsic for a given method that can be compiled and
      * installed for the method.
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Sat Aug 12 01:21:21 2017 +0000
@@ -22,7 +22,6 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import java.lang.management.ManagementFactory;
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
@@ -30,22 +29,6 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Objects;
-import javax.management.Attribute;
-import javax.management.AttributeList;
-import javax.management.AttributeNotFoundException;
-import javax.management.DynamicMBean;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanException;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanParameterInfo;
-import javax.management.MBeanRegistrationException;
-import javax.management.MBeanServer;
-import javax.management.MalformedObjectNameException;
-import javax.management.NotCompliantMBeanException;
-import javax.management.ObjectName;
-import javax.management.ReflectionException;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
@@ -66,14 +49,14 @@
 import org.graalvm.util.Equivalence;
 import org.graalvm.util.UnmodifiableEconomicMap;
 
-public final class HotSpotGraalMBean implements DynamicMBean {
+public final class HotSpotGraalMBean implements javax.management.DynamicMBean {
     private static Object mBeanServerField;
     private final HotSpotGraalCompiler compiler;
     private final OptionValues options;
     private final EconomicMap, Object> changes;
     private final EconomicSet methodDumps;
     private volatile EconomicSet> loaders;
-    private ObjectName registered;
+    private javax.management.ObjectName registered;
     private OptionValues cachedOptions;
 
     private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) {
@@ -89,11 +72,11 @@
     private static boolean isMXServerOn() {
         if (mBeanServerField == null) {
             try {
-                final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
+                final Field field = java.lang.management.ManagementFactory.class.getDeclaredField("platformMBeanServer");
                 field.setAccessible(true);
                 mBeanServerField = field;
             } catch (Exception ex) {
-                mBeanServerField = ManagementFactory.class;
+                mBeanServerField = java.lang.management.ManagementFactory.class;
             }
         }
         if (mBeanServerField instanceof Field) {
@@ -113,7 +96,7 @@
         return mbean;
     }
 
-    public ObjectName ensureRegistered(boolean check) {
+    public javax.management.ObjectName ensureRegistered(boolean check) {
         for (int cnt = 0;; cnt++) {
             if (registered != null) {
                 return registered;
@@ -122,14 +105,14 @@
                 return null;
             }
             try {
-                MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
-                ObjectName name = new ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
+                javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
+                javax.management.ObjectName name = new javax.management.ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
                 mbs.registerMBean(this, name);
                 registered = name;
                 break;
-            } catch (MalformedObjectNameException | MBeanRegistrationException | NotCompliantMBeanException ex) {
+            } catch (javax.management.MalformedObjectNameException | javax.management.MBeanRegistrationException | javax.management.NotCompliantMBeanException ex) {
                 throw new IllegalStateException(ex);
-            } catch (InstanceAlreadyExistsException ex) {
+            } catch (javax.management.InstanceAlreadyExistsException ex) {
                 continue;
             }
         }
@@ -188,14 +171,14 @@
     }
 
     @Override
-    public void setAttribute(Attribute attribute) throws AttributeNotFoundException {
-        Attribute newAttr = setImpl(attribute);
+    public void setAttribute(javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException {
+        javax.management.Attribute newAttr = setImpl(attribute);
         if (newAttr == null) {
-            throw new AttributeNotFoundException();
+            throw new javax.management.AttributeNotFoundException();
         }
     }
 
-    private Attribute setImpl(Attribute attribute) {
+    private javax.management.Attribute setImpl(javax.management.Attribute attribute) {
         cachedOptions = null;
         for (OptionDescriptor option : allOptionDescriptors()) {
             if (option.getName().equals(attribute.getName())) {
@@ -207,22 +190,22 @@
     }
 
     @Override
-    public AttributeList getAttributes(String[] names) {
-        AttributeList list = new AttributeList();
+    public javax.management.AttributeList getAttributes(String[] names) {
+        javax.management.AttributeList list = new javax.management.AttributeList();
         for (String name : names) {
             Object value = getAttribute(name);
             if (value != null) {
-                list.add(new Attribute(name, value));
+                list.add(new javax.management.Attribute(name, value));
             }
         }
         return list;
     }
 
     @Override
-    public AttributeList setAttributes(AttributeList attributes) {
-        AttributeList setOk = new AttributeList();
-        for (Attribute attr : attributes.asList()) {
-            Attribute newAttr = setImpl(attr);
+    public javax.management.AttributeList setAttributes(javax.management.AttributeList attributes) {
+        javax.management.AttributeList setOk = new javax.management.AttributeList();
+        for (javax.management.Attribute attr : attributes.asList()) {
+            javax.management.Attribute newAttr = setImpl(attr);
             if (newAttr != null) {
                 setOk.add(newAttr);
             }
@@ -231,7 +214,7 @@
     }
 
     @Override
-    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+    public Object invoke(String actionName, Object[] params, String[] signature) throws javax.management.MBeanException, javax.management.ReflectionException {
         if ("dumpMethod".equals(actionName)) {
             try {
                 String className = param(params, 0, "className", String.class, null);
@@ -241,7 +224,7 @@
                 Number port = param(params, 4, "port", Number.class, 4445);
                 dumpMethod(className, methodName, filter, host, port.intValue());
             } catch (Exception ex) {
-                throw new ReflectionException(ex);
+                throw new javax.management.ReflectionException(ex);
             }
         }
         return null;
@@ -261,7 +244,7 @@
         throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
     }
 
-    public void dumpMethod(String className, String methodName, String filter, String host, int port) throws MBeanException {
+    public void dumpMethod(String className, String methodName, String filter, String host, int port) throws javax.management.MBeanException {
         String jvmName = MetaUtil.toInternalName(className);
         methodDumps.add(new Dump(host, port, jvmName, methodName, filter));
 
@@ -293,41 +276,41 @@
             }
         }
         if (found.isEmpty()) {
-            throw new MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
+            throw new javax.management.MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
         }
     }
 
     @Override
-    public MBeanInfo getMBeanInfo() {
-        List attrs = new ArrayList<>();
+    public javax.management.MBeanInfo getMBeanInfo() {
+        List attrs = new ArrayList<>();
         if (registered != null) {
             for (OptionDescriptor descr : allOptionDescriptors()) {
-                attrs.add(new MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
+                attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
             }
         }
-        MBeanOperationInfo[] ops = {
-                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
-                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                        }, "void", MBeanOperationInfo.ACTION),
-                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
-                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
-                        }, "void", MBeanOperationInfo.ACTION),
-                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
-                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
-                                        new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
-                                        new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
-                        }, "void", MBeanOperationInfo.ACTION)
+        javax.management.MBeanOperationInfo[] ops = {
+                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
+                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                        }, "void", javax.management.MBeanOperationInfo.ACTION),
+                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
+                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                        }, "void", javax.management.MBeanOperationInfo.ACTION),
+                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
+                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                                        new javax.management.MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
+                                        new javax.management.MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
+                        }, "void", javax.management.MBeanOperationInfo.ACTION)
         };
 
-        return new MBeanInfo(
+        return new javax.management.MBeanInfo(
                         HotSpotGraalMBean.class.getName(),
                         "Graal",
-                        attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
+                        attrs.toArray(new javax.management.MBeanAttributeInfo[attrs.size()]),
                         null, ops, null);
     }
 
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Sat Aug 12 01:21:21 2017 +0000
@@ -30,10 +30,13 @@
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 
 import java.util.ArrayList;
+import java.util.EnumMap;
 import java.util.List;
+import java.util.Map;
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.api.runtime.GraalRuntime;
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.target.Backend;
@@ -95,6 +98,7 @@
 
     private final OptionValues options;
     private final DiagnosticsOutputDirectory outputDirectory;
+    private final Map compilationProblemsPerAction;
     private final HotSpotGraalMBean mBean;
 
     /**
@@ -114,11 +118,12 @@
         }
 
         outputDirectory = new DiagnosticsOutputDirectory(options);
+        compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class);
         snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
 
         HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
-        this.mBean = HotSpotGraalMBean.create(compiler);
+        this.mBean = createHotSpotGraalMBean(compiler);
 
         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
 
@@ -167,6 +172,14 @@
         bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
     }
 
+    private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) {
+        try {
+            return HotSpotGraalMBean.create(compiler);
+        } catch (LinkageError ex) {
+            return null;
+        }
+    }
+
     private HotSpotBackend registerBackend(HotSpotBackend backend) {
         Class arch = backend.getTarget().arch.getClass();
         HotSpotBackend oldValue = backends.put(arch, backend);
@@ -192,12 +205,12 @@
 
     @Override
     public OptionValues getOptions() {
-        return mBean.optionsFor(options, null);
+        return mBean == null ? options : mBean.optionsFor(options, null);
     }
 
     @Override
     public OptionValues getOptions(ResolvedJavaMethod forMethod) {
-        return mBean.optionsFor(options, forMethod);
+        return mBean == null ? options : mBean.optionsFor(options, forMethod);
     }
 
     @Override
@@ -298,4 +311,9 @@
     public DiagnosticsOutputDirectory getOutputDirectory() {
         return outputDirectory;
     }
+
+    @Override
+    public Map getCompilationProblemsPerAction() {
+        return compilationProblemsPerAction;
+    }
 }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Sat Aug 12 01:21:21 2017 +0000
@@ -22,7 +22,10 @@
  */
 package org.graalvm.compiler.hotspot;
 
+import java.util.Map;
+
 import org.graalvm.compiler.api.runtime.GraalRuntime;
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
@@ -95,4 +98,9 @@
      * Gets a directory into which diagnostics such crash reports and dumps should be written.
      */
     DiagnosticsOutputDirectory getOutputDirectory();
+
+    /**
+     * Gets the map used to count compilation problems at each {@link ExceptionAction} level.
+     */
+    Map getCompilationProblemsPerAction();
 }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java	Sat Aug 12 01:21:21 2017 +0000
@@ -27,7 +27,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
-import java.lang.management.ManagementFactory;
 
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
@@ -53,8 +52,8 @@
     private String getFilename(OptionValues options) {
         String name = getValue(options);
         if (name.contains("%p")) {
-            String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
             try {
+                String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
                 int index = runtimeName.indexOf('@');
                 if (index != -1) {
                     long pid = Long.parseLong(runtimeName.substring(0, index));
@@ -63,6 +62,8 @@
                 name = name.replaceAll("%p", runtimeName);
             } catch (NumberFormatException e) {
 
+            } catch (LinkageError err) {
+                name = String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
             }
         }
         if (name.contains("%t")) {
@@ -124,7 +125,7 @@
                 /*
                  * Add the JVM and Java arguments to the log file to help identity it.
                  */
-                String inputArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments());
+                String inputArguments = String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
                 ps.println("VM Arguments: " + inputArguments);
                 String cmd = System.getProperty("sun.java.command");
                 if (cmd != null) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Sat Aug 12 01:21:21 2017 +0000
@@ -510,6 +510,8 @@
          */
         private void processPlaceholderFrameStates(IntrinsicContext intrinsic) {
             StructuredGraph graph = parser.getGraph();
+            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "Before processPlaceholderFrameStates in %s", parser.method);
+            boolean sawInvalidFrameState = false;
             for (Node node : graph.getNewNodes(mark)) {
                 if (node instanceof FrameState) {
                     FrameState frameState = (FrameState) node;
@@ -547,6 +549,7 @@
                                     FrameState newFrameState = graph.add(new FrameState(BytecodeFrame.INVALID_FRAMESTATE_BCI));
                                     newFrameState.setNodeSourcePosition(frameState.getNodeSourcePosition());
                                     frameState.replaceAndDelete(newFrameState);
+                                    sawInvalidFrameState = true;
                                 } else {
                                     // An intrinsic for a void method.
                                     FrameState newFrameState = frameStateBuilder.create(parser.stream.nextBCI(), null);
@@ -585,6 +588,17 @@
                     }
                 }
             }
+            if (sawInvalidFrameState) {
+                JavaKind returnKind = parser.getInvokeReturnType().getJavaKind();
+                FrameStateBuilder frameStateBuilder = parser.frameState;
+                ValueNode returnValue = frameStateBuilder.pop(returnKind);
+                StateSplitProxyNode proxy = graph.add(new StateSplitProxyNode(returnValue));
+                parser.lastInstr.setNext(proxy);
+                frameStateBuilder.push(returnKind, proxy);
+                proxy.setStateAfter(parser.createFrameState(parser.stream.nextBCI(), proxy));
+                parser.lastInstr = proxy;
+            }
+            graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "After processPlaceholderFrameStates in %s", parser.method);
         }
     }
 
@@ -1345,7 +1359,7 @@
             /*
              * Special handling for runtimes that rewrite an invocation of MethodHandle.invoke(...)
              * or MethodHandle.invokeExact(...) to a static adapter. HotSpot does this - see
-             * https://wiki.openjdk.java.net/display/HotSpot/Method+handles+and+invokedynamic
+             * https://wikis.oracle.com/display/HotSpotInternals/Method+handles +and+invokedynamic
              */
             boolean hasReceiver = !((ResolvedJavaMethod) target).isStatic();
             JavaConstant appendix = constantPool.lookupAppendix(stream.readCPI(), Bytecodes.INVOKEVIRTUAL);
@@ -1987,7 +2001,7 @@
      */
     private boolean tryFastInlineAccessor(ValueNode[] args, ResolvedJavaMethod targetMethod) {
         byte[] bytecode = targetMethod.getCode();
-        if (bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
+        if (bytecode != null && bytecode.length == ACCESSOR_BYTECODE_LENGTH &&
                         Bytes.beU1(bytecode, 0) == ALOAD_0 &&
                         Bytes.beU1(bytecode, 1) == GETFIELD) {
             int b4 = Bytes.beU1(bytecode, 4);
@@ -2188,6 +2202,14 @@
                     lastInstr = finishInstruction(returnMergeNode, frameState);
                 }
             }
+            /*
+             * Propagate any side effects into the caller when parsing intrinsics.
+             */
+            if (parser.frameState.isAfterSideEffect() && parsingIntrinsic()) {
+                for (StateSplit sideEffect : parser.frameState.sideEffects()) {
+                    frameState.addSideEffect(sideEffect);
+                }
+            }
 
             FixedWithNextNode calleeBeforeUnwindNode = parser.getBeforeUnwindNode();
             if (calleeBeforeUnwindNode != null) {
@@ -3037,7 +3059,7 @@
         ConstantNode falseValue = graph.unique(ConstantNode.forInt(falseBlockInt));
         ValueNode conditionalNode = ConditionalNode.create(condition, trueValue, falseValue);
         if (conditionalNode.graph() == null) {
-            conditionalNode = graph.addOrUnique(conditionalNode);
+            conditionalNode = graph.addOrUniqueWithInputs(conditionalNode);
         }
         if (genReturn) {
             JavaKind returnKind = method.getSignature().getReturnKind().getStackKind();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Sat Aug 12 01:21:21 2017 +0000
@@ -102,6 +102,7 @@
     private final StructuredGraph graph;
     private final boolean clearNonLiveLocals;
     private FrameState outerFrameState;
+    private NodeSourcePosition outerSourcePosition;
 
     /**
      * The closest {@link StateSplit#hasSideEffect() side-effect} predecessors. There will be more
@@ -364,13 +365,12 @@
             // Skip intrinsic frames
             parent = parser.getNonIntrinsicAncestor();
         }
-        return create(null, constantReceiver, bci, parent, hideSubstitutionStates);
+        return create(constantReceiver, bci, parent, hideSubstitutionStates);
     }
 
-    private NodeSourcePosition create(NodeSourcePosition o, JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
-        NodeSourcePosition outer = o;
-        if (outer == null && parent != null) {
-            outer = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
+    private NodeSourcePosition create(JavaConstant receiver, int bci, BytecodeParser parent, boolean hideSubstitutionStates) {
+        if (outerSourcePosition == null && parent != null) {
+            outerSourcePosition = parent.getFrameStateBuilder().createBytecodePosition(parent.bci(), hideSubstitutionStates);
         }
         if (bci == BytecodeFrame.AFTER_EXCEPTION_BCI && parent != null) {
             return FrameState.toSourcePosition(outerFrameState);
@@ -378,7 +378,7 @@
         if (bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
             throw shouldNotReachHere();
         }
-        return new NodeSourcePosition(receiver, outer, code.getMethod(), bci);
+        return new NodeSourcePosition(receiver, outerSourcePosition, code.getMethod(), bci);
     }
 
     public FrameStateBuilder copy() {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/NotOnDebug.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011, 2012, 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.
+ */
+package org.graalvm.compiler.jtt.hotspot;
+
+import org.junit.rules.DisableOnDebug;
+import org.junit.rules.TestRule;
+import org.junit.rules.Timeout;
+
+public final class NotOnDebug {
+    public static TestRule create(Timeout seconds) {
+        try {
+            return new DisableOnDebug(seconds);
+        } catch (LinkageError ex) {
+            return null;
+        }
+    }
+
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/hotspot/Test6959129.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,13 +25,12 @@
 import org.graalvm.compiler.jtt.JTTTest;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Test6959129 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static long test() {
         int min = Integer.MAX_VALUE - 30000;
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_contended01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Monitor_contended01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         boolean started = false;
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitor_notowner01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Monitor_notowner01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     static Object monitor = new Object();
     static Object finished = new Object();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Monitorenter01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     static final Object object = new Object();
 
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Monitorenter02.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Monitorenter02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     static final Object object = new Object();
 
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Object_wait01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait02.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Object_wait02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait03.java	Sat Aug 12 01:21:21 2017 +0000
@@ -30,11 +30,11 @@
 import org.graalvm.compiler.nodes.Cancellable;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 
 public class Object_wait03 extends JTTTest {
 
@@ -48,7 +48,7 @@
      */
     static final long TIMEOUT_MS = COMPILATION_TIMEOUT_MS * 2;
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.millis(TIMEOUT_MS));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.millis(TIMEOUT_MS));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Object_wait04.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Object_wait04 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/SynchronizedLoopExit01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,9 +25,9 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
@@ -39,7 +39,7 @@
  */
 public final class SynchronizedLoopExit01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     protected Object object = new Object();
     protected volatile boolean drained = false;
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted02.java	Sat Aug 12 01:21:21 2017 +0000
@@ -27,17 +27,17 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Assert;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 //Test all, mainly monitors
 public class Thread_isInterrupted02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static final Object start = new Object();
     private static final Object end = new Object();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted03.java	Sat Aug 12 01:21:21 2017 +0000
@@ -23,9 +23,9 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
@@ -35,7 +35,7 @@
 // Interrupted while sleeping, throws an interrupted exception
 public class Thread_isInterrupted03 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test() throws InterruptedException {
         final Thread1 thread = new Thread1();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_isInterrupted05.java	Sat Aug 12 01:21:21 2017 +0000
@@ -23,9 +23,9 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
@@ -35,7 +35,7 @@
 // Interrupted during wait, with interrupter joining
 public class Thread_isInterrupted05 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test() throws InterruptedException {
         final WaitInterruptee waitInterruptee = new WaitInterruptee();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Thread_join01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join02.java	Sat Aug 12 01:21:21 2017 +0000
@@ -28,15 +28,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Thread_join02 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_join03.java	Sat Aug 12 01:21:21 2017 +0000
@@ -28,15 +28,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public class Thread_join03 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     private static class TestClass implements Runnable {
         @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_sleep01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Thread_sleep01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test(int i) throws InterruptedException {
         final long before = System.currentTimeMillis();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.jtt/src/org/graalvm/compiler/jtt/threads/Thread_yield01.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,15 +25,15 @@
 package org.graalvm.compiler.jtt.threads;
 
 import org.graalvm.compiler.jtt.JTTTest;
+import org.graalvm.compiler.jtt.hotspot.NotOnDebug;
 import org.junit.Rule;
 import org.junit.Test;
-import org.junit.rules.DisableOnDebug;
 import org.junit.rules.TestRule;
 import org.junit.rules.Timeout;
 
 public final class Thread_yield01 extends JTTTest {
 
-    @Rule public TestRule timeout = new DisableOnDebug(Timeout.seconds(20));
+    @Rule public TestRule timeout = NotOnDebug.create(Timeout.seconds(20));
 
     public static boolean test() {
         Thread.yield();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Sat Aug 12 01:21:21 2017 +0000
@@ -110,6 +110,8 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            boolean isNegated = false;
+            int jccPos = masm.position();
             /*
              * The strategy for emitting jumps is: If either trueDestination or falseDestination is
              * the successor block, assume the block scheduler did the correct thing and jcc to the
@@ -120,15 +122,18 @@
              */
             if (crb.isSuccessorEdge(trueDestination)) {
                 jcc(masm, true, falseDestination);
+                isNegated = true;
             } else if (crb.isSuccessorEdge(falseDestination)) {
                 jcc(masm, false, trueDestination);
             } else if (trueDestinationProbability < 0.5) {
                 jcc(masm, true, falseDestination);
                 masm.jmp(trueDestination.label());
+                isNegated = true;
             } else {
                 jcc(masm, false, trueDestination);
                 masm.jmp(falseDestination.label());
             }
+            crb.recordBranch(jccPos, isNegated);
         }
 
         protected void jcc(AMD64MacroAssembler masm, boolean negate, LabelRef target) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Sat Aug 12 01:21:21 2017 +0000
@@ -34,11 +34,11 @@
 
 import org.graalvm.compiler.asm.AbstractAddress;
 import org.graalvm.compiler.asm.Assembler;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation;
 import org.graalvm.compiler.code.DataSection.Data;
 import org.graalvm.compiler.code.DataSection.RawData;
-import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.core.common.type.DataPointerConstant;
@@ -130,12 +130,12 @@
     /**
      * The LIR for which code is being generated.
      */
-    private LIR lir;
+    protected LIR lir;
 
     /**
      * The index of the block currently being emitted.
      */
-    private int currentBlockIndex;
+    protected int currentBlockIndex;
 
     /**
      * The object that emits code for managing a method's frame.
@@ -313,6 +313,15 @@
     }
 
     /**
+     * Notifies this object of a branch instruction at offset {@code pos} in the code.
+     *
+     * @param isNegated negation status of the branch's condition.
+     */
+    @SuppressWarnings("unused")
+    public void recordBranch(int pos, boolean isNegated) {
+    }
+
+    /**
      * Returns the integer value of any constant that can be represented by a 32-bit integer value,
      * including long constants that fit into the 32-bit range.
      */
@@ -520,4 +529,5 @@
     public OptionValues getOptions() {
         return options;
     }
+
 }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.phases/src/org/graalvm/compiler/loop/phases/LoopTransformations.java	Sat Aug 12 01:21:21 2017 +0000
@@ -22,6 +22,14 @@
  */
 package org.graalvm.compiler.loop.phases;
 
+import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
+import static org.graalvm.compiler.loop.MathUtil.add;
+import static org.graalvm.compiler.loop.MathUtil.sub;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 import org.graalvm.compiler.core.common.RetryableBailoutException;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
@@ -56,18 +64,9 @@
 import org.graalvm.compiler.nodes.calc.ConditionalNode;
 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
 import org.graalvm.compiler.nodes.extended.SwitchNode;
-import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
 
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
-import static org.graalvm.compiler.loop.MathUtil.add;
-import static org.graalvm.compiler.loop.MathUtil.sub;
-
 public abstract class LoopTransformations {
 
     private LoopTransformations() {
@@ -282,10 +281,10 @@
 
             // The pre and post loops don't require safepoints at all
             for (SafepointNode safepoint : preLoop.nodes().filter(SafepointNode.class)) {
-                GraphUtil.removeFixedWithUnusedInputs(safepoint);
+                graph.removeFixed(safepoint);
             }
             for (SafepointNode safepoint : postLoop.nodes().filter(SafepointNode.class)) {
-                GraphUtil.removeFixedWithUnusedInputs(safepoint);
+                graph.removeFixed(safepoint);
             }
         }
         graph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph, "InsertPrePostLoops %s", loop);
@@ -442,7 +441,7 @@
     }
 
     public static boolean isUnrollableLoop(LoopEx loop) {
-        if (!loop.isCounted() || !loop.counted().getCounter().isConstantStride()) {
+        if (!loop.isCounted() || !loop.counted().getCounter().isConstantStride() || !loop.loop().getChildren().isEmpty()) {
             return false;
         }
         LoopBeginNode loopBegin = loop.loopBegin();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Sat Aug 12 01:21:21 2017 +0000
@@ -22,6 +22,9 @@
  */
 package org.graalvm.compiler.loop;
 
+import java.util.LinkedList;
+import java.util.List;
+
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
@@ -60,9 +63,6 @@
 import org.graalvm.util.EconomicMap;
 import org.graalvm.util.Equivalence;
 
-import java.util.LinkedList;
-import java.util.List;
-
 public class LoopFragmentInside extends LoopFragment {
 
     /**
@@ -153,7 +153,7 @@
             if (duplicatedNode != null) {
                 mainPhiNode.setValueAt(1, duplicatedNode);
             } else {
-                assert mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1));
+                assert mainPhiNode.valueAt(1).isConstant() || mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1)) : mainPhiNode.valueAt(1);
             }
         }
 
@@ -162,7 +162,7 @@
         // Remove any safepoints from the original copy leaving only the duplicated one
         assert loop.whole().nodes().filter(SafepointNode.class).count() == nodes().filter(SafepointNode.class).count();
         for (SafepointNode safepoint : loop.whole().nodes().filter(SafepointNode.class)) {
-            GraphUtil.removeFixedWithUnusedInputs(safepoint);
+            graph().removeFixed(safepoint);
         }
 
         int unrollFactor = mainLoopBegin.getUnrollFactor();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayDuplicationBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayDuplicationBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,110 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-package micro.benchmarks;
-
-import java.util.Arrays;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Level;
-import org.openjdk.jmh.annotations.OperationsPerInvocation;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.Setup;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.TearDown;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-@State(Scope.Thread)
-public class ArrayDuplicationBenchmark extends GraalBenchmark {
-
-    /** How large should the test-arrays be. */
-    private static final int TESTSIZE = 300;
-
-    private Object[][] testObjectArray;
-
-    private Object[] dummy;
-
-    @Setup
-    public void setup() {
-        testObjectArray = new Object[TESTSIZE][];
-        for (int i = 0; i < TESTSIZE; i++) {
-            testObjectArray[i] = new Object[20];
-        }
-    }
-
-    @Setup(Level.Iteration)
-    public void iterationSetup() {
-        dummy = new Object[TESTSIZE * 3];
-    }
-
-    @TearDown(Level.Iteration)
-    public void iterationTearDown() {
-        dummy = null;
-    }
-
-    @Benchmark
-    @OperationsPerInvocation(TESTSIZE)
-    public Object[] normalArraycopy() {
-        int j = 0;
-        for (int i = 0; i < TESTSIZE; i++) {
-            dummy[j++] = normalArraycopy(testObjectArray[i]);
-        }
-        return dummy;
-    }
-
-    public Object[] normalArraycopy(Object[] cache) {
-        Object[] result = new Object[cache.length];
-        System.arraycopy(cache, 0, result, 0, result.length);
-        return result;
-    }
-
-    @Benchmark
-    @OperationsPerInvocation(TESTSIZE)
-    public Object[] arraysCopyOf() {
-        int j = 0;
-        for (int i = 0; i < TESTSIZE; i++) {
-            dummy[j++] = arraysCopyOf(testObjectArray[i]);
-        }
-        return dummy;
-    }
-
-    public Object[] arraysCopyOf(Object[] cache) {
-        return Arrays.copyOf(cache, cache.length);
-    }
-
-    @Benchmark
-    @OperationsPerInvocation(TESTSIZE)
-    public Object[] cloneObjectArray() {
-        int j = 0;
-        for (int i = 0; i < TESTSIZE; i++) {
-            dummy[j++] = arraysClone(testObjectArray[i]);
-        }
-        return dummy;
-    }
-
-    @SuppressWarnings("cast")
-    public Object[] arraysClone(Object[] cache) {
-        return (Object[]) cache.clone();
-    }
-
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ArrayListBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, 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.
- */
-package micro.benchmarks;
-
-import java.util.ArrayList;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Level;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.Setup;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-/**
- * Benchmarks cost of ArrayList.
- */
-public class ArrayListBenchmark extends GraalBenchmark {
-
-    private static final int N = 100;
-
-    @State(Scope.Benchmark)
-    public static class ThreadState {
-        final ArrayList list = new ArrayList<>(N);
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public void addBoxedAndClear(ThreadState state) {
-        for (int i = 0; i < N; ++i) {
-            state.list.add(i);
-        }
-        state.list.clear();
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public void addNullAndClear(ThreadState state) {
-        for (int i = 0; i < N; ++i) {
-            state.list.add(null);
-        }
-        state.list.clear();
-    }
-
-    @State(Scope.Benchmark)
-    public static class ClearedThreadState {
-        final ArrayList list = new ArrayList<>(N);
-
-        // We don't want to measure the cost of list clearing
-        @Setup(Level.Invocation)
-        public void beforeInvocation() {
-            list.clear();
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public void addNull(ClearedThreadState state) {
-        for (int i = 0; i < N; ++i) {
-            state.list.add(null);
-        }
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/BoxingBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/BoxingBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, 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.
- */
-package micro.benchmarks;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-/**
- * Benchmarks cost of ArrayList.
- */
-public class BoxingBenchmark extends GraalBenchmark {
-
-    @State(Scope.Benchmark)
-    public static class ThreadState {
-        int value = 42;
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public Integer addBoxed(ThreadState state) {
-        return Integer.valueOf(state.value);
-    }
-
-    @SuppressWarnings("unused")
-    @Benchmark
-    @Warmup(iterations = 20)
-    public int doNothing(ThreadState state) {
-        return 42;
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ConcurrentSkipListBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/ConcurrentSkipListBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, 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.
- */
-package micro.benchmarks;
-
-import java.util.concurrent.ConcurrentSkipListMap;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-/**
- * Benchmarks cost of ArrayList.
- */
-public class ConcurrentSkipListBenchmark extends GraalBenchmark {
-
-    private static final int N = 100;
-
-    @State(Scope.Benchmark)
-    public static class ThreadState {
-        ConcurrentSkipListMap list = new ConcurrentSkipListMap<>();
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public void addBoxed(ThreadState state) {
-        for (int i = 0; i < N; ++i) {
-            state.list.put(i, i);
-        }
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/GuardedIntrinsicBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/GuardedIntrinsicBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-package micro.benchmarks;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Level;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.Setup;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-/**
- * Benchmarks cost of guarded intrinsics at indirect call sites.
- */
-public class GuardedIntrinsicBenchmark extends GraalBenchmark {
-
-    public static class HashcodeState {
-        public Object val1;
-        public Object val2;
-
-        public HashcodeState(Object val1, Object val2) {
-            this.val1 = val1;
-            this.val2 = val2;
-        }
-
-        int getNextHashCode() {
-            return val1.hashCode();
-        }
-
-        protected void swap() {
-            Object tmp = val1;
-            val1 = val2;
-            val2 = tmp;
-        }
-    }
-
-    /**
-     * Objects that all override {@link Object#hashCode()}. The objects used have hashCode
-     * implementations that are basically getters as we want to measure the overhead of hashCode
-     * dispatch, not the cost of the hashCode implementation.
-     */
-    @State(Scope.Benchmark)
-    public static class OverrideHashcode extends HashcodeState {
-        public OverrideHashcode() {
-            super(Short.valueOf((short) 100), Integer.valueOf(42));
-        }
-
-        @Setup(Level.Invocation)
-        public void beforeInvocation() {
-            swap();
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 10)
-    public int overrideHashCode(OverrideHashcode state) {
-        return state.getNextHashCode();
-    }
-
-    /**
-     * Objects that do not override {@link Object#hashCode()}.
-     */
-    @State(Scope.Benchmark)
-    public static class InheritHashcode extends HashcodeState {
-        public InheritHashcode() {
-            super(Class.class, Runtime.getRuntime());
-        }
-
-        @Setup(Level.Invocation)
-        public void beforeInvocation() {
-            swap();
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 10)
-    public int inheritHashCode(InheritHashcode state) {
-        return state.getNextHashCode();
-    }
-
-    /**
-     * Some objects that override {@link Object#hashCode()} and some that don't.
-     */
-    @State(Scope.Benchmark)
-    public static class MixedHashcode extends HashcodeState {
-        public MixedHashcode() {
-            super(Short.valueOf((short) 100), Runtime.getRuntime());
-        }
-
-        @Setup(Level.Invocation)
-        public void beforeInvocation() {
-            swap();
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 10)
-    public int mixedHashCode(MixedHashcode state) {
-        return state.getNextHashCode();
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/HashBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/HashBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, 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.
- */
-package micro.benchmarks;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-/**
- * Benchmarks cost of hasing a character array.
- */
-public class HashBenchmark extends GraalBenchmark {
-
-    @State(Scope.Benchmark)
-    public static class ThreadState {
-        char[] characters = ("Hello world from the HashBenchmark!").toCharArray();
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public int hash(ThreadState state) {
-        int value = 0;
-        char[] array = state.characters;
-        for (int i = 0; i < array.length; ++i) {
-            value = value * 31 + array[i];
-        }
-        return value;
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/MathFunctionBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/MathFunctionBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-package micro.benchmarks;
-
-import java.util.Random;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-/**
- * Benchmarks cost of Math intrinsics.
- */
-public class MathFunctionBenchmark extends GraalBenchmark {
-
-    @State(Scope.Benchmark)
-    public static class ThreadState {
-        double[] data = randomDoubles(100);
-        double[] result = new double[100];
-
-        static double[] randomDoubles(int len) {
-            double[] data = new double[len];
-            Random r = new Random();
-            for (int i = 0; i < data.length; i++) {
-                data[i] = r.nextDouble();
-            }
-            return data;
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 5)
-    public void mathLog(ThreadState state) {
-        double[] data = state.data;
-        for (int i = 0; i < data.length; i++) {
-            double[] result = state.result;
-            result[i] = Math.log(data[i]);
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 5)
-    public void mathLog10(ThreadState state) {
-        double[] data = state.data;
-        for (int i = 0; i < data.length; i++) {
-            double[] result = state.result;
-            result[i] = Math.log10(data[i]);
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 5)
-    public void mathSin(ThreadState state) {
-        double[] data = state.data;
-        for (int i = 0; i < data.length; i++) {
-            double[] result = state.result;
-            result[i] = Math.sin(data[i]);
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 5)
-    public void mathCos(ThreadState state) {
-        double[] data = state.data;
-        for (int i = 0; i < data.length; i++) {
-            double[] result = state.result;
-            result[i] = Math.cos(data[i]);
-        }
-    }
-
-    @Benchmark
-    @Warmup(iterations = 5)
-    public void mathTan(ThreadState state) {
-        double[] data = state.data;
-        for (int i = 0; i < data.length; i++) {
-            double[] result = state.result;
-            result[i] = Math.tan(data[i]);
-        }
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/SimpleSyncBenchmark.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/SimpleSyncBenchmark.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- */
-package micro.benchmarks;
-
-import org.openjdk.jmh.annotations.Benchmark;
-import org.openjdk.jmh.annotations.Scope;
-import org.openjdk.jmh.annotations.State;
-import org.openjdk.jmh.annotations.Warmup;
-
-import org.graalvm.compiler.microbenchmarks.graal.GraalBenchmark;
-
-/**
- * Benchmarks cost of non-contended synchronization.
- */
-public class SimpleSyncBenchmark extends GraalBenchmark {
-
-    public static class Person {
-        public int age;
-
-        public Person(int age) {
-            this.age = age;
-        }
-
-        public synchronized int getAge() {
-            return age;
-        }
-
-        public synchronized void setAge(int age) {
-            this.age = age;
-        }
-
-        public synchronized void setAgeIfNonZero(int age) {
-            if (age != 0) {
-                this.age = age;
-            }
-        }
-    }
-
-    @State(Scope.Benchmark)
-    public static class ThreadState {
-        Person person = new Person(22);
-        int newAge = 45;
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public void setAgeCond(ThreadState state) {
-        Person person = state.person;
-        person.setAgeIfNonZero(state.newAge);
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public int getAge(ThreadState state) {
-        Person person = state.person;
-        return person.getAge();
-    }
-
-    @Benchmark
-    @Warmup(iterations = 20)
-    public int getAndIncAge(ThreadState state) {
-        Person person = state.person;
-        int oldAge = person.getAge();
-        person.setAge(oldAge + 1);
-        return oldAge;
-    }
-}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/package-info.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.microbenchmarks/src/micro/benchmarks/package-info.java	Sat Aug 12 02:13:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-/*
- * Copyright (c) 2016, 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.
- */
-/**
- * This package contains micro benchmarks outside the org.graalvm.compiler namespace so that they
- * will be subject to Graal compilation even if {@code -Dgraal.CompileGraalWithC1Only=true}.
- */
-package micro.benchmarks;
\ No newline at end of file
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/ConditionalNode.java	Sat Aug 12 01:21:21 2017 +0000
@@ -145,14 +145,45 @@
     }
 
     public static ValueNode canonicalizeConditional(LogicNode condition, ValueNode trueValue, ValueNode falseValue, Stamp stamp) {
-        // this optimizes the case where a value that can only be 0 or 1 is materialized to 0 or 1
-        if (trueValue.isConstant() && falseValue.isConstant() && condition instanceof IntegerEqualsNode) {
-            IntegerEqualsNode equals = (IntegerEqualsNode) condition;
-            if (equals.getY().isConstant() && equals.getY().asConstant().equals(JavaConstant.INT_0) && equals.getX().stamp() instanceof IntegerStamp) {
-                IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
-                if (equalsXStamp.upMask() == 1) {
-                    if (trueValue.asConstant().equals(JavaConstant.INT_0) && falseValue.asConstant().equals(JavaConstant.INT_1)) {
-                        return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
+        // this optimizes the case where a value from the range 0 - 1 is mapped to the range 0 - 1
+        if (trueValue.isConstant() && falseValue.isConstant() && trueValue.stamp() instanceof IntegerStamp && falseValue.stamp() instanceof IntegerStamp) {
+            long constTrueValue = trueValue.asJavaConstant().asLong();
+            long constFalseValue = falseValue.asJavaConstant().asLong();
+            if (condition instanceof IntegerEqualsNode) {
+                IntegerEqualsNode equals = (IntegerEqualsNode) condition;
+                if (equals.getY().isConstant() && equals.getX().stamp() instanceof IntegerStamp) {
+                    IntegerStamp equalsXStamp = (IntegerStamp) equals.getX().stamp();
+                    if (equalsXStamp.upMask() == 1) {
+                        long equalsY = equals.getY().asJavaConstant().asLong();
+                        if (equalsY == 0) {
+                            if (constTrueValue == 0 && constFalseValue == 1) {
+                                // return x when: x == 0 ? 0 : 1;
+                                return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
+                            } else if (constTrueValue == 1 && constFalseValue == 0) {
+                                // negate a boolean value via xor
+                                return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
+                            }
+                        } else if (equalsY == 1) {
+                            if (constTrueValue == 1 && constFalseValue == 0) {
+                                // return x when: x == 1 ? 1 : 0;
+                                return IntegerConvertNode.convertUnsigned(equals.getX(), stamp);
+                            } else if (constTrueValue == 0 && constFalseValue == 1) {
+                                // negate a boolean value via xor
+                                return IntegerConvertNode.convertUnsigned(XorNode.create(equals.getX(), ConstantNode.forIntegerStamp(equals.getX().stamp(), 1)), stamp);
+                            }
+                        }
+                    }
+                }
+            } else if (condition instanceof IntegerTestNode) {
+                // replace IntegerTestNode with AndNode for the following patterns:
+                // (value & 1) == 0 ? 0 : 1
+                // (value & 1) == 1 ? 1 : 0
+                IntegerTestNode integerTestNode = (IntegerTestNode) condition;
+                if (integerTestNode.getY().isConstant()) {
+                    assert integerTestNode.getX().stamp() instanceof IntegerStamp;
+                    long testY = integerTestNode.getY().asJavaConstant().asLong();
+                    if (testY == 1 && constTrueValue == 0 && constFalseValue == 1) {
+                        return IntegerConvertNode.convertUnsigned(AndNode.create(integerTestNode.getX(), integerTestNode.getY()), stamp);
                     }
                 }
             }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/IntegerEqualsNode.java	Sat Aug 12 01:21:21 2017 +0000
@@ -153,6 +153,7 @@
             } else if (forX.stamp().alwaysDistinct(forY.stamp())) {
                 return LogicConstantNode.contradiction();
             }
+
             if (forX instanceof AddNode && forY instanceof AddNode) {
                 AddNode addX = (AddNode) forX;
                 AddNode addY = (AddNode) forY;
@@ -176,6 +177,7 @@
                     return create(v1, v2);
                 }
             }
+
             return super.canonical(constantReflection, metaAccess, options, smallestCompareWidth, condition, unorderedIsTrue, forX, forY);
         }
 
@@ -255,6 +257,15 @@
                         return new LogicNegationNode(new IntegerTestNode(andNode.getX(), andNode.getY()));
                     }
                 }
+
+                if (nonConstant instanceof XorNode && nonConstant.stamp() instanceof IntegerStamp) {
+                    XorNode xorNode = (XorNode) nonConstant;
+                    if (xorNode.getY().isJavaConstant() && xorNode.getY().asJavaConstant().asLong() == 1 && ((IntegerStamp) xorNode.getX().stamp()).upMask() == 1) {
+                        // x ^ 1 == 0 is the same as x == 1 if x in [0, 1]
+                        // x ^ 1 == 1 is the same as x == 0 if x in [0, 1]
+                        return new IntegerEqualsNode(xorNode.getX(), ConstantNode.forIntegerStamp(xorNode.getX().stamp(), primitiveConstant.asLong() ^ 1));
+                    }
+                }
             }
             return super.canonicalizeSymmetricConstant(constantReflection, metaAccess, options, smallestCompareWidth, condition, constant, nonConstant, mirrored, unorderedIsTrue);
         }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/StateSplitProxyNode.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/StateSplitProxyNode.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/StateSplitProxyNode.java	Sat Aug 12 01:21:21 2017 +0000
@@ -37,6 +37,9 @@
 
 /**
  * This node provides a state split along with the functionality of {@link FixedValueAnchorNode}.
+ * This is used to capture a state for deoptimization when a node has side effects which aren't
+ * easily represented. The anchored value is usually part of the FrameState since this forces uses
+ * of the value below this node so they will consume this frame state instead of an earlier one.
  */
 @NodeInfo(cycles = CYCLES_0, size = SIZE_0)
 public final class StateSplitProxyNode extends FixedValueAnchorNode implements Canonicalizable, StateSplit {
@@ -44,6 +47,19 @@
     public static final NodeClass TYPE = NodeClass.create(StateSplitProxyNode.class);
 
     @OptionalInput(InputType.State) FrameState stateAfter;
+    /**
+     * Disallows elimination of this node until after the FrameState has been consumed.
+     */
+    private final boolean delayElimination;
+
+    public StateSplitProxyNode(ValueNode object) {
+        this(object, false);
+    }
+
+    public StateSplitProxyNode(ValueNode object, boolean delayElimination) {
+        super(TYPE, object);
+        this.delayElimination = delayElimination;
+    }
 
     @Override
     public FrameState stateAfter() {
@@ -62,13 +78,9 @@
         return true;
     }
 
-    public StateSplitProxyNode(ValueNode object) {
-        super(TYPE, object);
-    }
-
     @Override
     public Node canonical(CanonicalizerTool tool) {
-        if (object.isConstant()) {
+        if (object.isConstant() && !delayElimination || stateAfter == null) {
             return object;
         }
         return this;
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/GraphBuilderContext.java	Sat Aug 12 01:21:21 2017 +0000
@@ -34,8 +34,8 @@
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
 import org.graalvm.compiler.nodes.CallTargetNode;
+import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.graalvm.compiler.nodes.ConstantNode;
-import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.graalvm.compiler.nodes.FixedGuardNode;
 import org.graalvm.compiler.nodes.LogicNode;
 import org.graalvm.compiler.nodes.PiNode;
@@ -241,7 +241,12 @@
      */
     default int getDepth() {
         GraphBuilderContext parent = getParent();
-        return parent == null ? 0 : 1 + parent.getDepth();
+        int result = 0;
+        while (parent != null) {
+            result++;
+            parent = parent.getParent();
+        }
+        return result;
     }
 
     /**
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoadIndexedNode.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,6 +25,7 @@
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_8;
 
+import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.TypeReference;
@@ -84,10 +85,21 @@
         if (kind == JavaKind.Object && type != null && type.isArray()) {
             return StampFactory.object(TypeReference.createTrusted(assumptions, type.getComponentType()));
         } else {
-            return StampFactory.forKind(kind);
+            JavaKind preciseKind = determinePreciseArrayElementType(array, kind);
+            return StampFactory.forKind(preciseKind);
         }
     }
 
+    private static JavaKind determinePreciseArrayElementType(ValueNode array, JavaKind kind) {
+        if (kind == JavaKind.Byte) {
+            ResolvedJavaType javaType = ((ObjectStamp) array.stamp()).type();
+            if (javaType != null && javaType.isArray() && javaType.getComponentType() != null && javaType.getComponentType().getJavaKind() == JavaKind.Boolean) {
+                return JavaKind.Boolean;
+            }
+        }
+        return kind;
+    }
+
     @Override
     public boolean inferStamp() {
         return updateStamp(stamp.improveWith(createStamp(graph().getAssumptions(), array(), elementKind())));
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java	Sat Aug 12 01:21:21 2017 +0000
@@ -47,6 +47,7 @@
 import org.graalvm.compiler.phases.Phase;
 
 public class ExpandLogicPhase extends Phase {
+    private static final double EPSILON = 1E-6;
 
     @Override
     protected void run(StructuredGraph graph) {
@@ -99,18 +100,39 @@
     }
 
     private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
+        /*
+         * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into two
+         * separate IfNodes: if(X) and if(Y)
+         *
+         * for computing the probabilities P(X) and P(Y), we use two different approaches. The first
+         * one assumes that the shortCircuitProbability and the probability on the IfNode were
+         * created with each other in mind. If this assumption does not hold, we fall back to
+         * another mechanism for computing the probabilities.
+         */
         AbstractBeginNode trueTarget = ifNode.trueSuccessor();
         AbstractBeginNode falseTarget = ifNode.falseSuccessor();
-        // while the first if node is reached by all cases, the true values are split between the
-        // first and the second if
-        double firstIfProbability = ifNode.probability(trueTarget) * shortCircuitProbability;
-        // the second if node is reached by a reduced number of true cases but the same number of
-        // false cases
-        double secondIfProbability = 1 - ifNode.probability(falseTarget) / (1 - firstIfProbability);
-        secondIfProbability = Math.min(1.0, Math.max(0.0, secondIfProbability));
-        if (Double.isNaN(secondIfProbability)) {
-            secondIfProbability = 0.5;
+
+        // 1st approach
+        // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
+        double firstIfTrueProbability = shortCircuitProbability;
+        double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
+        double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
+
+        if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
+            /*
+             * 2nd approach
+             *
+             * the assumption above did not hold, so we either used an artificial probability as
+             * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
+             *
+             * so, we distribute the if's trueSuccessorProbability between the newly generated if
+             * nodes according to the shortCircuitProbability. the following invariant is always
+             * true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
+             */
+            firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
+            secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
         }
+
         ifNode.clearSuccessors();
         Graph graph = ifNode.graph();
         AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
@@ -122,17 +144,30 @@
         AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
         AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
         if (yNegated) {
-            secondIfProbability = 1.0 - secondIfProbability;
+            secondIfTrueProbability = 1.0 - secondIfTrueProbability;
         }
         if (xNegated) {
-            firstIfProbability = 1.0 - firstIfProbability;
+            firstIfTrueProbability = 1.0 - firstIfTrueProbability;
         }
-        AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfProbability)));
-        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfProbability));
+        AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
+        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
         ifNode.replaceAtPredecessor(firstIf);
         ifNode.safeDelete();
     }
 
+    private static boolean doubleEquals(double a, double b) {
+        assert !Double.isNaN(a) && !Double.isNaN(b) && !Double.isInfinite(a) && !Double.isInfinite(b);
+        return a - EPSILON < b && a + EPSILON > b;
+    }
+
+    private static double sanitizeProbability(double value) {
+        double newValue = Math.min(1.0, Math.max(0.0, value));
+        if (Double.isNaN(newValue)) {
+            newValue = 0.5;
+        }
+        return newValue;
+    }
+
     private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional) {
         ValueNode trueTarget = conditional.trueValue();
         ValueNode falseTarget = conditional.falseValue();
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java	Sat Aug 12 01:21:21 2017 +0000
@@ -42,6 +42,8 @@
 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
 import org.graalvm.util.EconomicMap;
 
+import jdk.vm.ci.code.BytecodeFrame;
+
 /**
  * This phase transfers {@link FrameState} nodes from {@link StateSplit} nodes to
  * {@link DeoptimizingNode DeoptimizingNodes}.
@@ -71,7 +73,11 @@
                 StateSplit stateSplit = (StateSplit) node;
                 FrameState stateAfter = stateSplit.stateAfter();
                 if (stateAfter != null) {
-                    currentState = stateAfter;
+                    if (stateAfter.bci == BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+                        currentState = null;
+                    } else {
+                        currentState = stateAfter;
+                    }
                     stateSplit.setStateAfter(null);
                 }
             }
@@ -141,7 +147,10 @@
                 return null;
             }
         }
-        return singleState;
+        if (singleState != null && singleState.bci != BytecodeFrame.INVALID_FRAMESTATE_BCI) {
+            return singleState;
+        }
+        return null;
     }
 
     @Override
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/PhaseSuite.java	Sat Aug 12 01:21:21 2017 +0000
@@ -131,13 +131,13 @@
         return findNextPhase(it, phaseClass, false);
     }
 
+    @SuppressWarnings("unchecked")
     public static  boolean findNextPhase(ListIterator> it, Class> phaseClass, boolean recursive) {
         while (it.hasNext()) {
             BasePhase phase = it.next();
             if (phaseClass.isInstance(phase)) {
                 return true;
             } else if (recursive && phase instanceof PhaseSuite) {
-                @SuppressWarnings("unchecked")
                 PhaseSuite suite = (PhaseSuite) phase;
                 if (suite.findPhase(phaseClass, true) != null) {
                     return true;
@@ -151,6 +151,7 @@
      * Removes the first instance of the given phase class, looking recursively into inner phase
      * suites.
      */
+    @SuppressWarnings("unchecked")
     public boolean removePhase(Class> phaseClass) {
         ListIterator> it = phases.listIterator();
         while (it.hasNext()) {
@@ -159,7 +160,6 @@
                 it.remove();
                 return true;
             } else if (phase instanceof PhaseSuite) {
-                @SuppressWarnings("unchecked")
                 PhaseSuite innerSuite = (PhaseSuite) phase;
                 if (innerSuite.removePhase(phaseClass)) {
                     if (innerSuite.phases.isEmpty()) {
@@ -176,6 +176,7 @@
      * Removes the first instance of the given phase class, looking recursively into inner phase
      * suites.
      */
+    @SuppressWarnings("unchecked")
     public boolean replacePhase(Class> phaseClass, BasePhase newPhase) {
         ListIterator> it = phases.listIterator();
         while (it.hasNext()) {
@@ -184,7 +185,6 @@
                 it.set(newPhase);
                 return true;
             } else if (phase instanceof PhaseSuite) {
-                @SuppressWarnings("unchecked")
                 PhaseSuite innerSuite = (PhaseSuite) phase;
                 if (innerSuite.removePhase(phaseClass)) {
                     if (innerSuite.phases.isEmpty()) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,7 +25,6 @@
 import static org.graalvm.compiler.debug.DebugConfig.asJavaMethod;
 
 import java.io.IOException;
-import java.lang.management.ManagementFactory;
 import java.nio.channels.ClosedByInterruptException;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -82,10 +81,18 @@
     public GraphPrinterDumpHandler(GraphPrinterSupplier printerSupplier) {
         this.printerSupplier = printerSupplier;
         /* Add the JVM and Java arguments to the graph properties to help identify it. */
-        this.jvmArguments = String.join(" ", ManagementFactory.getRuntimeMXBean().getInputArguments());
+        this.jvmArguments = jvmArguments();
         this.sunJavaCommand = System.getProperty("sun.java.command");
     }
 
+    private static String jvmArguments() {
+        try {
+            return String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
+        } catch (LinkageError err) {
+            return "unknown";
+        }
+    }
+
     private void ensureInitialized(Graph graph) {
         if (printer == null) {
             if (failuresCount >= FAILURE_LIMIT) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTrackingTest.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTrackingTest.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTrackingTest.java	Sat Aug 12 01:21:21 2017 +0000
@@ -24,6 +24,8 @@
 
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.debug.DebugCloseable;
+import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
@@ -80,7 +82,10 @@
     @Test(expected = GraalError.class)
     @SuppressWarnings("try")
     public void testVerification() {
-        compile(getResolvedJavaMethod("verificationSnippet"), null);
+        DebugContext debug = getDebugContext();
+        try (DebugCloseable d = debug.disableIntercept(); DebugContext.Scope s = debug.scope("PointerTrackingTest")) {
+            compile(getResolvedJavaMethod("verificationSnippet"), null);
+        }
     }
 
     public static long verificationSnippet(Object obj) {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Sat Aug 12 01:21:21 2017 +0000
@@ -29,24 +29,46 @@
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
+import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.core.common.type.StampFactory;
+import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.GraalGraphError;
 import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
+import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.debug.OpaqueNode;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Registration;
+import org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
+import org.graalvm.compiler.phases.common.FloatingReadPhase;
+import org.graalvm.compiler.phases.common.FrameStateAssignmentPhase;
+import org.graalvm.compiler.phases.common.GuardLoweringPhase;
+import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.graalvm.word.LocationIdentity;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
 import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 /**
@@ -158,6 +180,14 @@
         static int copyFirstL2R(byte[] left, byte[] right) {
             return copyFirstL2RBody(left, right);
         }
+
+        static int nonVoidIntrinsicWithCall(@SuppressWarnings("unused") int x, int y) {
+            return y;
+        }
+
+        static int nonVoidIntrinsicWithOptimizedSplit(int x) {
+            return x;
+        }
     }
 
     @ClassSubstitution(TestObject.class)
@@ -240,18 +270,45 @@
         private static String apply(Function f, String value) {
             return f.apply(value);
         }
+
+        @MethodSubstitution(isStatic = true)
+        static int nonVoidIntrinsicWithCall(int x, int y) {
+            nonVoidIntrinsicWithCallStub(x);
+            return y;
+        }
+
+        @MethodSubstitution(isStatic = true)
+        static int nonVoidIntrinsicWithOptimizedSplit(int x) {
+            if (x == GraalDirectives.opaque(x)) {
+                nonVoidIntrinsicWithCallStub(x);
+            }
+            return x;
+        }
+
+        public static void nonVoidIntrinsicWithCallStub(int zLen) {
+            nonVoidIntrinsicWithCallStub(STUB_CALL, zLen);
+        }
+
+        static final ForeignCallDescriptor STUB_CALL = new ForeignCallDescriptor("stubCall", void.class, int.class);
+
+        @NodeIntrinsic(ForeignCallNode.class)
+        private static native void nonVoidIntrinsicWithCallStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, int zLen);
+
     }
 
     @Override
     protected void registerInvocationPlugins(InvocationPlugins invocationPlugins) {
         BytecodeProvider replacementBytecodeProvider = getSystemClassLoaderBytecodeProvider();
         Registration r = new Registration(invocationPlugins, TestObject.class, replacementBytecodeProvider);
-        new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, null);
+        NodeIntrinsicPluginFactory.InjectionProvider injections = new DummyInjectionProvider();
+        new PluginFactory_ReplacementsParseTest().registerPlugins(invocationPlugins, injections);
         r.registerMethodSubstitution(TestObjectSubstitutions.class, "nextAfter", double.class, double.class);
         r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringize", Object.class);
         r.registerMethodSubstitution(TestObjectSubstitutions.class, "stringizeId", Receiver.class);
         r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirst", byte[].class, byte[].class, boolean.class);
         r.registerMethodSubstitution(TestObjectSubstitutions.class, "copyFirstL2R", byte[].class, byte[].class);
+        r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithCall", int.class, int.class);
+        r.registerMethodSubstitution(TestObjectSubstitutions.class, "nonVoidIntrinsicWithOptimizedSplit", int.class);
 
         if (replacementBytecodeProvider.supportsInvokedynamic()) {
             r.registerMethodSubstitution(TestObjectSubstitutions.class, "identity", String.class);
@@ -496,4 +553,108 @@
             inlineInvokeDecision = null;
         }
     }
+
+    public static int nonVoidIntrinsicWithCall(int x, int y) {
+        if (TestObject.nonVoidIntrinsicWithCall(x, y) == x) {
+            GraalDirectives.deoptimize();
+        }
+        return y;
+    }
+
+    /**
+     * This tests the case where an intrinsic ends with a runtime call but returns some kind of
+     * value. This requires that a FrameState is available after the {@link ForeignCallNode} since
+     * the return value must be computed on return from the call.
+     */
+    @Test
+    public void testNonVoidIntrinsicWithCall() {
+        testGraph("nonVoidIntrinsicWithCall");
+    }
+
+    public static int nonVoidIntrinsicWithOptimizedSplit(int x) {
+        if (TestObject.nonVoidIntrinsicWithOptimizedSplit(x) == x) {
+            GraalDirectives.deoptimize();
+        }
+        return x;
+    }
+
+    /**
+     * This is similar to {@link #testNonVoidIntrinsicWithCall()} but has a merge after the call
+     * which would normally capture the {@link FrameState} but in this case we force the merge to be
+     * optimized away.
+     */
+    @Test
+    public void testNonVoidIntrinsicWithOptimizedSplit() {
+        testGraph("nonVoidIntrinsicWithOptimizedSplit");
+    }
+
+    @SuppressWarnings("try")
+    private void testGraph(String name) {
+        StructuredGraph graph = parseEager(name, StructuredGraph.AllowAssumptions.YES);
+        try (DebugContext.Scope s0 = graph.getDebug().scope(name, graph)) {
+            for (OpaqueNode node : graph.getNodes().filter(OpaqueNode.class)) {
+                node.replaceAndDelete(node.getValue());
+            }
+            HighTierContext context = getDefaultHighTierContext();
+            CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+            new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, context);
+            new FloatingReadPhase().apply(graph);
+            canonicalizer.apply(graph, context);
+            new DeadCodeEliminationPhase().apply(graph);
+            new GuardLoweringPhase().apply(graph, getDefaultMidTierContext());
+            new FrameStateAssignmentPhase().apply(graph);
+        } catch (Throwable e) {
+            throw graph.getDebug().handle(e);
+        }
+    }
+
+    private class DummyInjectionProvider implements NodeIntrinsicPluginFactory.InjectionProvider {
+        @SuppressWarnings("unchecked")
+        @Override
+        public  T getInjectedArgument(Class type) {
+            if (type == ForeignCallsProvider.class) {
+                return (T) new ForeignCallsProvider() {
+                    @Override
+                    public LIRKind getValueKind(JavaKind javaKind) {
+                        return null;
+                    }
+
+                    @Override
+                    public boolean isReexecutable(ForeignCallDescriptor descriptor) {
+                        return false;
+                    }
+
+                    @Override
+                    public LocationIdentity[] getKilledLocations(ForeignCallDescriptor descriptor) {
+                        return new LocationIdentity[0];
+                    }
+
+                    @Override
+                    public boolean canDeoptimize(ForeignCallDescriptor descriptor) {
+                        return false;
+                    }
+
+                    @Override
+                    public boolean isGuaranteedSafepoint(ForeignCallDescriptor descriptor) {
+                        return false;
+                    }
+
+                    @Override
+                    public ForeignCallLinkage lookupForeignCall(ForeignCallDescriptor descriptor) {
+                        return null;
+                    }
+                };
+            }
+            if (type == SnippetReflectionProvider.class) {
+                return (T) getSnippetReflection();
+            }
+            return null;
+        }
+
+        @Override
+        public Stamp getInjectedStamp(Class type, boolean nonNull) {
+            JavaKind kind = JavaKind.fromJavaClass(type);
+            return StampFactory.forKind(kind);
+        }
+    }
 }
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/RedefineIntrinsicTest.java	Sat Aug 12 01:21:21 2017 +0000
@@ -100,6 +100,12 @@
 
     @Test
     public void test() throws Throwable {
+        try {
+            Class.forName("java.lang.instrument.Instrumentation");
+        } catch (ClassNotFoundException ex) {
+            // skip this test if java.instrument JDK9 module is missing
+            return;
+        }
         String recursionPropName = getClass().getName() + ".recursion";
         if (Java8OrEarlier || Boolean.getBoolean(recursionPropName)) {
             testHelper();
@@ -134,7 +140,10 @@
         testAgainstExpected(callIntrinsicGetValue, new Result("intrinsic", null), receiver, args);
 
         // Apply redefinition of intrinsic bytecode
-        redefineIntrinsic();
+        if (!redefineIntrinsic()) {
+            // running on JDK9 without agent
+            return;
+        }
 
         // Expect redefinition to have no effect
         Assert.assertEquals("original", Original.getValue());
@@ -166,7 +175,7 @@
         jar.closeEntry();
     }
 
-    static void redefineIntrinsic() throws Exception {
+    static boolean redefineIntrinsic() throws Exception {
         Manifest manifest = new Manifest();
         manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
         Attributes mainAttrs = manifest.getMainAttributes();
@@ -181,13 +190,13 @@
             add(jarStream, Redefiner.class);
             jarStream.close();
 
-            loadAgent(jar);
+            return loadAgent(jar);
         } finally {
             Files.deleteIfExists(jar);
         }
     }
 
-    public static void loadAgent(Path agent) throws Exception {
+    public static boolean loadAgent(Path agent) throws Exception {
         String vmName = ManagementFactory.getRuntimeMXBean().getName();
         int p = vmName.indexOf('@');
         assumeTrue("VM name not in @ format: " + vmName, p != -1);
@@ -197,8 +206,19 @@
             ClassLoader cl = ToolProvider.getSystemToolClassLoader();
             c = Class.forName("com.sun.tools.attach.VirtualMachine", true, cl);
         } else {
-            // I don't know what changed to make this necessary...
-            c = Class.forName("com.sun.tools.attach.VirtualMachine", true, RedefineIntrinsicTest.class.getClassLoader());
+            try {
+                // I don't know what changed to make this necessary...
+                c = Class.forName("com.sun.tools.attach.VirtualMachine", true, RedefineIntrinsicTest.class.getClassLoader());
+            } catch (ClassNotFoundException ex) {
+                try {
+                    Class.forName("javax.naming.Reference");
+                } catch (ClassNotFoundException coreNamingMissing) {
+                    // if core JDK classes aren't found, we are probably running in a
+                    // JDK9 java.base environment and then missing class is OK
+                    return false;
+                }
+                throw ex;
+            }
         }
         Method attach = c.getDeclaredMethod("attach", String.class);
         Method loadAgent = c.getDeclaredMethod("loadAgent", String.class, String.class);
@@ -206,6 +226,7 @@
         Object vm = attach.invoke(null, pid);
         loadAgent.invoke(vm, agent.toString(), "");
         detach.invoke(vm);
+        return true;
     }
 
     public static class RedefinerAgent {
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java	Sat Aug 12 01:21:21 2017 +0000
@@ -435,11 +435,11 @@
         }
 
         @Override
-        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode arg1, ValueNode arg2, ValueNode arg3, ValueNode arg4,
-                        ValueNode arg5, ValueNode arg6, ValueNode arg7) {
-            if (arg3.isConstant()) {
-                b.addPush(JavaKind.Int,
-                                new StringIndexOfNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), arg1, arg2, arg3, arg4, arg5, arg6, arg7));
+        public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, InvocationPlugin.Receiver receiver, ValueNode source, ValueNode sourceOffset, ValueNode sourceCount,
+                        ValueNode target, ValueNode targetOffset, ValueNode targetCount, ValueNode origFromIndex) {
+            if (target.isConstant()) {
+                b.addPush(JavaKind.Int, new StringIndexOfNode(b.getInvokeKind(), targetMethod, b.bci(), b.getInvokeReturnStamp(b.getAssumptions()), source, sourceOffset, sourceCount,
+                                target, targetOffset, targetCount, origFromIndex));
                 return true;
             }
             return false;
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecode.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecode.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecode.java	Sat Aug 12 01:21:21 2017 +0000
@@ -25,7 +25,6 @@
 import java.io.ByteArrayInputStream;
 import java.io.DataInputStream;
 import java.io.IOException;
-import java.lang.instrument.Instrumentation;
 
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
@@ -45,7 +44,8 @@
 
 /**
  * The bytecode properties of a method as parsed directly from a class file without any
- * {@linkplain Instrumentation instrumentation} or other rewriting performed on the bytecode.
+ * {@linkplain java.lang.instrument.Instrumentation instrumentation} or other rewriting performed on
+ * the bytecode.
  */
 public class ClassfileBytecode implements Bytecode {
 
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java	Sat Aug 12 01:21:21 2017 +0000
@@ -28,7 +28,6 @@
 import java.io.DataInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.lang.instrument.Instrumentation;
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.Bytecode;
@@ -45,8 +44,8 @@
 
 /**
  * A {@link BytecodeProvider} that provides bytecode properties of a {@link ResolvedJavaMethod} as
- * parsed from a class file. This avoids all {@linkplain Instrumentation instrumentation} and any
- * bytecode rewriting performed by the VM.
+ * parsed from a class file. This avoids all {@linkplain java.lang.instrument.Instrumentation
+ * instrumentation} and any bytecode rewriting performed by the VM.
  *
  * This mechanism retrieves class files based on the name and {@link ClassLoader} of existing
  * {@link Class} instances. It bypasses all VM parsing and verification of the class file and
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java	Sat Aug 12 02:13:29 2017 +0200
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java	Sat Aug 12 01:21:21 2017 +0000
@@ -263,10 +263,10 @@
     /**
      * This tries to canonicalize the node based on improved (replaced) inputs.
      */
+    @SuppressWarnings("unchecked")
     private boolean processNodeWithScalarReplacedInputs(ValueNode node, FixedNode insertBefore, BlockT state, GraphEffectList effects) {
         ValueNode canonicalizedValue = node;
         if (node instanceof Canonicalizable.Unary) {
-            @SuppressWarnings("unchecked")
             Canonicalizable.Unary canonicalizable = (Canonicalizable.Unary) node;
             ObjectState valueObj = getObjectState(state, canonicalizable.getValue());
             ValueNode valueAlias = valueObj != null ? valueObj.getMaterializedValue() : getScalarAlias(canonicalizable.getValue());
@@ -274,7 +274,6 @@
                 canonicalizedValue = (ValueNode) canonicalizable.canonical(tool, valueAlias);
             }
         } else if (node instanceof Canonicalizable.Binary) {
-            @SuppressWarnings("unchecked")
             Canonicalizable.Binary canonicalizable = (Canonicalizable.Binary) node;
             ObjectState xObj = getObjectState(state, canonicalizable.getX());
             ValueNode xAlias = xObj != null ? xObj.getMaterializedValue() : getScalarAlias(canonicalizable.getX());
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayDuplicationBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayDuplicationBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package micro.benchmarks;
+
+import java.util.Arrays;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.OperationsPerInvocation;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.TearDown;
+
+@State(Scope.Thread)
+public class ArrayDuplicationBenchmark extends BenchmarkBase {
+
+    /** How large should the test-arrays be. */
+    private static final int TESTSIZE = 300;
+
+    private Object[][] testObjectArray;
+
+    private Object[] dummy;
+
+    @Setup
+    public void setup() {
+        testObjectArray = new Object[TESTSIZE][];
+        for (int i = 0; i < TESTSIZE; i++) {
+            testObjectArray[i] = new Object[20];
+        }
+    }
+
+    @Setup(Level.Iteration)
+    public void iterationSetup() {
+        dummy = new Object[TESTSIZE * 3];
+    }
+
+    @TearDown(Level.Iteration)
+    public void iterationTearDown() {
+        dummy = null;
+    }
+
+    @Benchmark
+    @OperationsPerInvocation(TESTSIZE)
+    public Object[] normalArraycopy() {
+        int j = 0;
+        for (int i = 0; i < TESTSIZE; i++) {
+            dummy[j++] = normalArraycopy(testObjectArray[i]);
+        }
+        return dummy;
+    }
+
+    public Object[] normalArraycopy(Object[] cache) {
+        Object[] result = new Object[cache.length];
+        System.arraycopy(cache, 0, result, 0, result.length);
+        return result;
+    }
+
+    @Benchmark
+    @OperationsPerInvocation(TESTSIZE)
+    public Object[] arraysCopyOf() {
+        int j = 0;
+        for (int i = 0; i < TESTSIZE; i++) {
+            dummy[j++] = arraysCopyOf(testObjectArray[i]);
+        }
+        return dummy;
+    }
+
+    public Object[] arraysCopyOf(Object[] cache) {
+        return Arrays.copyOf(cache, cache.length);
+    }
+
+    @Benchmark
+    @OperationsPerInvocation(TESTSIZE)
+    public Object[] cloneObjectArray() {
+        int j = 0;
+        for (int i = 0; i < TESTSIZE; i++) {
+            dummy[j++] = arraysClone(testObjectArray[i]);
+        }
+        return dummy;
+    }
+
+    @SuppressWarnings("cast")
+    public Object[] arraysClone(Object[] cache) {
+        return (Object[]) cache.clone();
+    }
+
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayListBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ArrayListBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017, 2017, 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.
+ */
+package micro.benchmarks;
+
+import java.util.ArrayList;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of ArrayList.
+ */
+public class ArrayListBenchmark extends BenchmarkBase {
+
+    private static final int N = 100;
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+        final ArrayList list = new ArrayList<>(N);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public void addBoxedAndClear(ThreadState state) {
+        for (int i = 0; i < N; ++i) {
+            state.list.add(i);
+        }
+        state.list.clear();
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public void addNullAndClear(ThreadState state) {
+        for (int i = 0; i < N; ++i) {
+            state.list.add(null);
+        }
+        state.list.clear();
+    }
+
+    @State(Scope.Benchmark)
+    public static class ClearedThreadState {
+        final ArrayList list = new ArrayList<>(N);
+
+        // We don't want to measure the cost of list clearing
+        @Setup(Level.Invocation)
+        public void beforeInvocation() {
+            list.clear();
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public void addNull(ClearedThreadState state) {
+        for (int i = 0; i < N; ++i) {
+            state.list.add(null);
+        }
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/BenchmarkBase.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/BenchmarkBase.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2015, 2017, 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.
+ */
+package micro.benchmarks;
+
+import org.openjdk.jmh.annotations.Fork;
+import org.openjdk.jmh.annotations.Measurement;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Base class for JMH benchmarks.
+ */
+@Warmup(iterations = BenchmarkBase.Defaults.WARMUP_ITERATIONS)
+@Measurement(iterations = BenchmarkBase.Defaults.MEASUREMENT_ITERATIONS)
+@Fork(BenchmarkBase.Defaults.FORKS)
+public class BenchmarkBase {
+
+    public static class Defaults {
+        public static final int MEASUREMENT_ITERATIONS = 5;
+        public static final int WARMUP_ITERATIONS = 5;
+        public static final int FORKS = 1;
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/BoxingBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/BoxingBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 2017, 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.
+ */
+package micro.benchmarks;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of ArrayList.
+ */
+public class BoxingBenchmark extends BenchmarkBase {
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+        int value = 42;
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public Integer addBoxed(ThreadState state) {
+        return Integer.valueOf(state.value);
+    }
+
+    @SuppressWarnings("unused")
+    @Benchmark
+    @Warmup(iterations = 20)
+    public int doNothing(ThreadState state) {
+        return 42;
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ConcurrentSkipListBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/ConcurrentSkipListBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 2017, 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.
+ */
+package micro.benchmarks;
+
+import java.util.concurrent.ConcurrentSkipListMap;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of ArrayList.
+ */
+public class ConcurrentSkipListBenchmark extends BenchmarkBase {
+
+    private static final int N = 100;
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+        ConcurrentSkipListMap list = new ConcurrentSkipListMap<>();
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public void addBoxed(ThreadState state) {
+        for (int i = 0; i < N; ++i) {
+            state.list.put(i, i);
+        }
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/GuardedIntrinsicBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/GuardedIntrinsicBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package micro.benchmarks;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Level;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.Setup;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of guarded intrinsics at indirect call sites.
+ */
+public class GuardedIntrinsicBenchmark extends BenchmarkBase {
+
+    public static class HashcodeState {
+        public Object val1;
+        public Object val2;
+
+        public HashcodeState(Object val1, Object val2) {
+            this.val1 = val1;
+            this.val2 = val2;
+        }
+
+        int getNextHashCode() {
+            return val1.hashCode();
+        }
+
+        protected void swap() {
+            Object tmp = val1;
+            val1 = val2;
+            val2 = tmp;
+        }
+    }
+
+    /**
+     * Objects that all override {@link Object#hashCode()}. The objects used have hashCode
+     * implementations that are basically getters as we want to measure the overhead of hashCode
+     * dispatch, not the cost of the hashCode implementation.
+     */
+    @State(Scope.Benchmark)
+    public static class OverrideHashcode extends HashcodeState {
+        public OverrideHashcode() {
+            super(Short.valueOf((short) 100), Integer.valueOf(42));
+        }
+
+        @Setup(Level.Invocation)
+        public void beforeInvocation() {
+            swap();
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 10)
+    public int overrideHashCode(OverrideHashcode state) {
+        return state.getNextHashCode();
+    }
+
+    /**
+     * Objects that do not override {@link Object#hashCode()}.
+     */
+    @State(Scope.Benchmark)
+    public static class InheritHashcode extends HashcodeState {
+        public InheritHashcode() {
+            super(Class.class, Runtime.getRuntime());
+        }
+
+        @Setup(Level.Invocation)
+        public void beforeInvocation() {
+            swap();
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 10)
+    public int inheritHashCode(InheritHashcode state) {
+        return state.getNextHashCode();
+    }
+
+    /**
+     * Some objects that override {@link Object#hashCode()} and some that don't.
+     */
+    @State(Scope.Benchmark)
+    public static class MixedHashcode extends HashcodeState {
+        public MixedHashcode() {
+            super(Short.valueOf((short) 100), Runtime.getRuntime());
+        }
+
+        @Setup(Level.Invocation)
+        public void beforeInvocation() {
+            swap();
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 10)
+    public int mixedHashCode(MixedHashcode state) {
+        return state.getNextHashCode();
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/HashBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/HashBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 2017, 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.
+ */
+package micro.benchmarks;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of hashing a character array.
+ */
+public class HashBenchmark extends BenchmarkBase {
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+        char[] characters = ("Hello world from the HashBenchmark!").toCharArray();
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public int hash(ThreadState state) {
+        int value = 0;
+        char[] array = state.characters;
+        for (int i = 0; i < array.length; ++i) {
+            value = value * 31 + array[i];
+        }
+        return value;
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/MathFunctionBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/MathFunctionBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package micro.benchmarks;
+
+import java.util.Random;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of Math intrinsics.
+ */
+public class MathFunctionBenchmark extends BenchmarkBase {
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+        double[] data = randomDoubles(100);
+        double[] result = new double[100];
+
+        static double[] randomDoubles(int len) {
+            double[] data = new double[len];
+            Random r = new Random();
+            for (int i = 0; i < data.length; i++) {
+                data[i] = r.nextDouble();
+            }
+            return data;
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public void mathLog(ThreadState state) {
+        double[] data = state.data;
+        for (int i = 0; i < data.length; i++) {
+            double[] result = state.result;
+            result[i] = Math.log(data[i]);
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public void mathLog10(ThreadState state) {
+        double[] data = state.data;
+        for (int i = 0; i < data.length; i++) {
+            double[] result = state.result;
+            result[i] = Math.log10(data[i]);
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public void mathSin(ThreadState state) {
+        double[] data = state.data;
+        for (int i = 0; i < data.length; i++) {
+            double[] result = state.result;
+            result[i] = Math.sin(data[i]);
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public void mathCos(ThreadState state) {
+        double[] data = state.data;
+        for (int i = 0; i < data.length; i++) {
+            double[] result = state.result;
+            result[i] = Math.cos(data[i]);
+        }
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public void mathTan(ThreadState state) {
+        double[] data = state.data;
+        for (int i = 0; i < data.length; i++) {
+            double[] result = state.result;
+            result[i] = Math.tan(data[i]);
+        }
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/SimpleSyncBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/SimpleSyncBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+package micro.benchmarks;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of non-contended synchronization.
+ */
+public class SimpleSyncBenchmark extends BenchmarkBase {
+
+    public static class Person {
+        public int age;
+
+        public Person(int age) {
+            this.age = age;
+        }
+
+        public synchronized int getAge() {
+            return age;
+        }
+
+        public synchronized void setAge(int age) {
+            this.age = age;
+        }
+
+        public synchronized void setAgeIfNonZero(int age) {
+            if (age != 0) {
+                this.age = age;
+            }
+        }
+    }
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+        Person person = new Person(22);
+        int newAge = 45;
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public void setAgeCond(ThreadState state) {
+        Person person = state.person;
+        person.setAgeIfNonZero(state.newAge);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public int getAge(ThreadState state) {
+        Person person = state.person;
+        return person.getAge();
+    }
+
+    @Benchmark
+    @Warmup(iterations = 20)
+    public int getAndIncAge(ThreadState state) {
+        Person person = state.person;
+        int oldAge = person.getAge();
+        person.setAge(oldAge + 1);
+        return oldAge;
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/StringBenchmark.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/StringBenchmark.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, 2017, 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.
+ */
+package micro.benchmarks;
+
+import java.util.concurrent.TimeUnit;
+
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.annotations.Warmup;
+
+/**
+ * Benchmarks cost of {@link String#indexOf(int)} and {@link String#indexOf(String)}.
+ */
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+public class StringBenchmark extends BenchmarkBase {
+
+    @State(Scope.Benchmark)
+    public static class BenchState {
+        char ch1 = 'Q';
+        char ch2 = 'X';
+        String s1 = "Qu";
+        String s2 = "ne";
+
+        // Checkstyle: stop
+        String lorem = "Lorem ipsum dolor sit amet, consectetur adipisici elit, sed eiusmod tempor incidunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquid ex ea commodi consequat. Quis aute iure reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";
+        // Checkstyle: resume
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public int indexOfChar(BenchState state) {
+        return state.lorem.indexOf(state.ch1);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public int indexOfCharNotFound(BenchState state) {
+        return state.lorem.indexOf(state.ch2);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public int indexOfString(BenchState state) {
+        return state.lorem.indexOf(state.s1);
+    }
+
+    @Benchmark
+    @Warmup(iterations = 5)
+    public int indexOfStringNotFound(BenchState state) {
+        return state.lorem.indexOf(state.s2);
+    }
+}
diff -r 22196b3c7dfd -r 76fb4ae9fd2f hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/package-info.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.micro.benchmarks/src/micro/benchmarks/package-info.java	Sat Aug 12 01:21:21 2017 +0000
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+/**
+ * This package contains micro benchmarks outside the org.graalvm.compiler namespace so that they
+ * will be subject to Graal compilation even if {@code -Dgraal.CompileGraalWithC1Only=true}.
+ */
+package micro.benchmarks;
\ No newline at end of file