changeset 54204:55c262f4f5a1

8220389: Update Graal Reviewed-by: kvn, dlong
author jwilhelm
date Wed, 20 Mar 2019 22:53:44 +0100
parents 18547cad9ec6
children d9f43dfbe524
files src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerStampShiftTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationBailoutActionHelp.txt src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationFailureActionHelp.txt src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayEqualsStub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java
diffstat 21 files changed, 396 insertions(+), 141 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/IntegerStampShiftTest.java	Wed Mar 20 22:53:44 2019 +0100
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, 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.core.test;
+
+import org.junit.Test;
+
+public class IntegerStampShiftTest extends GraalCompilerTest {
+
+    public static int unsignedShiftPositiveInt(boolean f) {
+        int h = f ? 0x7FFFFFF0 : 0x7FFFFF00;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftPositiveInt() {
+        test("unsignedShiftPositiveInt", false);
+    }
+
+    public static int unsignedShiftNegativeInt(boolean f) {
+        int h = f ? 0xFFFFFFF0 : 0xFFFFFF00;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftNegativeInt() {
+        test("unsignedShiftNegativeInt", false);
+    }
+
+    public static long unsignedShiftPositiveLong(boolean f) {
+        long h = f ? 0x7FFFFFFFFFFFFFF0L : 0x7FFFFFFFFFFFFF00L;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftPositiveLong() {
+        test("unsignedShiftPositiveLong", false);
+    }
+
+    public static long unsignedShiftNegativeLong(boolean f) {
+        long h = f ? 0xFFFFFFFFFFFFFFF0L : 0xFFFFFFFFFFFFFF00L;
+        return h >>> 8;
+    }
+
+    @Test
+    public void testUnsignedShiftNegativeLong() {
+        test("unsignedShiftNegativeLong", false);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Wed Mar 20 22:53:44 2019 +0100
@@ -25,7 +25,7 @@
 package org.graalvm.compiler.core;
 
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
 import static org.graalvm.compiler.core.GraalCompilerOptions.MaxCompilationProblemsPerAction;
@@ -45,14 +45,13 @@
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
 import org.graalvm.compiler.debug.PathUtilities;
 import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.code.BailoutException;
 
 /**
  * Wrapper for a compilation that centralizes what action to take based on
- * {@link GraalCompilerOptions#CompilationBailoutAction} and
+ * {@link GraalCompilerOptions#CompilationBailoutAsFailure} and
  * {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
  * compilation.
  */
@@ -71,14 +70,17 @@
          * Print nothing to the console.
          */
         Silent,
+
         /**
          * Print a stack trace to the console.
          */
         Print,
+
         /**
          * An exception causes the compilation to be retried with extra diagnostics enabled.
          */
         Diagnose,
+
         /**
          * Same as {@link #Diagnose} except that the VM process is exited after retrying.
          */
@@ -122,27 +124,30 @@
     protected abstract T handleException(Throwable t);
 
     /**
-     * Gets the action to take based on the value of {@code actionKey} in {@code options}.
+     * Gets the action to take based on the value of
+     * {@link GraalCompilerOptions#CompilationBailoutAsFailure},
+     * {@link GraalCompilerOptions#CompilationFailureAction} and
+     * {@link GraalCompilerOptions#ExitVMOnException} in {@code options}.
      *
-     * Subclasses can override this to choose a different action based on factors such as whether
-     * {@code actionKey} has been explicitly set in {@code options} for example.
+     * Subclasses can override this to choose a different action.
      *
      * @param cause the cause of the bailout or failure
      */
-    protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
-        if (actionKey == CompilationFailureAction) {
-            if (ExitVMOnException.getValue(options)) {
-                assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
-                assert ExitVMOnException.getDefaultValue() != true;
-                if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
-                    TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
-                                    CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
-                                    ExitVMOnException.getName());
-                }
-                return ExceptionAction.ExitVM;
+    protected ExceptionAction lookupAction(OptionValues options, Throwable cause) {
+        if (cause instanceof BailoutException && !CompilationBailoutAsFailure.getValue(options)) {
+            return ExceptionAction.Silent;
+        }
+        if (ExitVMOnException.getValue(options)) {
+            assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
+            assert ExitVMOnException.getDefaultValue() != true;
+            if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
+                TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
+                                CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
+                                ExitVMOnException.getName());
             }
+            return ExceptionAction.ExitVM;
         }
-        return actionKey.getValue(options);
+        return CompilationFailureAction.getValue(options);
     }
 
     /**
@@ -173,15 +178,6 @@
         } catch (Throwable cause) {
             OptionValues initialOptions = initialDebug.getOptions();
 
-            String causeType = "failure";
-            EnumOptionKey<ExceptionAction> actionKey;
-            if (cause instanceof BailoutException) {
-                actionKey = CompilationBailoutAction;
-                causeType = "bailout";
-            } else {
-                actionKey = CompilationFailureAction;
-                causeType = "failure";
-            }
             synchronized (CompilationFailureAction) {
                 // Serialize all compilation failure handling.
                 // This prevents retry compilation storms and interleaving
@@ -191,9 +187,9 @@
                 // forced crash (i.e., use of GraalCompilerOptions.CrashAt)
                 // is truncated.
 
-                ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
+                ExceptionAction action = lookupAction(initialOptions, cause);
 
-                action = adjustAction(initialOptions, actionKey, action);
+                action = adjustAction(initialOptions, action);
 
                 if (action == ExceptionAction.Silent) {
                     return handleException(cause);
@@ -204,16 +200,14 @@
                     try (PrintStream ps = new PrintStream(baos)) {
                         ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
                         cause.printStackTrace(ps);
-                        ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                        causeType,
-                                        actionKey.getName(), ExceptionAction.Silent,
-                                        actionKey.getName(), ExceptionAction.Silent);
-                        ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
+                        ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                        CompilationFailureAction.getName(), ExceptionAction.Silent,
+                                        CompilationFailureAction.getName(), ExceptionAction.Silent);
+                        ps.printf("To capture more information for diagnosing or reporting a compilation failure, " +
                                         "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
-                                        causeType,
-                                        actionKey.getName(), ExceptionAction.Diagnose,
+                                        CompilationFailureAction.getName(), ExceptionAction.Diagnose,
                                         ExceptionAction.ExitVM,
-                                        actionKey.getName(), ExceptionAction.Diagnose);
+                                        CompilationFailureAction.getName(), ExceptionAction.Diagnose);
                     }
                     TTY.print(baos.toString());
                     return handleException(cause);
@@ -249,15 +243,13 @@
                 try (PrintStream ps = new PrintStream(baos)) {
                     ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
                     cause.printStackTrace(ps);
-                    ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                    causeType,
-                                    actionKey.getName(), ExceptionAction.Silent,
-                                    actionKey.getName(), ExceptionAction.Silent);
-                    ps.printf("To print a message for a compilation %s without retrying the compilation, " +
+                    ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                    CompilationFailureAction.getName(), ExceptionAction.Silent,
+                                    CompilationFailureAction.getName(), ExceptionAction.Silent);
+                    ps.printf("To print a message for a compilation failure without retrying the compilation, " +
                                     "set %s to %s (e.g., -Dgraal.%s=%s).%n",
-                                    causeType,
-                                    actionKey.getName(), ExceptionAction.Print,
-                                    actionKey.getName(), ExceptionAction.Print);
+                                    CompilationFailureAction.getName(), ExceptionAction.Print,
+                                    CompilationFailureAction.getName(), ExceptionAction.Print);
                     if (dumpPath != null) {
                         ps.println("Retrying compilation of " + this);
                     } else {
@@ -320,7 +312,7 @@
      * Adjusts {@code initialAction} if necessary based on
      * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
      */
-    private ExceptionAction adjustAction(OptionValues initialOptions, EnumOptionKey<ExceptionAction> actionKey, ExceptionAction initialAction) {
+    private ExceptionAction adjustAction(OptionValues initialOptions, ExceptionAction initialAction) {
         ExceptionAction action = initialAction;
         int maxProblems = MaxCompilationProblemsPerAction.getValue(initialOptions);
         if (action != ExceptionAction.ExitVM) {
@@ -329,7 +321,7 @@
                     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(),
+                            TTY.printf("Warning: adjusting %s from %s to %s after %s (%d) failed compilations%n", CompilationFailureAction, action, action.quieter(),
                                             MaxCompilationProblemsPerAction, maxProblems);
                             // Ensure that the message above is only printed once
                             problemsHandledPerAction.put(action, problems + 1);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Wed Mar 20 22:53:44 2019 +0100
@@ -44,13 +44,12 @@
                    "suffix will raise a bailout exception and a ':PermanentBailout' " +
                    "suffix will raise a permanent bailout exception.", type = OptionType.Debug)
     public static final OptionKey<String> CrashAt = new OptionKey<>(null);
-    @Option(help = "file:doc-files/CompilationBailoutActionHelp.txt", type = OptionType.User)
-    public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent);
-    @Option(help = "Specifies the action to take when compilation fails with a bailout exception. " +
-                   "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
-     public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
-    @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. " +
+    @Option(help = "Treat compilation bailouts like compilation failures.", type = OptionType.User)
+    public static final OptionKey<Boolean> CompilationBailoutAsFailure = new OptionKey<>(false);
+    @Option(help = "file:doc-files/CompilationFailureActionHelp.txt", type = OptionType.User)
+    public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Silent);
+    @Option(help = "The maximum number of compilation failures to handle with the action specified " +
+                   "by CompilationFailureAction before changing to a less verbose action. " +
                    "This does not apply to the ExitVM action.", type = OptionType.User)
     public static final OptionKey<Integer> MaxCompilationProblemsPerAction = new OptionKey<>(2);
     @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.User)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationBailoutActionHelp.txt	Wed Mar 20 17:28:29 2019 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-Specifies the action to take when compilation fails with a bailout exception.
-The accepted values are:
-    Silent - Print nothing to the console.
-     Print - Print a stack trace to the console.
-  Diagnose - Retry the compilation with extra diagnostics.
-    ExitVM - Same as Diagnose except that the VM process exits after retrying.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/doc-files/CompilationFailureActionHelp.txt	Wed Mar 20 22:53:44 2019 +0100
@@ -0,0 +1,6 @@
+Specifies the action to take when compilation fails.
+The accepted values are:
+    Silent - Print nothing to the console.
+     Print - Print a stack trace to the console.
+  Diagnose - Retry the compilation with extra diagnostics.
+    ExitVM - Same as Diagnose except that the VM process exits after retrying.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64ArrayEqualsStub.java	Wed Mar 20 22:53:44 2019 +0100
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2019, 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.hotspot.amd64;
+
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
+import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
+import org.graalvm.compiler.hotspot.stubs.SnippetStub;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.replacements.nodes.ArrayEqualsNode;
+import jdk.internal.vm.compiler.word.Pointer;
+
+import jdk.vm.ci.meta.JavaKind;
+
+public final class AMD64ArrayEqualsStub extends SnippetStub {
+
+    public static final ForeignCallDescriptor STUB_BOOLEAN_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "booleanArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_BYTE_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "byteArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_CHAR_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "charArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_SHORT_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "shortArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_INT_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "intArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_LONG_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "longArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_FLOAT_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "floatArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+    public static final ForeignCallDescriptor STUB_DOUBLE_ARRAY_EQUALS = new ForeignCallDescriptor(
+                    "doubleArraysEquals", boolean.class, Pointer.class, Pointer.class, int.class);
+
+    public AMD64ArrayEqualsStub(ForeignCallDescriptor foreignCallDescriptor, OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
+        super(foreignCallDescriptor.getName(), options, providers, linkage);
+    }
+
+    @Snippet
+    private static boolean booleanArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Boolean);
+    }
+
+    @Snippet
+    private static boolean byteArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Byte);
+    }
+
+    @Snippet
+    private static boolean charArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Char);
+    }
+
+    @Snippet
+    private static boolean shortArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Short);
+    }
+
+    @Snippet
+    private static boolean intArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Int);
+    }
+
+    @Snippet
+    private static boolean longArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Long);
+    }
+
+    @Snippet
+    private static boolean floatArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Float);
+    }
+
+    @Snippet
+    private static boolean doubleArraysEquals(Pointer array1, Pointer array2, int length) {
+        return ArrayEqualsNode.equals(array1, array2, length, JavaKind.Double);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Wed Mar 20 22:53:44 2019 +0100
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.hotspot.amd64;
 
 import static jdk.vm.ci.common.InitTimer.timer;
+import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -160,7 +161,7 @@
                     HotSpotConstantReflectionProvider constantReflection, HotSpotHostForeignCallsProvider foreignCalls, HotSpotMetaAccessProvider metaAccess,
                     HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, HotSpotWordTypes wordTypes) {
         Plugins plugins = HotSpotGraphBuilderPlugins.create(compilerConfiguration, config, wordTypes, metaAccess, constantReflection, snippetReflection, foreignCalls, replacements);
-        AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false);
+        AMD64GraphBuilderPlugins.register(plugins, replacements.getDefaultReplacementBytecodeProvider(), (AMD64) target.arch, false, JAVA_SPECIFICATION_VERSION >= 9);
         return plugins;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Wed Mar 20 22:53:44 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -121,6 +121,22 @@
         link(new AMD64ArrayIndexOfStub(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, options, providers,
                         registerStubCall(AMD64ArrayIndexOf.STUB_INDEX_OF_4_CHARS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
 
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
+        link(new AMD64ArrayEqualsStub(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, options, providers,
+                        registerStubCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS, LEAF, REEXECUTABLE, NO_LOCATIONS)));
         super.initialize(providers, options);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Wed Mar 20 22:53:44 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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
@@ -676,4 +676,32 @@
     protected StrategySwitchOp createStrategySwitchOp(SwitchStrategy strategy, LabelRef[] keyTargets, LabelRef defaultTarget, Variable key, AllocatableValue temp) {
         return new AMD64HotSpotStrategySwitchOp(strategy, keyTargets, defaultTarget, key, temp);
     }
+
+    @Override
+    public ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
+        if (constantLength >= 0 && constantLength * kind.getByteCount() < 2 * getMaxVectorSize()) {
+            // Yield constant-length arrays comparison assembly
+            return null;
+        }
+        switch (kind) {
+            case Boolean:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BOOLEAN_ARRAY_EQUALS);
+            case Byte:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_BYTE_ARRAY_EQUALS);
+            case Char:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_CHAR_ARRAY_EQUALS);
+            case Short:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_SHORT_ARRAY_EQUALS);
+            case Int:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_INT_ARRAY_EQUALS);
+            case Long:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_LONG_ARRAY_EQUALS);
+            case Float:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_FLOAT_ARRAY_EQUALS);
+            case Double:
+                return getForeignCalls().lookupForeignCall(AMD64ArrayEqualsStub.STUB_DOUBLE_ARRAY_EQUALS);
+            default:
+                return null;
+        }
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.jdk9.test/src/org/graalvm/compiler/hotspot/jdk9/test/StringUTF16ToBytesGetCharsTest.java	Wed Mar 20 22:53:44 2019 +0100
@@ -26,8 +26,6 @@
 
 import static org.junit.Assume.assumeFalse;
 
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.hotspot.replacements.StringUTF16Substitutions;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -35,9 +33,11 @@
 import org.graalvm.compiler.replacements.arraycopy.ArrayCopyCallNode;
 import org.graalvm.compiler.replacements.test.MethodSubstitutionTest;
 import org.graalvm.compiler.test.AddExports;
