changeset 56947:03fbcd06b4c0

8233841: Update Graal Reviewed-by: kvn
author dlong
date Thu, 14 Nov 2019 12:21:00 -0800
parents 5d4c3724e4c7
children e6baa47fbacf
files src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64ElideL2ITest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallLinkage.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashMapGetTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.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.debug/src/org/graalvm/compiler/debug/GraalError.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEpilogueBlockEndOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEpilogueOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRestoreRbpOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.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/CompileTheWorldTest.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.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/HotSpotGraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.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/AMD64Call.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringLatin1InflateOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringUTF16CompressOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Ternary.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64VZeroUpper.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.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorCompareOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorFloatCompareOp.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorInstruction.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorUnary.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.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.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java
diffstat 47 files changed, 816 insertions(+), 283 deletions(-) [+]
line wrap: on
line diff
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64BaseAssembler.java	Thu Nov 14 12:21:00 2019 -0800
@@ -944,7 +944,7 @@
     }
 
     public final boolean vexPrefix(Register dst, Register nds, Register src, AVXSize size, int pp, int mmmmm, int w, int wEvex, boolean checkAVX) {
-        if (isAVX512Register(dst) || isAVX512Register(nds) || isAVX512Register(src)) {
+        if (isAVX512Register(dst) || isAVX512Register(nds) || isAVX512Register(src) || size == AVXSize.ZMM) {
             evexPrefix(dst, Register.None, nds, src, size, pp, mmmmm, wEvex, Z0, B0);
             return true;
         }
@@ -953,7 +953,7 @@
     }
 
     public final boolean vexPrefix(Register dst, Register nds, AMD64Address src, AVXSize size, int pp, int mmmmm, int w, int wEvex, boolean checkAVX) {
-        if (isAVX512Register(dst) || isAVX512Register(nds)) {
+        if (isAVX512Register(dst) || isAVX512Register(nds) || size == AVXSize.ZMM) {
             evexPrefix(dst, Register.None, nds, src, size, pp, mmmmm, wEvex, Z0, B0);
             return true;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64.test/src/org/graalvm/compiler/core/aarch64/test/AArch64ElideL2ITest.java	Thu Nov 14 12:21:00 2019 -0800
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, Arm Limited. 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.test;
+
+import org.graalvm.compiler.lir.LIRInstruction;
+import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp.BinaryConstOp;
+import org.junit.Test;
+
+import java.util.function.Predicate;
+
+public class AArch64ElideL2ITest extends AArch64MatchRuleTest {
+    private static final Predicate<LIRInstruction> predicate = op -> {
+        if (op instanceof BinaryConstOp && op.name().toUpperCase().equals("AND")) {
+            return true;
+        }
+        return false;
+    };
+
+    public int addWithSingleL2I(long m) {
+        return (int) m + 100;
+    }
+
+    @Test
+    public void testAddWithSingleL2I() {
+        test("addWithSingleL2I", 5L);
+        checkLIR("addWithSingleL2I", predicate, 0);
+    }
+
+    public int addWithTwoL2I(long m, long n) {
+        return (int) m + (int) n;
+    }
+
+    @Test
+    public void testAddWithTwoL2I() {
+        test("addWithTwoL2I", 5L, 0x1FFFFFFFFL);
+        checkLIR("addWithTwoL2I", predicate, 0);
+    }
+
+    public int addWithTwoNarrow(long m, long n) {
+        return (int) m + (short) n;
+    }
+
+    @Test
+    public void testAddWithTwoNarrow() {
+        test("addWithTwoNarrow", 0x80000000L, 6L);
+        checkLIR("addWithTwoNarrow", predicate, 1);
+    }
+
+    public int subSingleL2I(int m, long n) {
+        return m - (int) n;
+    }
+
+    @Test
+    public void testSubSingleL2I() {
+        test("subSingleL2I", 13, 40L);
+        checkLIR("subSingleL2I", predicate, 0);
+    }
+
+    public int shiftWithSingleL2I(long m) {
+        return ((int) m) >> 5;
+    }
+
+    @Test
+    public void testShiftWithSingleL2I() {
+        test("shiftWithSingleL2I", 234L);
+        checkLIR("shiftWithSingleL2I", predicate, 0);
+    }
+
+    public int shiftWithTwoL2I(long m, long n) {
+        return (int) m << (int) n;
+    }
+
+    @Test
+    public void testShiftWithTwoL2I() {
+        test("shiftWithTwoL2I", 234L, 3L);
+        checkLIR("shiftWithTwoL2I", predicate, 0);
+    }
+
+    public long shiftLongWithL2I(long a, int m) {
+        return a + ((m & 0xFFFFFFFFL) << (int) a);
+    }
+
+    @Test
+    public void testShiftLongWithL2I() {
+        test("shiftLongWithL2I", 0xFFFFFFFFL, 123);
+        checkLIR("shiftLongWithL2I", predicate, 1);
+    }
+
+    public int logicWithTwoL2I(long m, long n) {
+        return (int) m | (int) n;
+    }
+
+    @Test
+    public void testLogicWithTwoL2I() {
+        test("logicWithTwoL2I", 234L, 3L);
+        checkLIR("logicWithTwoL2I", predicate, 0);
+    }
+
+    public int negateL2I(long m) {
+        return -((int) m);
+    }
+
+    @Test
+    public void testNegateL2I() {
+        test("negateL2I", 0xFFFFFFFFL);
+        checkLIR("negateL2I", predicate, 0);
+    }
+
+    public int notL2I(long m) {
+        return ~((int) m);
+    }
+
+    @Test
+    public void testNotL2I() {
+        test("notL2I", 0xFFFFFFFFL);
+        checkLIR("notL2I", predicate, 0);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Thu Nov 14 12:21:00 2019 -0800
@@ -38,7 +38,6 @@
 import org.graalvm.compiler.core.gen.NodeMatchRules;
 import org.graalvm.compiler.core.match.ComplexMatchResult;
 import org.graalvm.compiler.core.match.MatchRule;
-import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.lir.LIRFrameState;
 import org.graalvm.compiler.lir.LabelRef;
 import org.graalvm.compiler.lir.Variable;
@@ -58,26 +57,33 @@
 import org.graalvm.compiler.nodes.calc.IntegerLessThanNode;
 import org.graalvm.compiler.nodes.calc.LeftShiftNode;
 import org.graalvm.compiler.nodes.calc.MulNode;
+import org.graalvm.compiler.nodes.calc.NarrowNode;
+import org.graalvm.compiler.nodes.calc.NegateNode;
 import org.graalvm.compiler.nodes.calc.NotNode;
 import org.graalvm.compiler.nodes.calc.OrNode;
 import org.graalvm.compiler.nodes.calc.RightShiftNode;
 import org.graalvm.compiler.nodes.calc.SubNode;
+import org.graalvm.compiler.nodes.calc.UnaryNode;
 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
 import org.graalvm.compiler.nodes.calc.XorNode;
 import org.graalvm.compiler.nodes.memory.Access;
 
 public class AArch64NodeMatchRules extends NodeMatchRules {
-    private static final EconomicMap<Class<? extends Node>, AArch64ArithmeticOp> nodeOpMap;
+    private static final EconomicMap<Class<? extends BinaryNode>, AArch64ArithmeticOp> binaryOpMap;
     private static final EconomicMap<Class<? extends BinaryNode>, AArch64BitFieldOp.BitFieldOpCode> bitFieldOpMap;
     private static final EconomicMap<Class<? extends BinaryNode>, AArch64MacroAssembler.ShiftType> shiftTypeMap;
 
     static {
-        nodeOpMap = EconomicMap.create(Equivalence.IDENTITY, 5);
-        nodeOpMap.put(AddNode.class, AArch64ArithmeticOp.ADD);
-        nodeOpMap.put(SubNode.class, AArch64ArithmeticOp.SUB);
-        nodeOpMap.put(AndNode.class, AArch64ArithmeticOp.AND);
-        nodeOpMap.put(OrNode.class, AArch64ArithmeticOp.OR);
-        nodeOpMap.put(XorNode.class, AArch64ArithmeticOp.XOR);
+        binaryOpMap = EconomicMap.create(Equivalence.IDENTITY, 9);
+        binaryOpMap.put(AddNode.class, AArch64ArithmeticOp.ADD);
+        binaryOpMap.put(SubNode.class, AArch64ArithmeticOp.SUB);
+        binaryOpMap.put(MulNode.class, AArch64ArithmeticOp.MUL);
+        binaryOpMap.put(AndNode.class, AArch64ArithmeticOp.AND);
+        binaryOpMap.put(OrNode.class, AArch64ArithmeticOp.OR);
+        binaryOpMap.put(XorNode.class, AArch64ArithmeticOp.XOR);
+        binaryOpMap.put(LeftShiftNode.class, AArch64ArithmeticOp.SHL);
+        binaryOpMap.put(RightShiftNode.class, AArch64ArithmeticOp.ASHR);
+        binaryOpMap.put(UnsignedRightShiftNode.class, AArch64ArithmeticOp.LSHR);
 
         bitFieldOpMap = EconomicMap.create(Equivalence.IDENTITY, 2);
         bitFieldOpMap.put(UnsignedRightShiftNode.class, AArch64BitFieldOp.BitFieldOpCode.UBFX);
@@ -153,6 +159,10 @@
         };
     }
 
+    private static boolean isNarrowingLongToInt(NarrowNode narrow) {
+        return narrow.getInputBits() == 64 && narrow.getResultBits() == 32;
+    }
+
     @MatchRule("(And (UnsignedRightShift=shift a Constant=b) Constant=c)")
     @MatchRule("(LeftShift=shift (And a Constant=c) Constant=b)")
     public ComplexMatchResult unsignedBitField(BinaryNode shift, ValueNode a, ConstantNode b, ConstantNode c) {
@@ -194,7 +204,7 @@
     @MatchRule("(Sub=binary a (RightShift=shift b Constant))")
     @MatchRule("(Sub=binary a (UnsignedRightShift=shift b Constant))")
     public ComplexMatchResult addSubShift(BinaryNode binary, ValueNode a, BinaryNode shift) {
-        AArch64ArithmeticOp op = nodeOpMap.get(binary.getClass());
+        AArch64ArithmeticOp op = binaryOpMap.get(binary.getClass());
         assert op != null;
         return emitBinaryShift(op, a, shift, false);
     }
@@ -218,7 +228,7 @@
     @MatchRule("(Xor=binary a (Not (RightShift=shift b Constant)))")
     @MatchRule("(Xor=binary a (Not (UnsignedRightShift=shift b Constant)))")
     public ComplexMatchResult logicShift(BinaryNode binary, ValueNode a, BinaryNode shift) {
-        AArch64ArithmeticOp op = nodeOpMap.get(binary.getClass());
+        AArch64ArithmeticOp op = binaryOpMap.get(binary.getClass());
         assert op != null;
         ValueNode operand = binary.getX() == a ? binary.getY() : binary.getX();
         boolean isShiftNot = operand instanceof NotNode;
@@ -252,6 +262,75 @@
                         resultKind, AArch64ArithmeticOp.SMULL, true, operand(a), operand(b));
     }
 
+    @MatchRule("(Add=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(Sub=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(Mul=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(And=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(Or=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(Xor=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(LeftShift=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(RightShift=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(UnsignedRightShift=binary (Narrow=narrow a) (Narrow b))")
+    @MatchRule("(Add=binary a (Narrow=narrow b))")
+    @MatchRule("(Sub=binary a (Narrow=narrow b))")
+    @MatchRule("(Mul=binary a (Narrow=narrow b))")
+    @MatchRule("(And=binary a (Narrow=narrow b))")
+    @MatchRule("(Or=binary a (Narrow=narrow b))")
+    @MatchRule("(Xor=binary a (Narrow=narrow b))")
+    @MatchRule("(LeftShift=binary a (Narrow=narrow b))")
+    @MatchRule("(RightShift=binary a (Narrow=narrow b))")
+    @MatchRule("(UnsignedRightShift=binary a (Narrow=narrow b))")
+    @MatchRule("(Sub=binary (Narrow=narrow a) b)")
+    @MatchRule("(LeftShift=binary (Narrow=narrow a) b)")
+    @MatchRule("(RightShift=binary (Narrow=narrow a) b)")
+    @MatchRule("(UnsignedRightShift=binary (Narrow=narrow a) b)")
+    public ComplexMatchResult elideL2IForBinary(BinaryNode binary, NarrowNode narrow) {
+        assert binary.getStackKind().isNumericInteger();
+
+        ValueNode a = narrow;
+        ValueNode b = binary.getX() == narrow ? binary.getY() : binary.getX();
+        boolean isL2Ia = isNarrowingLongToInt((NarrowNode) a);
+        boolean isL2Ib = (b instanceof NarrowNode) && isNarrowingLongToInt((NarrowNode) b);
+        if (!isL2Ia && !isL2Ib) {
+            return null;
+        }
+        // Get the value of L2I NarrowNode as the src value.
+        ValueNode src1 = isL2Ia ? ((NarrowNode) a).getValue() : a;
+        ValueNode src2 = isL2Ib ? ((NarrowNode) b).getValue() : b;
+
+        AArch64ArithmeticOp op = binaryOpMap.get(binary.getClass());
+        assert op != null;
+        boolean commutative = binary.getNodeClass().isCommutative();
+        LIRKind resultKind = LIRKind.fromJavaKind(gen.target().arch, binary.getStackKind());
+
+        // Must keep the right operator order for un-commutative binary operations.
+        if (a == binary.getX()) {
+            return builder -> getArithmeticLIRGenerator().emitBinary(
+                            resultKind, op, commutative, operand(src1), operand(src2));
+        }
+        return builder -> getArithmeticLIRGenerator().emitBinary(
+                        resultKind, op, commutative, operand(src2), operand(src1));
+    }
+
+    @MatchRule("(Negate=unary (Narrow=narrow value))")
+    @MatchRule("(Not=unary (Narrow=narrow value))")
+    public ComplexMatchResult elideL2IForUnary(UnaryNode unary, NarrowNode narrow) {
+        assert unary.getStackKind().isNumericInteger();
+        if (!isNarrowingLongToInt(narrow)) {
+            return null;
+        }
+
+        AArch64ArithmeticOp op = unary instanceof NegateNode ? AArch64ArithmeticOp.NEG
+                        : AArch64ArithmeticOp.NOT;
+        return builder -> {
+            AllocatableValue input = gen.asAllocatable(operand(narrow.getValue()));
+            LIRKind resultKind = LIRKind.fromJavaKind(gen.target().arch, unary.getStackKind());
+            Variable result = gen.newVariable(resultKind);
+            gen.append(new AArch64ArithmeticOp.UnaryOp(op, result, moveSp(input)));
+            return result;
+        };
+    }
+
     @MatchRule("(Mul (Negate a) b)")
     @MatchRule("(Negate (Mul a b))")
     public ComplexMatchResult multiplyNegate(ValueNode a, ValueNode b) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallLinkage.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallLinkage.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -73,4 +73,13 @@
      * the VM to be able to inspect the thread's execution state.
      */
     boolean needsDebugInfo();
+
+    /**
+     * Returns true if further cleanup on the float registers is needed after performing the foreign
+     * call. This is critical on AMD64 as there is a performance penalty switching between legacy
+     * SSE and AVX instruction while the upper halves of the xmm registers are not zero.
+     */
+    default boolean needsClearUpperVectorRegisters() {
+        return false;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashMapGetTest.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/HashMapGetTest.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,7 +52,7 @@
         for (IfNode ifNode : lastCompiledGraph.getNodes(IfNode.TYPE)) {
             LogicNode condition = ifNode.condition();
             if (ifNode.getTrueSuccessorProbability() < 0.4 && condition instanceof ObjectEqualsNode) {
-                assertTrue(ifNode.trueSuccessor().next() instanceof ReturnNode, "Expected return.", ifNode.trueSuccessor(), ifNode.trueSuccessor().next());
+                assertTrue(ifNode.trueSuccessor().next() instanceof ReturnNode, "Expected return but got %s (trueSuccessor: %s)", ifNode.trueSuccessor().next(), ifNode.trueSuccessor());
             }
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/UnsafeVirtualizationTest.java	Thu Nov 14 12:21:00 2019 -0800
@@ -24,8 +24,7 @@
 
 package org.graalvm.compiler.core.test;
 
-import java.lang.reflect.Field;
-
+import org.graalvm.compiler.core.test.ea.EATestBase.TestClassInt;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
 import org.graalvm.compiler.nodes.spi.CoreProviders;
@@ -39,75 +38,45 @@
 
 public class UnsafeVirtualizationTest extends GraalCompilerTest {
 
-    public static class Base {
-        /*
-         * This padding ensure that the size of the Base class ends up as a multiple of 8, which
-         * makes the first field of the subclass 8-byte aligned.
-         */
-        double padding;
-    }
-
-    public static class A extends Base {
-        int f1;
-        int f2;
-    }
-
-    private static final long AF1Offset;
-    private static final long AF2Offset;
-    static {
-        long o1 = -1;
-        long o2 = -1;
-        try {
-            Field f1 = A.class.getDeclaredField("f1");
-            Field f2 = A.class.getDeclaredField("f2");
-            o1 = UNSAFE.objectFieldOffset(f1);
-            o2 = UNSAFE.objectFieldOffset(f2);
-        } catch (NoSuchFieldException | SecurityException e) {
-            throw new AssertionError(e);
-        }
-        AF1Offset = o1;
-        AF2Offset = o2;
-    }
-
     public static int unsafeSnippet1(double i1) {
-        A a = new A();
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset);
+        TestClassInt a = new TestClassInt();
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        return UNSAFE.getInt(a, TestClassInt.fieldOffset1) + UNSAFE.getInt(a, TestClassInt.fieldOffset2);
     }
 
     public static long unsafeSnippet2a(int i1) {
-        A a = new A();
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        a.f1 = i1;
-        return UNSAFE.getLong(a, AF1Offset);
+        TestClassInt a = new TestClassInt();
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        a.setFirstField(i1);
+        return UNSAFE.getLong(a, TestClassInt.fieldOffset1);
     }
 
     public static long unsafeSnippet2b(int i1) {
-        A a = new A();
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        a.f2 = i1;
-        return UNSAFE.getLong(a, AF1Offset);
+        TestClassInt a = new TestClassInt();
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        a.setSecondField(i1);
+        return UNSAFE.getLong(a, TestClassInt.fieldOffset1);
     }
 
     public static long unsafeSnippet3a(int i1) {
-        A a = new A();
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        UNSAFE.putInt(a, AF1Offset, i1);
-        return UNSAFE.getLong(a, AF1Offset);
+        TestClassInt a = new TestClassInt();
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        UNSAFE.putInt(a, TestClassInt.fieldOffset1, i1);
+        return UNSAFE.getLong(a, TestClassInt.fieldOffset1);
     }
 
     public static long unsafeSnippet3b(int i1) {
-        A a = new A();
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        UNSAFE.putInt(a, AF2Offset, i1);
-        return UNSAFE.getLong(a, AF1Offset);
+        TestClassInt a = new TestClassInt();
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        UNSAFE.putInt(a, TestClassInt.fieldOffset2, i1);
+        return UNSAFE.getLong(a, TestClassInt.fieldOffset1);
     }
 
     public static int unsafeSnippet4(double i1) {
-        A a = new A();
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        UNSAFE.putDouble(a, AF1Offset, i1);
-        return UNSAFE.getInt(a, AF1Offset) + UNSAFE.getInt(a, AF2Offset);
+        TestClassInt a = new TestClassInt();
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        UNSAFE.putDouble(a, TestClassInt.fieldOffset1, i1);
+        return UNSAFE.getInt(a, TestClassInt.fieldOffset1) + UNSAFE.getInt(a, TestClassInt.fieldOffset2);
     }
 
     @Test
@@ -141,7 +110,7 @@
     }
 
     public void testPartialEscapeReadElimination(String snippet, boolean canonicalizeBefore, Object... args) {
-        assert AF1Offset % 8 == 0 : "First of the two int-fields must be 8-byte aligned";
+        assert TestClassInt.fieldOffset1 % 8 == 0 : "First of the two int-fields must be 8-byte aligned";
 
         ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
         StructuredGraph graph = parseEager(snippet, AllowAssumptions.NO);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EATestBase.java	Thu Nov 14 12:21:00 2019 -0800
@@ -87,6 +87,46 @@
         public int hashCode() {
             return x + 13 * y;
         }
+
+        public static final long fieldOffset1;
+        public static final long fieldOffset2;
+        public static final boolean firstFieldIsX;
+
+        static {
+            try {
+                long localFieldOffset1 = UNSAFE.objectFieldOffset(EATestBase.TestClassInt.class.getField("x"));
+                // Make the fields 8 byte aligned (Required for testing setLong on Architectures
+                // which does not support unaligned memory access
+                if (localFieldOffset1 % 8 == 0) {
+                    fieldOffset1 = localFieldOffset1;
+                    fieldOffset2 = UNSAFE.objectFieldOffset(EATestBase.TestClassInt.class.getField("y"));
+                    firstFieldIsX = true;
+                } else {
+                    fieldOffset1 = UNSAFE.objectFieldOffset(EATestBase.TestClassInt.class.getField("y"));
+                    fieldOffset2 = UNSAFE.objectFieldOffset(EATestBase.TestClassInt.class.getField("z"));
+                    firstFieldIsX = false;
+                }
+                assert fieldOffset2 == fieldOffset1 + 4;
+            } catch (Exception e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        public void setFirstField(int v) {
+            if (firstFieldIsX) {
+                x = v;
+            } else {
+                y = v;
+            }
+        }
+
+        public void setSecondField(int v) {
+            if (firstFieldIsX) {
+                y = v;
+            } else {
+                z = v;
+            }
+        }
     }
 
     public static class TestClassObject {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/UnsafeEATest.java	Thu Nov 14 12:21:00 2019 -0800
@@ -48,27 +48,6 @@
 
     public static int zero = 0;
 
-    private static final long fieldOffset1;
-    private static final long fieldOffset2;
-
-    static {
-        try {
-            long localFieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("x"));
-            // Make the fields 8 byte aligned (Required for testing setLong on Architectures which
-            // does not support unaligned memory access
-            if (localFieldOffset1 % 8 == 0) {
-                fieldOffset1 = localFieldOffset1;
-                fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("y"));
-            } else {
-                fieldOffset1 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("y"));
-                fieldOffset2 = UNSAFE.objectFieldOffset(TestClassInt.class.getField("z"));
-            }
-            assert fieldOffset2 == fieldOffset1 + 4;
-        } catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-
     @Override
     protected void testEscapeAnalysis(String snippet, JavaConstant expectedConstantResult, boolean iterativeEscapeAnalysis) {
         // Exercise both a graph containing UnsafeAccessNodes and one which has been possibly been
@@ -134,8 +113,8 @@
 
     public static int testSimpleIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putInt(x, fieldOffset1, 101);
-        return UNSAFE.getInt(x, fieldOffset1);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset1, 101);
+        return UNSAFE.getInt(x, TestClassInt.fieldOffset1);
     }
 
     @Test
@@ -145,7 +124,7 @@
 
     public static TestClassInt testMaterializedIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putInt(x, fieldOffset1, 101);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset1, 101);
         return x;
     }
 
@@ -156,8 +135,8 @@
 
     public static double testSimpleDoubleSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, 10.1);
-        return UNSAFE.getDouble(x, fieldOffset1);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10.1);
+        return UNSAFE.getDouble(x, TestClassInt.fieldOffset1);
     }
 
     @Test
@@ -167,9 +146,9 @@
 
     public static int testSimpleDoubleOverwriteWithIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, 10.1);
-        UNSAFE.putInt(x, fieldOffset1, 10);
-        return UNSAFE.getInt(x, fieldOffset1);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10.1);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset1, 10);
+        return UNSAFE.getInt(x, TestClassInt.fieldOffset1);
     }
 
     @Test
