8226771: Update Graal
authordlong
Thu, 25 Jul 2019 17:35:58 -0400
changeset 57537 ecc6e394475f
parent 57536 67cce1b84a9a
child 57539 e95f52891ce5
8226771: Update Graal Reviewed-by: kvn
src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java
src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ConstantProbablityBranchFoldingTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LoweringProviderMixin.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadReplacementPhase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/ConstantStackMoveTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/StackStoreTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LoweringProviderMixin.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SparcLoweringProviderMixin.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationPiTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalNodeTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueConcreteMethodBugTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/SwitchFoldingTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.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/gen/DebugInfoBuilder.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Position.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotStrategySwitchOp.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/ExceedMaxOopMapStackOffset.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/MitigateExceedingMaxOopMapStackOffsetTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BoxDeoptimizationTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompressedOopTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalManagementTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIVersionCheckTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/NodeCostDumpUtil.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationContext.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.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/CompilationWatchDog.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalServices.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicateBase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/VMErrorNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/Log.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.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.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/ConstantStackCastTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTestTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackMoveTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.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.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryMarkerNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardProxyNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ObjectWriteBarrier.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialArrayRangeWriteBarrier.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialWriteBarrier.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/WriteBarrier.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewObjectNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/SwitchFoldable.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfDispatchNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/WriteRegisterNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java
--- a/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java	Thu Jul 25 17:35:58 2019 -0400
@@ -156,9 +156,10 @@
                         platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
                         process();
                     }