-import org.junit.Before;
 import org.junit.Test;
 
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
 /**
  * Test substitutions for (innate) methods StringUTF16.toBytes and StringUTF16.getChars provided by
  * {@link StringUTF16Substitutions}.
@@ -48,8 +48,7 @@
     private static final int N = 1000;
     private static final int N_OVERFLOW = 10;
 
-    @Before
-    public void checkAMD64() {
+    public StringUTF16ToBytesGetCharsTest() {
         assumeFalse(Java8OrEarlier);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BigIntegerIntrinsicsTest.java	Wed Mar 20 22:53:44 2019 +0100
@@ -21,6 +21,8 @@
  * questions.
  */
 
+
+
 package org.graalvm.compiler.hotspot.test;
 
 import java.lang.reflect.InvocationTargetException;
@@ -193,8 +195,7 @@
         Object invokeCode(Object... args) {
             try {
                 return testcode.executeVarargs(args);
-            }
-            catch (InvalidInstalledCodeException e) {
+            } catch (InvalidInstalledCodeException e) {
                 // Ensure the installed code is valid, possibly recompiled.
                 testcode = getCode(testmethod);
 
@@ -208,8 +209,7 @@
         private Object invokeSafe(ResolvedJavaMethod method, Object receiver, Object... args) {
             try {
                 return invoke(method, receiver, args);
-            } catch (IllegalAccessException   | InvocationTargetException |
-                     IllegalArgumentException | InstantiationException e) {
+            } catch (IllegalAccessException | InvocationTargetException | IllegalArgumentException | InstantiationException e) {
                 throw new RuntimeException(e);
             }
         }
@@ -220,8 +220,7 @@
         private InstalledCode testcode;
     }
 
-    private static GraalHotSpotVMConfig config =
-        ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
+    private static GraalHotSpotVMConfig config = ((HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class)).getVMConfig();
 
     private static BigInteger bigTwo = BigInteger.valueOf(2);
     private static Random rnd = new Random(17);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Wed Mar 20 22:53:44 2019 +0100
@@ -26,7 +26,7 @@
 
 import static java.util.Collections.singletonList;
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
@@ -215,7 +215,7 @@
         compilationOptionsCopy.putAll(compilationOptions);
 
         // We want to see stack traces when a method fails to compile
-        CompilationBailoutAction.putIfAbsent(compilationOptionsCopy, Print);
+        CompilationBailoutAsFailure.putIfAbsent(compilationOptionsCopy, true);
         CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
 
         // By default only report statistics for the CTW threads themselves
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Wed Mar 20 22:53:44 2019 +0100
@@ -24,7 +24,7 @@
 
 package org.graalvm.compiler.hotspot.test;
 
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
@@ -44,7 +44,7 @@
 
     @Test
     public void testJDK() throws Throwable {
-        ExceptionAction originalBailoutAction = CompilationBailoutAction.getValue(getInitialOptions());
+        boolean originalBailoutAction = CompilationBailoutAsFailure.getValue(getInitialOptions());
         ExceptionAction originalFailureAction = CompilationFailureAction.getValue(getInitialOptions());
         // Compile a couple classes in rt.jar
         HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime();
@@ -52,7 +52,7 @@
         OptionValues initialOptions = getInitialOptions();
         EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
         new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
-        assert CompilationBailoutAction.getValue(initialOptions) == originalBailoutAction;
+        assert CompilationBailoutAsFailure.getValue(initialOptions) == originalBailoutAction;
         assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Wed Mar 20 22:53:44 2019 +0100
@@ -31,7 +31,6 @@
 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
 import org.graalvm.compiler.bytecode.BytecodeStream;
 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
-import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.GraalCompilerOptions;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
@@ -134,8 +133,8 @@
         OptionValues goptions = options;
         // Silence diagnostics for permanent bailout errors as they
         // are expected for some OSR tests.
-        if (!GraalCompilerOptions.CompilationBailoutAction.hasBeenSet(options)) {
-            goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAction, ExceptionAction.Silent);
+        if (!GraalCompilerOptions.CompilationBailoutAsFailure.hasBeenSet(options)) {
+            goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAsFailure, false);
         }
         // ensure eager resolving
         StructuredGraph graph = parseEager(method, AllowAssumptions.YES, goptions);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Wed Mar 20 22:53:44 2019 +0100
@@ -26,7 +26,7 @@
 
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
 import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
-import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAsFailure;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
@@ -47,7 +47,6 @@
 import org.graalvm.compiler.debug.DebugDumpScope;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TimerKey;
-import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
@@ -145,25 +144,34 @@
         }
 
         @Override