@@ -183,9 +162,9 @@
 
     public static int testSimpleDoubleOverwriteWithSecondIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, 10.1);
-        UNSAFE.putInt(x, fieldOffset1, 10);
-        return UNSAFE.getInt(x, fieldOffset2);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10.1);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset1, 10);
+        return UNSAFE.getInt(x, TestClassInt.fieldOffset2);
     }
 
     @Test
@@ -199,9 +178,9 @@
 
     public static int testSimpleDoubleOverwriteWithFirstIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, 10.1);
-        UNSAFE.putInt(x, fieldOffset2, 10);
-        return UNSAFE.getInt(x, fieldOffset1);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10.1);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset2, 10);
+        return UNSAFE.getInt(x, TestClassInt.fieldOffset1);
     }
 
     @Test
@@ -215,9 +194,9 @@
 
     public static int testSimpleLongOverwriteWithSecondIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putLong(x, fieldOffset1, 0x1122334455667788L);
-        UNSAFE.putInt(x, fieldOffset1, 10);
-        return UNSAFE.getInt(x, fieldOffset2);
+        UNSAFE.putLong(x, TestClassInt.fieldOffset1, 0x1122334455667788L);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset1, 10);
+        return UNSAFE.getInt(x, TestClassInt.fieldOffset2);
     }
 
     @Test