-                } catch (SecurityException e) {
+                } catch (SecurityException | UnsatisfiedLinkError | NoClassDefFoundError | UnsupportedOperationException e) {
                     // Without permission to find or create the MBeanServer,
                     // we cannot process any Graal mbeans.
+                    // Various other errors can occur in the ManagementFactory (JDK-8076557)
                     deferred = null;
                 }
             } else {
--- a/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.libgraal/src/jdk/internal/vm/compiler/libgraal/OptionsEncoder.java	Thu Jul 25 17:35:58 2019 -0400
@@ -171,4 +171,3 @@
         return res;
     }
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/ConstantProbablityBranchFoldingTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,69 @@
+/*
+ * 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.api.directives.test;
+
+import org.graalvm.compiler.api.directives.GraalDirectives;
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.graph.iterators.NodeIterable;
+import org.graalvm.compiler.nodes.IfNode;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ConstantProbablityBranchFoldingTest extends GraalCompilerTest {
+
+    public static int branchFoldingSnippet1() {
+        if (GraalDirectives.injectBranchProbability(0.5, true)) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    public static int branchFoldingSnippet2() {
+        if (GraalDirectives.injectBranchProbability(0.5, false)) {
+            return 1;
+        } else {
+            return 2;
+        }
+    }
+
+    @Test
+    public void testEarlyFolding1() {
+        test("branchFoldingSnippet1");
+    }
+
+    @Test
+    public void testEarlyFolding2() {
+        test("branchFoldingSnippet2");
+    }
+
+    @Override
+    protected void checkLowTierGraph(StructuredGraph graph) {
+        NodeIterable<IfNode> ifNodes = graph.getNodes(IfNode.TYPE);
+        Assert.assertEquals("IfNode count", 0, ifNodes.count());
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64BitCountAssemblerTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -75,6 +75,9 @@
                 AArch64MacroAssembler masm = new AArch64MacroAssembler(target);
                 Register dst = registerConfig.getReturnRegister(JavaKind.Int);
                 Register src = asRegister(cc.getArgument(0));
+                // Generate a nop first as AArch64 Hotspot requires instruction at nmethod verified
+                // entry to be a jump or nop. (See https://github.com/oracle/graal/issues/1439)
+                masm.nop();
                 RegisterArray registers = registerConfig.filterAllocatableRegisters(AArch64Kind.V64_BYTE, registerConfig.getAllocatableRegisters());
                 masm.popcnt(size, dst, src, registers.get(registers.size() - 1));
                 masm.ret(AArch64.lr);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LoweringProviderMixin.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,41 @@
+/*
+ * 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.aarch64;
+
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
+
+public interface AArch64LoweringProviderMixin extends LoweringProvider {
+
+    @Override
+    default Integer smallestCompareWidth() {
+        return 32;
+    }
+
+    @Override
+    default boolean supportBulkZeroing() {
+        return false;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -80,9 +80,9 @@
      */
     public static void replace(ReadNode readNode) {
         assert readNode.getUsageCount() == 1;
-        assert readNode.getUsageAt(0) instanceof ZeroExtendNode || readNode.getUsageAt(0) instanceof SignExtendNode;
+        assert readNode.usages().first() instanceof ZeroExtendNode || readNode.usages().first() instanceof SignExtendNode;
 
-        ValueNode usage = (ValueNode) readNode.getUsageAt(0);
+        ValueNode usage = (ValueNode) readNode.usages().first();
         boolean isSigned = usage instanceof SignExtendNode;
         IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadReplacementPhase.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadReplacementPhase.java	Thu Jul 25 17:35:58 2019 -0400
@@ -49,7 +49,7 @@
             if (node instanceof ReadNode) {
                 ReadNode readNode = (ReadNode) node;
                 if (readNode.hasExactlyOneUsage()) {
-                    Node usage = readNode.getUsageAt(0);
+                    Node usage = readNode.usages().first();
                     if (usage instanceof ZeroExtendNode || usage instanceof SignExtendNode) {
                         AArch64ReadNode.replace(readNode);
                     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java	Thu Jul 25 17:35:58 2019 -0400
@@ -24,8 +24,10 @@
 
 package org.graalvm.compiler.core.aarch64;
 
+import java.util.List;
 import java.util.ListIterator;
 
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.java.DefaultSuitesCreator;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.options.OptionValues;
@@ -37,24 +39,33 @@
 import org.graalvm.compiler.phases.tiers.Suites;
 
 public class AArch64SuitesCreator extends DefaultSuitesCreator {
-    private final Class<? extends Phase> insertReadReplacementBefore;
+    private final List<Class<? extends Phase>> insertReadReplacementBeforePositions;
 
-    public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, Class<? extends Phase> insertReadReplacementBefore) {
+    public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, List<Class<? extends Phase>> insertReadReplacementBeforePositions) {
         super(compilerConfiguration, plugins);
-        this.insertReadReplacementBefore = insertReadReplacementBefore;
+        this.insertReadReplacementBeforePositions = insertReadReplacementBeforePositions;
     }
 
     @Override
     public Suites createSuites(OptionValues options) {
         Suites suites = super.createSuites(options);
-
-        ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(insertReadReplacementBefore);
-        // Put AArch64ReadReplacementPhase right before the SchedulePhase
-        while (PhaseSuite.findNextPhase(findPhase, insertReadReplacementBefore)) {
-            // Search for last occurrence of SchedulePhase
+        ListIterator<BasePhase<? super LowTierContext>> findPhase = null;
+        for (Class<? extends Phase> phase : insertReadReplacementBeforePositions) {
+            findPhase = suites.getLowTier().findPhase(phase);
+            if (findPhase != null) {
+                // Put AArch64ReadReplacementPhase right before the requested phase
+                while (PhaseSuite.findNextPhase(findPhase, phase)) {
+                    // Search for last occurrence of SchedulePhase
+                }
+                findPhase.previous();
+                break;
+            }
         }
-        findPhase.previous();
-        findPhase.add(new AArch64ReadReplacementPhase());
+        if (findPhase != null) {
+            findPhase.add(new AArch64ReadReplacementPhase());
+        } else {
+            throw GraalError.shouldNotReachHere("Cannot find phase to insert AArch64ReadReplacementPhase");
+        }
         return suites;
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/ConstantStackMoveTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/ConstantStackMoveTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -143,7 +143,7 @@
     }
 
     @Test
-    public void runByte() throws Throwable {
+    public void runByte() {
         runTest("testByte");
     }
 
@@ -157,7 +157,7 @@
     }
 
     @Test
-    public void runShort() throws Throwable {
+    public void runShort() {
         runTest("testShort");
     }
 
@@ -171,7 +171,7 @@
     }
 
     @Test
-    public void runInt() throws Throwable {
+    public void runInt() {
         runTest("testInt");
     }
 
@@ -185,7 +185,7 @@
     }
 
     @Test
-    public void runLong() throws Throwable {
+    public void runLong() {
         runTest("testLong");
     }
 
@@ -199,7 +199,7 @@
     }
 
     @Test
-    public void runFloat() throws Throwable {
+    public void runFloat() {
         runTest("testFloat");
     }
 
@@ -213,7 +213,7 @@
     }
 
     @Test
-    public void runDouble() throws Throwable {
+    public void runDouble() {
         runTest("testDouble");
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/StackStoreTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/StackStoreTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -113,7 +113,7 @@
     }
 
     @Test
-    public void run0() throws Throwable {
+    public void run0() {
         runTest("test0", 0xDEADDEAD);
     }
 
@@ -122,7 +122,7 @@
     }
 
     @Test
-    public void run1() throws Throwable {
+    public void run1() {
         runTest("test1", 0xDEADDEAD);
     }
 
@@ -131,7 +131,7 @@
     }
 
     @Test
-    public void run2() throws Throwable {
+    public void run2() {
         runTest("test2", 0xDEADDEAD);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Thu Jul 25 17:35:58 2019 -0400
@@ -126,6 +126,7 @@
 import org.graalvm.compiler.lir.amd64.AMD64Unary;
 import org.graalvm.compiler.lir.amd64.AMD64ZeroMemoryOp;
 import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary;
+import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryConstFloatOp;
 import org.graalvm.compiler.lir.amd64.vector.AMD64VectorBinary.AVXBinaryOp;
 import org.graalvm.compiler.lir.amd64.vector.AMD64VectorUnary;
 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
@@ -1360,9 +1361,13 @@
         }
     }
 
-    private Variable emitBinary(LIRKind resultKind, VexRVMOp op, Value a, Value b) {
+    protected Variable emitBinary(LIRKind resultKind, VexRVMOp op, Value a, Value b) {
         Variable result = getLIRGen().newVariable(resultKind);
-        getLIRGen().append(new AVXBinaryOp(op, getRegisterSize(result), result, asAllocatable(a), asAllocatable(b)));
+        if (b instanceof ConstantValue && (b.getPlatformKind() == AMD64Kind.SINGLE || b.getPlatformKind() == AMD64Kind.DOUBLE)) {
+            getLIRGen().append(new AVXBinaryConstFloatOp(op, getRegisterSize(result), result, asAllocatable(a), (ConstantValue) b));
+        } else {
+            getLIRGen().append(new AVXBinaryOp(op, getRegisterSize(result), result, asAllocatable(a), asAllocatable(b)));
+        }
         return result;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Thu Jul 25 17:35:58 2019 -0400
@@ -47,8 +47,8 @@
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
 import org.graalvm.compiler.asm.amd64.AMD64BaseAssembler.OperandSize;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.calc.Condition;
@@ -80,10 +80,10 @@
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatBranchOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondMoveOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.FloatCondSetOp;
+import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.ReturnOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.StrategySwitchOp;
 import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.TableSwitchOp;
-import org.graalvm.compiler.lir.amd64.AMD64ControlFlow.HashTableSwitchOp;
 import org.graalvm.compiler.lir.amd64.AMD64LFenceOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move;
 import org.graalvm.compiler.lir.amd64.AMD64Move.CompareAndSwapOp;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LoweringProviderMixin.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,41 @@
+/*
+ * 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.amd64;
+
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
+
+public interface AMD64LoweringProviderMixin extends LoweringProvider {
+
+    @Override
+    default Integer smallestCompareWidth() {
+        return 8;
+    }
+
+    @Override
+    default boolean supportBulkZeroing() {
+        return true;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -50,6 +50,7 @@
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.PrimitiveConstant;
 import jdk.vm.ci.meta.Value;
 
 public abstract class AMD64MoveFactory extends AMD64MoveFactoryBase {
@@ -65,6 +66,9 @@
             switch (c.getJavaKind()) {
                 case Long:
                     return NumUtil.isInt(c.asLong());
+                case Float:
+                case Double:
+                    return false;
                 case Object:
                     return c.isNull();
                 default:
@@ -75,6 +79,12 @@
     }
 
     @Override
+    public boolean mayEmbedConstantLoad(Constant constant) {
+        // Only consider not inlineable constants here.
+        return constant instanceof PrimitiveConstant && ((PrimitiveConstant) constant).getJavaKind().isNumericFloat();
+    }
+
+    @Override
     public boolean allowConstantToStackMove(Constant constant) {
         if (constant instanceof DataPointerConstant) {
             return false;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Thu Jul 25 17:35:58 2019 -0400
@@ -289,4 +289,6 @@
     @Option(help = "If applicable, use bulk zeroing instructions when the zeroing size in bytes exceeds this threshold.", type = OptionType.Expert)
     public static final OptionKey<Integer> MinimalBulkZeroingSize = new OptionKey<>(2048);
 
+    @Option(help = "Alignment in bytes for loop header blocks.", type = OptionType.Expert)
+    public static final OptionKey<Integer> LoopHeaderAlignment = new OptionKey<>(16);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/UnsafeArrayTypeWriter.java	Thu Jul 25 17:35:58 2019 -0400
@@ -32,6 +32,8 @@
 import static org.graalvm.compiler.core.common.util.TypeConversion.asU4;
 import static org.graalvm.compiler.serviceprovider.GraalUnsafeAccess.getUnsafe;
 
+import java.nio.ByteBuffer;
+
 import org.graalvm.compiler.core.common.calc.UnsignedMath;
 
 import sun.misc.Unsafe;
@@ -103,6 +105,17 @@
         return result;
     }
 
+    /** Copies the buffer into the provided ByteBuffer at its current position. */
+    public final ByteBuffer toByteBuffer(ByteBuffer buffer) {
+        assert buffer.remaining() <= totalSize;
+        int initialPos = buffer.position();
+        for (Chunk cur = firstChunk; cur != null; cur = cur.next) {
+            buffer.put(cur.data, 0, cur.size);
+        }
+        assert buffer.position() - initialPos == totalSize;
+        return buffer;
+    }
+
     @Override
     public final void putS1(long value) {
         long offset = writeOffset(Byte.BYTES);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCArithmeticLIRGenerator.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SparcLoweringProviderMixin.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,41 @@
+/*
+ * 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.sparc;
+
+import org.graalvm.compiler.nodes.spi.LoweringProvider;
+
+public interface SparcLoweringProviderMixin extends LoweringProvider {
+
+    @Override
+    default Integer smallestCompareWidth() {
+        return 32;
+    }
+
+    @Override
+    default boolean supportBulkZeroing() {
+        return false;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationPiTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationPiTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -63,4 +63,3 @@
         test("testSnippet1", 1);
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalNodeTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalNodeTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.core.test;
 
+import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.junit.Test;
 
 public class ConditionalNodeTest extends GraalCompilerTest {
@@ -106,4 +107,23 @@
         sink0 = 1;
         return Math.min(-1, value);
     }
+
+    @Test
+    public void test4() {
+        test("conditionalTest4", this, 0);
+        test("conditionalTest4", this, 1);
+    }
+
+    int a;
+    InvokeKind b;
+
+    public static int conditionalTest4(ConditionalNodeTest node, int a) {
+        if (a == 1) {
+            node.b = InvokeKind.Virtual;
+        } else {
+            node.b = InvokeKind.Special;
+        }
+        node.a = a;
+        return a;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -53,17 +53,18 @@
         String[] extensions = new String[]{".cfg", ".bgv", ".graph-strings"};
         EconomicMap<OptionKey<?>, Object> overrides = OptionValues.newOptionMap();
         overrides.put(DebugOptions.DumpPath, dumpDirectoryPath.toString());
+        overrides.put(DebugOptions.PrintCFG, true);
         overrides.put(DebugOptions.PrintGraph, PrintGraphTarget.File);
         overrides.put(DebugOptions.PrintCanonicalGraphStrings, true);
         overrides.put(DebugOptions.Dump, "*");
 
         // Generate dump files.
         test(new OptionValues(getInitialOptions(), overrides), "snippet");
-        // Check that Ideal files got created, in the right place.
+        // Check that IGV files got created, in the right place.
         checkForFiles(dumpDirectoryPath, extensions);
 
         // Clean up the generated files.
-        scrubDirectory(dumpDirectoryPath);
+        removeDirectory(dumpDirectoryPath);
     }
 
     /**
@@ -92,24 +93,4 @@
             assertTrue(paths[0].equals(paths[i]), paths[0] + " != " + paths[i]);
         }
     }
-
-    /**
-     * Remove the temporary directory.
-     */
-    private static void scrubDirectory(Path directoryPath) {
-        try {
-            try (DirectoryStream<Path> stream = Files.newDirectoryStream(directoryPath)) {
-                for (Path filePath : stream) {
-                    if (Files.isRegularFile(filePath)) {
-                        Files.delete(filePath);
-                    } else if (Files.isDirectory(filePath)) {
-                        scrubDirectory(filePath);
-                    }
-                }
-            }
-            Files.delete(directoryPath);
-        } catch (IOException ioe) {
-            ioe.printStackTrace();
-        }
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueConcreteMethodBugTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/FindUniqueConcreteMethodBugTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -29,7 +29,6 @@
 import jdk.vm.ci.meta.ResolvedJavaType;
 
 import org.junit.Assert;
-import org.junit.Ignore;
 import org.junit.Test;
 
 public class FindUniqueConcreteMethodBugTest extends GraalCompilerTest {
@@ -44,7 +43,6 @@
      * {@link PersonImpl#getName()} and {@link Tenant#getName()}).
      */
     @Test
-    @Ignore("fix HotSpotResolvedObjectTypeImpl.findUniqueConcreteMethod")
     public void test() throws NoSuchMethodException {
         ResolvedJavaMethod ifaceMethod = getMetaAccess().lookupJavaMethod(Person.class.getDeclaredMethod("getName"));
 
@@ -64,9 +62,8 @@
         // this causes a VM crash as getLabelLength() directly invokes PersonImpl.getName().
         test("getLabelLength", tenant);
 
-        ResolvedJavaMethod expected = null;
         AssumptionResult<ResolvedJavaMethod> actual = getMetaAccess().lookupJavaType(AbstractPerson.class).findUniqueConcreteMethod(ifaceMethod);
-        Assert.assertEquals(expected, actual.getResult());
+        Assert.assertNull(String.valueOf(actual), actual);
 
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1116,8 +1116,14 @@
         return graph;
     }
 
+    @SuppressWarnings("try")
     protected void applyFrontEnd(StructuredGraph graph) {
-        GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), getOptimisticOptimizations(), graph.getProfilingInfo(), createSuites(graph.getOptions()));
+        DebugContext debug = graph.getDebug();
+        try (DebugContext.Scope s = debug.scope("FrontEnd", graph)) {
+            GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), getOptimisticOptimizations(), graph.getProfilingInfo(), createSuites(graph.getOptions()));
+        } catch (Throwable e) {
+            throw debug.handle(e);
+        }
     }
 
     protected StructuredGraph lastCompiledGraph;
--- /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/SwitchFoldingTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,491 @@
+/*
+ * 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.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.junit.Test;
+
+public class SwitchFoldingTest extends GraalCompilerTest {
+
+    private static final String REFERENCE_SNIPPET = "referenceSnippet";
+    private static final String REFERENCE_SNIPPET_2 = "reference2Snippet";
+    private static final String REFERENCE_SNIPPET_3 = "reference3Snippet";
+    private static final String REFERENCE_SNIPPET_4 = "reference4Snippet";
+    private static final String REFERENCE_SNIPPET_5 = "reference5Snippet";
+
+    public static int referenceSnippet(int a) {
+        switch (a) {
+            case 0:
+                return 10;
+            case 1:
+                return 5;
+            case 2:
+                return 3;
+            case 3:
+                return 11;
+            case 4:
+                return 14;
+            case 5:
+                return 2;
+            case 6:
+                return 1;
+            case 7:
+                return 0;
+            case 8:
+                return 7;
+            default:
+                return 6;
+        }
+    }
+
+    public static int reference2Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 4;
+            case 1:
+            case 2:
+                return 1;
+            case 3:
+                return 6;
+            default:
+                return 7;
+        }
+    }
+
+    public static int reference3Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 4;
+            case 1:
+            case 2:
+            case 4:
+                return 6;
+            case 6:
+            case 7:
+            default:
+                return 7;
+        }
+    }
+
+    public static int test1Snippet(int a) {
+        if (a == 0) {
+            return 10;
+        } else if (a == 1) {
+            return 5;
+        } else if (a == 2) {
+            return 3;
+        } else if (a == 3) {
+            return 11;
+        } else if (a == 4) {
+            return 14;
+        } else if (a == 5) {
+            return 2;
+        } else if (a == 6) {
+            return 1;
+        } else if (a == 7) {
+            return 0;
+        } else if (a == 8) {
+            return 7;
+        } else {
+            return 6;
+        }
+    }
+
+    @Test
+    public void test1() {
+        test1("test1Snippet");
+    }
+
+    public static int test2Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 10;
+            case 1:
+                return 5;
+            case 2:
+                return 3;
+            case 3:
+                return 11;
+            case 4:
+                return 14;
+            default:
+                switch (a) {
+                    case 5:
+                        return 2;
+                    case 6:
+                        return 1;
+                    case 7:
+                        return 0;
+                    case 8:
+                        return 7;
+                    default:
+                        return 6;
+                }
+        }
+    }
+
+    @Test
+    public void test2() {
+        test1("test2Snippet");
+    }
+
+    public static int test3Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 10;
+            default:
+                switch (a) {
+                    case 1:
+                        return 5;
+                    default:
+                        switch (a) {
+                            case 2:
+                                return 3;
+                            default:
+                                switch (a) {
+                                    case 3:
+                                        return 11;
+                                    default:
+                                        switch (a) {
+                                            case 4:
+                                                return 14;
+                                            default:
+                                                switch (a) {
+                                                    case 5:
+                                                        return 2;
+                                                    default:
+                                                        switch (a) {
+                                                            case 6:
+                                                                return 1;
+                                                            default:
+                                                                switch (a) {
+                                                                    case 7:
+                                                                        return 0;
+                                                                    default:
+                                                                        switch (a) {
+                                                                            case 8:
+                                                                                return 7;
+                                                                            default:
+                                                                                return 6;
+                                                                        }
+                                                                }
+                                                        }
+                                                }
+                                        }
+                                }
+                        }
+                }
+        }
+    }
+
+    @Test
+    public void test3() {
+        test1("test3Snippet");
+    }
+
+    public static int test4Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 10;
+            case 1:
+                return 5;
+            case 2:
+                return 3;
+            case 3:
+                return 11;
+            case 4:
+                return 14;
+            case 5:
+                return 2;
+            case 6:
+                return 1;
+            default:
+                if (a == 7) {
+                    return 0;
+                } else if (a == 8) {
+                    return 7;
+                } else {
+                    return 6;
+                }
+        }
+    }
+
+    @Test
+    public void test4() {
+        test1("test4Snippet");
+    }
+
+    public static int test5Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 10;
+            default:
+                switch (a) {
+                    case 1:
+                        return 5;
+                    default:
+                        switch (a) {
+                            case 2:
+                                return 3;
+                            default:
+                                switch (a) {
+                                    case 3:
+                                        return 11;
+                                    default:
+                                        switch (a) {
+                                            case 4:
+                                                return 14;
+                                            default:
+                                                switch (a) {
+                                                    case 5:
+                                                        return 2;
+                                                    default:
+                                                        switch (a) {
+                                                            case 6:
+                                                                return 1;
+                                                            default:
+                                                                if (a == 7) {
+                                                                    return 0;
+                                                                } else if (a == 8) {
+                                                                    return 7;
+                                                                } else {
+                                                                    return 6;
+                                                                }
+                                                        }
+                                                }
+                                        }
+                                }
+                        }
+                }
+        }
+    }
+
+    @Test
+    public void test5() {
+        test1("test5Snippet");
+    }
+
+    public static int test6Snippet(int a) {
+        if (a == 0) {
+            return 10;
+        } else {
+            switch (a) {
+                case 1:
+                    return 5;
+                default:
+                    if (a == 2) {
+                        return 3;
+                    } else if (a == 3) {
+                        return 11;
+                    } else {
+                        switch (a) {
+                            case 4:
+                                return 14;
+                            case 5:
+                                return 2;
+                            case 6:
+                                return 1;
+                            default:
+                                if (a == 7) {
+                                    return 0;
+                                } else if (a == 8) {
+                                    return 7;
+                                } else {
+                                    return 6;
+                                }
+                        }
+                    }
+
+            }
+        }
+    }
+
+    @Test
+    public void test6() {
+        test1("test6Snippet");
+    }
+
+    public static int test7Snippet(int a) {
+        if (a == 0) {
+            return 4;
+        } else {
+            switch (a) {
+                case 1:
+                case 2:
+                    return 1;
+                case 3:
+                    return 6;
+                default:
+                    return 7;
+            }
+        }
+    }
+
+    @Test
+    public void test7() {
+        test2("test7Snippet");
+    }
+
+    public static int test8Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 4;
+            case 1:
+            case 2:
+            case 7:
+            default:
+                switch (a) {
+                    case 2:
+                    case 6:
+                    default:
+                        switch (a) {
+                            case 1:
+                            case 2:
+                            case 4:
+                                return 6;
+                            default:
+                                return 7;
+                        }
+                }
+        }
+    }
+
+    @Test
+    public void test8() {
+        test3("test8Snippet");
+    }
+
+    public static int reference4Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 4;
+            case 1:
+            case 2:
+            case 4:
+                return 6;
+            case 6:
+                return 7;
+            case 7:
+                return 7;
+            default:
+                return 7;
+        }
+    }
+
+    public static int test9Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 4;
+            case 1:
+            case 2:
+            case 4:
+                return 6;
+            case 6:
+            case 7:
+            default:
+                if (a == 6) {
+                    return 7;
+                } else if (a == 7) {
+                    return 7;
+                } else {
+                    return 7;
+                }
+        }
+    }
+
+    @Test
+    public void test9() {
+        test4("test9Snippet");
+    }
+
+    public static int reference5Snippet(int a) {
+        switch (a) {
+            case 0:
+                return 4;
+            case 1:
+                return 1;
+            case 2:
+                return 1;
+            case 3:
+                return 6;
+            default:
+                return 7;
+        }
+    }
+
+    public static int test10Snippet(int a) {
+        if (a == 0) {
+            return 4;
+        } else {
+            if (a == 1 || a == 2) {
+                return 1;
+            } else {
+                switch (a) {
+                    case 3:
+                        return 6;
+                    default:
+                        return 7;
+                }
+            }
+        }
+    }
+
+    @Test
+    public void test10() {
+        test5("test10Snippet");
+    }
+
+    private void test1(String snippet) {
+        test(snippet, REFERENCE_SNIPPET);
+    }
+
+    private void test2(String snippet) {
+        test(snippet, REFERENCE_SNIPPET_2);
+    }
+
+    private void test3(String snippet) {
+        test(snippet, REFERENCE_SNIPPET_3);
+    }
+
+    private void test4(String snippet) {
+        test(snippet, REFERENCE_SNIPPET_4);
+    }
+
+    private void test5(String snippet) {
+        test(snippet, REFERENCE_SNIPPET_5);
+    }
+
+    private void test(String snippet, String ref) {
+        StructuredGraph graph = parseEager(snippet, StructuredGraph.AllowAssumptions.YES);
+        DebugContext debug = graph.getDebug();
+        debug.dump(DebugContext.BASIC_LEVEL, graph, "Graph");
+        new CanonicalizerPhase().apply(graph, getProviders());
+        StructuredGraph referenceGraph = parseEager(ref, StructuredGraph.AllowAssumptions.YES);
+        assertEquals(referenceGraph, graph);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/backend/BackendTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -45,10 +45,10 @@
     }
 
     @SuppressWarnings("try")
-    protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) {
+    protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph, OptimisticOptimizations optimizations) {
         DebugContext debug = graph.getDebug();
         try (DebugContext.Scope s = debug.scope("FrontEnd")) {
-            GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), OptimisticOptimizations.NONE, graph.getProfilingInfo(), createSuites(graph.getOptions()));
+            GraalCompiler.emitFrontEnd(getProviders(), getBackend(), graph, getDefaultGraphBuilderSuite(), optimizations, graph.getProfilingInfo(), createSuites(graph.getOptions()));
         } catch (Throwable e) {
             throw debug.handle(e);
         }
@@ -57,4 +57,7 @@
         return lirGen;
     }
 
+    protected LIRGenerationResult getLIRGenerationResult(final StructuredGraph graph) {
+        return getLIRGenerationResult(graph, OptimisticOptimizations.NONE);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Jul 25 17:35:58 2019 -0400
@@ -302,10 +302,16 @@
         }
     }
 
+    /**
+     * Calls {@link System#exit(int)} in the runtime embedding the Graal compiler. This will be a
+     * different runtime than Graal's runtime in the case of libgraal.
+     */
+    protected abstract void exitHostVM(int status);
+
     private void maybeExitVM(ExceptionAction action) {
         if (action == ExitVM) {
             TTY.println("Exiting VM after retry compilation of " + this);
-            System.exit(-1);
+            exitHostVM(-1);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Thu Jul 25 17:35:58 2019 -0400
@@ -156,10 +156,6 @@
                 }
                 assert checkValues(vobjValue.getType(), values, slotKinds);
                 vobjValue.setValues(values, slotKinds);
-
-                if (vobjNode instanceof VirtualBoxingNode) {
-                    GraalServices.markVirtualObjectAsAutoBox(vobjValue);
-                }
             }
 
             virtualObjectsArray = new VirtualObject[virtualObjects.size()];
@@ -323,7 +319,8 @@
                     assert obj.entryCount() == 0 || state instanceof VirtualObjectState;
                     VirtualObject vobject = virtualObjects.get(obj);
                     if (vobject == null) {
-                        vobject = VirtualObject.get(obj.type(), virtualObjects.size());
+                        boolean isAutoBox = obj instanceof VirtualBoxingNode;
+                        vobject = GraalServices.createVirtualObject(obj.type(), virtualObjects.size(), isAutoBox);
                         virtualObjects.put(obj, vobject);
                         pendingVirtualObjects.add(obj);
                     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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.core/src/org/graalvm/compiler/core/target/Backend.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Thu Jul 25 17:35:58 2019 -0400
@@ -257,7 +257,6 @@
      * @throws BailoutException if the code installation failed
      */
     public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) {
-        System.out.println(compilationResult.getSpeculationLog());
         return createInstalledCode(debug, method, compilationResult, null, true);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Thu Jul 25 17:35:58 2019 -0400
@@ -818,22 +818,24 @@
 
     private void replaceAtMatchingUsages(Node other, Predicate<Node> filter, Node toBeDeleted) {
         if (filter == null) {
-            fail("filter cannot be null");
+            throw fail("filter cannot be null");
         }
         checkReplaceWith(other);
         int i = 0;
-        while (i < this.getUsageCount()) {
+        int usageCount = this.getUsageCount();
+        while (i < usageCount) {
             Node usage = this.getUsageAt(i);
             if (filter.test(usage)) {
                 replaceAtUsage(other, toBeDeleted, usage);
                 this.movUsageFromEndTo(i);
+                usageCount--;
             } else {
                 ++i;
             }
         }
     }
 
-    public Node getUsageAt(int index) {
+    private Node getUsageAt(int index) {
         if (index == 0) {
             return this.usage0;
         } else if (index == 1) {
@@ -848,14 +850,35 @@
         replaceAtMatchingUsages(other, usagePredicate, null);
     }
 
+    private void replaceAtUsagePos(Node other, Node usage, Position pos) {
+        pos.initialize(usage, other);
+        maybeNotifyInputChanged(usage);
+        if (other != null) {
+            other.addUsage(usage);
+        }
+    }
+
     public void replaceAtUsages(InputType type, Node other) {
         checkReplaceWith(other);
-        for (Node usage : usages().snapshot()) {
+        int i = 0;
+        int usageCount = this.getUsageCount();
+        if (usageCount == 0) {
+            return;
+        }
+        usages: while (i < usageCount) {
+            Node usage = this.getUsageAt(i);
             for (Position pos : usage.inputPositions()) {
                 if (pos.getInputType() == type && pos.get(usage) == this) {
-                    pos.set(usage, other);
+                    replaceAtUsagePos(other, usage, pos);
+                    this.movUsageFromEndTo(i);
+                    usageCount--;
+                    continue usages;
                 }
             }
+            i++;
+        }
+        if (hasNoUsages()) {
+            maybeNotifyZeroUsages(this);
         }
     }
 
@@ -913,6 +936,14 @@
         }
     }
 
+    public void replaceFirstInput(Node oldInput, Node newInput, InputType type) {
+        for (Position pos : inputPositions()) {
+            if (pos.getInputType() == type && pos.get(this) == oldInput) {
+                pos.set(this, newInput);
+            }
+        }
+    }
+
     public void clearInputs() {
         assert assertFalse(isDeleted(), "cannot clear inputs of deleted node");
         getNodeClass().unregisterAtInputsAsUsage(this);
@@ -1059,6 +1090,8 @@
                 assertFalse(input.isDeleted(), "input was deleted %s", input);
                 assertTrue(input.isAlive(), "input is not alive yet, i.e., it was not yet added to the graph");
                 assertTrue(pos.getInputType() == InputType.Unchecked || input.isAllowedUsageType(pos.getInputType()), "invalid usage type %s %s", input, pos.getInputType());
+                Class<?> expectedType = pos.getType();
+                assertTrue(expectedType.isAssignableFrom(input.getClass()), "Invalid input type for %s: expected a %s but was a %s", pos, expectedType, input.getClass());
             }
         }
         return true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Thu Jul 25 17:35:58 2019 -0400
@@ -126,7 +126,7 @@
             field.setAccessible(true);
             return (NodeClass<T>) field.get(null);
         } catch (IllegalArgumentException | IllegalAccessException | NoSuchFieldException | SecurityException e) {
-            throw new RuntimeException(e);
+            throw new RuntimeException("Could not load Graal NodeClass TYPE field for " + clazz, e);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java	Thu Jul 25 17:35:58 2019 -0400
@@ -127,6 +127,7 @@
     private boolean check(Node node) {
         assert node.graph() == graph : String.format("%s is not part of the graph", node);
         assert !isNew(node) : "this node was added to the graph after creating the node map : " + node;
+        assert node.isAlive() : "this node is not alive: " + node;
         return true;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Position.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Position.java	Thu Jul 25 17:35:58 2019 -0400
@@ -146,4 +146,12 @@
     public int getIndex() {
         return index;
     }
+
+    public Class<?> getType() {
+        if (index < edges.getDirectCount()) {
+            return edges.getType(index);
+        } else {
+            return Node.class;
+        }
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Thu Jul 25 17:35:58 2019 -0400
@@ -49,6 +49,7 @@
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
 import org.graalvm.compiler.core.gen.LIRGenerationProvider;
+import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotDataBuilder;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -72,12 +73,16 @@
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.serviceprovider.GraalUnsafeAccess;
 
 import jdk.vm.ci.aarch64.AArch64Kind;
 import jdk.vm.ci.code.CallingConvention;
+import jdk.vm.ci.code.CompilationRequest;
+import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.RegisterConfig;
 import jdk.vm.ci.code.StackSlot;
+import jdk.vm.ci.code.site.Mark;
 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
 import jdk.vm.ci.hotspot.HotSpotSentinelConstant;
 import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig;
@@ -85,6 +90,8 @@
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
+import sun.misc.Unsafe;
+
 /**
  * HotSpot AArch64 specific backend.
  */
@@ -126,6 +133,46 @@
         }
     }
 
+    @Override
+    public InstalledCode createInstalledCode(DebugContext debug,
+                    ResolvedJavaMethod method,
+                    CompilationRequest compilationRequest,
+                    CompilationResult compilationResult,
+                    InstalledCode predefinedInstalledCode,
+                    boolean isDefault,
+                    Object[] context) {
+        boolean isStub = (method == null);
+        boolean isAOT = compilationResult.isImmutablePIC();
+        if (!isStub && !isAOT) {
+            // Non-stub compilation results are installed into HotSpot as nmethods. As AArch64 has
+            // a constraint that the instruction at nmethod verified entry point should be a nop or
+            // jump, AArch64HotSpotBackend always generate a nop placeholder before the code body
+            // for non-AOT compilations. See AArch64HotSpotBackend.emitInvalidatePlaceholder(). This
+            // assert checks if the nop placeholder is generated at all required places, including
+            // in manually assembled code in CodeGenTest cases.
+            assert hasInvalidatePlaceholder(compilationResult);
+        }
+        return super.createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, context);
+    }
+
+    private boolean hasInvalidatePlaceholder(CompilationResult compilationResult) {
+        byte[] targetCode = compilationResult.getTargetCode();
+        int verifiedEntryOffset = 0;
+        for (Mark mark : compilationResult.getMarks()) {
+            Object markId = mark.id;
+            if (markId instanceof Integer && (int) markId == config.MARKID_VERIFIED_ENTRY) {
+                // The nmethod verified entry is located at some pc offset.
+                verifiedEntryOffset = mark.pcOffset;
+                break;
+            }
+        }
+        Unsafe unsafe = GraalUnsafeAccess.getUnsafe();
+        int instruction = unsafe.getIntVolatile(targetCode, unsafe.arrayBaseOffset(byte[].class) + verifiedEntryOffset);
+        AArch64MacroAssembler masm = new AArch64MacroAssembler(getTarget());
+        masm.nop();
+        return instruction == masm.getInt(0);
+    }
+
     private class HotSpotFrameContext implements FrameContext {
         final boolean isStub;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Thu Jul 25 17:35:58 2019 -0400
@@ -29,6 +29,7 @@
 import static jdk.vm.ci.common.InitTimer.timer;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 
 import org.graalvm.compiler.bytecode.BytecodeProvider;
@@ -193,7 +194,7 @@
 
     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
                     @SuppressWarnings("unused") Replacements replacements) {
-        AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, SchedulePhase.class);
+        AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, Arrays.asList(SchedulePhase.class));
         Phase addressLoweringPhase = new AddressLoweringByUsePhase(new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
         return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLoweringProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -25,6 +25,7 @@
 
 package org.graalvm.compiler.hotspot.aarch64;
 
+import org.graalvm.compiler.core.aarch64.AArch64LoweringProviderMixin;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.graph.Node;
@@ -45,7 +46,7 @@
 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
 import jdk.vm.ci.meta.MetaAccessProvider;
 
-public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
+public class AArch64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements AArch64LoweringProviderMixin {
 
     private AArch64IntegerArithmeticSnippets integerArithmeticSnippets;
     private AArch64FloatArithmeticSnippets floatArithmeticSnippets;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -27,6 +27,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotBackend.Options.GraalArithmeticStubs;
 
 import org.graalvm.compiler.api.replacements.Snippet;
+import org.graalvm.compiler.core.amd64.AMD64LoweringProviderMixin;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.graph.Node;
@@ -53,7 +54,7 @@
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
-public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
+public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements AMD64LoweringProviderMixin {
 
     private AMD64ConvertSnippets.Templates convertSnippets;
     private ProbabilisticProfileSnippets.Templates profileSnippets;
@@ -135,14 +136,4 @@
         ForeignCallNode call = graph.add(new ForeignCallNode(foreignCalls, dispatchNode.getStubCallDescriptor(), dispatchNode.getStubCallArgs()));
         graph.replaceFixed(dispatchNode, call);
     }
-
-    @Override
-    public Integer smallestCompareWidth() {
-        return 8;
-    }
-
-    @Override
-    public boolean supportBulkZeroing() {
-        return true;
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotStrategySwitchOp.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotStrategySwitchOp.java	Thu Jul 25 17:35:58 2019 -0400
@@ -34,7 +34,7 @@
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.ValueUtil;
-import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
+import jdk.vm.ci.hotspot.HotSpotConstant;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.Value;
 
@@ -58,8 +58,8 @@
 
         @Override
         protected void emitComparison(Constant c) {
-            if (c instanceof HotSpotMetaspaceConstant) {
-                HotSpotMetaspaceConstant meta = (HotSpotMetaspaceConstant) c;
+            if (c instanceof HotSpotConstant) {
+                HotSpotConstant meta = (HotSpotConstant) c;
                 if (meta.isCompressed()) {
                     crb.recordInlineDataInCode(meta);
                     masm.cmpl(keyRegister, 0xDEADDEAD);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -28,6 +28,7 @@
 import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
 
 import java.io.File;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
@@ -100,7 +101,7 @@
     }
 
     @Test
-    public void spawnSubprocess() throws Throwable {
+    public void spawnSubprocess() throws IOException, InterruptedException {
         Assume.assumeFalse("subprocess already spawned -> skip", Boolean.getBoolean(SUBPROCESS_PROPERTY));
         List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
         vmArgs.add("-XX:JVMCICounterSize=1");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/ExceedMaxOopMapStackOffset.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/ExceedMaxOopMapStackOffset.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -120,7 +120,7 @@
     }
 
     @Test
-    public void runStackObjects() throws Throwable {
+    public void runStackObjects() {
         int max = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig().maxOopMapStackOffset;
         if (max == Integer.MAX_VALUE) {
             max = 16 * 1024 - 64;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/MitigateExceedingMaxOopMapStackOffsetTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.lir.test/src/org/graalvm/compiler/hotspot/lir/test/MitigateExceedingMaxOopMapStackOffsetTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -153,7 +153,7 @@
     }
 
     @Test
-    public void runStackObjects() throws Throwable {
+    public void runStackObjects() {
         int max = ((HotSpotBackend) getBackend()).getRuntime().getVMConfig().maxOopMapStackOffset;
         Assume.assumeFalse("no limit on oop map size", max == Integer.MAX_VALUE);
         numPrimitiveSlots = (max / 8) * 2;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLoweringProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLoweringProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -25,6 +25,7 @@
 package org.graalvm.compiler.hotspot.sparc;
 
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
+import org.graalvm.compiler.core.sparc.SparcLoweringProviderMixin;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.meta.DefaultHotSpotLoweringProvider;
@@ -36,7 +37,7 @@
 import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
 import jdk.vm.ci.meta.MetaAccessProvider;
 
-public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider {
+public class SPARCHotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements SparcLoweringProviderMixin {
 
     public SPARCHotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers,
                     HotSpotConstantReflectionProvider constantReflection, TargetDescription target) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BoxDeoptimizationTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/BoxDeoptimizationTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -24,85 +24,97 @@
 
 package org.graalvm.compiler.hotspot.test;
 
+import static org.graalvm.compiler.serviceprovider.JavaVersionUtil.JAVA_SPEC;
+
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Test;
 
 public class BoxDeoptimizationTest extends GraalCompilerTest {
-    private static boolean isJDK13OrLater = JavaVersionUtil.JAVA_SPEC >= 13;
 
-    public static void testInteger() {
-        Object[] values = {42, new Exception()};
+    private static void checkJDK() {
+        Assume.assumeTrue(JAVA_SPEC == 8 || JAVA_SPEC >= 13);
+    }
+
+    public static void testIntegerSnippet() {
+        Object[] values = {42, -42, new Exception()};
         GraalDirectives.deoptimize();
         Assert.assertSame(values[0], Integer.valueOf(42));
+        Assert.assertSame(values[1], Integer.valueOf(-42));
     }
 
     @Test
-    public void test1() {
-        Assume.assumeTrue(isJDK13OrLater);
-        test("testInteger");
+    public void testInteger() {
+        checkJDK();
+        test("testIntegerSnippet");
     }
 
-    public static void testLong() {
-        Object[] values = {42L, new Exception()};
+    public static void testLongSnippet() {
+        long highBitsOnly = 2L << 40;
+        Object[] values = {42L, -42L, highBitsOnly, new Exception()};
         GraalDirectives.deoptimize();
         Assert.assertSame(values[0], Long.valueOf(42));
+        Assert.assertSame(values[1], Long.valueOf(-42));
+        Assert.assertNotSame(values[2], highBitsOnly);
     }
 
     @Test
-    public void test2() {
-        Assume.assumeTrue(isJDK13OrLater);
-        test("testLong");
+    public void testLong() {
+        checkJDK();
+        test("testLongSnippet");
     }
 
-    public static void testChar() {
-        Object[] values = {'a', new Exception()};
+    public static void testCharSnippet() {
+        Object[] values = {'a', 'Z', new Exception()};
         GraalDirectives.deoptimize();
         Assert.assertSame(values[0], Character.valueOf('a'));
+        Assert.assertSame(values[1], Character.valueOf('Z'));
     }
 
     @Test
-    public void test3() {
-        Assume.assumeTrue(isJDK13OrLater);
-        test("testChar");
+    public void testChar() {
+        checkJDK();
+        test("testCharSnippet");
     }
 
-    public static void testShort() {
-        Object[] values = {(short) 42, new Exception()};
+    public static void testShortSnippet() {
+        Object[] values = {(short) 42, (short) -42, new Exception()};
         GraalDirectives.deoptimize();
         Assert.assertSame(values[0], Short.valueOf((short) 42));
+        Assert.assertSame(values[1], Short.valueOf((short) -42));
     }
 
     @Test
-    public void test4() {
-        Assume.assumeTrue(isJDK13OrLater);
-        test("testShort");
+    public void testShort() {
+        checkJDK();
+        test("testShortSnippet");
     }
 
-    public static void testByte() {
-        Object[] values = {(byte) 42, new Exception()};
+    public static void testByteSnippet() {
+        Object[] values = {(byte) 42, (byte) -42, new Exception()};
         GraalDirectives.deoptimize();
         Assert.assertSame(values[0], Byte.valueOf((byte) 42));
+        Assert.assertSame(values[1], Byte.valueOf((byte) -42));
     }
 
     @Test
-    public void test5() {
-        Assume.assumeTrue(isJDK13OrLater);
-        test("testByte");
+    public void testByte() {
+        checkJDK();
+        test("testByteSnippet");
     }
 
-    public static void testBoolean() {
-        Object[] values = {true, new Exception()};
+    public static void testBooleanSnippet() {
+        Object[] values = {true, false, new Exception()};
         GraalDirectives.deoptimize();
         Assert.assertSame(values[0], Boolean.valueOf(true));
+        Assert.assertSame(values[1], Boolean.valueOf(false));
     }
 
     @Test
-    public void test6() {
-        Assume.assumeTrue(isJDK13OrLater);
-        test("testBoolean");
+    public void testBoolean() {
+        checkJDK();
+        test("testBooleanSnippet");
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu Jul 25 17:35:58 2019 -0400
@@ -24,6 +24,9 @@
 
 package org.graalvm.compiler.hotspot.test;
 
+import static org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins.aesDecryptName;
+import static org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins.aesEncryptName;
+
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -41,6 +44,7 @@
 import org.graalvm.compiler.api.test.Graal;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
@@ -501,21 +505,17 @@
                             "java/util/zip/CRC32C.updateDirectByteBuffer(IJII)I");
         }
 
+        boolean implNames = HotSpotGraphBuilderPlugins.cbcUsesImplNames(config);
+        String cbcEncryptName = implNames ? "implEncrypt" : "encrypt";
+        String cbcDecryptName = implNames ? "implDecrypt" : "decrypt";
+
         // AES intrinsics
         if (!config.useAESIntrinsics) {
-            if (isJDK9OrHigher()) {
-                add(ignore,
-                                "com/sun/crypto/provider/AESCrypt.implDecryptBlock([BI[BI)V",
-                                "com/sun/crypto/provider/AESCrypt.implEncryptBlock([BI[BI)V",
-                                "com/sun/crypto/provider/CipherBlockChaining.implDecrypt([BII[BI)I",
-                                "com/sun/crypto/provider/CipherBlockChaining.implEncrypt([BII[BI)I");
-            } else {
-                add(ignore,
-                                "com/sun/crypto/provider/AESCrypt.decryptBlock([BI[BI)V",
-                                "com/sun/crypto/provider/AESCrypt.encryptBlock([BI[BI)V",
-                                "com/sun/crypto/provider/CipherBlockChaining.decrypt([BII[BI)I",
-                                "com/sun/crypto/provider/CipherBlockChaining.encrypt([BII[BI)I");
-            }
+            add(ignore,
+                            "com/sun/crypto/provider/AESCrypt." + aesDecryptName + "([BI[BI)V",
+                            "com/sun/crypto/provider/AESCrypt." + aesEncryptName + "([BI[BI)V",
+                            "com/sun/crypto/provider/CipherBlockChaining." + cbcDecryptName + "([BII[BI)I",
+                            "com/sun/crypto/provider/CipherBlockChaining." + cbcEncryptName + "([BII[BI)I");
         }
 
         // BigInteger intrinsics
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -29,6 +29,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -209,10 +210,9 @@
             System.out.println(proc);
         }
 
-        List<Probe> probes = new ArrayList<>(initialProbes);
-        Probe diagnosticProbe = null;
-        if (!extraVmArgs.contains("-Dgraal.TruffleCompilationExceptionsAreFatal=true")) {
-            diagnosticProbe = new Probe("Graal diagnostic output saved in ", 1);
+        try {
+            List<Probe> 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
@@ -220,22 +220,20 @@
                     return actualOccurrences > 0 ? null : "expected at least 1 occurrence";
                 }
             });
-        }
 
-        for (String line : proc.output) {
-            for (Probe probe : probes) {
-                if (probe.matches(line)) {
-                    break;
+            for (String line : proc.output) {
+                for (Probe probe : probes) {
+                    if (probe.matches(line)) {
+                        break;
+                    }
                 }
             }
-        }
-        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));
+            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));
+                }
             }
-        }
-        if (diagnosticProbe != null) {
             String line = diagnosticProbe.lastMatchingLine;
             int substringStart = line.indexOf(diagnosticProbe.substring);
             int substringLength = diagnosticProbe.substring.length();
@@ -263,8 +261,10 @@
                 }
             } finally {
                 zip.delete();
-                dumpPath.delete();
             }
+        } finally {
+            Path directory = dumpPath.toPath();
+            removeDirectory(directory);
         }
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompressedOopTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompressedOopTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -313,8 +313,8 @@
         Assert.assertTrue(buffer.length() == 28);
         String a = new String("TestTestTestTestTestTestTest");
         installedBenchmarkCode.executeVarargs(buffer, a.toCharArray());
-        Assert.assertTrue(buffer.length() == 56);
-        Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+        Assert.assertEquals(56, buffer.length());
+        Assert.assertEquals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest", buffer.toString());
     }
 
     public static void stringBuilderTest(Object c1, Object c2) {
@@ -339,8 +339,8 @@
         for (int i = 0; i < add.length; i++) {
             buffer.append(add[i]);
         }
-        Assert.assertTrue(buffer.length() == 56);
-        Assert.assertTrue(buffer.toString().equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+        Assert.assertEquals(56, buffer.length());
+        Assert.assertEquals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest", buffer.toString());
     }
 
     @Test
@@ -356,8 +356,8 @@
         char[] dst = new char[buffer.length() * 2];
         System.arraycopy(buffer.toString().toCharArray(), 0, dst, 0, buffer.length());
         System.arraycopy(a.toCharArray(), 0, dst, buffer.length(), buffer.length());
-        Assert.assertTrue(dst.length == 56);
-        Assert.assertTrue(new String(dst).equals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest"));
+        Assert.assertEquals(56, dst.length);
+        Assert.assertEquals("TestTestTestTestTestTestTestTestTestTestTestTestTestTest", new String(dst));
     }
 
     @Test
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotCryptoSubstitutionTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -35,12 +35,11 @@
 import javax.crypto.KeyGenerator;
 import javax.crypto.SecretKey;
 
-import org.junit.Assert;
-import org.junit.Test;
-
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
+import org.junit.Assert;
+import org.junit.Test;
 
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -91,7 +90,10 @@
 
     @Test
     public void testCipherBlockChainingIntrinsics() throws Exception {
-        if (compileAndInstall("com.sun.crypto.provider.CipherBlockChaining", HotSpotGraphBuilderPlugins.cbcEncryptName, HotSpotGraphBuilderPlugins.cbcDecryptName)) {
+        boolean implNames = HotSpotGraphBuilderPlugins.cbcUsesImplNames(runtime().getVMConfig());
+        String cbcEncryptName = implNames ? "implEncrypt" : "encrypt";
+        String cbcDecryptName = implNames ? "implDecrypt" : "decrypt";
+        if (compileAndInstall("com.sun.crypto.provider.CipherBlockChaining", cbcEncryptName, cbcDecryptName)) {
             ByteArrayOutputStream actual = new ByteArrayOutputStream();
             actual.write(runEncryptDecrypt(aesKey, "AES/CBC/NoPadding"));
             actual.write(runEncryptDecrypt(aesKey, "AES/CBC/PKCS5Padding"));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalManagementTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalManagementTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -378,12 +378,15 @@
         MBeanAttributeInfo dumpPath = findAttributeInfo("DumpPath", info);
         MBeanAttributeInfo printGraphFile = findAttributeInfo("PrintGraphFile", info);
         MBeanAttributeInfo showDumpFiles = findAttributeInfo("ShowDumpFiles", info);
+        MBeanAttributeInfo methodFilter = findAttributeInfo("MethodFilter", info);
         Object originalDumpPath = server.getAttribute(mbeanName, dumpPath.getName());
         Object originalPrintGraphFile = server.getAttribute(mbeanName, printGraphFile.getName());
         Object originalShowDumpFiles = server.getAttribute(mbeanName, showDumpFiles.getName());
+        Object originalMethodFilter = server.getAttribute(mbeanName, methodFilter.getName());
         final File tmpDir = new File(HotSpotGraalManagementTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
 
         server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), quoted(tmpDir)));
+        server.setAttribute(mbeanName, new Attribute(methodFilter.getName(), ""));
         // Force output to a file even if there's a running IGV instance available.
         server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), true));
         server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), false));
@@ -392,6 +395,7 @@
             server.invoke(mbeanName, "dumpMethod", params, null);
             boolean found = false;
             String expectedIgvDumpSuffix = "[Arrays.asList(Object[])List].bgv";
+            Assert.assertTrue(tmpDir.toString() + " was not created or is not a directory", tmpDir.isDirectory());
             List<String> dumpPathEntries = Arrays.asList(tmpDir.list());
             for (String entry : dumpPathEntries) {
                 if (entry.endsWith(expectedIgvDumpSuffix)) {
@@ -403,8 +407,11 @@
                                 dumpPathEntries.stream().collect(Collectors.joining(System.lineSeparator()))));
             }
         } finally {
-            deleteDirectory(tmpDir.toPath());
+            if (tmpDir.isDirectory()) {
+                deleteDirectory(tmpDir.toPath());
+            }
             server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), originalDumpPath));
+            server.setAttribute(mbeanName, new Attribute(methodFilter.getName(), originalMethodFilter));
             server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), originalPrintGraphFile));
             server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), originalShowDumpFiles));
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIVersionCheckTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/JVMCIVersionCheckTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -27,9 +27,13 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Random;
 
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.hotspot.JVMCIVersionCheck;
+import org.graalvm.compiler.hotspot.JVMCIVersionCheck.Version;
+import org.graalvm.compiler.hotspot.JVMCIVersionCheck.Version2;
+import org.graalvm.compiler.hotspot.JVMCIVersionCheck.Version3;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -43,24 +47,37 @@
             props.put(name, sprops.getProperty(name));
         }
 
-        for (int i = 0; i < 100; i++) {
+        long seed = Long.getLong("test.seed", System.nanoTime());
+        Random random = new Random(seed);
+
+        for (int i = 0; i < 50; i++) {
             int minMajor = i;
-            int minMinor = 100 - i;
-            for (int j = 0; j < 100; j++) {
+            int minMinor = 50 - i;
+            for (int j = 0; j < 50; j++) {
                 int major = j;
-                int minor = 100 - j;
+                int minor = 50 - j;
+
+                for (int k = 0; k < 30; k++) {
+                    int minBuild = random.nextInt(100);
+                    int build = random.nextInt(100);
 
-                boolean ok = (major > minMajor) || (major == minMajor && minor >= minMinor);
-                for (String sep : new String[]{".", "-b"}) {
-                    String javaVmVersion = String.format("prefix-jvmci-%03d%s%03d-suffix", major, sep, minor);
-                    if (ok) {
-                        JVMCIVersionCheck.check(props, minMajor, minMinor, "1.8", javaVmVersion, false);
-                    } else {
-                        try {
-                            JVMCIVersionCheck.check(props, minMajor, minMinor, "1.8", javaVmVersion, false);
-                            Assert.fail("expected to fail checking " + javaVmVersion + " against " + minMajor + "." + minMinor);
-                        } catch (InternalError e) {
-                            // pass
+                    for (Version version : new Version[]{new Version2(major, minor), new Version3(major, minor, build)}) {
+                        for (Version minVersion : new Version[]{new Version2(minMajor, minMinor), new Version3(minMajor, minMinor, minBuild)}) {
+                            String javaVmVersion = String.format("prefix-jvmci-%s-suffix", version);
+                            if (!version.isLessThan(minVersion)) {
+                                try {
+                                    JVMCIVersionCheck.check(props, minVersion, "1.8", javaVmVersion, false);
+                                } catch (InternalError e) {
+                                    throw new AssertionError("Failed " + JVMCIVersionCheckTest.class.getSimpleName() + " with -Dtest.seed=" + seed, e);
+                                }
+                            } else {
+                                try {
+                                    JVMCIVersionCheck.check(props, minVersion, "1.8", javaVmVersion, false);
+                                    Assert.fail("expected to fail checking " + javaVmVersion + " against " + minVersion + " (-Dtest.seed=" + seed + ")");
+                                } catch (InternalError e) {
+                                    // pass
+                                }
+                            }
                         }
                     }
                 }
@@ -72,8 +89,9 @@
             for (String version : new String[]{"0" + sep + Long.MAX_VALUE, Long.MAX_VALUE + sep + 0}) {
                 String javaVmVersion = String.format("prefix-jvmci-%s-suffix", version);
                 try {
-                    JVMCIVersionCheck.check(props, 0, 59, "1.8", javaVmVersion, false);
-                    Assert.fail("expected to fail checking " + javaVmVersion + " against 0.59");
+                    Version2 minVersion = new Version2(0, 59);
+                    JVMCIVersionCheck.check(props, minVersion, "1.8", javaVmVersion, false);
+                    Assert.fail("expected to fail checking " + javaVmVersion + " against " + minVersion);
                 } catch (InternalError e) {
                     // pass
                 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/NodeCostDumpUtil.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/NodeCostDumpUtil.java	Thu Jul 25 17:35:58 2019 -0400
@@ -234,4 +234,3 @@
     }
 
 }
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationContext.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+import org.graalvm.compiler.debug.GraalError;
+
+import jdk.vm.ci.meta.JavaConstant;
+
+/**
+ * A context for scoping the lifetime of foreign objects.
+ *
+ * The need for this mechanism is best explained with an example. When folding a GETFIELD bytecode
+ * denoting a {@code final static} non-primitive field, libgraal can create a {@link JavaConstant}
+ * wrapping a handle to the field's value in the HotSpot heap. This handle must be released before
+ * HotSpot can reclaim the object it references. Performing a compilation in the scope of a
+ * {@linkplain HotSpotGraalServices#openLocalCompilationContext local} context ensures the handle is
+ * released once the compilation completes, allowing the HotSpot GC to subsequently reclaim the
+ * HotSpot object. When libgraal creates data structures that outlive a single compilation and may
+ * contain foreign object references (e.g. snippet graphs), it must enter the
+ * {@linkplain HotSpotGraalServices#enterGlobalCompilationContext global} context. Foreign object
+ * handles created in the global context are only released once their {@link JavaConstant} wrappers
+ * are reclaimed by the libgraal GC.
+ *
+ * {@link CompilationContext}s have no impact on {@link JavaConstant}s that do not encapsulate a
+ * foreign object reference.
+ *
+ * The object returned by {@link HotSpotGraalServices#enterGlobalCompilationContext} or
+ * {@link HotSpotGraalServices#openLocalCompilationContext} should be used in a try-with-resources
+ * statement. Failure to close a context will almost certainly result in foreign objects being
+ * leaked.
+ */
+public class CompilationContext implements AutoCloseable {
+    private final AutoCloseable impl;
+
+    CompilationContext(AutoCloseable impl) {
+        this.impl = impl;
+    }
+
+    @Override
+    public void close() {
+        try {
+            impl.close();
+        } catch (Exception e) {
+            GraalError.shouldNotReachHere(e);
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationCounters.java	Thu Jul 25 17:35:58 2019 -0400
@@ -26,6 +26,7 @@
 
 import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.fmt;
 import static org.graalvm.compiler.hotspot.HotSpotGraalCompiler.str;
+
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.Map;
@@ -35,9 +36,10 @@
 
 import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.options.Option;
+import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.options.OptionKey;
+
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
@@ -85,7 +87,7 @@
                 }
             }
             TTY.flush();
-            System.exit(-1);
+            HotSpotGraalServices.exit(-1);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Thu Jul 25 17:35:58 2019 -0400
@@ -97,8 +97,13 @@
         }
 
         @Override
+        protected void exitHostVM(int status) {
+            HotSpotGraalServices.exit(status);
+        }
+
+        @Override
         public String toString() {
-            return getMethod().format("%H.%n(%p)");
+            return getMethod().format("%H.%n(%p) @ " + getEntryBCI());
         }
 
         @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationWatchDog.java	Thu Jul 25 17:35:58 2019 -0400
@@ -238,7 +238,7 @@
                                             TTY.printf("======================= WATCH DOG THREAD =======================%n" +
                                                             "%s took %d identical stack traces, which indicates a stuck compilation (id=%d) of %s%n%sExiting VM%n", this,
                                                             numberOfIdenticalStackTraces, currentId, fmt(currentMethod), fmt(lastStackTrace));
-                                            System.exit(-1);
+                                            HotSpotGraalServices.exit(-1);
                                         }
                                     } else if (newStackTrace) {
                                         synchronized (CompilationWatchDog.class) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Thu Jul 25 17:35:58 2019 -0400
@@ -200,7 +200,7 @@
                 for (CompilerConfigurationFactory candidate : getAllCandidates()) {
                     System.out.println("    " + candidate.name);
                 }
-                System.exit(0);
+                HotSpotGraalServices.exit(0);
             } else if (value != null) {
                 for (CompilerConfigurationFactory candidate : GraalServices.load(CompilerConfigurationFactory.class)) {
                     if (candidate.name.equals(value)) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Thu Jul 25 17:35:58 2019 -0400
@@ -111,39 +111,41 @@
 
     @SuppressWarnings("try")
     CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues initialOptions) {
-        if (graalRuntime.isShutdown()) {
-            return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), true);
-        }
+        try (CompilationContext scope = HotSpotGraalServices.openLocalCompilationContext(request)) {
+            if (graalRuntime.isShutdown()) {
+                return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), true);
+            }
 
-        ResolvedJavaMethod method = request.getMethod();
+            ResolvedJavaMethod method = request.getMethod();
 
-        if (graalRuntime.isBootstrapping()) {
-            if (DebugOptions.BootstrapInitializeOnly.getValue(initialOptions)) {
-                return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true);
-            }
-            if (bootstrapWatchDog != null) {
-                if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) {
-                    // Drain the compilation queue to expedite completion of the bootstrap
-                    return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true);
+            if (graalRuntime.isBootstrapping()) {
+                if (DebugOptions.BootstrapInitializeOnly.getValue(initialOptions)) {
+                    return HotSpotCompilationRequestResult.failure(String.format("Skip compilation because %s is enabled", DebugOptions.BootstrapInitializeOnly.getName()), true);
+                }
+                if (bootstrapWatchDog != null) {
+                    if (bootstrapWatchDog.hitCriticalCompilationRateOrTimeout()) {
+                        // Drain the compilation queue to expedite completion of the bootstrap
+                        return HotSpotCompilationRequestResult.failure("hit critical bootstrap compilation rate or timeout", true);
+                    }
                 }
             }
-        }
-        HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request;
-        CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault);
-        OptionValues options = task.filterOptions(initialOptions);
-        try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options);
-                        BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request);
-                        CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) {
-            if (compilationCounters != null) {
-                compilationCounters.countCompilation(method);
+            HotSpotCompilationRequest hsRequest = (HotSpotCompilationRequest) request;
+            CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, shouldRetainLocalVariables(hsRequest.getJvmciEnv()), installAsDefault);
+            OptionValues options = task.filterOptions(initialOptions);
+            try (CompilationWatchDog w1 = CompilationWatchDog.watch(method, hsRequest.getId(), options);
+                            BootstrapWatchDog.Watch w2 = bootstrapWatchDog == null ? null : bootstrapWatchDog.watch(request);
+                            CompilationAlarm alarm = CompilationAlarm.trackCompilationPeriod(options);) {
+                if (compilationCounters != null) {
+                    compilationCounters.countCompilation(method);
+                }
+                CompilationRequestResult r = null;
+                try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM);
+                                Activation a = debug.activate()) {
+                    r = task.runCompilation(debug);
+                }
+                assert r != null;
+                return r;
             }
-            CompilationRequestResult r = null;
-            try (DebugContext debug = graalRuntime.openDebugContext(options, task.getCompilationIdentifier(), method, getDebugHandlersFactories(), DebugContext.DEFAULT_LOG_STREAM);
-                            Activation a = debug.activate()) {
-                r = task.runCompilation(debug);
-            }
-            assert r != null;
-            return r;
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalServices.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalServices.java	Thu Jul 25 17:35:58 2019 -0400
@@ -26,6 +26,9 @@
 
 import jdk.vm.ci.hotspot.HotSpotMetaData;
 
+/**
+ * JDK 13 version of {@code HotSpotGraalServices}.
+ */
 public class HotSpotGraalServices {
 
     /**
@@ -35,4 +38,17 @@
     public static byte[] getImplicitExceptionBytes(HotSpotMetaData metaData) {
         return metaData.implicitExceptionBytes();
     }
+
+    public static CompilationContext enterGlobalCompilationContext() {
+        return null;
+    }
+
+    @SuppressWarnings("unused")
+    public static CompilationContext openLocalCompilationContext(Object description) {
+        return null;
+    }
+
+    public static void exit(int status) {
+        System.exit(status);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotReplacementsImpl.java	Thu Jul 25 17:35:58 2019 -0400
@@ -208,6 +208,7 @@
         return super.getSnippet(method, recursiveEntry, args, trackNodeSourcePosition, replaceePosition, options);
     }
 
+    @SuppressWarnings("try")
     private StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, Object[] args, StructuredGraph.AllowAssumptions allowAssumptions, OptionValues options) {
         boolean useEncodedGraphs = UseEncodedGraphs.getValue(options);
         if (IS_IN_NATIVE_IMAGE || useEncodedGraphs) {
@@ -219,11 +220,15 @@
                 if (getEncodedSnippets() == null) {
                     throw GraalError.shouldNotReachHere("encoded snippets not found");
                 }
-                StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options);
-                if (graph == null) {
-                    throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
+                // Snippets graphs can contain foreign object reference and
+                // outlive a single compilation.
+                try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) {
+                    StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, this, args, allowAssumptions, options);
+                    if (graph == null) {
+                        throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)"));
+                    }
+                    return graph;
                 }
-                return graph;
             }
         } else {
             assert registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotTTYStreamProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -42,6 +42,7 @@
 import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.graalvm.compiler.serviceprovider.ServiceProvider;
 
+import jdk.vm.ci.common.NativeImageReinitialize;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.services.Services;
 
@@ -96,7 +97,7 @@
          * initialization.
          */
         class DelayedOutputStream extends OutputStream {
-            private volatile OutputStream lazy;
+            @NativeImageReinitialize private volatile OutputStream lazy;
 
             private OutputStream lazy() {
                 if (lazy == null) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicateBase.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicateBase.java	Thu Jul 25 17:35:58 2019 -0400
@@ -43,4 +43,3 @@
         return HotSpotJVMCICompilerFactory.CompilationLevelAdjustment.ByHolder;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Thu Jul 25 17:35:58 2019 -0400
@@ -28,6 +28,8 @@
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Mechanism for checking that the current Java runtime environment supports the minimum JVMCI API
@@ -41,8 +43,107 @@
  */
 public final class JVMCIVersionCheck {
 
-    private static final int JVMCI8_MIN_MAJOR_VERSION = 19;
-    private static final int JVMCI8_MIN_MINOR_VERSION = 1;
+    private static final Version JVMCI8_MIN_VERSION = new Version3(19, 2, 1);
+
+    public interface Version {
+        boolean isLessThan(Version other);
+
+        static Version parse(String vmVersion) {
+            Matcher m = Pattern.compile(".*-jvmci-(\\d+)\\.(\\d+)-b(\\d+).*").matcher(vmVersion);
+            if (m.matches()) {
+                try {
+                    int major = Integer.parseInt(m.group(1));
+                    int minor = Integer.parseInt(m.group(2));
+                    int build = Integer.parseInt(m.group(3));
+                    return new Version3(major, minor, build);
+                } catch (NumberFormatException e) {
+                    // ignore
+                }
+            }
+            m = Pattern.compile(".*-jvmci-(\\d+)(?:\\.|-b)(\\d+).*").matcher(vmVersion);
+            if (m.matches()) {
+                try {
+                    int major = Integer.parseInt(m.group(1));
+                    int minor = Integer.parseInt(m.group(2));
+                    return new Version2(major, minor);
+                } catch (NumberFormatException e) {
+                    // ignore
+                }
+            }
+            return null;
+        }
+    }
+
+    public static class Version2 implements Version {
+        private final int major;
+        private final int minor;
+
+        public Version2(int major, int minor) {
+            this.major = major;
+            this.minor = minor;
+        }
+
+        @Override
+        public boolean isLessThan(Version other) {
+            if (other.getClass() == Version3.class) {
+                return true;
+            }
+            Version2 o = (Version2) other;
+            if (this.major < o.major) {
+                return true;
+            }
+            if (this.major == o.major && this.minor < o.minor) {
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            if (major >= 19) {
+                return String.format("%d-b%02d", major, minor);
+            } else {
+                return String.format("%d.%d", major, minor);
+            }
+        }
+    }
+
+    public static class Version3 implements Version {
+        private final int major;
+        private final int minor;
+        private final int build;
+
+        public Version3(int major, int minor, int build) {
+            this.major = major;
+            this.minor = minor;
+            this.build = build;
+        }
+
+        @Override
+        public boolean isLessThan(Version other) {
+            if (other.getClass() == Version2.class) {
+                return false;
+            }
+            Version3 o = (Version3) other;
+            if (this.major < o.major) {
+                return true;
+            }
+            if (this.major == o.major) {
+                if (this.minor < o.minor) {
+                    return true;
+                }
+                if (this.minor == o.minor && this.build < o.build) {
+                    return true;
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%d.%d-b%02d", major, minor, build);
+        }
+    }
 
     private static void failVersionCheck(Map<String, String> props, boolean exit, String reason, Object... args) {
         Formatter errorMessage = new Formatter().format(reason, args);
@@ -53,9 +154,7 @@
         errorMessage.format("Currently used Java home directory is %s.%n", javaHome);
         errorMessage.format("Currently used VM configuration is: %s%n", vmName);
         if (props.get("java.specification.version").compareTo("1.9") < 0) {
-            errorMessage.format("Download the latest JVMCI JDK 8 from " +
-                            "https://www.oracle.com/technetwork/graalvm/downloads/index.html or " +
-                            "https://github.com/graalvm/openjdk8-jvmci-builder/releases");
+            errorMessage.format("Download the latest JVMCI JDK 8 from https://github.com/graalvm/openjdk8-jvmci-builder/releases");
         } else {
             errorMessage.format("Download JDK 11 or later.");
         }
@@ -74,7 +173,6 @@
 
     private final String javaSpecVersion;
     private final String vmVersion;
-    private int cursor;
     private final Map<String, String> props;
 
     private JVMCIVersionCheck(Map<String, String> props, String javaSpecVersion, String vmVersion) {
@@ -85,112 +183,28 @@
 
     static void check(Map<String, String> props, boolean exitOnFailure) {
         JVMCIVersionCheck checker = new JVMCIVersionCheck(props, props.get("java.specification.version"), props.get("java.vm.version"));
-        checker.run(exitOnFailure, JVMCI8_MIN_MAJOR_VERSION, JVMCI8_MIN_MINOR_VERSION);
+        checker.run(exitOnFailure, JVMCI8_MIN_VERSION);
     }
 
     /**
      * Entry point for testing.
      */
     public static void check(Map<String, String> props,
-                    int jvmci8MinMajorVersion,
-                    int jvmci8MinMinorVersion,
+                    Version minVersion,
                     String javaSpecVersion,
-                    String javaVmVersion,
-                    boolean exitOnFailure) {
+                    String javaVmVersion, boolean exitOnFailure) {
         JVMCIVersionCheck checker = new JVMCIVersionCheck(props, javaSpecVersion, javaVmVersion);
-        checker.run(exitOnFailure, jvmci8MinMajorVersion, jvmci8MinMinorVersion);
-    }
-
-    /**
-     * Parses a positive decimal number at {@link #cursor}.
-     *
-     * @return -1 if there is no positive decimal number at {@link #cursor}
-     */
-    private int parseNumber() {
-        int result = -1;
-        while (cursor < vmVersion.length()) {
-            int digit = vmVersion.charAt(cursor) - '0';
-            if (digit >= 0 && digit <= 9) {
-                if (result == -1) {
-                    result = digit;
-                } else {
-                    long r = (long) result * (long) 10;
-                    if ((int) r != r) {
-                        // Overflow
-                        return -1;
-                    }
-                    result = (int) r + digit;
-                }
-                cursor++;
-            } else {
-                break;
-            }
-        }
-        return result;
+        checker.run(exitOnFailure, minVersion);
     }
 
-    /**
-     * Parse {@code "."} or {@code "-b"} at {@link #cursor}.
-     *
-     * @return {@code true} iff there was an expected separator at {@link #cursor}
-     */
-    private boolean parseSeparator() {
-        if (cursor < vmVersion.length()) {
-            char ch = vmVersion.charAt(cursor);
-            if (ch == '.') {
-                cursor++;
-                return true;
-            }
-            if (ch == '-') {
-                cursor++;
-                if (cursor < vmVersion.length()) {
-                    if (vmVersion.charAt(cursor) == 'b') {
-                        cursor++;
-                        return true;
-                    }
+    private void run(boolean exitOnFailure, Version minVersion) {
+        if (javaSpecVersion.compareTo("1.9") < 0) {
+            Version v = Version.parse(vmVersion);
+            if (v != null) {
+                if (v.isLessThan(minVersion)) {
+                    failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion);
                 }
-                return false;
-            }
-        }
-        return false;
-    }
-
-    private static String getJVMCIVersionString(int major, int minor) {
-        if (major >= 19) {
-            return String.format("%d-b%02d", major, minor);
-        } else {
-            return String.format("%d.%d", major, minor);
-        }
-    }
-
-    private void run(boolean exitOnFailure, int jvmci8MinMajorVersion, int jvmci8MinMinorVersion) {
-        // Don't use regular expressions to minimize Graal startup time
-        if (javaSpecVersion.compareTo("1.9") < 0) {
-            cursor = vmVersion.indexOf("-jvmci-");
-            if (cursor >= 0) {
-                cursor += "-jvmci-".length();
-                int major = parseNumber();
-                if (major == -1) {
-                    failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
-                                    "Cannot read JVMCI major version from java.vm.version property: %s.%n", vmVersion);
-                    return;
-                }
-
-                if (parseSeparator()) {
-                    int minor = parseNumber();
-                    if (minor == -1) {
-                        failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
-                                        "Cannot read JVMCI minor version from java.vm.version property: %s.%n", vmVersion);
-                        return;
-                    }
-
-                    if (major > jvmci8MinMajorVersion || (major >= jvmci8MinMajorVersion && minor >= jvmci8MinMinorVersion)) {
-                        return;
-                    }
-                    failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n",
-                                    getJVMCIVersionString(major, minor), getJVMCIVersionString(jvmci8MinMajorVersion, jvmci8MinMinorVersion));
-                    return;
-                }
+                return;
             }
             failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
                             "Cannot read JVMCI version from java.vm.version property: %s.%n", vmVersion);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -182,7 +182,7 @@
 /**
  * HotSpot implementation of {@link LoweringProvider}.
  */
-public class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider {
+public abstract class DefaultHotSpotLoweringProvider extends DefaultJavaLoweringProvider implements HotSpotLoweringProvider {
 
     protected final HotSpotGraalRuntimeProvider runtime;
     protected final HotSpotRegistersProvider registers;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Jul 25 17:35:58 2019 -0400
@@ -44,6 +44,7 @@
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.TypeReference;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.nodes.CurrentJavaThreadNode;
 import org.graalvm.compiler.hotspot.replacements.AESCryptSubstitutions;
@@ -106,6 +107,7 @@
 import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeUtil;
+import jdk.vm.ci.hotspot.VMIntrinsicMethod;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.DeoptimizationAction;
 import jdk.vm.ci.meta.JavaKind;
@@ -429,8 +431,6 @@
         r.registerMethodSubstitution(ThreadSubstitutions.class, "isInterrupted", Receiver.class, boolean.class);
     }
 
-    public static final String cbcEncryptName;
-    public static final String cbcDecryptName;
     public static final String aesEncryptName;
     public static final String aesDecryptName;
 
@@ -439,15 +439,11 @@
 
     static {
         if (JavaVersionUtil.JAVA_SPEC <= 8) {
-            cbcEncryptName = "encrypt";
-            cbcDecryptName = "decrypt";
             aesEncryptName = "encryptBlock";
             aesDecryptName = "decryptBlock";
             reflectionClass = "sun.reflect.Reflection";
             constantPoolClass = "sun.reflect.ConstantPool";
         } else {
-            cbcEncryptName = "implEncrypt";
-            cbcDecryptName = "implDecrypt";
             aesEncryptName = "implEncryptBlock";
             aesDecryptName = "implDecryptBlock";
             reflectionClass = "jdk.internal.reflect.Reflection";
@@ -455,6 +451,19 @@
         }
     }
 
+    public static boolean cbcUsesImplNames(GraalHotSpotVMConfig config) {
+        for (VMIntrinsicMethod intrinsic : config.getStore().getIntrinsics()) {
+            if ("com/sun/crypto/provider/CipherBlockChaining".equals(intrinsic.declaringClass)) {
+                if ("encrypt".equals(intrinsic.name)) {
+                    return false;
+                } else if ("implEncrypt".equals(intrinsic.name)) {
+                    return true;
+                }
+            }
+        }
+        throw GraalError.shouldNotReachHere();
+    }
+
     private static void registerAESPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
         if (config.useAESIntrinsics) {
             assert config.aescryptEncryptBlockStub != 0L;
@@ -464,9 +473,15 @@
             String arch = config.osArch;
             String decryptSuffix = arch.equals("sparc") ? "WithOriginalKey" : "";
             Registration r = new Registration(plugins, "com.sun.crypto.provider.CipherBlockChaining", bytecodeProvider);
+
+            boolean implNames = cbcUsesImplNames(config);
+            String cbcEncryptName = implNames ? "implEncrypt" : "encrypt";
+            String cbcDecryptName = implNames ? "implDecrypt" : "decrypt";
+
             r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcEncryptName, Receiver.class, byte[].class, int.class, int.class, byte[].class, int.class);
             r.registerMethodSubstitution(CipherBlockChainingSubstitutions.class, cbcDecryptName, cbcDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, int.class, byte[].class,
                             int.class);
+
             r = new Registration(plugins, "com.sun.crypto.provider.AESCrypt", bytecodeProvider);
             r.registerMethodSubstitution(AESCryptSubstitutions.class, aesEncryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class);
             r.registerMethodSubstitution(AESCryptSubstitutions.class, aesDecryptName, aesDecryptName + decryptSuffix, Receiver.class, byte[].class, int.class, byte[].class, int.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotNodePlugin.java	Thu Jul 25 17:35:58 2019 -0400
@@ -244,4 +244,3 @@
 
     private static final LocationIdentity JAVA_THREAD_SHOULD_POST_ON_EXCEPTIONS_FLAG_LOCATION = NamedLocationIdentity.mutable("JavaThread::_should_post_on_exceptions_flag");
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/VMErrorNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/VMErrorNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java	Thu Jul 25 17:35:58 2019 -0400
@@ -41,7 +41,6 @@
 import org.graalvm.compiler.loop.phases.LoopTransformations;
 import org.graalvm.compiler.nodeinfo.InputType;
 import org.graalvm.compiler.nodeinfo.Verbosity;
-import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.EntryMarkerNode;
 import org.graalvm.compiler.nodes.EntryProxyNode;
 import org.graalvm.compiler.nodes.FixedGuardNode;
@@ -159,11 +158,8 @@
             LoopEx loop = loops.loop(l);
             loop.loopBegin().markOsrLoop();
             LoopTransformations.peel(loop);
-            osr.replaceAtUsages(InputType.Guard, AbstractBeginNode.prevBegin((FixedNode) osr.predecessor()));
-            for (Node usage : osr.usages().snapshot()) {
-                EntryProxyNode proxy = (EntryProxyNode) usage;
-                proxy.replaceAndDelete(proxy.value());
-            }
+
+            osr.prepareDelete();
             GraphUtil.removeFixedWithUnusedInputs(osr);
             debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
         } while (true);
@@ -228,6 +224,7 @@
             }
 
             osr.replaceAtUsages(InputType.Guard, osrStart);
+            osr.replaceAtUsages(InputType.Anchor, osrStart);
         }
         debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
         GraphUtil.killCFG(start);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/Log.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/Log.java	Thu Jul 25 17:35:58 2019 -0400
@@ -191,4 +191,3 @@
         println("");
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Thu Jul 25 17:35:58 2019 -0400
@@ -212,14 +212,27 @@
     }
 
     @Snippet
-    public static Object allocateInstance(@ConstantParameter long size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
-                    @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
+    public static Object allocateInstance(@ConstantParameter long size,
+                    KlassPointer hub,
+                    Word prototypeMarkWord,
+                    @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
+                    @ConstantParameter Register threadRegister,
+                    @ConstantParameter boolean constantSize,
+                    @ConstantParameter String typeContext,
                     @ConstantParameter Counters counters) {
-        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
+        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, hub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, constantSize, typeContext, counters));
     }
 
-    public static Object allocateInstanceHelper(long size, KlassPointer hub, Word prototypeMarkWord, boolean fillContents,
-                    Register threadRegister, boolean constantSize, String typeContext, Counters counters) {
+    public static Object allocateInstanceHelper(long size,
+                    KlassPointer hub,
+                    Word prototypeMarkWord,
+                    boolean fillContents,
+                    boolean emitMemoryBarrier,
+                    Register threadRegister,
+                    boolean constantSize,
+                    String typeContext,
+                    Counters counters) {
         Object result;
         Word thread = registerAsWord(threadRegister);
         Word top = readTlabTop(thread);
@@ -228,7 +241,7 @@
         if (useTLAB(INJECTED_VMCONFIG) && probability(FAST_PATH_PROBABILITY, newTop.belowOrEqual(end))) {
             writeTlabTop(thread, newTop);
             emitPrefetchAllocate(newTop, false);
-            result = formatObject(hub, size, top, prototypeMarkWord, fillContents, constantSize, counters);
+            result = formatObject(hub, size, top, prototypeMarkWord, fillContents, emitMemoryBarrier, constantSize, counters);
         } else {
             Counters theCounters = counters;
             if (theCounters != null && theCounters.stub != null) {
@@ -255,18 +268,27 @@
     private static native Object newInstanceOrNull(@ConstantNodeParameter ForeignCallDescriptor descriptor, KlassPointer hub);
 
     @Snippet
-    public static Object allocateInstancePIC(@ConstantParameter long size, KlassPointer hub, Word prototypeMarkWord, @ConstantParameter boolean fillContents,
-                    @ConstantParameter Register threadRegister, @ConstantParameter boolean constantSize, @ConstantParameter String typeContext,
+    public static Object allocateInstancePIC(@ConstantParameter long size,
+                    KlassPointer hub,
+                    Word prototypeMarkWord,
+                    @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
+                    @ConstantParameter Register threadRegister,
+                    @ConstantParameter boolean constantSize,
+                    @ConstantParameter String typeContext,
                     @ConstantParameter Counters counters) {
         // Klass must be initialized by the time the first instance is allocated, therefore we can
         // just load it from the corresponding cell and avoid the resolution check. We have to use a
         // fixed load though, to prevent it from floating above the initialization.
         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
-        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, threadRegister, constantSize, typeContext, counters));
+        return piCastToSnippetReplaceeStamp(allocateInstanceHelper(size, picHub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, constantSize, typeContext, counters));
     }
 
     @Snippet
-    public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass, @ConstantParameter boolean fillContents, @ConstantParameter Register threadRegister,
+    public static Object allocateInstanceDynamic(Class<?> type, Class<?> classClass,
+                    @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
+                    @ConstantParameter Register threadRegister,
                     @ConstantParameter Counters counters) {
         if (probability(SLOW_PATH_PROBABILITY, type == null)) {
             DeoptimizeNode.deopt(None, RuntimeConstraint);
@@ -277,10 +299,15 @@
             DeoptimizeNode.deopt(None, RuntimeConstraint);
         }
 
-        return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, threadRegister, counters, nonNullType));
+        return PiNode.piCastToSnippetReplaceeStamp(allocateInstanceDynamicHelper(type, fillContents, emitMemoryBarrier, threadRegister, counters, nonNullType));
     }
 
-    private static Object allocateInstanceDynamicHelper(Class<?> type, boolean fillContents, Register threadRegister, Counters counters, Class<?> nonNullType) {
+    private static Object allocateInstanceDynamicHelper(Class<?> type,
+                    boolean fillContents,
+                    boolean emitMemoryBarrier,
+                    Register threadRegister,
+                    Counters counters,
+                    Class<?> nonNullType) {
         KlassPointer hub = ClassGetHubNode.readClass(nonNullType);
         if (probability(FAST_PATH_PROBABILITY, !hub.isNull())) {
             KlassPointer nonNullHub = ClassGetHubNode.piCastNonNull(hub, SnippetAnchorNode.anchor());
@@ -299,7 +326,7 @@
                      * FIXME(je,ds): we should actually pass typeContext instead of "" but late
                      * binding of parameters is not yet supported by the GraphBuilderPlugin system.
                      */
-                    return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, threadRegister, false, "", counters);
+                    return allocateInstanceHelper(layoutHelper, nonNullHub, prototypeMarkWord, fillContents, emitMemoryBarrier, threadRegister, false, "", counters);
                 }
             } else {
                 DeoptimizeNode.deopt(None, RuntimeConstraint);
@@ -320,6 +347,7 @@
                     @ConstantParameter int headerSize,
                     @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
                     @ConstantParameter Register threadRegister,
                     @ConstantParameter boolean maybeUnroll,
                     @ConstantParameter String typeContext,
@@ -328,7 +356,7 @@
         // Primitive array types are eagerly pre-resolved. We can use a floating load.
         KlassPointer picHub = LoadConstantIndirectlyNode.loadKlass(hub);
         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
-                        threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
+                        emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
     }
 
     @Snippet
@@ -338,6 +366,7 @@
                     @ConstantParameter int headerSize,
                     @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
                     @ConstantParameter Register threadRegister,
                     @ConstantParameter boolean maybeUnroll,
                     @ConstantParameter String typeContext,
@@ -346,7 +375,7 @@
         // Array type would be resolved by dominating resolution.
         KlassPointer picHub = LoadConstantIndirectlyFixedNode.loadKlass(hub);
         return allocateArrayImpl(picHub, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
-                        threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
+                        emitMemoryBarrier, threadRegister, maybeUnroll, typeContext, useBulkZeroing, counters);
     }
 
     @Snippet
@@ -356,6 +385,7 @@
                     @ConstantParameter int headerSize,
                     @ConstantParameter int log2ElementSize,
                     @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
                     @ConstantParameter Register threadRegister,
                     @ConstantParameter boolean maybeUnroll,
                     @ConstantParameter String typeContext,
@@ -367,7 +397,7 @@
                         headerSize,
                         log2ElementSize,
                         fillContents,
-                        threadRegister,
+                        emitMemoryBarrier, threadRegister,
                         maybeUnroll,
                         typeContext,
                         useBulkZeroing,
@@ -384,8 +414,18 @@
         return config.areNullAllocationStubsAvailable();
     }
 
-    private static Object allocateArrayImpl(KlassPointer hub, int length, Word prototypeMarkWord, int headerSize, int log2ElementSize, boolean fillContents, Register threadRegister,
-                    boolean maybeUnroll, String typeContext, boolean useBulkZeroing, Counters counters) {
+    private static Object allocateArrayImpl(KlassPointer hub,
+                    int length,
+                    Word prototypeMarkWord,
+                    int headerSize,
+                    int log2ElementSize,
+                    boolean fillContents,
+                    boolean emitMemoryBarrier,
+                    Register threadRegister,
+                    boolean maybeUnroll,
+                    String typeContext,
+                    boolean useBulkZeroing,
+                    Counters counters) {
         Object result;
         long allocationSize = arrayAllocationSize(length, headerSize, log2ElementSize);
         Word thread = registerAsWord(threadRegister);
@@ -400,7 +440,7 @@
             if (theCounters != null && theCounters.arrayLoopInit != null) {
                 theCounters.arrayLoopInit.inc();
             }
-            result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, maybeUnroll, useBulkZeroing, counters);
+            result = formatArray(hub, allocationSize, length, headerSize, top, prototypeMarkWord, fillContents, emitMemoryBarrier, maybeUnroll, useBulkZeroing, counters);
         } else {
             result = newArrayStub(hub, length);
         }
@@ -461,19 +501,29 @@
                     Class<?> voidClass,
                     int length,
                     @ConstantParameter boolean fillContents,
+                    @ConstantParameter boolean emitMemoryBarrier,
                     @ConstantParameter Register threadRegister,
                     @ConstantParameter JavaKind knownElementKind,
                     @ConstantParameter int knownLayoutHelper,
                     @ConstantParameter boolean useBulkZeroing,
                     Word prototypeMarkWord,
                     @ConstantParameter Counters counters) {
-        Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, threadRegister, knownElementKind,
+        Object result = allocateArrayDynamicImpl(elementType, voidClass, length, fillContents, emitMemoryBarrier, threadRegister, knownElementKind,
                         knownLayoutHelper, useBulkZeroing, prototypeMarkWord, counters);
         return result;
     }
 
-    private static Object allocateArrayDynamicImpl(Class<?> elementType, Class<?> voidClass, int length, boolean fillContents, Register threadRegister, JavaKind knownElementKind,
-                    int knownLayoutHelper, boolean useBulkZeroing, Word prototypeMarkWord, Counters counters) {
+    private static Object allocateArrayDynamicImpl(Class<?> elementType,
+                    Class<?> voidClass,
+                    int length,
+                    boolean fillContents,
+                    boolean emitMemoryBarrier,
+                    Register threadRegister,
+                    JavaKind knownElementKind,
+                    int knownLayoutHelper,
+                    boolean useBulkZeroing,
+                    Word prototypeMarkWord,
+                    Counters counters) {
         /*
          * We only need the dynamic check for void when we have no static information from
          * knownElementKind.
@@ -516,7 +566,7 @@
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
 
         Object result = allocateArrayImpl(nonNullKlass, length, prototypeMarkWord, headerSize, log2ElementSize, fillContents,
-                        threadRegister, false, "dynamic type", useBulkZeroing, counters);
+                        emitMemoryBarrier, threadRegister, false, "dynamic type", useBulkZeroing, counters);
         return piArrayCastToSnippetReplaceeStamp(verifyOop(result), length);
     }
 
@@ -650,7 +700,14 @@
     /**
      * Formats some allocated memory with an object header and zeroes out the rest.
      */
-    private static Object formatObject(KlassPointer hub, long size, Word memory, Word compileTimePrototypeMarkWord, boolean fillContents, boolean constantSize, Counters counters) {
+    private static Object formatObject(KlassPointer hub,
+                    long size,
+                    Word memory,
+                    Word compileTimePrototypeMarkWord,
+                    boolean fillContents,
+                    boolean emitMemoryBarrier,
+                    boolean constantSize,
+                    Counters counters) {
         Word prototypeMarkWord = useBiasedLocking(INJECTED_VMCONFIG) ? hub.readWord(prototypeMarkWordOffset(INJECTED_VMCONFIG), PROTOTYPE_MARK_WORD_LOCATION) : compileTimePrototypeMarkWord;
         initializeObjectHeader(memory, prototypeMarkWord, hub);
         if (fillContents) {
@@ -658,7 +715,9 @@
         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
             fillWithGarbage(size, memory, constantSize, instanceHeaderSize(INJECTED_VMCONFIG), false, counters);
         }
-        MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
+        if (emitMemoryBarrier) {
+            MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
+        }
         return memory.toObjectNonNull();
     }
 
@@ -677,8 +736,17 @@
     /**
      * Formats some allocated memory with an object header and zeroes out the rest.
      */
-    private static Object formatArray(KlassPointer hub, long allocationSize, int length, int headerSize, Word memory, Word prototypeMarkWord, boolean fillContents, boolean maybeUnroll,
-                    boolean useBulkZeroing, Counters counters) {
+    private static Object formatArray(KlassPointer hub,
+                    long allocationSize,
+                    int length,
+                    int headerSize,
+                    Word memory,
+                    Word prototypeMarkWord,
+                    boolean fillContents,
+                    boolean emitMemoryBarrier,
+                    boolean maybeUnroll,
+                    boolean useBulkZeroing,
+                    Counters counters) {
         memory.writeInt(arrayLengthOffset(INJECTED_VMCONFIG), length, LocationIdentity.init());
         /*
          * store hub last as the concurrent garbage collectors assume length is valid if hub field
@@ -690,7 +758,9 @@
         } else if (REPLACEMENTS_ASSERTIONS_ENABLED) {
             fillWithGarbage(allocationSize, memory, false, headerSize, maybeUnroll, counters);
         }
-        MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
+        if (emitMemoryBarrier) {
+            MembarNode.memoryBarrier(MemoryBarriers.STORE_STORE, LocationIdentity.init());
+        }
         return memory.toObjectNonNull();
     }
 
@@ -756,6 +826,7 @@
             args.add("hub", hub);
             args.add("prototypeMarkWord", type.prototypeMarkWord());
             args.addConst("fillContents", newInstanceNode.fillContents());
+            args.addConst("emitMemoryBarrier", newInstanceNode.emitMemoryBarrier());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("constantSize", true);
             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? type.toJavaName(false) : "");
@@ -799,6 +870,7 @@
             args.addConst("headerSize", headerSize);
             args.addConst("log2ElementSize", log2ElementSize);
             args.addConst("fillContents", newArrayNode.fillContents());
+            args.addConst("emitMemoryBarrier", newArrayNode.emitMemoryBarrier());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("maybeUnroll", length.isConstant());
             args.addConst("typeContext", ProfileAllocations.getValue(localOptions) ? arrayType.toJavaName(false) : "");
@@ -816,6 +888,7 @@
             assert classClass != null;
             args.add("classClass", classClass);
             args.addConst("fillContents", newInstanceNode.fillContents());
+            args.addConst("emitMemoryBarrier", newInstanceNode.emitMemoryBarrier());
             args.addConst("threadRegister", registers.getThreadRegister());
             args.addConst("counters", counters);
 
@@ -833,6 +906,7 @@
             ValueNode length = newArrayNode.length();
             args.add("length", length.isAlive() ? length : graph.addOrUniqueWithInputs(length));
             args.addConst("fillContents", newArrayNode.fillContents());
+            args.addConst("emitMemoryBarrier", newArrayNode.emitMemoryBarrier());
             args.addConst("threadRegister", registers.getThreadRegister());
             /*
              * We use Kind.Illegal as a marker value instead of null because constant snippet
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Thu Jul 25 17:35:58 2019 -0400
@@ -391,7 +391,6 @@
 import org.graalvm.compiler.nodes.extended.LoadHubNode;
 import org.graalvm.compiler.nodes.extended.MembarNode;
 import org.graalvm.compiler.nodes.extended.StateSplitProxyNode;
-import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.ClassInitializationPlugin;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
@@ -624,7 +623,6 @@
     }
 
     static class IntrinsicScope extends InliningScope {
-        StateSplit returnStateSplit;
         ArrayList<StateSplit> invalidStateUsers;
 
         IntrinsicScope(BytecodeParser parser) {
@@ -635,6 +633,7 @@
             super(parser, callee, args);
         }
 
+        @SuppressWarnings("unlikely-arg-type")
         @Override
         public void close() {
             IntrinsicContext intrinsic = parser.intrinsicContext;
@@ -1405,7 +1404,7 @@
         if (profile == null || profile.getNotRecordedProbability() > 0.0) {
             return null;
         } else {
-            return append(new ValueAnchorNode(null));
+            return BeginNode.prevBegin(lastInstr);
         }
     }
 
@@ -4794,6 +4793,9 @@
         }
     }
 
+    private static final int SWITCH_DEOPT_UNSEEN = -2;
+    private static final int SWITCH_DEOPT_SEEN = -1;
+
     private void genSwitch(BytecodeSwitch bs) {
         int bci = bci();
         ValueNode value = frameState.pop(JavaKind.Int);
@@ -4811,20 +4813,16 @@
         ArrayList<BciBlock> actualSuccessors = new ArrayList<>();
         int[] keys = new int[nofCases];
         int[] keySuccessors = new int[nofCasesPlusDefault];
-        int deoptSuccessorIndex = -1;
+        int deoptSuccessorIndex = SWITCH_DEOPT_UNSEEN;
         int nextSuccessorIndex = 0;
         boolean constantValue = value.isConstant();
         for (int i = 0; i < nofCasesPlusDefault; i++) {
             if (i < nofCases) {
                 keys[i] = bs.keyAt(i);
             }
-
             if (!constantValue && isNeverExecutedCode(keyProbabilities[i])) {
-                if (deoptSuccessorIndex < 0) {
-                    deoptSuccessorIndex = nextSuccessorIndex++;
-                    actualSuccessors.add(null);
-                }
-                keySuccessors[i] = deoptSuccessorIndex;
+                deoptSuccessorIndex = SWITCH_DEOPT_SEEN;
+                keySuccessors[i] = SWITCH_DEOPT_SEEN;
             } else {
                 int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
                 SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
@@ -4859,20 +4857,31 @@
          *
          * The following code rewires deoptimization stub to existing resolved branch target if
          * the target is connected by more than 1 cases.
+         *
+         * If this operation rewires every deoptimization seen to an existing branch, care is
+         * taken that we do not spawn a branch that will never be taken.
          */
-        if (deoptSuccessorIndex >= 0) {
-            int[] connectedCases = new int[nextSuccessorIndex];
+        if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
+            int[] connectedCases = new int[nextSuccessorIndex + 1];
             for (int i = 0; i < nofCasesPlusDefault; i++) {
-                connectedCases[keySuccessors[i]]++;
+                connectedCases[keySuccessors[i] + 1]++;
             }
 
             for (int i = 0; i < nofCasesPlusDefault; i++) {
-                if (keySuccessors[i] == deoptSuccessorIndex) {
+                if (keySuccessors[i] == SWITCH_DEOPT_SEEN) {
                     int targetBci = i < nofCases ? bs.targetAt(i) : bs.defaultTarget();
                     SuccessorInfo info = bciToBlockSuccessorIndex.get(targetBci);
                     int rewiredIndex = info.actualIndex;
-                    if (rewiredIndex >= 0 && connectedCases[rewiredIndex] > 1) {
+                    if (rewiredIndex >= 0 && connectedCases[rewiredIndex + 1] > 1) {
+                        // Rewire
                         keySuccessors[i] = info.actualIndex;
+                    } else {
+                        if (deoptSuccessorIndex == SWITCH_DEOPT_SEEN) {
+                            // Spawn deopt successor if needed.
+                            deoptSuccessorIndex = nextSuccessorIndex++;
+                            actualSuccessors.add(null);
+                        }
+                        keySuccessors[i] = deoptSuccessorIndex;
                     }
                 }
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Thu Jul 25 17:35:58 2019 -0400
@@ -528,8 +528,8 @@
                 break;
             case Object:
                 if (input.isNull()) {
-                    if (crb.mustReplaceWithNullRegister(input)) {
-                        masm.mov(64, dst, crb.nullRegister);
+                    if (crb.mustReplaceWithUncompressedNullRegister(input)) {
+                        masm.mov(64, dst, crb.uncompressedNullRegister);
                     } else {
                         masm.mov(dst, 0);
                     }
@@ -725,7 +725,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
-            Register nullRegister = crb.nullRegister;
+            Register nullRegister = crb.uncompressedNullRegister;
             if (!nullRegister.equals(Register.None)) {
                 emitConversion(asRegister(result), asRegister(input), nullRegister, masm);
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Thu Jul 25 17:35:58 2019 -0400
@@ -645,4 +645,3 @@
         return ((AMD64) tool.target().arch).getFeatures().contains(cpuFeature);
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ControlFlow.java	Thu Jul 25 17:35:58 2019 -0400
@@ -213,7 +213,7 @@
                         masm.cmpq(keyRegister, (AMD64Address) crb.asLongConstRef(jc));
                         break;
                     case Object:
-                        AMD64Move.const2reg(crb, masm, asRegister(scratch), jc);
+                        AMD64Move.const2reg(crb, masm, asRegister(scratch), jc, AMD64Kind.QWORD);
                         masm.cmpptr(keyRegister, asRegister(scratch));
                         break;
                     default:
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Thu Jul 25 17:35:58 2019 -0400
@@ -156,7 +156,7 @@
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
             if (isRegister(result)) {
-                const2reg(crb, masm, asRegister(result), input);
+                const2reg(crb, masm, asRegister(result), input, (AMD64Kind) result.getPlatformKind());
             } else {
                 assert isStackSlot(result);
                 const2stack(crb, masm, result, input);
@@ -557,7 +557,7 @@
             }
         } else if (isJavaConstant(input)) {
             if (isRegister(result)) {
-                const2reg(crb, masm, asRegister(result), asJavaConstant(input));
+                const2reg(crb, masm, asRegister(result), asJavaConstant(input), moveKind);
             } else if (isStackSlot(result)) {
                 const2stack(crb, masm, result, asJavaConstant(input));
             } else {
@@ -645,7 +645,7 @@
         }
     }
 
-    public static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, JavaConstant input) {
+    public static void const2reg(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register result, JavaConstant input, AMD64Kind moveKind) {
         /*
          * Note: we use the kind of the input operand (and not the kind of the result operand)
          * because they don't match in all cases. For example, an object constant can be loaded to a
@@ -691,20 +691,34 @@
                 }
                 break;
             case Object:
+                assert moveKind != null : "a nun-null moveKind is required for loading an object constant";
                 // Do not optimize with an XOR as this instruction may be between
                 // a CMP and a Jcc in which case the XOR will modify the condition
                 // flags and interfere with the Jcc.
                 if (input.isNull()) {
-                    if (crb.mustReplaceWithNullRegister(input)) {
-                        masm.movq(result, crb.nullRegister);
+                    if (moveKind == AMD64Kind.QWORD && crb.mustReplaceWithUncompressedNullRegister(input)) {
+                        masm.movq(result, crb.uncompressedNullRegister);
                     } else {
+                        // Upper bits will be zeroed so this also works for narrow oops
                         masm.movslq(result, 0);
                     }
-                } else if (crb.target.inlineObjects) {
-                    crb.recordInlineDataInCode(input);
-                    masm.movq(result, 0xDEADDEADDEADDEADL, true);
                 } else {
-                    masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
+                    if (crb.target.inlineObjects) {
+                        crb.recordInlineDataInCode(input);
+                        if (moveKind == AMD64Kind.DWORD) {
+                            // Support for narrow oops
+                            masm.movl(result, 0xDEADDEAD, true);
+                        } else {
+                            masm.movq(result, 0xDEADDEADDEADDEADL, true);
+                        }
+                    } else {
+                        if (moveKind == AMD64Kind.DWORD) {
+                            // Support for narrow oops
+                            masm.movl(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
+                        } else {
+                            masm.movq(result, (AMD64Address) crb.recordDataReferenceInCode(input, 0));
+                        }
+                    }
                 }
                 break;
             default:
@@ -752,13 +766,13 @@
                 break;
             case Object:
                 if (input.isNull()) {
-                    if (crb.mustReplaceWithNullRegister(input)) {
-                        masm.movq(dest, crb.nullRegister);
+                    if (crb.mustReplaceWithUncompressedNullRegister(input)) {
+                        masm.movq(dest, crb.uncompressedNullRegister);
                         return;
                     }
                     imm = 0;
                 } else {
-                    throw GraalError.shouldNotReachHere("Non-null object constants must be in register");
+                    throw GraalError.shouldNotReachHere("Non-null object constants must be in a register");
                 }
                 break;
             default:
@@ -941,7 +955,7 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-            Register nullRegister = crb.nullRegister;
+            Register nullRegister = crb.uncompressedNullRegister;
             if (!nullRegister.equals(Register.None)) {
                 emitConversion(asRegister(result), asRegister(input), nullRegister, masm);
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java	Thu Jul 25 17:35:58 2019 -0400
@@ -34,6 +34,7 @@
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 import org.graalvm.compiler.lir.framemap.FrameMap;
 
+import jdk.vm.ci.amd64.AMD64Kind;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.RegisterSaveLayout;
 import jdk.vm.ci.meta.JavaConstant;
@@ -66,7 +67,7 @@
         for (int i = 0; i < zappedRegisters.length; i++) {
             Register reg = zappedRegisters[i];
             if (reg != null) {
-                AMD64Move.const2reg(crb, masm, reg, zapValues[i]);
+                AMD64Move.const2reg(crb, masm, reg, zapValues[i], AMD64Kind.QWORD);
             }
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java	Thu Jul 25 17:35:58 2019 -0400
@@ -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
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexRVMOp;
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.asm.amd64.AVXKind;
+import org.graalvm.compiler.lir.ConstantValue;
 import org.graalvm.compiler.lir.LIRFrameState;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
@@ -42,6 +43,7 @@
 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
+import jdk.vm.ci.amd64.AMD64Kind;
 import jdk.vm.ci.meta.AllocatableValue;
 
 public class AMD64VectorBinary {
@@ -102,6 +104,38 @@
         }
     }
 
+    public static final class AVXBinaryConstFloatOp extends AMD64LIRInstruction {
+
+        public static final LIRInstructionClass<AVXBinaryConstFloatOp> TYPE = LIRInstructionClass.create(AVXBinaryConstFloatOp.class);
+
+        @Opcode private final VexRVMOp opcode;
+        private final AVXKind.AVXSize size;
+
+        @Def({REG}) protected AllocatableValue result;
+        @Use({REG}) protected AllocatableValue x;
+        protected ConstantValue y;
+
+        public AVXBinaryConstFloatOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, ConstantValue y) {
+            super(TYPE);
+            assert y.getPlatformKind() == AMD64Kind.SINGLE || y.getPlatformKind() == AMD64Kind.DOUBLE;
+            this.opcode = opcode;
+            this.size = size;
+            this.result = result;
+            this.x = x;
+            this.y = y;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            if (y.getPlatformKind() == AMD64Kind.SINGLE) {
+                opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asFloatConstRef(y.getJavaConstant()));
+            } else {
+                assert y.getPlatformKind() == AMD64Kind.DOUBLE;
+                opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asDoubleConstRef(y.getJavaConstant()));
+            }
+        }
+    }
+
     public static final class AVXBinaryMemoryOp extends AMD64LIRInstruction {
         public static final LIRInstructionClass<AVXBinaryMemoryOp> TYPE = LIRInstructionClass.create(AVXBinaryMemoryOp.class);
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/ConstantStackCastTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/ConstantStackCastTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -99,7 +99,7 @@
     }
 
     @Test
-    public void runByte() throws Throwable {
+    public void runByte() {
         runTest("testByte", (byte) 0);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -254,7 +254,7 @@
 
     @java.lang.annotation.Retention(RetentionPolicy.RUNTIME)
     @java.lang.annotation.Target(ElementType.METHOD)
-    public static @interface LIRIntrinsic {
+    public @interface LIRIntrinsic {
     }
 
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTestTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/LIRTestTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -54,7 +54,7 @@
     }
 
     @Test
-    public void runInt() throws Throwable {
+    public void runInt() {
         runTest("testGetOutput", Integer.MIN_VALUE, 0, supply(() -> new int[3]));
         runTest("testGetOutput", -1, Integer.MAX_VALUE, supply(() -> new int[3]));
         runTest("testGetOutput", 0, 42, supply(() -> new int[3]));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackMoveTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackMoveTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -98,7 +98,7 @@
     }
 
     @Test
-    public void runInt() throws Throwable {
+    public void runInt() {
         runTest("testInt", Integer.MIN_VALUE, supply(() -> new int[4]));
         runTest("testInt", -1, supply(() -> new int[4]));
         runTest("testInt", 0, supply(() -> new int[4]));
@@ -125,7 +125,7 @@
     }
 
     @Test
-    public void runLong() throws Throwable {
+    public void runLong() {
         runTest("testLong", Long.MIN_VALUE, supply(() -> new long[3]));
         runTest("testLong", -1L, supply(() -> new long[3]));
         runTest("testLong", 0L, supply(() -> new long[3]));
@@ -152,7 +152,7 @@
     }
 
     @Test
-    public void runFloat() throws Throwable {
+    public void runFloat() {
         runTest("testFloat", Float.MIN_VALUE, supply(() -> new float[3]));
         runTest("testFloat", -1f, supply(() -> new float[3]));
         runTest("testFloat", -0.1f, supply(() -> new float[3]));
@@ -217,7 +217,7 @@
     }
 
     @Test
-    public void runShort() throws Throwable {
+    public void runShort() {
         runTest("testShort", Short.MIN_VALUE, supply(() -> new short[3]));
         runTest("testShort", (short) -1, supply(() -> new short[3]));
         runTest("testShort", (short) 0, supply(() -> new short[3]));
@@ -251,7 +251,7 @@
     }
 
     @Test
-    public void runByte() throws Throwable {
+    public void runByte() {
         runTest("testByte", Byte.MIN_VALUE, supply(() -> new byte[3]));
         runTest("testByte", (byte) -1, supply(() -> new byte[3]));
         runTest("testByte", (byte) 0, supply(() -> new byte[3]));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2017, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -139,7 +139,7 @@
     }
 
     @Test
-    public void runByte() throws Throwable {
+    public void runByte() {
         runTest("testByte", Byte.MIN_VALUE, supply(() -> new byte[3]));
         runTest("testByte", (byte) -1, supply(() -> new byte[3]));
         runTest("testByte", (byte) 0, supply(() -> new byte[3]));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRVerifier.java	Thu Jul 25 17:35:58 2019 -0400
@@ -25,7 +25,7 @@
 package org.graalvm.compiler.lir;
 
 import static org.graalvm.compiler.lir.LIRValueUtil.asVariable;
-import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
+import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isVariable;
 import static jdk.vm.ci.code.ValueUtil.asRegister;
@@ -242,7 +242,7 @@
         if ((isVariable(value) && flags.contains(OperandFlag.REG)) ||
             (isRegister(value) && flags.contains(OperandFlag.REG)) ||
             (isStackSlotValue(value) && flags.contains(OperandFlag.STACK)) ||
-            (isJavaConstant(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
+            (isConstantValue(value) && flags.contains(OperandFlag.CONST) && mode != OperandMode.DEF) ||
             (isIllegal(value) && flags.contains(OperandFlag.ILLEGAL))) {
             return;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java	Thu Jul 25 17:35:58 2019 -0400
@@ -35,6 +35,7 @@
 
 import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
@@ -154,7 +155,7 @@
         @Override
         public void emitCode(CompilationResultBuilder crb) {
             if (align) {
-                crb.asm.align(crb.target.wordSize * 2);
+                crb.asm.align(GraalOptions.LoopHeaderAlignment.getValue(crb.getOptions()));
             }
             crb.asm.bind(label);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Thu Jul 25 17:35:58 2019 -0400
@@ -127,7 +127,7 @@
     public final Assembler asm;
     public final DataBuilder dataBuilder;
     public final CompilationResult compilationResult;
-    public final Register nullRegister;
+    public final Register uncompressedNullRegister;
     public final TargetDescription target;
     public final CodeCacheProvider codeCache;
     public final ForeignCallsProvider foreignCalls;
@@ -171,17 +171,44 @@
      */
     private boolean conservativeLabelOffsets = false;
 
-    public final boolean mustReplaceWithNullRegister(JavaConstant nullConstant) {
-        return !nullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant);
+    public final boolean mustReplaceWithUncompressedNullRegister(JavaConstant nullConstant) {
+        return !uncompressedNullRegister.equals(Register.None) && JavaConstant.NULL_POINTER.equals(nullConstant);
     }
 
-    public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext,
-                    OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) {
-        this(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, nullRegister, EconomicMap.create(Equivalence.DEFAULT));
+    public CompilationResultBuilder(CodeCacheProvider codeCache,
+                    ForeignCallsProvider foreignCalls,
+                    FrameMap frameMap,
+                    Assembler asm,
+                    DataBuilder dataBuilder,
+                    FrameContext frameContext,
+                    OptionValues options,
+                    DebugContext debug,
+                    CompilationResult compilationResult,
+                    Register uncompressedNullRegister) {
+        this(codeCache,
+                        foreignCalls,
+                        frameMap,
+                        asm,
+                        dataBuilder,
+                        frameContext,
+                        options,
+                        debug,
+                        compilationResult,
+                        uncompressedNullRegister,
+                        EconomicMap.create(Equivalence.DEFAULT));
     }
 
-    public CompilationResultBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder, FrameContext frameContext,
-                    OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister, EconomicMap<Constant, Data> dataCache) {
+    public CompilationResultBuilder(CodeCacheProvider codeCache,
+                    ForeignCallsProvider foreignCalls,
+                    FrameMap frameMap,
+                    Assembler asm,
+                    DataBuilder dataBuilder,
+                    FrameContext frameContext,
+                    OptionValues options,
+                    DebugContext debug,
+                    CompilationResult compilationResult,
+                    Register uncompressedNullRegister,
+                    EconomicMap<Constant, Data> dataCache) {
         this.target = codeCache.getTarget();
         this.codeCache = codeCache;
         this.foreignCalls = foreignCalls;
@@ -189,7 +216,7 @@
         this.asm = asm;
         this.dataBuilder = dataBuilder;
         this.compilationResult = compilationResult;
-        this.nullRegister = nullRegister;
+        this.uncompressedNullRegister = uncompressedNullRegister;
         this.frameContext = frameContext;
         this.options = options;
         this.debug = debug;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilderFactory.java	Thu Jul 25 17:35:58 2019 -0400
@@ -52,8 +52,8 @@
 
         @Override
         public CompilationResultBuilder createBuilder(CodeCacheProvider codeCache, ForeignCallsProvider foreignCalls, FrameMap frameMap, Assembler asm, DataBuilder dataBuilder,
-                        FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult, Register nullRegister) {
-            return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, nullRegister);
+                        FrameContext frameContext, OptionValues options, DebugContext debug, CompilationResult compilationResult, Register uncompressedNullRegister) {
+            return new CompilationResultBuilder(codeCache, foreignCalls, frameMap, asm, dataBuilder, frameContext, options, debug, compilationResult, uncompressedNullRegister);
         }
     };
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerator.java	Thu Jul 25 17:35:58 2019 -0400
@@ -60,9 +60,9 @@
 import org.graalvm.compiler.lir.StandardOp.BlockEndOp;
 import org.graalvm.compiler.lir.StandardOp.LabelOp;
 import org.graalvm.compiler.lir.StandardOp.SaveRegistersOp;
-import org.graalvm.compiler.lir.hashing.Hasher;
 import org.graalvm.compiler.lir.SwitchStrategy;
 import org.graalvm.compiler.lir.Variable;
+import org.graalvm.compiler.lir.hashing.Hasher;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
@@ -230,11 +230,31 @@
     }
 
     @Override
+    public Variable emitReadRegister(Register register, ValueKind<?> kind) {
+        return emitMove(register.asValue(kind));
+    }
+
+    @Override
+    public void emitWriteRegister(Register dst, Value src, ValueKind<?> kind) {
+        emitMove(dst.asValue(kind), src);
+    }
+
+    @Override
     public void emitMoveConstant(AllocatableValue dst, Constant src) {
         append(moveFactory.createLoad(dst, src));
     }
 
     @Override
+    public boolean canInlineConstant(Constant constant) {
+        return moveFactory.canInlineConstant(constant);
+    }
+
+    @Override
+    public boolean mayEmbedConstantLoad(Constant constant) {
+        return moveFactory.mayEmbedConstantLoad(constant);
+    }
+
+    @Override
     public Value emitConstant(LIRKind kind, Constant constant) {
         if (moveFactory.canInlineConstant(constant)) {
             return new ConstantValue(toRegisterKind(kind), constant);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Thu Jul 25 17:35:58 2019 -0400
@@ -65,14 +65,22 @@
     interface MoveFactory {
 
         /**
+         * Checks whether the loading of the supplied constant can be deferred until usage.
+         */
+        @SuppressWarnings("unused")
+        default boolean mayEmbedConstantLoad(Constant constant) {
+            return false;
+        }
+
+        /**
          * Checks whether the supplied constant can be used without loading it into a register for
          * most operations, i.e., for commonly used arithmetic, logical, and comparison operations.
          *
-         * @param c The constant to check.
+         * @param constant The constant to check.
          * @return True if the constant can be used directly, false if the constant needs to be in a
          *         register.
          */
-        boolean canInlineConstant(Constant c);
+        boolean canInlineConstant(Constant constant);
 
         /**
          * @param constant The constant that might be moved to a stack slot.
@@ -130,6 +138,10 @@
 
     BlockScope getBlockScope(AbstractBlockBase<?> block);
 
+    boolean canInlineConstant(Constant constant);
+
+    boolean mayEmbedConstantLoad(Constant constant);
+
     Value emitConstant(LIRKind kind, Constant constant);
 
     Value emitJavaConstant(JavaConstant constant);
@@ -192,6 +204,10 @@
 
     void emitMove(AllocatableValue dst, Value src);
 
+    Variable emitReadRegister(Register register, ValueKind<?> kind);
+
+    void emitWriteRegister(Register dst, Value src, ValueKind<?> wordStamp);
+
     void emitMoveConstant(AllocatableValue dst, Constant src);
 
     Variable emitAddress(AllocatableValue stackslot);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssa/SSAVerifier.java	Thu Jul 25 17:35:58 2019 -0400
@@ -26,7 +26,7 @@
 package org.graalvm.compiler.lir.ssa;
 
 import static jdk.vm.ci.code.ValueUtil.isRegister;
-import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
+import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 
 import java.util.BitSet;
@@ -137,7 +137,7 @@
     }
 
     private static boolean shouldProcess(Value value) {
-        return !value.equals(Value.ILLEGAL) && !isJavaConstant(value) && !isRegister(value) && !isStackSlotValue(value);
+        return !value.equals(Value.ILLEGAL) && !isConstantValue(value) && !isRegister(value) && !isStackSlotValue(value);
     }
 
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop.test/src/org/graalvm/compiler/loop/test/LoopPartialUnrollTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -26,7 +26,9 @@
 
 import java.util.ListIterator;
 
+import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
@@ -216,6 +218,25 @@
         test("testSignExtensionSnippet", 9L);
     }
 
+    public static Object objectPhi(int n) {
+        Integer v = Integer.valueOf(200);
+        GraalDirectives.blackhole(v); // Prevents PEA
+        Integer r = 1;
+
+        for (int i = 0; iterationCount(100, i < n); i++) {
+            GraalDirectives.blackhole(r); // Create a phi of two loop invariants
+            r = v;
+        }
+
+        return r;
+    }
+
+    @Test
+    public void testObjectPhi() {
+        OptionValues options = new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false);
+        test(options, "objectPhi", 1);
+    }
+
     @Override
     protected Suites createSuites(OptionValues opts) {
         Suites suites = super.createSuites(opts).copy();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Thu Jul 25 17:35:58 2019 -0400
@@ -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
@@ -344,7 +344,7 @@
                 }
             }
         }
-        LoopFragment.computeNodes(branchNodes, branch.graph(), blocks, exits);
+        LoopFragment.computeNodes(branchNodes, branch.graph(), this, blocks, exits);
     }
 
     public EconomicMap<Node, InductionVariable> getInductionVariables() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Thu Jul 25 17:35:58 2019 -0400
@@ -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
@@ -25,12 +25,11 @@
 package org.graalvm.compiler.loop;
 
 import java.util.ArrayDeque;
-import java.util.Collections;
 import java.util.Deque;
 import java.util.Iterator;
 
 import jdk.internal.vm.compiler.collections.EconomicMap;
-import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
 import org.graalvm.compiler.graph.Node;
@@ -42,18 +41,15 @@
 import org.graalvm.compiler.nodes.FixedNode;
 import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.GuardNode;
-import org.graalvm.compiler.nodes.GuardPhiNode;
 import org.graalvm.compiler.nodes.GuardProxyNode;
 import org.graalvm.compiler.nodes.Invoke;
+import org.graalvm.compiler.nodes.LoopBeginNode;
 import org.graalvm.compiler.nodes.LoopExitNode;
 import org.graalvm.compiler.nodes.MergeNode;
-import org.graalvm.compiler.nodes.NodeView;
 import org.graalvm.compiler.nodes.PhiNode;
 import org.graalvm.compiler.nodes.ProxyNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.ValuePhiNode;
-import org.graalvm.compiler.nodes.ValueProxyNode;
 import org.graalvm.compiler.nodes.VirtualState;
 import org.graalvm.compiler.nodes.cfg.Block;
 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
@@ -199,17 +195,7 @@
         }
     }
 
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks) {
-        return computeNodes(graph, blocks, Collections.emptyList());
-    }
-
-    protected static NodeBitMap computeNodes(Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
-        final NodeBitMap nodes = graph.createNodeBitMap();
-        computeNodes(nodes, graph, blocks, earlyExits);
-        return nodes;
-    }
-
-    protected static void computeNodes(NodeBitMap nodes, Graph graph, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
+    protected static void computeNodes(NodeBitMap nodes, Graph graph, LoopEx loop, Iterable<AbstractBeginNode> blocks, Iterable<AbstractBeginNode> earlyExits) {
         for (AbstractBeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
@@ -261,11 +247,11 @@
             for (Node n : b.getBlockNodes()) {
                 if (n instanceof CommitAllocationNode) {
                     for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
-                        markFloating(worklist, obj, nodes, nonLoopNodes);
+                        markFloating(worklist, loop, obj, nodes, nonLoopNodes);
                     }
                 }
                 if (n instanceof MonitorEnterNode) {
-                    markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
+                    markFloating(worklist, loop, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
                 }
                 if (n instanceof AbstractMergeNode) {
                     /*
@@ -274,12 +260,12 @@
                      */
                     for (PhiNode phi : ((AbstractMergeNode) n).phis()) {
                         for (Node usage : phi.usages()) {
-                            markFloating(worklist, usage, nodes, nonLoopNodes);
+                            markFloating(worklist, loop, usage, nodes, nonLoopNodes);
                         }
                     }
                 }
                 for (Node usage : n.usages()) {
-                    markFloating(worklist, usage, nodes, nonLoopNodes);
+                    markFloating(worklist, loop, usage, nodes, nonLoopNodes);
                 }
             }
         }
@@ -331,10 +317,14 @@
         workList.push(entry);
     }
 
-    private static void markFloating(Deque<WorkListEntry> workList, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
+    private static void markFloating(Deque<WorkListEntry> workList, LoopEx loop, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
         if (isLoopNode(start, loopNodes, nonLoopNodes).isKnown()) {
             return;
         }
+
+        LoopBeginNode loopBeginNode = loop.loopBegin();
+        ControlFlowGraph cfg = loop.loopsData().getCFG();
+
         pushWorkList(workList, start, loopNodes);
         while (!workList.isEmpty()) {
             WorkListEntry currentEntry = workList.peek();
@@ -352,13 +342,27 @@
                 workList.pop();
                 boolean isLoopNode = currentEntry.isLoopNode;
                 Node current = currentEntry.n;
-                if (!isLoopNode && current instanceof GuardNode) {
-                    /*
-                     * (gd) this is only OK if we are not going to make loop transforms based on
-                     * this
-                     */
-                    assert !((GuardNode) current).graph().hasValueProxies();
-                    isLoopNode = true;
+                if (!isLoopNode && current instanceof GuardNode && !current.hasUsages()) {
+                    GuardNode guard = (GuardNode) current;
+                    if (isLoopNode(guard.getCondition(), loopNodes, nonLoopNodes) != TriState.FALSE) {
+                        ValueNode anchor = guard.getAnchor().asNode();
+                        TriState isAnchorInLoop = isLoopNode(anchor, loopNodes, nonLoopNodes);
+                        if (isAnchorInLoop != TriState.FALSE) {
+                            if (!(anchor instanceof LoopExitNode && ((LoopExitNode) anchor).loopBegin() == loopBeginNode)) {
+                                /*
+                                 * (gd) this is wrong in general, it's completely avoidable while we
+                                 * are doing loop transforms using ValueProxies. If it happens after
+                                 * it could still cause problem.
+                                 */
+                                assert !((GuardNode) current).graph().hasValueProxies();
+                                isLoopNode = true;
+                            }
+                        } else if (AbstractControlFlowGraph.strictlyDominates(cfg.blockFor(anchor), cfg.blockFor(loopBeginNode))) {
+                            // The anchor is above the loop. The no-usage guard can potentially be
+                            // scheduled inside the loop.
+                            isLoopNode = true;
+                        }
+                    }
                 }
                 if (isLoopNode) {
                     loopNodes.mark(current);
@@ -467,14 +471,7 @@
                     final ValueNode replaceWith;
                     ValueNode newVpn = prim(newEarlyExitIsLoopExit ? vpn : vpn.value());
                     if (newVpn != null) {
-                        PhiNode phi;
-                        if (vpn instanceof ValueProxyNode) {
-                            phi = graph.addWithoutUnique(new ValuePhiNode(vpn.stamp(NodeView.DEFAULT), merge));
-                        } else if (vpn instanceof GuardProxyNode) {
-                            phi = graph.addWithoutUnique(new GuardPhiNode(merge));
-                        } else {
-                            throw GraalError.shouldNotReachHere();
-                        }
+                        PhiNode phi = vpn.createPhi(merge);
                         phi.addInput(vpn);
                         phi.addInput(newVpn);
                         replaceWith = phi;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Thu Jul 25 17:35:58 2019 -0400
@@ -169,12 +169,13 @@
         LoopBeginNode mainLoopBegin = loop.loopBegin();
         ArrayList<ValueNode> backedgeValues = new ArrayList<>();
         for (PhiNode mainPhiNode : mainLoopBegin.phis()) {
-            ValueNode duplicatedNode = getDuplicatedNode(mainPhiNode.valueAt(1));
+            ValueNode originalNode = mainPhiNode.valueAt(1);
+            ValueNode duplicatedNode = getDuplicatedNode(originalNode);
             if (duplicatedNode == null) {
-                if (mainLoopBegin.isPhiAtMerge(mainPhiNode.valueAt(1))) {
-                    duplicatedNode = ((PhiNode) (mainPhiNode.valueAt(1))).valueAt(1);
+                if (mainLoopBegin.isPhiAtMerge(originalNode)) {
+                    duplicatedNode = ((PhiNode) (originalNode)).valueAt(1);
                 } else {
-                    assert mainPhiNode.valueAt(1).isConstant() : mainPhiNode.valueAt(1);
+                    assert originalNode.isConstant() || loop.isOutsideLoop(originalNode) : "Not duplicated node " + originalNode;
                 }
             }
             backedgeValues.add(duplicatedNode);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java	Thu Jul 25 17:35:58 2019 -0400
@@ -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
@@ -64,7 +64,9 @@
     public NodeBitMap nodes() {
         if (nodes == null) {
             Loop<Block> loop = loop().loop();
-            nodes = LoopFragment.computeNodes(graph(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirBlocks(loop.getLoopExits()));
+            NodeBitMap loopNodes = graph().createNodeBitMap();
+            LoopFragment.computeNodes(loopNodes, graph(), loop(), LoopFragment.toHirBlocks(loop.getBlocks()), LoopFragment.toHirBlocks(loop.getLoopExits()));
+            nodes = loopNodes;
         }
         return nodes;
     }
@@ -110,7 +112,6 @@
 
     @Override
     public void insertBefore(LoopEx loop) {
-        // TODO Auto-generated method stub
-
+        // nothing to do
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/AbstractBeginNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -59,21 +59,20 @@
         Node next = from;
         while (next != null) {
             if (next instanceof AbstractBeginNode) {
-                AbstractBeginNode begin = (AbstractBeginNode) next;
-                return begin;
+                return (AbstractBeginNode) next;
             }
             next = next.predecessor();
         }
         return null;
     }
 
-    private void evacuateGuards(FixedNode evacuateFrom) {
+    private void evacuateAnchored(FixedNode evacuateFrom) {
         if (!hasNoUsages()) {
             AbstractBeginNode prevBegin = prevBegin(evacuateFrom);
             assert prevBegin != null;
-            for (Node anchored : anchored().snapshot()) {
-                anchored.replaceFirstInput(this, prevBegin);
-            }
+            replaceAtUsages(InputType.Anchor, prevBegin);
+            replaceAtUsages(InputType.Guard, prevBegin);
+            assert anchored().isEmpty() : anchored().snapshot();
         }
     }
 
@@ -82,7 +81,7 @@
     }
 
     public void prepareDelete(FixedNode evacuateFrom) {
-        evacuateGuards(evacuateFrom);
+        evacuateAnchored(evacuateFrom);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ConstantNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -38,11 +38,14 @@
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.NodeMap;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.lir.ConstantValue;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodeinfo.Verbosity;
 import org.graalvm.compiler.nodes.calc.FloatingNode;
+import org.graalvm.compiler.nodes.cfg.Block;
 import org.graalvm.compiler.nodes.spi.ArrayLengthProvider;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
@@ -143,14 +146,32 @@
 
     @Override
     public void generate(NodeLIRBuilderTool gen) {
-        LIRKind kind = gen.getLIRGeneratorTool().getLIRKind(stamp(NodeView.DEFAULT));
+        LIRGeneratorTool lirTool = gen.getLIRGeneratorTool();
+        LIRKind kind = lirTool.getLIRKind(stamp(NodeView.DEFAULT));
         if (onlyUsedInVirtualState()) {
             gen.setResult(this, new ConstantValue(kind, value));
+        } else if (lirTool.canInlineConstant(value) || (lirTool.mayEmbedConstantLoad(value) && hasExactlyOneUsage() && onlyUsedInCurrentBlock())) {
+            gen.setResult(this, new ConstantValue(lirTool.toRegisterKind(kind), value));
         } else {
             gen.setResult(this, gen.getLIRGeneratorTool().emitConstant(kind, value));
         }
     }
 
+    /**
+     * Expecting false for loop invariant.
+     */
+    private boolean onlyUsedInCurrentBlock() {
+        assert graph().getLastSchedule() != null;
+        NodeMap<Block> nodeBlockMap = graph().getLastSchedule().getNodeToBlockMap();
+        Block currentBlock = nodeBlockMap.get(this);
+        for (Node usage : usages()) {
+            if (currentBlock != nodeBlockMap.get(usage)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     private boolean onlyUsedInVirtualState() {
         for (Node n : this.usages()) {
             if (n instanceof VirtualState) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryMarkerNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EntryMarkerNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -30,7 +30,9 @@
 
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.IterableNodeType;
+import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
@@ -51,4 +53,24 @@
     public void generate(NodeLIRBuilderTool gen) {
         throw new GraalError("OnStackReplacementNode should not survive");
     }
+
+    @Override
+    public NodeIterable<Node> anchored() {
+        return super.anchored().filter(n -> {
+            if (n instanceof EntryProxyNode) {
+                EntryProxyNode proxyNode = (EntryProxyNode) n;
+                return proxyNode.proxyPoint != this;
+            }
+            return true;
+        });
+    }
+
+    @Override
+    public void prepareDelete(FixedNode evacuateFrom) {
+        for (Node usage : usages().filter(EntryProxyNode.class).snapshot()) {
+            EntryProxyNode proxy = (EntryProxyNode) usage;
+            proxy.replaceAndDelete(proxy.value());
+        }
+        super.prepareDelete(evacuateFrom);
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FixedGuardNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -30,19 +30,22 @@
 
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.graph.IterableNodeType;
+import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.nodes.spi.SwitchFoldable;
 
 import jdk.vm.ci.meta.DeoptimizationAction;
 import jdk.vm.ci.meta.DeoptimizationReason;
 import jdk.vm.ci.meta.SpeculationLog;
 
 @NodeInfo(nameTemplate = "FixedGuard(!={p#negated}) {p#reason/s}", allowedUsageTypes = Guard, size = SIZE_2, cycles = CYCLES_2)
-public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType {
+public final class FixedGuardNode extends AbstractFixedGuardNode implements Lowerable, IterableNodeType, SwitchFoldable {
     public static final NodeClass<FixedGuardNode> TYPE = NodeClass.create(FixedGuardNode.class);
 
     public FixedGuardNode(LogicNode condition, DeoptimizationReason deoptReason, DeoptimizationAction action) {
@@ -115,4 +118,92 @@
     public boolean canDeoptimize() {
         return true;
     }
+
+    @Override
+    public Node getNextSwitchFoldableBranch() {
+        return next();
+    }
+
+    @Override
+    public boolean isInSwitch(ValueNode switchValue) {
+        return hasNoUsages() && isNegated() && SwitchFoldable.maybeIsInSwitch(condition()) && SwitchFoldable.sameSwitchValue(condition(), switchValue);
+    }
+
+    @Override
+    public void cutOffCascadeNode() {
+        /* nop */
+    }
+
+    @Override
+    public void cutOffLowestCascadeNode() {
+        setNext(null);
+    }
+
+    @Override
+    public boolean isDefaultSuccessor(AbstractBeginNode beginNode) {
+        return beginNode.next() == next();
+    }
+
+    @Override
+    public AbstractBeginNode getDefault() {
+        FixedNode defaultNode = next();
+        setNext(null);
+        return BeginNode.begin(defaultNode);
+    }
+
+    @Override
+    public ValueNode switchValue() {
+        if (SwitchFoldable.maybeIsInSwitch(condition())) {
+            return ((IntegerEqualsNode) condition()).getX();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isNonInitializedProfile() {
+        // @formatter:off
+        // Checkstyle: stop
+        /*
+         * These nodes can appear in non initialized cascades. Though they are technically profiled
+         * nodes, their presence does not really prevent us from constructing a uniform distribution
+         * for the new switch, while keeping these to probability 0. Furthermore, these can be the
+         * result of the pattern:
+         * if (c) {
+         *     CompilerDirectives.transferToInterpreter();
+         * }
+         * Since we cannot differentiate this case from, say, a guard created because profiling
+         * determined that the branch was never taken, and given what we saw before, we will
+         * consider all fixedGuards as nodes with no profiles for switch folding purposes.
+         */
+        // Checkstyle: resume
+        // @formatter:on
+        return true;
+    }
+
+    @Override
+    public int intKeyAt(int i) {
+        assert i == 0;
+        return ((IntegerEqualsNode) condition()).getY().asJavaConstant().asInt();
+    }
+
+    @Override
+    public double keyProbability(int i) {
+        return 0;
+    }
+
+    @Override
+    public AbstractBeginNode keySuccessor(int i) {
+        DeoptimizeNode deopt = new DeoptimizeNode(getAction(), getReason(), getSpeculation());
+        deopt.setNodeSourcePosition(getNodeSourcePosition());
+        AbstractBeginNode begin = new BeginNode();
+        // Link the two nodes, but do not add them to the graph yet, so we do not need to remove
+        // them on an abort.
+        begin.next = deopt;
+        return begin;
+    }
+
+    @Override
+    public double defaultProbability() {
+        return 1.0d;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java	Thu Jul 25 17:35:58 2019 -0400
@@ -319,7 +319,7 @@
         public static final NodeClass<ProxyPlaceholder> TYPE = NodeClass.create(ProxyPlaceholder.class);
 
         @Input ValueNode value;
-        @Input(InputType.Unchecked) Node proxyPoint;
+        @Input(InputType.Association) Node proxyPoint;
 
         public ProxyPlaceholder(ValueNode value, MergeNode proxyPoint) {
             super(TYPE, value.stamp(NodeView.DEFAULT));
@@ -884,14 +884,7 @@
 
                 if (!merge.isPhiAtMerge(existing)) {
                     /* Now we have two different values, so we need to create a phi node. */
-                    PhiNode phi;
-                    if (proxy instanceof ValueProxyNode) {
-                        phi = graph.addWithoutUnique(new ValuePhiNode(proxy.stamp(NodeView.DEFAULT), merge));
-                    } else if (proxy instanceof GuardProxyNode) {
-                        phi = graph.addWithoutUnique(new GuardPhiNode(merge));
-                    } else {
-                        throw GraalError.shouldNotReachHere();
-                    }
+                    PhiNode phi = proxy.createPhi(merge);
                     /* Add the inputs from all previous exits. */
                     for (int j = 0; j < merge.phiPredecessorCount() - 1; j++) {
                         phi.addInput(existing);
@@ -1336,6 +1329,11 @@
      * @param methodScope The current method.
      */
     protected void cleanupGraph(MethodScope methodScope) {
+        for (MergeNode merge : graph.getNodes(MergeNode.TYPE)) {
+            for (ProxyPlaceholder placeholder : merge.usages().filter(ProxyPlaceholder.class).snapshot()) {
+                placeholder.replaceAndDelete(placeholder.value);
+            }
+        }
         assert verifyEdges();
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardProxyNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GuardProxyNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -62,6 +62,11 @@
     }
 
     @Override
+    public PhiNode createPhi(AbstractMergeNode merge) {
+        return graph().addWithoutUnique(new GuardPhiNode(merge));
+    }
+
+    @Override
     public Node getOriginalNode() {
         return (value == null ? null : value.asNode());
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -42,6 +42,7 @@
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.type.FloatStamp;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.PrimitiveStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.debug.CounterKey;
@@ -71,8 +72,10 @@
 import org.graalvm.compiler.nodes.java.LoadFieldNode;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.nodes.spi.SwitchFoldable;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 
+import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
@@ -87,7 +90,7 @@
  * of a comparison.
  */
 @NodeInfo(cycles = CYCLES_1, size = SIZE_2, sizeRationale = "2 jmps")
-public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable {
+public final class IfNode extends ControlSplitNode implements Simplifiable, LIRLowerable, SwitchFoldable {
     public static final NodeClass<IfNode> TYPE = NodeClass.create(IfNode.class);
 
     private static final CounterKey CORRECTED_PROBABILITIES = DebugContext.counter("CorrectedProbabilities");
@@ -297,6 +300,10 @@
             return;
         }
 
+        if (switchTransformationOptimization(tool)) {
+            return;
+        }
+
         if (falseSuccessor().hasNoUsages() && (!(falseSuccessor() instanceof LoopExitNode)) && falseSuccessor().next() instanceof IfNode &&
                         !(((IfNode) falseSuccessor().next()).falseSuccessor() instanceof LoopExitNode)) {
             AbstractBeginNode intermediateBegin = falseSuccessor();
@@ -454,6 +461,70 @@
         return true;
     }
 
+    // SwitchFoldable implementation.
+
+    @Override
+    public Node getNextSwitchFoldableBranch() {
+        return falseSuccessor();
+    }
+
+    @Override
+    public boolean isInSwitch(ValueNode switchValue) {
+        return SwitchFoldable.maybeIsInSwitch(condition()) && SwitchFoldable.sameSwitchValue(condition(), switchValue);
+    }
+
+    @Override
+    public void cutOffCascadeNode() {
+        setTrueSuccessor(null);
+    }
+
+    @Override
+    public void cutOffLowestCascadeNode() {
+        setFalseSuccessor(null);
+        setTrueSuccessor(null);
+    }
+
+    @Override
+    public AbstractBeginNode getDefault() {
+        return falseSuccessor();
+    }
+
+    @Override
+    public ValueNode switchValue() {
+        if (SwitchFoldable.maybeIsInSwitch(condition())) {
+            return ((IntegerEqualsNode) condition()).getX();
+        }
+        return null;
+    }
+
+    @Override
+    public boolean isNonInitializedProfile() {
+        return getTrueSuccessorProbability() == 0.5d;
+    }
+
+    @Override
+    public int intKeyAt(int i) {
+        assert i == 0;
+        return ((IntegerEqualsNode) condition()).getY().asJavaConstant().asInt();
+    }
+
+    @Override
+    public double keyProbability(int i) {
+        assert i == 0;
+        return getTrueSuccessorProbability();
+    }
+
+    @Override
+    public AbstractBeginNode keySuccessor(int i) {
+        assert i == 0;
+        return trueSuccessor();
+    }
+
+    @Override
+    public double defaultProbability() {
+        return 1.0d - getTrueSuccessorProbability();
+    }
+
     /**
      * Try to optimize this as if it were a {@link ConditionalNode}.
      */
@@ -606,6 +677,50 @@
                         }
                     }
                 }
+            } else if (y instanceof PrimitiveConstant && ((PrimitiveConstant) y).asLong() < 0 && falseSuccessor().next() instanceof IfNode) {
+                IfNode ifNode2 = (IfNode) falseSuccessor().next();
+                AbstractBeginNode falseSucc = ifNode2.falseSuccessor();
+                AbstractBeginNode trueSucc = ifNode2.trueSuccessor();
+                IntegerBelowNode below = null;
+                if (ifNode2.condition() instanceof IntegerLessThanNode) {
+                    ValueNode x = lessThan.getX();
+                    IntegerLessThanNode lessThan2 = (IntegerLessThanNode) ifNode2.condition();
+                    /*
+                     * Convert x >= -C1 && x < C2, represented as !(x < -C1) && x < C2, into an
+                     * unsigned compare. This condition is equivalent to x + C1 |<| C1 + C2 if C1 +
+                     * C2 does not overflow.
+                     */
+                    Constant c2 = lessThan2.getY().stamp(view).asConstant();
+                    if (lessThan2.getX() == x && c2 instanceof PrimitiveConstant && ((PrimitiveConstant) c2).asLong() > 0 &&
+                                    x.stamp(view).isCompatible(lessThan.getY().stamp(view)) &&
+                                    x.stamp(view).isCompatible(lessThan2.getY().stamp(view)) &&
+                                    sameDestination(trueSuccessor(), ifNode2.falseSuccessor)) {
+                        long newLimitValue = -((PrimitiveConstant) y).asLong() + ((PrimitiveConstant) c2).asLong();
+                        // Make sure the limit fits into the target type without overflow.
+                        if (newLimitValue > 0 && newLimitValue <= CodeUtil.maxValue(PrimitiveStamp.getBits(x.stamp(view)))) {
+                            ConstantNode newLimit = ConstantNode.forIntegerStamp(x.stamp(view), newLimitValue, graph());
+                            ConstantNode c1 = ConstantNode.forIntegerStamp(x.stamp(view), -((PrimitiveConstant) y).asLong(), graph());
+                            ValueNode addNode = graph().addOrUniqueWithInputs(AddNode.create(x, c1, view));
+                            below = graph().unique(new IntegerBelowNode(addNode, newLimit));
+                        }
+                    }
+                }
+                if (below != null) {
+                    try (DebugCloseable position = ifNode2.withNodeSourcePosition()) {
+                        ifNode2.setTrueSuccessor(null);
+                        ifNode2.setFalseSuccessor(null);
+
+                        IfNode newIfNode = graph().add(new IfNode(below, trueSucc, falseSucc, trueSuccessorProbability));
+                        // Remove the < -C1 test.
+                        tool.deleteBranch(trueSuccessor);
+                        graph().removeSplit(this, falseSuccessor);
+
+                        // Replace the second test with the new one.
+                        ifNode2.predecessor().replaceFirstSuccessor(ifNode2, newIfNode);
+                        ifNode2.safeDelete();
+                        return true;
+                    }
+                }
             }
         }
         return false;
@@ -1268,8 +1383,7 @@
     private MergeNode insertMerge(AbstractBeginNode begin, FrameState stateAfter) {
         MergeNode merge = graph().add(new MergeNode());
         if (!begin.anchored().isEmpty()) {
-            Object before = null;
-            before = begin.anchored().snapshot();
+            Object before = begin.anchored().snapshot();
             begin.replaceAtUsages(InputType.Guard, merge);
             begin.replaceAtUsages(InputType.Anchor, merge);
             assert begin.anchored().isEmpty() : before + " " + begin.anchored().snapshot();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ProxyNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -75,4 +75,6 @@
     public static GuardProxyNode forGuard(GuardingNode value, LoopExitNode exit, StructuredGraph graph) {
         return graph.unique(new GuardProxyNode(value, exit));
     }
+
+    public abstract PhiNode createPhi(AbstractMergeNode merge);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/ValueProxyNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -54,6 +54,11 @@
     }
 
     @Override
+    public PhiNode createPhi(AbstractMergeNode merge) {
+        return graph().addWithoutUnique(new ValuePhiNode(stamp(NodeView.DEFAULT), merge));
+    }
+
+    @Override
     public boolean inferStamp() {
         return updateStamp(value.stamp(NodeView.DEFAULT));
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/SignedRemNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -117,10 +117,7 @@
             return false;
         }
 
-        int compareAgainstZero = 0;
-        int usageCount = self.getUsageCount();
-        for (int i = 0; i < usageCount; i++) {
-            Node usage = self.getUsageAt(i);
+        for (Node usage : self.usages()) {
             if (usage instanceof IntegerEqualsNode) {
                 IntegerEqualsNode equalsNode = (IntegerEqualsNode) usage;
                 ValueNode node = equalsNode.getY();
@@ -131,12 +128,13 @@
                     ConstantNode constantNode = (ConstantNode) node;
                     Constant constant = constantNode.asConstant();
                     if (constant instanceof PrimitiveConstant && ((PrimitiveConstant) constant).asLong() == 0) {
-                        compareAgainstZero++;
+                        continue;
                     }
                 }
             }
+            return false;
         }
-        return compareAgainstZero == usageCount;
+        return true;
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BranchProbabilityNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -32,8 +32,11 @@
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.iterators.NodePredicates;
+import org.graalvm.compiler.graph.spi.Canonicalizable;
+import org.graalvm.compiler.graph.spi.CanonicalizerTool;
 import org.graalvm.compiler.graph.spi.Simplifiable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -56,7 +59,7 @@
  * intended primarily for snippets, so that they can define their fast and slow paths.
  */
 @NodeInfo(cycles = CYCLES_0, cyclesRationale = "Artificial Node", size = SIZE_0)
-public final class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable {
+public final class BranchProbabilityNode extends FloatingNode implements Simplifiable, Lowerable, Canonicalizable {
 
     public static final NodeClass<BranchProbabilityNode> TYPE = NodeClass.create(BranchProbabilityNode.class);
     public static final double LIKELY_PROBABILITY = 0.6;
@@ -98,6 +101,15 @@
     }
 
     @Override
+    public Node canonical(CanonicalizerTool tool) {
+        if (condition.isConstant()) {
+            // fold constant conditions early during PE
+            return condition;
+        }
+        return this;
+    }
+
+    @Override
     public void simplify(SimplifierTool tool) {
         if (!hasUsages()) {
             return;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/IntegerSwitchNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -36,6 +36,7 @@
 import org.graalvm.compiler.core.common.type.PrimitiveStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 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.Simplifiable;
 import org.graalvm.compiler.graph.spi.SimplifierTool;
@@ -51,6 +52,7 @@
 import org.graalvm.compiler.nodes.java.LoadIndexedNode;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import org.graalvm.compiler.nodes.spi.SwitchFoldable;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 
 import jdk.vm.ci.meta.DeoptimizationAction;
@@ -63,7 +65,7 @@
  * values. The actual implementation of the switch will be decided by the backend.
  */
 @NodeInfo
-public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable {
+public final class IntegerSwitchNode extends SwitchNode implements LIRLowerable, Simplifiable, SwitchFoldable {
     public static final NodeClass<IntegerSwitchNode> TYPE = NodeClass.create(IntegerSwitchNode.class);
 
     protected final int[] keys;
@@ -75,6 +77,7 @@
         this.keys = keys;
         assert value.stamp(NodeView.DEFAULT) instanceof PrimitiveStamp && value.stamp(NodeView.DEFAULT).getStackKind().isNumericInteger();
         assert assertSorted();
+        assert assertNoUntargettedSuccessor();
     }
 
     private boolean assertSorted() {
@@ -84,6 +87,18 @@
         return true;
     }
 
+    private boolean assertNoUntargettedSuccessor() {
+        boolean[] checker = new boolean[successors.size()];
+        for (int successorIndex : keySuccessors) {
+            checker[successorIndex] = true;
+        }
+        checker[defaultSuccessorIndex()] = true;
+        for (boolean b : checker) {
+            assert b;
+        }
+        return true;
+    }
+
     public IntegerSwitchNode(ValueNode value, int successorCount, int[] keys, double[] keyProbabilities, int[] keySuccessors) {
         this(value, new AbstractBeginNode[successorCount], keys, keyProbabilities, keySuccessors);
     }
@@ -104,6 +119,14 @@
         return JavaConstant.forInt(keys[i]);
     }
 
+    /**
+     * Gets the key at the specified index, as a java int.
+     */
+    @Override
+    public int intKeyAt(int i) {
+        return keys[i];
+    }
+
     @Override
     public int keyCount() {
         return keys.length;
@@ -148,9 +171,63 @@
             return;
         } else if (tryRemoveUnreachableKeys(tool, value().stamp(view))) {
             return;
+        } else if (switchTransformationOptimization(tool)) {
+            return;
         }
     }
 
+    private void addSuccessorForDeletion(AbstractBeginNode defaultNode) {
+        successors.add(defaultNode);
+    }
+
+    @Override
+    public Node getNextSwitchFoldableBranch() {
+        return defaultSuccessor();
+    }
+
+    @Override
+    public boolean isInSwitch(ValueNode switchValue) {
+        return value == switchValue;
+    }
+
+    @Override
+    public void cutOffCascadeNode() {
+        AbstractBeginNode toKill = defaultSuccessor();
+        clearSuccessors();
+        addSuccessorForDeletion(toKill);
+    }
+
+    @Override
+    public void cutOffLowestCascadeNode() {
+        clearSuccessors();
+    }
+
+    @Override
+    public AbstractBeginNode getDefault() {
+        return defaultSuccessor();
+    }
+
+    @Override
+    public ValueNode switchValue() {
+        return value();
+    }
+
+    @Override
+    public boolean isNonInitializedProfile() {
+        int nbSuccessors = getSuccessorCount();
+        double prob = 0.0d;
+        for (int i = 0; i < nbSuccessors; i++) {
+            if (keyProbabilities[i] > 0.0d) {
+                if (prob == 0.0d) {
+                    prob = keyProbabilities[i];
+                } else if (keyProbabilities[i] != prob) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
     static final class KeyData {
         final int key;
         final double keyProbability;
@@ -208,7 +285,7 @@
      * because {@link Enum#ordinal()} can change when recompiling an enum, it cannot be used
      * directly as the value that is switched on. An intermediate int[] array, which is initialized
      * once at run time based on the actual {@link Enum#ordinal()} values, is used.
-     *
+     * <p>
      * The {@link ConstantFieldProvider} of Graal already detects the int[] arrays and marks them as
      * {@link ConstantNode#isDefaultStable() stable}, i.e., the array elements are constant. The
      * code in this method detects array loads from such a stable array and re-wires the switch to
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/SwitchNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -198,6 +198,13 @@
     }
 
     /**
+     * Returns the probability of taking the default branch.
+     */
+    public double defaultProbability() {
+        return keyProbabilities[keyProbabilities.length - 1];
+    }
+
+    /**
      * Returns the index of the default (fall through) successor of this switch.
      */
     public int defaultSuccessorIndex() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ObjectWriteBarrier.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/ObjectWriteBarrier.java	Thu Jul 25 17:35:58 2019 -0400
@@ -50,4 +50,3 @@
         return precise;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialArrayRangeWriteBarrier.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialArrayRangeWriteBarrier.java	Thu Jul 25 17:35:58 2019 -0400
@@ -41,4 +41,3 @@
     }
 
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialWriteBarrier.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/SerialWriteBarrier.java	Thu Jul 25 17:35:58 2019 -0400
@@ -53,4 +53,3 @@
         return verifyOnly;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/WriteBarrier.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/gc/WriteBarrier.java	Thu Jul 25 17:35:58 2019 -0400
@@ -54,4 +54,3 @@
         return address;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/NodePlugin.java	Thu Jul 25 17:35:58 2019 -0400
@@ -243,4 +243,3 @@
         return false;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewObjectNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractNewObjectNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -32,9 +32,12 @@
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
 import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.extended.MembarNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 
+import jdk.vm.ci.code.MemoryBarriers;
+
 /**
  * The {@code AbstractNewObjectNode} is the base class for the new instance and new array nodes.
  */
@@ -44,6 +47,12 @@
     public static final NodeClass<AbstractNewObjectNode> TYPE = NodeClass.create(AbstractNewObjectNode.class);
     protected final boolean fillContents;
 
+    /**
+     * Controls whether this allocation emits a {@link MembarNode} with
+     * {@link MemoryBarriers#STORE_STORE} as part of the object initialization.
+     */
+    protected boolean emitMemoryBarrier = true;
+
     protected AbstractNewObjectNode(NodeClass<? extends AbstractNewObjectNode> c, Stamp stamp, boolean fillContents, FrameState stateBefore) {
         super(c, stamp, stateBefore);
         this.fillContents = fillContents;
@@ -65,4 +74,12 @@
     public boolean canDeoptimize() {
         return true;
     }
+
+    public boolean emitMemoryBarrier() {
+        return emitMemoryBarrier;
+    }
+
+    public void clearEmitMemoryBarrier() {
+        this.emitMemoryBarrier = false;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -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
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MethodCallTargetNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.graph.spi.SimplifierTool;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodeinfo.Verbosity;
+import org.graalvm.compiler.nodes.BeginNode;
 import org.graalvm.compiler.nodes.CallTargetNode;
 import org.graalvm.compiler.nodes.FixedGuardNode;
 import org.graalvm.compiler.nodes.Invoke;
@@ -43,7 +44,7 @@
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.extended.ValueAnchorNode;
+import org.graalvm.compiler.nodes.extended.AnchoringNode;
 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
 import org.graalvm.compiler.nodes.type.StampTool;
 
@@ -232,11 +233,7 @@
                  * an assumption but as we need an instanceof check anyway we can verify both
                  * properties by checking of the receiver is an instance of the single implementor.
                  */
-                ValueAnchorNode anchor = new ValueAnchorNode(null);
-                if (anchor != null) {
-                    graph().add(anchor);
-                    graph().addBeforeFixed(invoke().asNode(), anchor);
-                }
+                AnchoringNode anchor = BeginNode.prevBegin(invoke().asNode());
                 LogicNode condition = graph().addOrUniqueWithInputs(InstanceOfNode.create(speculatedType, receiver, getProfile(), anchor));
                 FixedGuardNode guard = graph().add(new FixedGuardNode(condition, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, false));
                 graph().addBeforeFixed(invoke().asNode(), guard);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/LoweringProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -50,15 +50,10 @@
     /**
      * Indicates the smallest width for comparing an integer value on the target platform.
      */
-    default Integer smallestCompareWidth() {
-        // most platforms only support 32 and 64 bit compares
-        return 32;
-    }
+    Integer smallestCompareWidth();
 
     /**
      * Indicates whether the target platform supports bulk zeroing instruction.
      */
-    default boolean supportBulkZeroing() {
-        return false;
-    }
+    boolean supportBulkZeroing();
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/SwitchFoldable.java	Thu Jul 25 17:35:58 2019 -0400
@@ -0,0 +1,507 @@
+/*
+ * 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.nodes.spi;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
+import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.PrimitiveStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.spi.SimplifierTool;
+import org.graalvm.compiler.nodes.AbstractBeginNode;
+import org.graalvm.compiler.nodes.BeginNode;
+import org.graalvm.compiler.nodes.FixedNode;
+import org.graalvm.compiler.nodes.LogicNode;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.ValueNodeInterface;
+import org.graalvm.compiler.nodes.calc.IntegerEqualsNode;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
+import org.graalvm.compiler.nodes.util.GraphUtil;
+
+/**
+ * Nodes that implement this interface can be collapsed to a single IntegerSwitch when they are seen
+ * in a cascade.
+ */
+@SuppressFBWarnings(value = {"UCF"}, justification = "javac spawns useless control flow in static initializer when using assert(asNode().isAlive())")
+public interface SwitchFoldable extends ValueNodeInterface {
+    Comparator<KeyData> SORTER = Comparator.comparingInt((KeyData k) -> k.key);
+
+    /**
+     * Returns the direct successor in the branch to check for SwitchFoldability.
+     */
+    Node getNextSwitchFoldableBranch();
+
+    /**
+     * Returns the value that will be used as the switch input. This value should be an int.
+     */
+    ValueNode switchValue();
+
+    /**
+     * Returns the branch that will close this switch folding, assuming this is called on the lowest
+     * node of the cascade.
+     */
+    AbstractBeginNode getDefault();
+
+    /**
+     * Determines whether the node should be folded in the current folding attempt.
+     *
+     * @param switchValue the value of the switch that will spawn through this folding attempt.
+     * @return true if this node should be folded in the current folding attempt, false otherwise.
+     * @see SwitchFoldable#maybeIsInSwitch(LogicNode)
+     * @see SwitchFoldable#sameSwitchValue(LogicNode, ValueNode)
+     */
+    boolean isInSwitch(ValueNode switchValue);
+
+    /**
+     * Removes the successors of this node, while keeping it linked to the rest of the cascade.
+     */
+    void cutOffCascadeNode();
+
+    /**
+     * Completely removes all successors from this node.
+     */
+    void cutOffLowestCascadeNode();
+
+    /**
+     * Returns the value of the i-th key of this node.
+     */
+    int intKeyAt(int i);
+
+    /**
+     * Returns the probability of seeing the i-th key of this node.
+     */
+    double keyProbability(int i);
+
+    /**
+     * Returns the branch to follow when seeing the i-th key of this node.
+     */
+    AbstractBeginNode keySuccessor(int i);
+
+    /**
+     * Returns the probability of going to the default branch.
+     */
+    double defaultProbability();
+
+    /**
+     * @return The number of keys the SwitchFoldable node will try to add.
+     */
+    default int keyCount() {
+        return 1;
+    }
+
+    /**
+     * Should be overridden if getDefault() has side effects.
+     */
+    default boolean isDefaultSuccessor(AbstractBeginNode successor) {
+        return successor == getDefault();
+    }
+
+    /**
+     * Heuristics that tries to determine whether or not a foldable node was profiled.
+     */
+    default boolean isNonInitializedProfile() {
+        return false;
+    }
+
+    static boolean maybeIsInSwitch(LogicNode condition) {
+        return condition instanceof IntegerEqualsNode && ((IntegerEqualsNode) condition).getY().isJavaConstant();
+    }
+
+    static boolean sameSwitchValue(LogicNode condition, ValueNode switchValue) {
+        return ((IntegerEqualsNode) condition).getX() == switchValue;
+    }
+
+    // Helper data structures
+
+    class Helper {
+        private Helper() {
+        }
+
+        private static boolean isDuplicateKey(int key, QuickQueryKeyData keyData) {
+            return keyData.contains(key);
+        }
+
+        private static int duplicateIndex(AbstractBeginNode begin, QuickQueryList<AbstractBeginNode> successors) {
+            return successors.indexOf(begin);
+        }
+
+        private static Node skipUpBegins(Node node) {
+            Node result = node;
+            while (result instanceof BeginNode && result.hasNoUsages()) {
+                result = result.predecessor();
+            }
+            return result;
+        }
+
+        private static Node skipDownBegins(Node node) {
+            Node result = node;
+            while (result instanceof BeginNode && result.hasNoUsages()) {
+                result = ((BeginNode) result).next();
+            }
+            return result;
+        }
+
+        private static SwitchFoldable getParentSwitchNode(SwitchFoldable node, ValueNode switchValue) {
+            Node result = skipUpBegins(node.asNode().predecessor());
+            if (result instanceof SwitchFoldable && ((SwitchFoldable) result).isInSwitch(switchValue)) {
+                return (SwitchFoldable) result;
+            }
+            return null;
+        }
+
+        private static SwitchFoldable getChildSwitchNode(SwitchFoldable node, ValueNode switchValue) {
+            Node result = skipDownBegins(node.getNextSwitchFoldableBranch());
+            if (result instanceof SwitchFoldable && ((SwitchFoldable) result).isInSwitch(switchValue)) {
+                return (SwitchFoldable) result;
+            }
+            return null;
+        }
+
+        private static int addDefault(SwitchFoldable node, QuickQueryList<AbstractBeginNode> successors) {
+            AbstractBeginNode defaultBranch = node.getDefault();
+            int index = successors.indexOf(defaultBranch);
+            if (index == -1) {
+                index = successors.size();
+                successors.add(defaultBranch);
+            }
+            return index;
+        }
+
+        private static int countNonDeoptSuccessors(QuickQueryKeyData keyData) {
+            int result = 0;
+            for (KeyData key : keyData.list) {
+                if (key.keyProbability > 0.0d) {
+                    result++;
+                }
+            }
+            return result;
+        }
+
+        /**
+         * Updates the current state of the IntegerSwitch that will be spawned. That means:
+         * <p>
+         * - Checking for duplicate keys: add the duplicate key's branch to duplicates
+         * <p>
+         * - For branches of non-duplicate keys: add them to successors and update the keyData
+         * accordingly
+         * <p>
+         * - Update the value of the cumulative probability, ie, multiply it by the probability of
+         * taking the next branch (according to {@link SwitchFoldable#getNextSwitchFoldableBranch})
+         * <p>
+         * </p>
+         *
+         * @see QuickQueryList
+         * @see QuickQueryKeyData
+         */
+        private static void updateSwitchData(SwitchFoldable node, QuickQueryKeyData keyData, QuickQueryList<AbstractBeginNode> newSuccessors, double[] cumulative, double[] totalProbabilities,
+                        QuickQueryList<AbstractBeginNode> duplicates) {
+            for (int i = 0; i < node.keyCount(); i++) {
+                int key = node.intKeyAt(i);
+                double keyProbability = cumulative[0] * node.keyProbability(i);
+                KeyData data;
+                AbstractBeginNode keySuccessor = node.keySuccessor(i);
+                if (isDuplicateKey(key, keyData)) {
+                    // Key was already seen
+                    data = keyData.fromKey(key);
+                    if (data.keySuccessor != KeyData.KEY_UNKNOWN) {
+                        // Unreachable key: kill it manually at the end
+                        if (!newSuccessors.contains(keySuccessor) && !duplicates.contains(keySuccessor) && keySuccessor.isAlive()) {
+                            // This might be a false alert, if one of the next keys points to it.
+                            duplicates.add(keySuccessor);
+                        }
+                        continue;
+                    }
+                    /*
+                     * A key might not be able to immediately link to its target, if it is shared
+                     * with the default target. In that case, we will need to resolve the target at
+                     * a later time, either by seeing this key going to a known target in later
+                     * cascade nodes, or by linking it to the overall default target at the very end
+                     * of the folding.
+                     */
+                } else {
+                    data = new KeyData(key, keyProbability, KeyData.KEY_UNKNOWN);
+                    totalProbabilities[0] += keyProbability;
+                    keyData.add(data);
+                }
+                if (keySuccessor.isUnregistered()) {
+                    // Shortcut map check if uninitialized node.
+                    data.keySuccessor = newSuccessors.size();
+                    newSuccessors.addUnique(keySuccessor);
+                } else {
+                    int pos = duplicateIndex(keySuccessor, newSuccessors);
+                    if (pos != -1) {
+                        // Target is already known
+                        data.keySuccessor = pos;
+                    } else if (!node.isDefaultSuccessor(keySuccessor)) {
+                        data.keySuccessor = newSuccessors.size();
+                        newSuccessors.add(keySuccessor);
+                    }
+                }
+            }
+            cumulative[0] *= node.defaultProbability();
+        }
+    }
+
+    final class KeyData {
+        private static final int KEY_UNKNOWN = -2;
+
+        private final int key;
+        private final double keyProbability;
+        private int keySuccessor;
+
+        KeyData(int key, double keyProbability, int keySuccessor) {
+            this.key = key;
+            this.keyProbability = keyProbability;
+            this.keySuccessor = keySuccessor;
+        }
+    }
+
+    /**
+     * Supports O(1) addition to the list, fast {@code contains} and {@code indexOf} queries
+     * (usually O(1), worst case O(n)), and O(1) random access.
+     */
+    final class QuickQueryList<T> {
+        private final List<T> list = new ArrayList<>();
+        private final EconomicMap<T, Integer> map = EconomicMap.create(Equivalence.IDENTITY);
+
+        private int indexOf(T begin) {
+            return map.get(begin, -1);
+        }
+
+        private boolean contains(T o) {
+            return map.containsKey(o);
+        }
+
+        @SuppressWarnings("unused")
+        private T get(int index) {
+            return list.get(index);
+        }
+
+        private boolean add(T item) {
+            map.put(item, list.size());
+            return list.add(item);
+        }
+
+        /**
+         * Adds an object, known to be unique beforehand.
+         */
+        private void addUnique(T item) {
+            list.add(item);
+        }
+
+        private int size() {
+            return list.size();
+        }
+    }
+
+    final class QuickQueryKeyData {
+        private final List<KeyData> list = new ArrayList<>();
+        private final EconomicMap<Integer, KeyData> map = EconomicMap.create();
+
+        private void add(KeyData key) {
+            assert !map.containsKey(key.key);
+            list.add(key);
+            map.put(key.key, key);
+        }
+
+        private boolean contains(int key) {
+            return map.containsKey(key);
+        }
+
+        private KeyData get(int index) {
+            return list.get(index);
+        }
+
+        private int size() {
+            return list.size();
+        }
+
+        private KeyData fromKey(int key) {
+            assert contains(key);
+            return map.get(key);
+        }
+
+        private void sort() {
+            list.sort(SORTER);
+        }
+
+    }
+
+    /**
+     * Collapses a cascade of foldables (IfNode, FixedGuard and IntegerSwitch) into a single switch.
+     */
+    default boolean switchTransformationOptimization(SimplifierTool tool) {
+        ValueNode switchValue = switchValue();
+        assert asNode().isAlive();
+        if (switchValue == null || !isInSwitch(switchValue) || (Helper.getParentSwitchNode(this, switchValue) == null && Helper.getChildSwitchNode(this, switchValue) == null)) {
+            // Don't bother trying if there is nothing to do.
+            return false;
+        }
+        Stamp switchStamp = switchValue.stamp(NodeView.DEFAULT);
+
+        // Abort if we do not have an int
+        if (!(switchStamp instanceof IntegerStamp)) {
+            return false;
+        }
+        if (PrimitiveStamp.getBits(switchStamp) > 32) {
+            return false;
+        }
+
+        // PlaceHolder for cascade traversal.
+        SwitchFoldable iteratingNode = this;
+        SwitchFoldable topMostSwitchNode = this;
+
+        // Find top-most foldable.
+        while (iteratingNode != null) {
+            topMostSwitchNode = iteratingNode;
+            iteratingNode = Helper.getParentSwitchNode(iteratingNode, switchValue);
+        }
+        QuickQueryKeyData keyData = new QuickQueryKeyData();
+        QuickQueryList<AbstractBeginNode> successors = new QuickQueryList<>();
+        QuickQueryList<AbstractBeginNode> potentiallyUnreachable = new QuickQueryList<>();
+        double[] cumulative = {1.0d};
+        double[] totalProbability = {0.0d};
+
+        iteratingNode = topMostSwitchNode;
+        SwitchFoldable lowestSwitchNode = topMostSwitchNode;
+
+        // If this stays true, we will need to spawn an uniform distribution.
+        boolean uninitializedProfiles = true;
+
+        // Go down the if cascade, collecting necessary data
+        while (iteratingNode != null) {
+            lowestSwitchNode = iteratingNode;
+            Helper.updateSwitchData(iteratingNode, keyData, successors, cumulative, totalProbability, potentiallyUnreachable);
+            if (!iteratingNode.isNonInitializedProfile()) {
+                uninitializedProfiles = false;
+            }
+            iteratingNode = Helper.getChildSwitchNode(iteratingNode, switchValue);
+        }
+
+        if (keyData.size() < 4 || lowestSwitchNode == topMostSwitchNode) {
+            // Abort if it's not worth the hassle
+            return false;
+        }
+
+        // At that point, we will commit the optimization.
+        StructuredGraph graph = asNode().graph();
+
+        // Sort the keys
+        keyData.sort();
+
+        /*
+         * The total probability might be different than 1 if there was a duplicate key which was
+         * erased by another branch whose probability was different (/ex: in the case where a method
+         * constituted of only a switch is inlined after a guard for a particular value of that
+         * switch). In that case, we need to re-normalize the probabilities. A more "correct" way
+         * would be to only re-normalize the probabilities of the switch after the guard, but this
+         * cannot be done without an additional overhead.
+         */
+        totalProbability[0] += cumulative[0];
+        assert totalProbability[0] > 0.0d;
+        double normalizationFactor = 1 / totalProbability[0];
+
+        // Spawn the required data structures
+        int newKeyCount = keyData.list.size();
+        int[] keys = new int[newKeyCount];
+        double[] keyProbabilities = new double[newKeyCount + 1];
+        int[] keySuccessors = new int[newKeyCount + 1];
+        int nonDeoptSuccessorCount = Helper.countNonDeoptSuccessors(keyData) + (cumulative[0] > 0.0d ? 1 : 0);
+        double uniform = (uninitializedProfiles && nonDeoptSuccessorCount > 0 ? 1 / (double) nonDeoptSuccessorCount : 1.0d);
+
+        // Add default
+        keyProbabilities[newKeyCount] = uninitializedProfiles && cumulative[0] > 0.0d ? uniform : normalizationFactor * cumulative[0];
+        keySuccessors[newKeyCount] = Helper.addDefault(lowestSwitchNode, successors);
+
+        // Add branches.
+        for (int i = 0; i < newKeyCount; i++) {
+            SwitchFoldable.KeyData data = keyData.get(i);
+            keys[i] = data.key;
+            keyProbabilities[i] = uninitializedProfiles && data.keyProbability > 0.0d ? uniform : normalizationFactor * data.keyProbability;
+            keySuccessors[i] = data.keySuccessor != KeyData.KEY_UNKNOWN ? data.keySuccessor : keySuccessors[newKeyCount];
+        }
+
+        // Spin an adapter if the value is narrower than an int
+        ValueNode adapter = null;
+        if (((IntegerStamp) switchStamp).getBits() < 32) {
+            adapter = graph.addOrUnique(new SignExtendNode(switchValue, 32));
+        } else {
+            adapter = switchValue;
+        }
+
+        // Spawn the switch node
+        IntegerSwitchNode toInsert = new IntegerSwitchNode(adapter, successors.size(), keys, keyProbabilities, keySuccessors);
+        graph.add(toInsert);
+
+        // Detach the cascade from the graph
+        lowestSwitchNode.cutOffLowestCascadeNode();
+        iteratingNode = lowestSwitchNode;
+        while (iteratingNode != null) {
+            if (iteratingNode != lowestSwitchNode) {
+                iteratingNode.cutOffCascadeNode();
+            }
+            iteratingNode = Helper.getParentSwitchNode(iteratingNode, switchValue);
+        }
+
+        // Place the new Switch node
+        topMostSwitchNode.asNode().replaceAtPredecessor(toInsert);
+        topMostSwitchNode.asNode().replaceAtUsages(toInsert);
+
+        // Attach the branches to the switch.
+        int pos = 0;
+        for (AbstractBeginNode begin : successors.list) {
+            if (begin.isUnregistered()) {
+                graph.add(begin.next());
+                graph.add(begin);
+                begin.setNext(begin.next());
+            }
+            toInsert.setBlockSuccessor(pos++, begin);
+        }
+
+        // Remove the cascade and unreachable code
+        GraphUtil.killCFG((FixedNode) topMostSwitchNode);
+        for (AbstractBeginNode duplicate : potentiallyUnreachable.list) {
+            if (duplicate.predecessor() == null) {
+                // Make sure the duplicate is not reachable.
+                assert duplicate.isAlive();
+                GraphUtil.killCFG(duplicate);
+            }
+        }
+
+        tool.addToWorkList(toInsert);
+
+        return true;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java	Thu Jul 25 17:35:58 2019 -0400
@@ -224,6 +224,14 @@
             }
         }
 
+        String optionStabilityName = getAnnotationValue(annotation, "stability", VariableElement.class).getSimpleName().toString();
+        if (optionStabilityName.equals("STABLE")) {
+            if (help.length() == 0) {
+                processingEnv.getMessager().printMessage(Kind.ERROR, "A stable option must have non-empty help text", element);
+                return;
+            }
+        }
+
         String optionTypeName = getAnnotationValue(annotation, "type", VariableElement.class).getSimpleName().toString();
         info.options.add(new OptionInfo(optionName, optionTypeName, help, extraHelp, optionType, declaringClass, field.getSimpleName().toString()));
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java	Thu Jul 25 17:35:58 2019 -0400
@@ -175,14 +175,9 @@
             AbstractBeginNode beginNode = b.getBeginNode();
             if (beginNode instanceof AbstractMergeNode && anchorBlock != b) {
                 AbstractMergeNode mergeNode = (AbstractMergeNode) beginNode;
-                for (GuardNode guard : mergeNode.guards().snapshot()) {
-                    try (DebugCloseable closeable = guard.withNodeSourcePosition()) {
-                        GuardNode newlyCreatedGuard = new GuardNode(guard.getCondition(), anchorBlock.getBeginNode(), guard.getReason(), guard.getAction(), guard.isNegated(), guard.getSpeculation(),
-                                        guard.getNoDeoptSuccessorPosition());
-                        GuardNode newGuard = mergeNode.graph().unique(newlyCreatedGuard);
-                        guard.replaceAndDelete(newGuard);
-                    }
-                }
+                mergeNode.replaceAtUsages(InputType.Anchor, anchorBlock.getBeginNode());
+                mergeNode.replaceAtUsages(InputType.Guard, anchorBlock.getBeginNode());
+                assert mergeNode.anchored().isEmpty();
             }
 
             FixedNode endNode = b.getEndNode();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/WriteBarrierAdditionPhase.java	Thu Jul 25 17:35:58 2019 -0400
@@ -48,4 +48,3 @@
         return false;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Thu Jul 25 17:35:58 2019 -0400
@@ -42,7 +42,6 @@
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.graph.CachedGraph;
 import org.graalvm.compiler.graph.Edges;
 import org.graalvm.compiler.graph.Graph;
@@ -66,7 +65,6 @@
 import org.graalvm.compiler.nodes.cfg.Block;
 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
 import org.graalvm.compiler.nodes.util.JavaConstantFormattable;
-import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.graphio.GraphBlocks;
 import org.graalvm.graphio.GraphElements;
 import org.graalvm.graphio.GraphLocations;
@@ -591,22 +589,8 @@
             this.graph = graph;
             StructuredGraph.ScheduleResult scheduleResult = null;
             if (graph instanceof StructuredGraph) {
-
                 StructuredGraph structuredGraph = (StructuredGraph) graph;
-                scheduleResult = structuredGraph.getLastSchedule();
-                if (scheduleResult == null) {
-
-                    // Also provide a schedule when an error occurs
-                    if (DebugOptions.PrintGraphWithSchedule.getValue(graph.getOptions()) || debug.contextLookup(Throwable.class) != null) {
-                        try {
-                            SchedulePhase schedule = new SchedulePhase(graph.getOptions());
-                            schedule.apply(structuredGraph);
-                            scheduleResult = structuredGraph.getLastSchedule();
-                        } catch (Throwable t) {
-                        }
-                    }
-
-                }
+                scheduleResult = GraalDebugHandlersFactory.tryGetSchedule(debug, structuredGraph);
             }
             cfg = scheduleResult == null ? debug.contextLookup(ControlFlowGraph.class) : scheduleResult.getCFG();
             blockToNodes = scheduleResult == null ? null : scheduleResult.getBlockToNodesMap();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java	Thu Jul 25 17:35:58 2019 -0400
@@ -211,12 +211,14 @@
             } else if (object instanceof StructuredGraph) {
                 if (cfgPrinter.cfg == null) {
                     StructuredGraph graph = (StructuredGraph) object;
-                    cfgPrinter.cfg = ControlFlowGraph.compute(graph, true, true, true, false);
-                    cfgPrinter.printCFG(message, cfgPrinter.cfg.getBlocks(), true);
-                } else {
+                    ScheduleResult scheduleResult = GraalDebugHandlersFactory.tryGetSchedule(debug, graph);
+                    if (scheduleResult != null) {
+                        cfgPrinter.cfg = scheduleResult.getCFG();
+                    }
+                }
+                if (cfgPrinter.cfg != null) {
                     cfgPrinter.printCFG(message, cfgPrinter.cfg.getBlocks(), true);
                 }
-
             } else if (object instanceof CompilationResult) {
                 final CompilationResult compResult = (CompilationResult) object;
                 cfgPrinter.printMachineCode(disassemble(codeCache, compResult, null), message);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java	Thu Jul 25 17:35:58 2019 -0400
@@ -28,16 +28,19 @@
 import java.util.List;
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugDumpHandler;
 import org.graalvm.compiler.debug.DebugHandler;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodeinfo.Verbosity;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.compiler.serviceprovider.ServiceProvider;
 
 @ServiceProvider(DebugHandlersFactory.class)
@@ -62,9 +65,6 @@
         }
         handlers.add(new NodeDumper());
         if (DebugOptions.PrintCFG.getValue(options) || DebugOptions.PrintBackendCFG.getValue(options)) {
-            if (DebugOptions.PrintCFG.getValue(options)) {
-                TTY.out.println("Complete C1Visualizer dumping slows down PrintBinaryGraphs: use -Dgraal.PrintCFG=false to disable it");
-            }
             handlers.add(new CFGPrinterObserver());
         }
         handlers.add(new NoDeadCodeVerifyHandler());
@@ -91,4 +91,20 @@
         return new CanonicalStringGraphPrinter(snippetReflection);
     }
 
+    @SuppressWarnings("try")
+    static ScheduleResult tryGetSchedule(DebugContext debug, StructuredGraph graph) {
+        ScheduleResult scheduleResult = graph.getLastSchedule();
+        if (scheduleResult == null) {
+            // Also provide a schedule when an error occurs
+            if (DebugOptions.PrintGraphWithSchedule.getValue(graph.getOptions()) || debug.contextLookup(Throwable.class) != null) {
+                try (DebugCloseable noIntercept = debug.disableIntercept()) {
+                    SchedulePhase schedule = new SchedulePhase(graph.getOptions());
+                    schedule.apply(graph);
+                    scheduleResult = graph.getLastSchedule();
+                } catch (Throwable t) {
+                }
+            }
+        }
+        return scheduleResult;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java	Thu Jul 25 17:35:58 2019 -0400
@@ -136,36 +136,26 @@
             // Get all current JavaMethod instances in the context.
             List<String> inlineContext = getInlineContext(graph);
 
-            if (inlineContext != previousInlineContext) {
+            if (!inlineContext.equals(previousInlineContext)) {
                 Map<Object, Object> properties = new HashMap<>();
                 properties.put("graph", graph.toString());
                 addCompilationId(properties, graph);
-                if (inlineContext.equals(previousInlineContext)) {
-                    /*
-                     * two different graphs have the same inline context, so make sure they appear
-                     * in different folders by closing and reopening the top scope.
-                     */
-                    int inlineDepth = previousInlineContext.size() - 1;
-                    closeScope(debug, inlineDepth);
-                    openScope(debug, inlineContext.get(inlineDepth), inlineDepth, properties);
-                } else {
-                    // Check for method scopes that must be closed since the previous dump.
-                    for (int i = 0; i < previousInlineContext.size(); ++i) {
-                        if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
-                            for (int inlineDepth = previousInlineContext.size() - 1; inlineDepth >= i; --inlineDepth) {
-                                closeScope(debug, inlineDepth);
-                            }
-                            break;
+                // Check for method scopes that must be closed since the previous dump.
+                for (int i = 0; i < previousInlineContext.size(); ++i) {
+                    if (i >= inlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
+                        for (int inlineDepth = previousInlineContext.size() - 1; inlineDepth >= i; --inlineDepth) {
+                            closeScope(debug, inlineDepth);
                         }
+                        break;
                     }
-                    // Check for method scopes that must be opened since the previous dump.
-                    for (int i = 0; i < inlineContext.size(); ++i) {
-                        if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
-                            for (int inlineDepth = i; inlineDepth < inlineContext.size(); ++inlineDepth) {
-                                openScope(debug, inlineContext.get(inlineDepth), inlineDepth, inlineDepth == inlineContext.size() - 1 ? properties : null);
-                            }
-                            break;
+                }
+                // Check for method scopes that must be opened since the previous dump.
+                for (int i = 0; i < inlineContext.size(); ++i) {
+                    if (i >= previousInlineContext.size() || !inlineContext.get(i).equals(previousInlineContext.get(i))) {
+                        for (int inlineDepth = i; inlineDepth < inlineContext.size(); ++inlineDepth) {
+                            openScope(debug, inlineContext.get(inlineDepth), inlineDepth, inlineDepth == inlineContext.size() - 1 ? properties : null);
                         }
+                        break;
                     }
                 }
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfDispatchNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64ArrayIndexOfDispatchNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -307,4 +307,3 @@
         return optimizedArrayIndexOf(descriptor, JavaKind.Char, JavaKind.Char, true, array, arrayLength, fromIndex, values);
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java	Thu Jul 25 17:35:58 2019 -0400
@@ -766,6 +766,8 @@
                     } else {
                         newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
                     }
+                    // The final STORE_STORE barrier will be emitted by finishAllocatedObjects
+                    newObject.clearEmitMemoryBarrier();
 
                     recursiveLowerings.add(newObject);
                     graph.addBeforeFixed(commit, newObject);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/arraycopy/ArrayCopyWithDelayedLoweringNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -60,4 +60,3 @@
         this.bci = bci;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ReadRegisterNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -91,7 +91,7 @@
             generator.getLIRGeneratorTool().emitIncomingValues(new Value[]{result});
         }
         if (!directUse) {
-            result = generator.getLIRGeneratorTool().emitMove(result);
+            result = generator.getLIRGeneratorTool().emitReadRegister(register, kind);
         }
         generator.setResult(this, result);
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/WriteRegisterNode.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/WriteRegisterNode.java	Thu Jul 25 17:35:58 2019 -0400
@@ -65,7 +65,7 @@
     @Override
     public void generate(NodeLIRBuilderTool generator) {
         Value val = generator.operand(value);
-        generator.getLIRGeneratorTool().emitMove(register.asValue(val.getValueKind()), val);
+        generator.getLIRGeneratorTool().emitWriteRegister(register, val, val.getValueKind());
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Thu Jul 25 17:35:58 2019 -0400
@@ -531,11 +531,7 @@
         return Math.fma(a, b, c);
     }
 
-    /**
-     * Set the flag in the {@link VirtualObject} that indicates that it is a boxed primitive that
-     * was produced as a result of a call to a {@code valueOf} method.
-     */
-    public static void markVirtualObjectAsAutoBox(VirtualObject virtualObject) {
-        virtualObject.setIsAutoBox(true);
+    public static VirtualObject createVirtualObject(ResolvedJavaType type, int id, boolean isAutoBox) {
+        return VirtualObject.get(type, id, isAutoBox);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalUnsafeAccess.java	Thu Jul 25 17:35:58 2019 -0400
@@ -67,4 +67,3 @@
         return UNSAFE;
     }
 }
-
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java	Thu Jul 25 17:35:58 2019 -0400
@@ -27,10 +27,16 @@
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 import static org.graalvm.compiler.debug.DebugContext.NO_DESCRIPTION;
 
+import java.io.IOException;
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.lang.reflect.Field;
 import java.lang.reflect.Method;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -499,4 +505,31 @@
     public static TestRule createTimeoutMillis(long milliseconds) {
         return createTimeout(milliseconds, TimeUnit.MILLISECONDS);
     }
+
+    /**
+     * Tries to recursively remove {@code directory}. If it fails with an {@link IOException}, the
+     * exception's {@code toString()} is printed to {@link System#err} and the exception is
+     * returned.
+     */
+    public static IOException removeDirectory(Path directory) {
+        try {
+            Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
+                @Override
+                public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                    Files.delete(file);
+                    return FileVisitResult.CONTINUE;
+                }
+
+                @Override
+                public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                    Files.delete(dir);
+                    return FileVisitResult.CONTINUE;
+                }
+            });
+        } catch (IOException e) {
+            System.err.println(e);
+            return e;
+        }
+        return null;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java	Thu Jul 25 11:44:37 2019 -0700
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java	Thu Jul 25 17:35:58 2019 -0400
@@ -217,7 +217,11 @@
                 long offset = store.offset().asJavaConstant().asLong();
                 boolean overflowAccess = isOverflowAccess(accessKind, componentKind);
                 int index = overflowAccess ? -1 : VirtualArrayNode.entryIndexForOffset(tool.getMetaAccess(), offset, accessKind, type.getComponentType(), Integer.MAX_VALUE);
-                return processStore(store, store.object(), location, index, accessKind, overflowAccess, store.value(), state, effects);
+                if (index != -1) {
+                    return processStore(store, store.object(), location, index, accessKind, overflowAccess, store.value(), state, effects);
+                } else {
+                    state.killReadCache(location, index);
+                }
             } else {
                 processIdentity(state, location);
             }