-        protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
-            // Respect current action if it has been explicitly set.
-            if (!actionKey.hasBeenSet(values)) {
-                if (actionKey == CompilationFailureAction) {
-                    // Automatically exit on non-bailout during bootstrap
-                    // or when assertions are enabled.
-                    if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
-                        return ExitVM;
-                    }
-                } else if (actionKey == CompilationBailoutAction && ((BailoutException) cause).isPermanent()) {
-                    // Get more info for permanent bailouts during bootstrap
-                    // or when assertions are enabled.
-                    assert CompilationBailoutAction.getDefaultValue() == ExceptionAction.Silent;
-                    if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
-                        return Diagnose;
+        protected ExceptionAction lookupAction(OptionValues values, Throwable cause) {
+            if (cause instanceof BailoutException) {
+                BailoutException bailout = (BailoutException) cause;
+                if (bailout.isPermanent()) {
+                    // Respect current action if it has been explicitly set.
+                    if (!CompilationBailoutAsFailure.hasBeenSet(values)) {
+                        // Get more info for permanent bailouts during bootstrap
+                        // or when assertions are enabled.
+                        if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+                            return Diagnose;
+                        }
+
                     }
                 }
+                if (!CompilationBailoutAsFailure.getValue(values)) {
+                    return super.lookupAction(values, cause);
+                }
             }
-            return super.lookupAction(values, actionKey, cause);
+
+            // Respect current action if it has been explicitly set.
+            if (!CompilationFailureAction.hasBeenSet(values)) {
+                // Automatically exit on failure during bootstrap
+                // or when assertions are enabled.
+                if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+                    return ExitVM;
+                }
+            }
+            return super.lookupAction(values, cause);
         }
 
         @SuppressWarnings("try")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Wed Mar 20 22:53:44 2019 +0100