@@ -231,9 +210,9 @@
 
     public static int testSimpleLongOverwriteWithFirstIntSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putLong(x, fieldOffset1, 0x1122334455667788L);
-        UNSAFE.putInt(x, fieldOffset2, 10);
-        return UNSAFE.getInt(x, fieldOffset1);
+        UNSAFE.putLong(x, TestClassInt.fieldOffset1, 0x1122334455667788L);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset2, 10);
+        return UNSAFE.getInt(x, TestClassInt.fieldOffset1);
     }
 
     @Test
@@ -250,12 +229,12 @@
         TestClassInt x;
         if (a) {
             x = new TestClassInt(0, 0);
-            UNSAFE.putDouble(x, fieldOffset1, doubleField);
+            UNSAFE.putDouble(x, TestClassInt.fieldOffset1, doubleField);
         } else {
             x = new TestClassInt();
-            UNSAFE.putDouble(x, fieldOffset1, doubleField2);
+            UNSAFE.putDouble(x, TestClassInt.fieldOffset1, doubleField2);
         }
-        return UNSAFE.getDouble(x, fieldOffset1);
+        return UNSAFE.getDouble(x, TestClassInt.fieldOffset1);
     }
 
     static class ExtendedTestClassInt extends TestClassInt {
@@ -271,14 +250,14 @@
         TestClassInt x;
         if (value == 1) {
             x = new TestClassInt();
-            UNSAFE.putDouble(x, fieldOffset1, 10);
+            UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10);
         } else {
             x = new TestClassInt();
-            UNSAFE.putInt(x, fieldOffset1, 0);
+            UNSAFE.putInt(x, TestClassInt.fieldOffset1, 0);
         }
-        UNSAFE.putInt(x, fieldOffset1, 0);
+        UNSAFE.putInt(x, TestClassInt.fieldOffset1, 0);
         if (value == 2) {
-            UNSAFE.putInt(x, fieldOffset2, 0);
+            UNSAFE.putInt(x, TestClassInt.fieldOffset2, 0);
         }
         GraalDirectives.deoptimizeAndInvalidate();
         return x;
@@ -291,7 +270,7 @@
 
     public static TestClassInt testMaterializedDoubleSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, 10.1);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10.1);
         return x;
     }
 
@@ -305,10 +284,10 @@
 
     public static TestClassInt testDeoptDoubleVarSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, doubleField);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, doubleField);
         doubleField2 = 123;
         try {
-            doubleField = ((int) UNSAFE.getDouble(x, fieldOffset1)) / zero;
+            doubleField = ((int) UNSAFE.getDouble(x, TestClassInt.fieldOffset1)) / zero;
         } catch (RuntimeException e) {
             return x;
         }
@@ -322,10 +301,10 @@
 
     public static TestClassInt testDeoptDoubleConstantSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putDouble(x, fieldOffset1, 10.123);
+        UNSAFE.putDouble(x, TestClassInt.fieldOffset1, 10.123);
         doubleField2 = 123;
         try {
-            doubleField = ((int) UNSAFE.getDouble(x, fieldOffset1)) / zero;
+            doubleField = ((int) UNSAFE.getDouble(x, TestClassInt.fieldOffset1)) / zero;
         } catch (RuntimeException e) {
             return x;
         }
@@ -342,10 +321,10 @@
 
     public static TestClassInt testDeoptLongVarSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putLong(x, fieldOffset1, longField);
+        UNSAFE.putLong(x, TestClassInt.fieldOffset1, longField);
         longField2 = 123;
         try {
-            longField = UNSAFE.getLong(x, fieldOffset1) / zero;
+            longField = UNSAFE.getLong(x, TestClassInt.fieldOffset1) / zero;
         } catch (RuntimeException e) {
             return x;
         }
@@ -359,10 +338,10 @@
 
     public static TestClassInt testDeoptLongConstantSnippet() {
         TestClassInt x = new TestClassInt();
-        UNSAFE.putLong(x, fieldOffset1, 0x2222222210123L);
+        UNSAFE.putLong(x, TestClassInt.fieldOffset1, 0x2222222210123L);
         longField2 = 123;
         try {
-            longField = UNSAFE.getLong(x, fieldOffset1) / zero;
+            longField = UNSAFE.getLong(x, TestClassInt.fieldOffset1) / zero;
         } catch (RuntimeException e) {
             return x;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Nov 14 12:21:00 2019 -0800
@@ -243,6 +243,9 @@
                 String message;
                 ByteArrayOutputStream baos = new ByteArrayOutputStream();
                 try (PrintStream ps = new PrintStream(baos)) {
+                    // This output is used by external tools to detect compilation failures.
+                    ps.println("[[[Graal compilation failure]]]");
+
                     ps.printf("%s: Compilation of %s failed:%n", Thread.currentThread(), this);
                     cause.printStackTrace(ps);
                     ps.printf("To disable compilation failure notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GraalError.java	Thu Nov 14 12:21:00 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -169,6 +169,14 @@
     }
 
     /**
+     * This constructor creates a {@link GraalError} for a given causing Throwable instance with
+     * detailed error message.
+     */
+    public GraalError(Throwable cause, String msg, Object... args) {
+        super(format(msg, args), cause);
+    }
+
+    /**
      * This constructor creates a {@link GraalError} and adds all the
      * {@linkplain #addContext(String) context} of another {@link GraalError}.
      *
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Thu Nov 14 12:21:00 2019 -0800
@@ -26,6 +26,7 @@
 
 import static jdk.vm.ci.amd64.AMD64.r10;
 import static jdk.vm.ci.amd64.AMD64.rax;
+import static jdk.vm.ci.amd64.AMD64.rbp;
 import static jdk.vm.ci.amd64.AMD64.rsp;
 import static jdk.vm.ci.code.ValueUtil.asRegister;
 import static org.graalvm.compiler.core.common.GraalOptions.CanOmitFrame;
@@ -93,7 +94,7 @@
     @Override
     protected FrameMapBuilder newFrameMapBuilder(RegisterConfig registerConfig) {
         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
-        FrameMap frameMap = new AMD64FrameMap(getCodeCache(), registerConfigNonNull, this);
+        FrameMap frameMap = new AMD64FrameMap(getCodeCache(), registerConfigNonNull, this, config.preserveFramePointer);
         return new AMD64FrameMapBuilder(frameMap, getCodeCache(), registerConfigNonNull);
     }
 
@@ -130,10 +131,12 @@
 
         final boolean isStub;
         final boolean omitFrame;
+        final boolean useStandardFrameProlog;
 
-        HotSpotFrameContext(boolean isStub, boolean omitFrame) {
+        HotSpotFrameContext(boolean isStub, boolean omitFrame, boolean useStandardFrameProlog) {
             this.isStub = isStub;
             this.omitFrame = omitFrame;
+            this.useStandardFrameProlog = useStandardFrameProlog;
         }
 
         @Override
@@ -157,6 +160,11 @@
                     // assert asm.position() - verifiedEntryPointOffset >=
                     // PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE;
                 }
+                if (useStandardFrameProlog) {
+                    // Stack-walking friendly instructions
+                    asm.push(rbp);
+                    asm.movq(rbp, rsp);
+                }
                 if (!isStub && asm.position() == verifiedEntryPointOffset) {
                     asm.subqWide(rsp, frameSize);
                     assert asm.position() - verifiedEntryPointOffset >= PATCHED_VERIFIED_ENTRY_POINT_INSTRUCTION_SIZE;
@@ -180,7 +188,12 @@
                 assert crb.frameMap.getRegisterConfig().getCalleeSaveRegisters() == null;
 
                 int frameSize = crb.frameMap.frameSize();
-                asm.incrementq(rsp, frameSize);
+                if (useStandardFrameProlog) {
+                    asm.movq(rsp, rbp);
+                    asm.pop(rbp);
+                } else {
+                    asm.incrementq(rsp, frameSize);
+                }
             }
         }
     }
@@ -202,7 +215,7 @@
 
         Stub stub = gen.getStub();
         Assembler masm = new AMD64MacroAssembler(getTarget());
-        HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame);
+        HotSpotFrameContext frameContext = new HotSpotFrameContext(stub != null, omitFrame, config.preserveFramePointer);
         DataBuilder dataBuilder = new HotSpotDataBuilder(getCodeCache().getTarget());
         CompilationResultBuilder crb = factory.createBuilder(getCodeCache(), getForeignCalls(), frameMap, masm, dataBuilder, frameContext, options, debug, compilationResult, Register.None);
         crb.setTotalFrameSize(frameMap.totalFrameSize());
@@ -330,7 +343,7 @@
     @Override
     public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) {
         RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;
-        return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo);
+        return new AMD64HotSpotRegisterAllocationConfig(registerConfigNonNull, allocationRestrictedTo, config.preserveFramePointer);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEpilogueBlockEndOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEpilogueBlockEndOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -24,6 +24,7 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
 import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
 
@@ -33,6 +34,7 @@
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
 import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
 
 /**
  * @see AMD64HotSpotEpilogueOp
@@ -43,7 +45,7 @@
         super(c);
     }
 
-    @Use({REG, STACK}) protected AllocatableValue savedRbp = PLACEHOLDER;
+    @Use({REG, STACK, ILLEGAL}) protected AllocatableValue savedRbp = Value.ILLEGAL;
 
     protected void leaveFrameAndRestoreRbp(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
         AMD64HotSpotEpilogueOp.leaveFrameAndRestoreRbp(savedRbp, crb, masm);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEpilogueOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -24,20 +24,23 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
-import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
 import static jdk.vm.ci.amd64.AMD64.rbp;
 import static jdk.vm.ci.code.ValueUtil.asRegister;
 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
 
 import org.graalvm.compiler.asm.amd64.AMD64Address;
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.amd64.AMD64FrameMap;
 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
 
 /**
  * Superclass for operations that use the value of RBP saved in a method's prologue.
@@ -48,14 +51,17 @@
         super(c);
     }
 
-    @Use({REG, STACK}) private AllocatableValue savedRbp = PLACEHOLDER;
+    @Use({REG, STACK, ILLEGAL}) private AllocatableValue savedRbp = Value.ILLEGAL;
 
     protected void leaveFrameAndRestoreRbp(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
         leaveFrameAndRestoreRbp(savedRbp, crb, masm);
     }
 
     static void leaveFrameAndRestoreRbp(AllocatableValue savedRbp, CompilationResultBuilder crb, AMD64MacroAssembler masm) {
-        if (isStackSlot(savedRbp)) {
+        if (Value.ILLEGAL.equals(savedRbp)) {
+            // RBP will be restored in FrameContext.leave(..). Nothing to do here.
+            assert ((AMD64FrameMap) crb.frameMap).useStandardFrameProlog() : "savedRbp is not initialized.";
+        } else if (isStackSlot(savedRbp)) {
             // Restoring RBP from the stack must be done before the frame is removed
             masm.movq(rbp, (AMD64Address) crb.asAddress(savedRbp));
         } else {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLIRGenerator.java	Thu Nov 14 12:21:00 2019 -0800
@@ -153,7 +153,7 @@
         SaveRbp(NoOp placeholder) {
             this.placeholder = placeholder;
             AMD64FrameMapBuilder frameMapBuilder = (AMD64FrameMapBuilder) getResult().getFrameMapBuilder();
-            this.reservedSlot = frameMapBuilder.allocateRBPSpillSlot();
+            this.reservedSlot = config.preserveFramePointer ? null : frameMapBuilder.allocateRBPSpillSlot();
         }
 
         /**
@@ -162,6 +162,7 @@
          * @param useStack specifies if rbp must be saved to the stack
          */
         public AllocatableValue finalize(boolean useStack) {
+            assert !config.preserveFramePointer : "rbp has been pushed onto the stack";
             AllocatableValue dst;
             if (useStack) {
                 dst = reservedSlot;
@@ -173,6 +174,10 @@
             placeholder.replace(getResult().getLIR(), new MoveFromRegOp(AMD64Kind.QWORD, dst, rbp.asValue(LIRKind.value(AMD64Kind.QWORD))));
             return dst;
         }
+
+        public void remove() {
+            placeholder.remove(getResult().getLIR());
+        }
     }
 
     private SaveRbp saveRbp;
@@ -183,10 +188,6 @@
         saveRbp = new SaveRbp(placeholder);
     }
 
-    protected SaveRbp getSaveRbp() {
-        return saveRbp;
-    }
-
     /**
      * Helper instruction to reserve a stack slot for the whole method. Note that the actual users
      * of the stack slot might be inserted after stack slot allocation. This dummy instruction
@@ -547,16 +548,21 @@
     public void beforeRegisterAllocation() {
         super.beforeRegisterAllocation();
         boolean hasDebugInfo = getResult().getLIR().hasDebugInfo();
-        AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
+
+        if (config.preserveFramePointer) {
+            saveRbp.remove();
+        } else {
+            AllocatableValue savedRbp = saveRbp.finalize(hasDebugInfo);
+            for (AMD64HotSpotRestoreRbpOp op : epilogueOps) {
+                op.setSavedRbp(savedRbp);
+            }
+        }
+
         if (hasDebugInfo) {
             getResult().setDeoptimizationRescueSlot(((AMD64FrameMapBuilder) getResult().getFrameMapBuilder()).allocateDeoptimizationRescueSlot());
         }
-
         getResult().setMaxInterpreterFrameSize(debugInfoBuilder.maxInterpreterFrameSize());
 
-        for (AMD64HotSpotRestoreRbpOp op : epilogueOps) {
-            op.setSavedRbp(savedRbp);
-        }
         if (BenchmarkCounters.enabled) {
             // ensure that the rescue slot is available
             LIRInstruction op = getOrInitRescueSlotOp();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRegisterAllocationConfig.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -83,8 +83,11 @@
     };
     // @formatter:on
 
-    AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo) {
+    private final boolean useStandardFrameProlog;
+
+    AMD64HotSpotRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo, boolean useStandardFrameProlog) {
         super(registerConfig, allocationRestrictedTo);
+        this.useStandardFrameProlog = useStandardFrameProlog;
     }
 
     @Override
@@ -93,6 +96,9 @@
         for (Register reg : registers) {
             regMap.set(reg.number);
         }
+        if (useStandardFrameProlog) {
+            regMap.clear(rbp.number);
+        }
 
         ArrayList<Register> allocatableRegisters = new ArrayList<>(registers.size());
         for (Register reg : registerAllocationOrder) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRestoreRbpOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotRestoreRbpOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -24,20 +24,9 @@
 
 package org.graalvm.compiler.hotspot.amd64;
 
-import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.lir.Variable;
-
-import jdk.vm.ci.amd64.AMD64Kind;
 import jdk.vm.ci.meta.AllocatableValue;
 
 public interface AMD64HotSpotRestoreRbpOp {
 
-    /**
-     * The type of location (i.e., stack or register) in which RBP is saved is not known until
-     * initial LIR generation is finished. Until then, we use a placeholder variable so that LIR
-     * verification is successful.
-     */
-    Variable PLACEHOLDER = new Variable(LIRKind.value(AMD64Kind.QWORD), Integer.MAX_VALUE);
-
     void setSavedRbp(AllocatableValue value);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotReturnOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -111,10 +111,14 @@
              * live value at this point should be the return value in either rax, or in xmm0 with
              * the upper half of the register unused, so we don't destroy any value here.
              */
-            if (masm.supports(CPUFeature.AVX)) {
+            if (masm.supports(CPUFeature.AVX) && crb.needsClearUpperVectorRegisters()) {
+                // If we decide to perform vzeroupper also for stubs (like what JDK9+ C2 does for
+                // intrinsics that employ AVX2 instruction), we need to be careful that it kills all
+                // the xmm registers (at least the upper halves).
                 masm.vzeroupper();
             }
         }
         masm.ret(0);
     }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu Nov 14 12:21:00 2019 -0800
@@ -158,11 +158,15 @@
     private static Collection<String> add(Collection<String> c, String... elements) {
         String[] sorted = elements.clone();
         Arrays.sort(sorted);
-        for (int i = 0; i < elements.length; i++) {
-            if (!elements[i].equals(sorted[i])) {
-                // Let's keep the list sorted for easier visual inspection
-                fail("Element %d is out of order, \"%s\"", i, elements[i]);
+        if (!Arrays.equals(elements, sorted)) {
+            int width = 2 + Arrays.asList(elements).stream().map(String::length).reduce(0, Integer::max);
+            Formatter fmt = new Formatter();
+            fmt.format("%-" + width + "s | sorted%n", "original");
+            fmt.format("%s%n", new String(new char[width * 2 + 2]).replace('\0', '='));
+            for (int i = 0; i < elements.length; i++) {
+                fmt.format("%-" + width + "s | %s%n", elements[i], sorted[i]);
             }
+            fail("Elements not sorted alphabetically:%n%s", fmt);
         }
         c.addAll(Arrays.asList(elements));
         return c;
@@ -517,8 +521,8 @@
         // AES intrinsics
         if (!config.useAESIntrinsics) {
             add(ignore,
+                            "com/sun/crypto/provider/AESCrypt." + aesDecryptName + "([BI[BI)V",
                             "com/sun/crypto/provider/AESCrypt." + aesEncryptName + "([BI[BI)V",
-                            "com/sun/crypto/provider/AESCrypt." + aesDecryptName + "([BI[BI)V",
                             "com/sun/crypto/provider/CipherBlockChaining." + cbcDecryptName + "([BII[BI)I",
                             "com/sun/crypto/provider/CipherBlockChaining." + cbcEncryptName + "([BII[BI)I");
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Thu Nov 14 12:21:00 2019 -0800
@@ -122,6 +122,12 @@
     public void testVMCompilation3() throws IOException, InterruptedException {
         assumeManagementLibraryIsLoadable();
         final int maxProblems = 2;
+        Probe failurePatternProbe = new Probe("[[[Graal compilation failure]]]", maxProblems) {
+            @Override
+            String test() {
+                return actualOccurrences > 0 && actualOccurrences <= maxProblems ? null : String.format("expected occurrences to be in [1 .. %d]", maxProblems);
+            }
+        };
         Probe retryingProbe = new Probe("Retrying compilation of", maxProblems) {
             @Override
             String test() {
@@ -140,6 +146,7 @@
             }
         };
         Probe[] probes = {
+                        failurePatternProbe,
                         retryingProbe,
                         adjustmentProbe
         };
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Thu Nov 14 12:21:00 2019 -0800
@@ -66,7 +66,7 @@
                         excludeMethodFilters,
                         verbose,
                         harnessOptions,
-                        new OptionValues(initialOptions, HighTier.Options.Inline, false));
+                        new OptionValues(initialOptions, HighTier.Options.Inline, false, CompilationFailureAction, ExceptionAction.Silent));
         ctw.compile();
         assert CompilationBailoutAsFailure.getValue(initialOptions) == originalBailoutAction;
         assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Nov 14 12:21:00 2019 -0800
@@ -111,6 +111,8 @@
     public final boolean useVectorizedMismatchIntrinsic = getFlag("UseVectorizedMismatchIntrinsic", Boolean.class, false);
     public final boolean useFMAIntrinsics = getFlag("UseFMA", Boolean.class, false);
 
+    public final boolean preserveFramePointer = getFlag("PreserveFramePointer", Boolean.class, false);
+
     /*
      * These are methods because in some JDKs the flags are visible but the stubs themselves haven't
      * been exported so we have to check both if the flag is on and if we have the stub.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java	Thu Nov 14 12:21:00 2019 -0800
@@ -304,4 +304,9 @@
     public String getSymbol() {
         return stub == null ? null : stub.toString();
     }
+
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return isCompiledStub() && mayContainFP();
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/JVMCIVersionCheck.java	Thu Nov 14 12:21:00 2019 -0800
@@ -43,7 +43,7 @@
  */
 public final class JVMCIVersionCheck {
 
-    private static final Version JVMCI8_MIN_VERSION = new Version3(19, 3, 2);
+    private static final Version JVMCI_MIN_VERSION = new Version3(19, 3, 4);
 
     public interface Version {
         boolean isLessThan(Version other);
@@ -145,7 +145,7 @@
         }
     }
 
-    private static void failVersionCheck(Map<String, String> props, boolean exit, String reason, Object... args) {
+    private void failVersionCheck(boolean exit, String reason, Object... args) {
         Formatter errorMessage = new Formatter().format(reason, args);
         String javaHome = props.get("java.home");
         String vmName = props.get("java.vm.name");
@@ -153,10 +153,14 @@
         errorMessage.format("this error or to \"warn\" to emit a warning and continue execution.%n");
         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) {
+        if (javaSpecVersion.compareTo("1.9") < 0) {
             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.");
+            if (javaSpecVersion.compareTo("11") == 0 && vmVersion.contains("-jvmci-")) {
+                errorMessage.format("Download the latest Labs OpenJDK 11 from https://github.com/graalvm/labs-openjdk-11/releases");
+            } else {
+                errorMessage.format("Download JDK 11 or later.");
+            }
         }
         String value = System.getenv("JVMCI_VERSION_CHECK");
         if ("warn".equals(value)) {
@@ -183,7 +187,7 @@
 
     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_VERSION);
+        checker.run(exitOnFailure, JVMCI_MIN_VERSION);
     }
 
     /**
@@ -202,14 +206,14 @@
             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);
+                    failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion);
                 }
                 return;
             }
-            failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
+            failVersionCheck(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);
         } else if (javaSpecVersion.compareTo("11") < 0) {
-            failVersionCheck(props, exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n");
+            failVersionCheck(exitOnFailure, "Graal is not compatible with the JVMCI API in JDK 9 and 10.%n");
         } else {
             if (vmVersion.contains("SNAPSHOT")) {
                 return;
@@ -218,28 +222,16 @@
                 // Allow local builds
                 return;
             }
-            if (vmVersion.startsWith("11-ea+")) {
-                String buildString = vmVersion.substring("11-ea+".length());
-                try {
-                    int build = Integer.parseInt(buildString);
-                    if (build < 20) {
-                        failVersionCheck(props, exitOnFailure, "Graal requires build 20 or later of JDK 11 early access binary, got build %d.%n", build);
-                        return;
-                    }
-                } catch (NumberFormatException e) {
-                    failVersionCheck(props, exitOnFailure, "Could not parse the JDK 11 early access build number from java.vm.version property: %s.%n", vmVersion);
-                    return;
-                }
-            } else if (vmVersion.contains("-jvmci-")) {
+            if (vmVersion.contains("-jvmci-")) {
                 // A "labsjdk"
                 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);
+                        failVersionCheck(exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal: %s < %s.%n", v, minVersion);
                     }
                     return;
                 }
-                failVersionCheck(props, exitOnFailure, "The VM does not support the minimum JVMCI API version required by Graal.%n" +
+                failVersionCheck(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);
             } else {
                 // Graal is compatible with all JDK versions as of 11 GA.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Nov 14 12:21:00 2019 -0800
@@ -35,9 +35,11 @@
 import java.lang.invoke.MutableCallSite;
 import java.lang.invoke.VolatileCallSite;
 import java.lang.reflect.Array;
+import java.lang.reflect.Type;
 import java.math.BigInteger;
 import java.util.zip.CRC32;
 
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
@@ -115,6 +117,7 @@
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MetaAccessProvider;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.services.Services;
 import sun.misc.Unsafe;
 
 /**
@@ -461,21 +464,29 @@
     }
 
     public static String lookupIntrinsicName(GraalHotSpotVMConfig config, String className, String name1, String name2) {
+        return selectIntrinsicName(config, className, name1, name2).getLeft();
+    }
+
+    /**
+     * Returns a pair of Strings where the left one represents the matched intrinsic name and the
+     * right one represents the mismatched intrinsic name.
+     */
+    public static Pair<String, String> selectIntrinsicName(GraalHotSpotVMConfig config, String className, String name1, String name2) {
         boolean foundName1 = false;
         boolean foundName2 = false;
-        String name = name1;
         for (VMIntrinsicMethod intrinsic : config.getStore().getIntrinsics()) {
             if (className.equals(intrinsic.declaringClass)) {
                 if (name1.equals(intrinsic.name)) {
                     foundName1 = true;
                 } else if (name2.equals(intrinsic.name)) {
                     foundName2 = true;
-                    name = name2;
                 }
             }
         }
-        if (foundName1 != foundName2) {
-            return name;
+        if (foundName1 && !foundName2) {
+            return Pair.create(name1, name2);
+        } else if (foundName2 && !foundName1) {
+            return Pair.create(name2, name1);
         }
         throw GraalError.shouldNotReachHere();
     }
@@ -500,19 +511,41 @@
             String arch = config.osArch;
             String decryptSuffix = arch.equals("sparc") ? "WithOriginalKey" : "";
 
-            String cbcEncryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implEncrypt", "encrypt");
-            String cbcDecryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implDecrypt", "decrypt");
             Registration r = new Registration(plugins, "com.sun.crypto.provider.CipherBlockChaining", replacements);
-            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);
 
-            String aesEncryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implEncryptBlock", "encryptBlock");
-            String aesDecryptName = lookupIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implDecryptBlock", "decryptBlock");
+            Pair<String, String> cbcEncryptName = selectIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implEncrypt", "encrypt");
+            registerAndCheckMismatch(r, CipherBlockChainingSubstitutions.class, cbcEncryptName, Receiver.class, byte[].class, int.class, int.class,
+                            byte[].class, int.class);
+
+            Pair<String, String> cbcDecryptName = selectIntrinsicName(config, "com/sun/crypto/provider/CipherBlockChaining", "implDecrypt", "decrypt");
+            registerAndCheckMismatch(r, CipherBlockChainingSubstitutions.class, cbcDecryptName, cbcDecryptName.getLeft() + decryptSuffix, Receiver.class, byte[].class, int.class, int.class,
+                            byte[].class, int.class);
 
             r = new Registration(plugins, "com.sun.crypto.provider.AESCrypt", replacements);
-            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);
+
+            Pair<String, String> aesEncryptName = selectIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implEncryptBlock", "encryptBlock");
+            registerAndCheckMismatch(r, AESCryptSubstitutions.class, aesEncryptName, Receiver.class, byte[].class, int.class, byte[].class, int.class);
+
+            Pair<String, String> aesDecryptName = selectIntrinsicName(config, "com/sun/crypto/provider/AESCrypt", "implDecryptBlock", "decryptBlock");
+            registerAndCheckMismatch(r, AESCryptSubstitutions.class, aesDecryptName, aesDecryptName.getLeft() + decryptSuffix, Receiver.class, byte[].class, int.class, byte[].class, int.class);
+        }
+    }
+
+    private static void registerAndCheckMismatch(Registration r, Class<?> substitutionClass, Pair<String, String> intrinsicNames, Type... argumentTypes) {
+        try {
+            r.registerMethodSubstitution(substitutionClass, intrinsicNames.getLeft(), argumentTypes);
+        } catch (NoSuchMethodError e) {
+            throw new GraalError(e, "Found method named '%s' instead of '%s' in class '%s'. This is most likely because the JVMCI JDK in %s was built on an incompatible base JDK.",
+                            intrinsicNames.getRight(), intrinsicNames.getLeft(), r.getDeclaringType().getTypeName(), Services.getSavedProperties().get("java.home"));
+        }
+    }
+
+    private static void registerAndCheckMismatch(Registration r, Class<?> substitutionClass, Pair<String, String> intrinsicNames, String substituteName, Type... argumentTypes) {
+        try {
+            r.registerMethodSubstitution(substitutionClass, intrinsicNames.getLeft(), substituteName, argumentTypes);
+        } catch (NoSuchMethodError e) {
+            throw new GraalError(e, "Found method named '%s' instead of '%s' in class '%s'. This is most likely because the JVMCI JDK in %s was built on an incompatible base JDK.",
+                            intrinsicNames.getRight(), intrinsicNames.getLeft(), r.getDeclaringType().getTypeName(), Services.getSavedProperties().get("java.home"));
         }
     }
 
@@ -544,21 +577,21 @@
             r.registerMethodSubstitution(DigestBaseSubstitutions.class, "implCompressMultiBlock0", Receiver.class, byte[].class, int.class, int.class);
         }
 
-        String implCompressName = lookupIntrinsicName(config, "sun/security/provider/SHA", "implCompress", "implCompress0");
+        Pair<String, String> implCompressName = selectIntrinsicName(config, "sun/security/provider/SHA", "implCompress", "implCompress0");
         if (useSha1) {
             assert config.sha1ImplCompress != 0L;
             Registration r = new Registration(plugins, "sun.security.provider.SHA", replacements);
-            r.registerMethodSubstitution(SHASubstitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class);
+            registerAndCheckMismatch(r, SHASubstitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class);
         }
         if (useSha256) {
             assert config.sha256ImplCompress != 0L;
             Registration r = new Registration(plugins, "sun.security.provider.SHA2", replacements);
-            r.registerMethodSubstitution(SHA2Substitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class);
+            registerAndCheckMismatch(r, SHA2Substitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class);
         }
         if (useSha512) {
             assert config.sha512ImplCompress != 0L;
             Registration r = new Registration(plugins, "sun.security.provider.SHA5", replacements);
-            r.registerMethodSubstitution(SHA5Substitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class);
+            registerAndCheckMismatch(r, SHA5Substitutions.class, implCompressName, "implCompress0", Receiver.class, byte[].class, int.class);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Thu Nov 14 12:21:00 2019 -0800
@@ -27,6 +27,7 @@
 import static java.util.Collections.singletonList;
 import static org.graalvm.compiler.core.GraalCompiler.emitFrontEnd;
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
+import static org.graalvm.compiler.core.common.GraalOptions.RegisterPressure;
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 import static org.graalvm.compiler.debug.DebugOptions.DebugStubsAndSnippets;
 import static org.graalvm.compiler.hotspot.HotSpotHostBackend.UNCOMMON_TRAP_HANDLER;
@@ -76,7 +77,7 @@
 
 /**
  * Base class for implementing some low level code providing the out-of-line slow path for a snippet
- * and/or a callee saved call to a HotSpot C/C++ runtime function or even a another compiled Java
+ * and/or a callee saved call to a HotSpot C/C++ runtime function or even another compiled Java
  * method.
  */
 public abstract class Stub {
@@ -135,7 +136,9 @@
      */
     public Stub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
         this.linkage = linkage;
-        this.options = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options));
+        // The RegisterPressure flag can be ignored by a compilation that runs out of registers, so
+        // the stub compilation must ignore the flag so that all allocatable registers are saved.
+        this.options = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options), RegisterPressure, null);
         this.providers = providers;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -579,4 +579,9 @@
             masm.movzwl(elem2, new AMD64Address(str2, index, scale2, 0));
         }
     }