@@ -41,6 +41,7 @@
 
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.services.Services;
 
 /**
  * The {@link #defaultOptions()} method returns the options values initialized in a HotSpot VM. The
@@ -89,15 +90,14 @@
     }
 
     /**
-     * Global options. The values for these options are initialized by parsing the file denoted by
-     * the {@code VM.getSavedProperty(String) saved} system property named
-     * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} if the file exists followed by parsing the options
-     * encoded in saved system properties whose names start with
-     * {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs are parsed from the aforementioned
-     * file with {@link Properties#load(java.io.Reader)}.
+     * Gets and parses options based on {@linkplain Services#getSavedProperties() saved system
+     * properties}. The values for these options are initialized by parsing the file denoted by the
+     * {@value #GRAAL_OPTIONS_FILE_PROPERTY_NAME} property followed by parsing the options encoded
+     * in properties whose names start with {@value #GRAAL_OPTION_PROPERTY_PREFIX}. Key/value pairs
+     * are parsed from the aforementioned file with {@link Properties#load(java.io.Reader)}.
      */
     @SuppressWarnings("try")
-    private static OptionValues initializeOptions() {
+    public static EconomicMap<OptionKey<?>, Object> parseOptions() {
         EconomicMap<OptionKey<?>, Object> values = OptionValues.newOptionMap();
         try (InitTimer t = timer("InitializeOptions")) {
 
@@ -142,7 +142,17 @@
             }
 
             OptionsParser.parseOptions(optionSettings, values, loader);
-            return new OptionValues(values);
+            return values;
         }
     }