+
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return true;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayEqualsOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -864,4 +864,9 @@
                 throw new IllegalStateException();
         }
     }
+
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return true;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayIndexOfOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -644,4 +644,9 @@
     private static boolean supports(LIRGeneratorTool tool, CPUFeature cpuFeature) {
         return ((AMD64) tool.target().arch).getFeatures().contains(cpuFeature);
     }
+
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return true;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Call.java	Thu Nov 14 12:21:00 2019 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -152,6 +152,11 @@
         public boolean destroysCallerSavedRegisters() {
             return callTarget.destroysRegisters();
         }
+
+        @Override
+        public boolean needsClearUpperVectorRegisters() {
+            return callTarget.needsClearUpperVectorRegisters();
+        }
     }
 
     @Opcode("NEAR_FOREIGN_CALL")
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64FrameMap.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -78,17 +78,15 @@
  */
 public class AMD64FrameMap extends FrameMap {
 
+    private final boolean useStandardFrameProlog;
     private StackSlot rbpSpillSlot;
 
-    public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory) {
-        this(codeCache, registerConfig, referenceMapFactory, false);
-    }
-
-    public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory, boolean useBasePointer) {
+    public AMD64FrameMap(CodeCacheProvider codeCache, RegisterConfig registerConfig, ReferenceMapBuilderFactory referenceMapFactory, boolean useStandardFrameProlog) {
         super(codeCache, registerConfig, referenceMapFactory);
         // (negative) offset relative to sp + total frame size
-        initialSpillSize = returnAddressSize() + (useBasePointer ? getTarget().arch.getWordSize() : 0);
-        spillSize = initialSpillSize;
+        this.useStandardFrameProlog = useStandardFrameProlog;
+        this.initialSpillSize = returnAddressSize() + (useStandardFrameProlog ? getTarget().arch.getWordSize() : 0);
+        this.spillSize = initialSpillSize;
     }
 
     @Override
@@ -141,4 +139,8 @@
                         spillSlotSize(LIRKind.value(AMD64Kind.QWORD)) : "Deoptimization rescue slot must be the first or second (if there is an RBP spill slot) stack slot";
         return allocateSpillSlot(LIRKind.value(AMD64Kind.QWORD));
     }
+
+    public boolean useStandardFrameProlog() {
+        return useStandardFrameProlog;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringLatin1InflateOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringLatin1InflateOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -275,4 +275,8 @@
         masm.bind(labelDone);
     }
 
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return true;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringUTF16CompressOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64StringUTF16CompressOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -340,4 +340,8 @@
         masm.bind(labelDone);
     }
 
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return true;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Ternary.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Ternary.java	Thu Nov 14 12:21:00 2019 -0800
@@ -37,6 +37,7 @@
 import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.amd64.vector.AMD64VectorInstruction;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
 import jdk.vm.ci.meta.AllocatableValue;
@@ -49,11 +50,10 @@
     /**
      * Instruction that has two {@link AllocatableValue} operands.
      */
-    public static class ThreeOp extends AMD64LIRInstruction {
+    public static class ThreeOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<ThreeOp> TYPE = LIRInstructionClass.create(ThreeOp.class);
 
         @Opcode private final VexRVMOp opcode;
-        private final AVXSize size;
 
         @Def({REG, HINT}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue x;
@@ -65,10 +65,8 @@
         @Alive({REG, STACK}) protected AllocatableValue z;
 
         public ThreeOp(VexRVMOp opcode, AVXSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y, AllocatableValue z) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
-
             this.result = result;
             this.x = x;
             this.y = y;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64VZeroUpper.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64VZeroUpper.java	Thu Nov 14 12:21:00 2019 -0800
@@ -32,6 +32,8 @@
 
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.amd64.AMD64Call.ForeignCallOp;
+import org.graalvm.compiler.lir.amd64.vector.AMD64VectorInstruction;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
 import jdk.vm.ci.amd64.AMD64;
@@ -40,6 +42,48 @@
 import jdk.vm.ci.code.RegisterValue;
 import jdk.vm.ci.meta.Value;
 
+/**
+ * vzeroupper is essential to avoid performance penalty during SSE-AVX transition. Specifically,
+ * once we have executed instructions that modify the upper bits (i.e., 128+) of the YMM registers,
+ * we need to perform vzeroupper to transit the state to 128bits before executing any SSE
+ * instructions. We don't need to place vzeroupper between VEX-encoded SSE instructions and legacy
+ * SSE instructions, nor between AVX instructions and VEX-encoded SSE instructions.
+ *
+ * When running Graal on HotSpot, we emit a vzeroupper LIR operation (i.e. an instance of this
+ * class) before a foreign call to the runtime function where Graal has no knowledge. The underlying
+ * reason is that HotSpot is SSE-compiled so as to support older CPUs. We also emit a vzeroupper
+ * instruction (see {@code AMD64HotSpotReturnOp.emitCode}) upon returning, if the current LIR graph
+ * contains LIR operations that touch the upper bits of the YMM registers, including but not limited
+ * to {@link AMD64VectorInstruction}, {@link AMD64ArrayCompareToOp}, {@link AMD64ArrayEqualsOp},
+ * {@link AMD64ArrayIndexOfOp}, and {@link ForeignCallOp} that invokes to Graal-compiled stubs. For
+ * the last case, since Graal-compiled stubs is under our control, we don't emit vzeroupper upon
+ * returning of the stub, but rather do that upon returning of the current method.
+ *
+ * On JDK8, C2 does not emit many vzeroupper instructions, potentially because that YMM registers
+ * are not heavily employed (C2 vectorization starts using YMM registers in 9, source
+ * https://cr.openjdk.java.net/~vlivanov/talks/2017_Vectorization_in_HotSpot_JVM.pdf) and thus less
+ * care has been taken to place these instructions. One example is that many intrinsics employ YMM
+ * registers starting from https://bugs.openjdk.java.net/browse/JDK-8005419, but does not properly
+ * place vzeroupper upon returning of the intrinsic stub or the caller of the stub.
+ *
+ * Most vzeroupper were added in JDK 10 (https://bugs.openjdk.java.net/browse/JDK-8178811), and was
+ * later restricted on Haswell Xeon due to performance regression
+ * (https://bugs.openjdk.java.net/browse/JDK-8190934). The actual condition for placing vzeroupper
+ * is at http://hg.openjdk.java.net/jdk/jdk/file/c7d9df2e470c/src/hotspot/cpu/x86/x86_64.ad#l428. To
+ * summarize, if nmethod employs YMM registers (or intrinsics which use them, search for
+ * clear_upper_avx() in opto/library_call.cpp) vzeroupper will be generated on nmethod's exit and
+ * before any calls in nmethod, because even compiled nmethods can still use only SSE instructions.
+ *
+ * This means, if a Java method performs a call to an intrinsic that employs YMM registers,
+ * C2-compiled code will place a vzeroupper before the call, upon exit of the stub and upon exit of
+ * this method. Graal will only place the last, because it ensures that Graal-compiled Java method
+ * and stubs will be consistent on using VEX-encoding.
+ *
+ * In SubstrateVM, since the whole image is compiled consistently with or without VEX encoding (the
+ * later is the default behavior, see {@code NativeImageGenerator.createTarget}), there is no need
+ * for vzeroupper. For dynamic compilation on a SubstrateVM image, if the image is SSE-compiled, we
+ * then need vzeroupper when returning from the dynamic compiled code to the pre-built image code.
+ */
 public class AMD64VZeroUpper extends AMD64LIRInstruction {
 
     public static final LIRInstructionClass<AMD64VZeroUpper> TYPE = LIRInstructionClass.create(AMD64VZeroUpper.class);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorBinary.java	Thu Nov 14 12:21:00 2019 -0800
@@ -40,7 +40,6 @@
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
-import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
 import jdk.vm.ci.amd64.AMD64Kind;
@@ -48,20 +47,18 @@
 
 public class AMD64VectorBinary {
 
-    public static final class AVXBinaryOp extends AMD64LIRInstruction {
+    public static final class AVXBinaryOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<AVXBinaryOp> TYPE = LIRInstructionClass.create(AVXBinaryOp.class);
 
         @Opcode private final VexRVMOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue x;
         @Use({REG, STACK}) protected AllocatableValue y;
 
         public AVXBinaryOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.x = x;
             this.y = y;
@@ -77,22 +74,20 @@
         }
     }
 
-    public static final class AVXBinaryConstOp extends AMD64LIRInstruction {
+    public static final class AVXBinaryConstOp extends AMD64VectorInstruction {
 
         public static final LIRInstructionClass<AVXBinaryConstOp> TYPE = LIRInstructionClass.create(AVXBinaryConstOp.class);
 
         @Opcode private final VexRRIOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue x;
         protected int y;
 
         public AVXBinaryConstOp(VexRRIOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, int y) {
-            super(TYPE);
+            super(TYPE, size);
             assert (y & 0xFF) == y;
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.x = x;
             this.y = y;
@@ -104,22 +99,20 @@
         }
     }
 
-    public static final class AVXBinaryConstFloatOp extends AMD64LIRInstruction {
+    public static final class AVXBinaryConstFloatOp extends AMD64VectorInstruction {
 
         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);
+            super(TYPE, size);
             assert y.getPlatformKind() == AMD64Kind.SINGLE || y.getPlatformKind() == AMD64Kind.DOUBLE;
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.x = x;
             this.y = y;
@@ -136,11 +129,10 @@
         }
     }
 
-    public static final class AVXBinaryMemoryOp extends AMD64LIRInstruction {
+    public static final class AVXBinaryMemoryOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<AVXBinaryMemoryOp> TYPE = LIRInstructionClass.create(AVXBinaryMemoryOp.class);
 
         @Opcode private final VexRVMOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({REG}) protected AllocatableValue x;
@@ -148,9 +140,8 @@
         @State protected LIRFrameState state;
 
         public AVXBinaryMemoryOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue x, AMD64AddressValue y, LIRFrameState state) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.x = x;
             this.y = y;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorCompareOp.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorCompareOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -35,16 +35,14 @@
 import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
-import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
 
 import jdk.vm.ci.meta.AllocatableValue;
 
-public final class AMD64VectorCompareOp extends AMD64LIRInstruction {
+public final class AMD64VectorCompareOp extends AMD64VectorInstruction {
     public static final LIRInstructionClass<AMD64VectorCompareOp> TYPE = LIRInstructionClass.create(AMD64VectorCompareOp.class);
 
     @Opcode private final VexRMOp opcode;
-    private final AVXSize size;
     @Use({REG}) protected AllocatableValue x;
     @Use({REG, STACK}) protected AllocatableValue y;
 
@@ -53,9 +51,8 @@
     }
 
     public AMD64VectorCompareOp(VexRMOp opcode, AVXSize size, AllocatableValue x, AllocatableValue y) {
-        super(TYPE);
+        super(TYPE, size);
         this.opcode = opcode;
-        this.size = size;
         this.x = x;
         this.y = y;
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorFloatCompareOp.java	Thu Nov 14 12:21:00 2019 -0800
@@ -0,0 +1,72 @@
+/*
+ * 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.lir.amd64.vector;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static jdk.vm.ci.code.ValueUtil.isRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.STACK;
+
+import org.graalvm.compiler.asm.amd64.AMD64Address;
+import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.VexFloatCompareOp;
+import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.meta.AllocatableValue;
+
+public class AMD64VectorFloatCompareOp extends AMD64LIRInstruction {
+    public static final LIRInstructionClass<AMD64VectorFloatCompareOp> TYPE = LIRInstructionClass.create(AMD64VectorFloatCompareOp.class);
+
+    @Opcode private final VexFloatCompareOp opcode;
+    private final AVXSize size;
+    @Def({REG}) protected AllocatableValue result;
+    @Use({REG}) protected AllocatableValue x;
+    @Use({REG, STACK}) protected AllocatableValue y;
+    private final VexFloatCompareOp.Predicate predicate;
+
+    public AMD64VectorFloatCompareOp(VexFloatCompareOp opcode, AVXSize size, AllocatableValue result, AllocatableValue x, AllocatableValue y, VexFloatCompareOp.Predicate predicate) {
+        super(TYPE);
+        this.opcode = opcode;
+        this.size = size;
+        this.result = result;
+        this.x = x;
+        this.y = y;
+        this.predicate = predicate;
+    }
+
+    @Override
+    public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+        if (isRegister(y)) {
+            opcode.emit(masm, size, asRegister(result), asRegister(x), asRegister(y), predicate);
+        } else {
+            opcode.emit(masm, size, asRegister(result), asRegister(x), (AMD64Address) crb.asAddress(y), predicate);
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorInstruction.java	Thu Nov 14 12:21:00 2019 -0800
@@ -0,0 +1,46 @@
+/*
+ * 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.lir.amd64.vector;
+
+import org.graalvm.compiler.asm.amd64.AVXKind.AVXSize;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
+
+public abstract class AMD64VectorInstruction extends AMD64LIRInstruction {
+
+    public static final LIRInstructionClass<AMD64VectorInstruction> TYPE = LIRInstructionClass.create(AMD64VectorInstruction.class);
+    protected final AVXSize size;
+
+    public AMD64VectorInstruction(LIRInstructionClass<? extends AMD64VectorInstruction> c, AVXSize size) {
+        super(c);
+        this.size = size;
+    }
+
+    @Override
+    public boolean needsClearUpperVectorRegisters() {
+        return size == AVXSize.YMM || size == AVXSize.ZMM;
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorMove.java	Thu Nov 14 12:21:00 2019 -0800
@@ -203,17 +203,15 @@
         }
     }
 
-    public abstract static class VectorMemOp extends AMD64LIRInstruction {
+    public abstract static class VectorMemOp extends AMD64VectorInstruction {
 
-        protected final AVXSize size;
         protected final VexMoveOp op;
 
         @Use({COMPOSITE}) protected AMD64AddressValue address;
         @State protected LIRFrameState state;
 
         protected VectorMemOp(LIRInstructionClass<? extends VectorMemOp> c, AVXSize size, VexMoveOp op, AMD64AddressValue address, LIRFrameState state) {
-            super(c);
-            this.size = size;
+            super(c, size);
             this.op = op;
             this.address = address;
             this.state = state;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorUnary.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/vector/AMD64VectorUnary.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -50,19 +50,17 @@
 
 public class AMD64VectorUnary {
 
-    public static final class AVXUnaryOp extends AMD64LIRInstruction {
+    public static final class AVXUnaryOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<AVXUnaryOp> TYPE = LIRInstructionClass.create(AVXUnaryOp.class);
 
         @Opcode private final VexRMOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({REG, STACK}) protected AllocatableValue input;
 
         public AVXUnaryOp(VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AllocatableValue input) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.input = input;
         }
@@ -77,20 +75,18 @@
         }
     }
 
-    public static final class AVXUnaryMemoryOp extends AMD64LIRInstruction {
+    public static final class AVXUnaryMemoryOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<AVXUnaryMemoryOp> TYPE = LIRInstructionClass.create(AVXUnaryMemoryOp.class);
 
         @Opcode private final VexRMOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({COMPOSITE}) protected AMD64AddressValue input;
         @State protected LIRFrameState state;
 
         public AVXUnaryMemoryOp(VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.input = input;
             this.state = state;
@@ -105,19 +101,17 @@
         }
     }
 
-    public static final class AVXBroadcastOp extends AMD64LIRInstruction {
+    public static final class AVXBroadcastOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<AVXBroadcastOp> TYPE = LIRInstructionClass.create(AVXBroadcastOp.class);
 
         @Opcode private final VexRMOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({REG, STACK, CONST}) protected Value input;
 
         public AVXBroadcastOp(VexRMOp opcode, AVXKind.AVXSize size, AllocatableValue result, Value input) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.input = input;
         }
@@ -136,20 +130,18 @@
         }
     }
 
-    public static final class AVXConvertMemoryOp extends AMD64LIRInstruction {
+    public static final class AVXConvertMemoryOp extends AMD64VectorInstruction {
         public static final LIRInstructionClass<AVXConvertMemoryOp> TYPE = LIRInstructionClass.create(AVXConvertMemoryOp.class);
 
         @Opcode private final VexRVMOp opcode;
-        private final AVXKind.AVXSize size;
 
         @Def({REG}) protected AllocatableValue result;
         @Use({COMPOSITE}) protected AMD64AddressValue input;
         @State protected LIRFrameState state;
 
         public AVXConvertMemoryOp(VexRVMOp opcode, AVXKind.AVXSize size, AllocatableValue result, AMD64AddressValue input, LIRFrameState state) {
-            super(TYPE);
+            super(TYPE, size);
             this.opcode = opcode;
-            this.size = size;
             this.result = result;
             this.input = input;
             this.state = state;
@@ -180,6 +172,8 @@
 
         @Override
         public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) {
+            // Note that we assume only XMM-size instructions are emitted here. Loosening this
+            // restriction would require informing AMD64HotSpotReturnOp when emitting vzeroupper.
             if (isRegister(input)) {
                 if (!asRegister(input).equals(asRegister(result))) {
                     // clear result register to avoid unnecessary dependency
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java	Thu Nov 14 12:21:00 2019 -0800
@@ -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
@@ -458,4 +458,8 @@
     public int hashCode() {
         return id;
     }
+
+    public boolean needsClearUpperVectorRegisters() {
+        return false;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Thu Nov 14 12:21:00 2019 -0800
@@ -692,4 +692,18 @@
     public void setConservativeLabelRanges() {
         this.conservativeLabelOffsets = true;
     }
+
+    public final boolean needsClearUpperVectorRegisters() {
+        for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
+            if (block == null) {
+                continue;
+            }
+            for (LIRInstruction op : lir.getLIRforBlock(block)) {
+                if (op.needsClearUpperVectorRegisters()) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/calc/CompareNode.java	Thu Nov 14 12:21:00 2019 -0800
@@ -354,4 +354,24 @@
 
         return comparison;
     }
+
+    public static LogicNode createFloatCompareNode(StructuredGraph graph, CanonicalCondition condition, ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) {
+        LogicNode result = createFloatCompareNode(condition, x, y, unorderedIsTrue, view);
+        return (result.graph() == null ? graph.addOrUniqueWithInputs(result) : result);
+    }
+
+    public static LogicNode createFloatCompareNode(CanonicalCondition condition, ValueNode x, ValueNode y, boolean unorderedIsTrue, NodeView view) {
+        assert x.getStackKind() == y.getStackKind();
+        assert x.getStackKind().isNumericFloat();
+
+        LogicNode comparison;
+        if (condition == CanonicalCondition.EQ) {
+            comparison = FloatEqualsNode.create(x, y, view);
+        } else {
+            assert condition == CanonicalCondition.LT;
+            comparison = FloatLessThanNode.create(x, y, unorderedIsTrue, view);
+        }
+
+        return comparison;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Thu Nov 14 12:21:00 2019 -0800
@@ -1401,7 +1401,7 @@
             if (declaringType instanceof ResolvedJavaSymbol) {
                 return checkResolvable(isOptional, ((ResolvedJavaSymbol) declaringType).getResolved(), binding);
             }
-            Class<?> declaringClass = InvocationPlugins.resolveType(declaringType, isOptional);
+            Class<?> declaringClass = resolveType(declaringType, isOptional);
             if (declaringClass == null) {
                 return true;
             }
@@ -1411,7 +1411,7 @@
                 }
             } else {
                 if (resolveMethod(declaringClass, binding) == null && !isOptional) {
-                    throw new AssertionError(String.format("Method not found: %s.%s%s", declaringClass.getName(), binding.name, binding.argumentsDescriptor));
+                    throw new NoSuchMethodError(String.format("%s.%s%s", declaringClass.getName(), binding.name, binding.argumentsDescriptor));
                 }
             }
             return true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java	Thu Nov 14 12:21:00 2019 -0800
@@ -132,12 +132,19 @@
             throw new IllegalArgumentException(msg.toString());
         }
 
+        Object value = parseOptionValue(desc, uncheckedValue);
+
+        desc.getOptionKey().update(values, value);
+    }
+
+    /** Parses a given option value with a known descriptor. */
+    public static Object parseOptionValue(OptionDescriptor desc, Object uncheckedValue) {
         Class<?> optionType = desc.getOptionValueType();
         Object value;
         if (!(uncheckedValue instanceof String)) {
             if (optionType != uncheckedValue.getClass()) {
                 String type = optionType.getSimpleName();
-                throw new IllegalArgumentException(type + " option '" + name + "' must have " + type + " value, not " + uncheckedValue.getClass() + " [toString: " + uncheckedValue + "]");
+                throw new IllegalArgumentException(type + " option '" + desc.getName() + "' must have " + type + " value, not " + uncheckedValue.getClass() + " [toString: " + uncheckedValue + "]");
             }
             value = uncheckedValue;
         } else {
@@ -148,7 +155,7 @@
                 } else if ("false".equals(valueString)) {
                     value = Boolean.FALSE;
                 } else {
-                    throw new IllegalArgumentException("Boolean option '" + name + "' must have value \"true\" or \"false\", not \"" + uncheckedValue + "\"");
+                    throw new IllegalArgumentException("Boolean option '" + desc.getName() + "' must have value \"true\" or \"false\", not \"" + uncheckedValue + "\"");
                 }
             } else if (optionType == String.class) {
                 value = valueString;
@@ -156,7 +163,7 @@
                 value = ((EnumOptionKey<?>) desc.getOptionKey()).valueOf(valueString);
             } else {
                 if (valueString.isEmpty()) {
-                    throw new IllegalArgumentException("Non empty value required for option '" + name + "'");
+                    throw new IllegalArgumentException("Non empty value required for option '" + desc.getName() + "'");
                 }
                 try {
                     if (optionType == Float.class) {
@@ -168,15 +175,14 @@
                     } else if (optionType == Long.class) {
                         value = Long.valueOf(parseLong(valueString));
                     } else {
-                        throw new IllegalArgumentException("Wrong value for option '" + name + "'");
+                        throw new IllegalArgumentException("Wrong value for option '" + desc.getName() + "'");
                     }
                 } catch (NumberFormatException nfe) {
-                    throw new IllegalArgumentException("Value for option '" + name + "' has invalid number format: " + valueString);
+                    throw new IllegalArgumentException("Value for option '" + desc.getName() + "' has invalid number format: " + valueString);
                 }
             }
         }
-
-        desc.getOptionKey().update(values, value);
+        return value;
     }
 
     private static long parseLong(String v) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java	Thu Nov 14 12:21:00 2019 -0800
@@ -1107,11 +1107,20 @@
 
         @Override
         public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset) {
+            // Opaque mode does not directly impose any ordering constraints with respect to other
+            // variables beyond Plain mode.
+            if (accessKind == AccessKind.OPAQUE && StampTool.isPointerAlwaysNull(object)) {
+                // OFF_HEAP_LOCATION accesses are not floatable => no membars needed for opaque.
+                return apply(b, targetMethod, unsafe, offset);
+            }
             // Emits a null-check for the otherwise unused receiver
             unsafe.get();
             if (accessKind.emitBarriers) {
                 b.add(new MembarNode(accessKind.preReadBarriers));
             }
+            // Raw accesses can be turned into floatable field accesses, the membars preserve the
+            // access mode. In the case of opaque access, and only for opaque, the location of the
+            // wrapping membars can be refined to the field location.
             createUnsafeAccess(object, b, (obj, loc) -> new RawLoadNode(obj, offset, unsafeAccessKind, loc));
             if (accessKind.emitBarriers) {
                 b.add(new MembarNode(accessKind.postReadBarriers));
@@ -1144,12 +1153,21 @@
 
         @Override
         public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) {
+            // Opaque mode does not directly impose any ordering constraints with respect to other
+            // variables beyond Plain mode.
+            if (accessKind == AccessKind.OPAQUE && StampTool.isPointerAlwaysNull(object)) {
+                // OFF_HEAP_LOCATION accesses are not floatable => no membars needed for opaque.
+                return apply(b, targetMethod, unsafe, offset, value);
+            }
             // Emits a null-check for the otherwise unused receiver
             unsafe.get();
             if (accessKind.emitBarriers) {
                 b.add(new MembarNode(accessKind.preWriteBarriers));
             }
             ValueNode maskedValue = b.maskSubWordValue(value, unsafeAccessKind);
+            // Raw accesses can be turned into floatable field accesses, the membars preserve the
+            // access mode. In the case of opaque access, and only for opaque, the location of the
+            // wrapping membars can be refined to the field location.
             createUnsafeAccess(object, b, (obj, loc) -> new RawStoreNode(obj, offset, maskedValue, unsafeAccessKind, loc));
             if (accessKind.emitBarriers) {
                 b.add(new MembarNode(accessKind.postWriteBarriers));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java	Thu Nov 14 11:16:14 2019 -0800
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MethodHandleNode.java	Thu Nov 14 12:21:00 2019 -0800
@@ -259,7 +259,7 @@
 
         Assumptions assumptions = adder.getAssumptions();
         ResolvedJavaMethod realTarget = null;
-        if (target.canBeStaticallyBound()) {
+        if (target.canBeStaticallyBound() || intrinsicMethod == IntrinsicMethod.LINK_TO_SPECIAL) {
             realTarget = target;
         } else {
             ResolvedJavaType targetType = target.getDeclaringClass();