+
+    /**
+     * Substituted by
+     * {@code com.oracle.svm.graal.hotspot.libgraal.Target_org_graalvm_compiler_hotspot_HotSpotGraalOptionValues}
+     * to update {@code com.oracle.svm.core.option.RuntimeOptionValues.singleton()} instead of
+     * creating a new {@link OptionValues} object.
+     */
+    private static OptionValues initializeOptions() {
+        return new OptionValues(parseOptions());
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Wed Mar 20 22:53:44 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, 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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Wed Mar 20 22:53:44 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -269,6 +269,11 @@
     Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length, int constantLength, boolean directPointers);
 
     @SuppressWarnings("unused")
+    default ForeignCallLinkage lookupArrayEqualsStub(JavaKind kind, int constantLength) {
+        return null;
+    }
+
+    @SuppressWarnings("unused")
     default Variable emitArrayEquals(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length, int constantLength, boolean directPointers) {
         throw GraalError.unimplemented("Array.equals with different types substitution is not implemented on this architecture");
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/UnsignedRightShiftNode.java	Wed Mar 20 22:53:44 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, 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
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.nodes.calc;
 
+import jdk.vm.ci.code.CodeUtil;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.ShiftOp.UShr;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
@@ -84,10 +85,13 @@
             Stamp xStampGeneric = forX.stamp(view);
             if (xStampGeneric instanceof IntegerStamp) {
                 IntegerStamp xStamp = (IntegerStamp) xStampGeneric;
+                long xMask = CodeUtil.mask(xStamp.getBits());
+                long xLowerBound = xStamp.lowerBound() & xMask;
+                long xUpperBound = xStamp.upperBound() & xMask;
 
-                if (xStamp.lowerBound() >>> amount == xStamp.upperBound() >>> amount) {
+                if (xLowerBound >>> amount == xUpperBound >>> amount) {
                     // The result of the shift is constant.
-                    return ConstantNode.forIntegerKind(stamp.getStackKind(), xStamp.lowerBound() >>> amount);
+                    return ConstantNode.forIntegerKind(stamp.getStackKind(), xLowerBound >>> amount);
                 }
 
                 if (amount == xStamp.getBits() - 1 && xStamp.lowerBound() == -1 && xStamp.upperBound() == 0) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java	Wed Mar 20 22:53:44 2019 +0100
@@ -32,7 +32,6 @@
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPECIFICATION_VERSION;
 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java11OrEarlier;
 import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.Java8OrEarlier;
 
@@ -71,7 +70,7 @@
 
 public class AMD64GraphBuilderPlugins {
 
-    public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks) {
+    public static void register(Plugins plugins, BytecodeProvider replacementsBytecodeProvider, AMD64 arch, boolean explicitUnsafeNullChecks, boolean emitJDK9StringSubstitutions) {
         InvocationPlugins invocationPlugins = plugins.getInvocationPlugins();
         invocationPlugins.defer(new Runnable() {
             @Override
@@ -83,8 +82,10 @@
                                 new JavaKind[]{JavaKind.Int, JavaKind.Long, JavaKind.Object, JavaKind.Boolean, JavaKind.Byte, JavaKind.Short, JavaKind.Char, JavaKind.Float, JavaKind.Double});
                 registerUnsafePlugins(invocationPlugins, replacementsBytecodeProvider, explicitUnsafeNullChecks);
                 registerStringPlugins(invocationPlugins, replacementsBytecodeProvider);
-                registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
-                registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+                if (emitJDK9StringSubstitutions) {
+                    registerStringLatin1Plugins(invocationPlugins, replacementsBytecodeProvider);
+                    registerStringUTF16Plugins(invocationPlugins, replacementsBytecodeProvider);
+                }
                 registerMathPlugins(invocationPlugins, arch, replacementsBytecodeProvider);
                 registerArraysEqualsPlugins(invocationPlugins, replacementsBytecodeProvider);
             }
@@ -215,30 +216,26 @@
     }
 
     private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
-            r.setAllowOverwrite(true);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
-        }
+        Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
+        r.setAllowOverwrite(true);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, char[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "inflate", byte[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringLatin1Substitutions.class, "indexOf", byte[].class, int.class, byte[].class, int.class, int.class);
     }
 
     private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
-            r.setAllowOverwrite(true);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
-            r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
-        }
+        Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
+        r.setAllowOverwrite(true);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", char[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "compress", byte[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfCharUnsafe", byte[].class, int.class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfUnsafe", byte[].class, int.class, byte[].class, int.class, int.class);
+        r.registerMethodSubstitution(AMD64StringUTF16Substitutions.class, "indexOfLatin1Unsafe", byte[].class, int.class, byte[].class, int.class, int.class);
     }
 
     private static void registerUnsafePlugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider, boolean explicitUnsafeNullChecks) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java	Wed Mar 20 17:28:29 2019 +0100
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java	Wed Mar 20 22:53:44 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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
@@ -26,11 +26,14 @@
 
 import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 
+import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.spi.Canonicalizable;
 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodeinfo.NodeCycles;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodeinfo.NodeSize;
@@ -48,11 +51,14 @@
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
+import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Value;
 
 // JaCoCo Exclude
@@ -63,6 +69,13 @@
 @NodeInfo(cycles = NodeCycles.CYCLES_UNKNOWN, size = NodeSize.SIZE_128)
 public final class ArrayEqualsNode extends FixedWithNextNode implements LIRLowerable, Canonicalizable, Virtualizable, MemoryAccess {
 
+    public static class Options {
+        // @formatter:off
+        @Option(help = "Use Array equals stubs instead of embedding all the emitted code.")
+        public static final OptionKey<Boolean> ArrayEqualsStubs = new OptionKey<>(true);
+        // @formatter:on
+    }
+
     public static final NodeClass<ArrayEqualsNode> TYPE = NodeClass.create(ArrayEqualsNode.class);
     /** {@link JavaKind} of the arrays to compare. */
     protected final JavaKind kind;
@@ -178,7 +191,7 @@
     }
 
     @NodeIntrinsic
-    static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
+    public static native boolean equals(Object array1, Object array2, int length, @ConstantNodeParameter JavaKind kind);
 
     public static boolean equals(boolean[] array1, boolean[] array2, int length) {
         return equals(array1, array2, length, JavaKind.Boolean);
@@ -214,11 +227,25 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
+        LIRGeneratorTool tool = gen.getLIRGeneratorTool();
         int constantLength = -1;
         if (length.isConstant()) {
             constantLength = length.asJavaConstant().asInt();
         }
-        Value result = gen.getLIRGeneratorTool().emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
+
+        if (Options.ArrayEqualsStubs.getValue(graph().getOptions())) {
+            ResolvedJavaMethod method = graph().method();
+            if (method != null && method.getAnnotation(Snippet.class) == null) {
+                ForeignCallLinkage linkage = tool.lookupArrayEqualsStub(kind, constantLength);
+                if (linkage != null) {
+                    Value result = tool.emitForeignCall(linkage, null, gen.operand(array1), gen.operand(array2), gen.operand(length));
+                    gen.setResult(this, result);
+                    return;
+                }
+            }
+        }
+
+        Value result = tool.emitArrayEquals(kind, gen.operand(array1), gen.operand(array2), gen.operand(length), constantLength, false);
         gen.setResult(this, result);
     }