changeset 46368:da05330bbc7b

Merge
author iignatyev
date Thu, 06 Apr 2017 21:14:07 +0000
parents 6e532778cb35 b9a1aa504eb5
children 7a0ae73888ff
files hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/DefaultCollectionsProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArrayMap.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ArraySet.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ConditionalEliminationLoadFieldConstantFoldTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GuardEliminationCornerCasesTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/RecursiveInliningTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/DefaultNodeCollectionsProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeCollectionsProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeNodeMap.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64DeoptimizationStub.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotEnterUnpackFramesStackFrameOp.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotLeaveUnpackFramesStackFrameOp.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64UncommonTrapStub.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCDeoptimizationStub.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotEnterUnpackFramesStackFrameOp.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotLeaveUnpackFramesStackFrameOp.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCUncommonTrapStub.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompressEncoding.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOption.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DeoptimizationFetchUnrollInfoCallNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/DirectCompareAndSwapNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EnterUnpackFramesStackFrameNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveCurrentStackFrameNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveDeoptimizedStackFrameNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/LeaveUnpackFramesStackFrameNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/PushInterpreterFrameNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SaveAllRegistersNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetAnchorNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/SnippetLocationProxyNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/UncommonTrapCallNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/DeoptimizationStub.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UncommonTrapStub.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/FastSSIBuilder.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIBuilder.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIBuilderBase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIConstructionPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIUtil.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/ssi/SSIVerifier.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationBeginNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationEndNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationInliningCallback.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/InstrumentationNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/IsMethodInlinedNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/MonitorProxyNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/instrumentation/RootNameNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeLoadNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeStoreNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/CompareAndSwapNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredCompareAndSwapNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/PiPushable.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionValueTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/DerivedOptionValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/NestedBooleanOptionValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/StableOptionValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/OptimizeGuardAnchorsPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PushThroughPiPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ValueAnchorCleanupPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/ExtractInstrumentationPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/HighTierReconcileInstrumentationPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/InlineInstrumentationPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/instrumentation/MidTierReconcileInstrumentationPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/IntegerMulExactFoldTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/InlineGraalDirectivesPlugin.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/DirectObjectStoreNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/Salver.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/SalverDebugConfigCustomizer.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/SalverOptions.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataDict.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/data/DataList.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractGraalDumper.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractMethodScopeDumper.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/AbstractSerializerDumper.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/Dumper.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/dumper/GraphDumper.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/AbstractDumpHandler.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/AbstractGraalDumpHandler.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/DumpHandler.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/handler/GraphDumpHandler.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/package-info.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/AbstractSerializer.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/JSONSerializer.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/serialize/Serializer.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/util/ECIDUtil.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/util/MethodContext.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/ChannelDumpWriter.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.salver/src/org/graalvm/compiler/salver/writer/DumpWriter.java
diffstat 995 files changed, 28681 insertions(+), 22760 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/.hgtags	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/.hgtags	Thu Apr 06 21:14:07 2017 +0000
@@ -565,3 +565,4 @@
 9211c2e89c1cd11ec2d5752b0f97131a7d7525c7 jdk-9+159
 94b4e2e5331d38eab6a3639c3511b2e0715df0e9 jdk-9+160
 191ffbdb3d7b734288daa7fb76b37a0a85dfe7eb jdk-9+161
+b01c519b715ef6f785d0631adee0a6537cf6c12e jdk-9+162
--- a/hotspot/make/CompileTools.gmk	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/make/CompileTools.gmk	Thu Apr 06 21:14:07 2017 +0000
@@ -47,11 +47,9 @@
   $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \
       SETUP := GENERATE_OLDBYTECODE, \
       SRC := \
-          $(SRC_DIR)/org.graalvm.compiler.common/src \
           $(SRC_DIR)/org.graalvm.compiler.core/src \
           $(SRC_DIR)/org.graalvm.compiler.core.common/src \
           $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \
-          $(SRC_DIR)/org.graalvm.compiler.api.collections/src \
           $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
           $(SRC_DIR)/org.graalvm.compiler.asm/src \
           $(SRC_DIR)/org.graalvm.compiler.bytecode/src \
@@ -68,6 +66,7 @@
           $(SRC_DIR)/org.graalvm.compiler.phases.common/src \
           $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
           $(SRC_DIR)/org.graalvm.compiler.virtual/src \
+          $(SRC_DIR)/org.graalvm.util/src \
           $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
           $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
           $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \
@@ -102,6 +101,7 @@
       SRC := \
           $(SRC_DIR)/org.graalvm.compiler.options/src \
           $(SRC_DIR)/org.graalvm.compiler.options.processor/src \
+          $(SRC_DIR)/org.graalvm.util/src \
           , \
       BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor, \
       JAR := $(BUILDTOOLS_OUTPUTDIR)/jdk.vm.compiler.options.processor.jar, \
@@ -114,9 +114,7 @@
   $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \
       SETUP := GENERATE_OLDBYTECODE, \
       SRC := \
-          $(SRC_DIR)/org.graalvm.compiler.common/src \
           $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \
-          $(SRC_DIR)/org.graalvm.compiler.api.collections/src \
           $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
           $(SRC_DIR)/org.graalvm.compiler.code/src \
           $(SRC_DIR)/org.graalvm.compiler.core.common/src \
@@ -125,6 +123,7 @@
           $(SRC_DIR)/org.graalvm.compiler.nodeinfo/src \
           $(SRC_DIR)/org.graalvm.compiler.options/src \
           $(SRC_DIR)/org.graalvm.compiler.serviceprovider/src \
+          $(SRC_DIR)/org.graalvm.util/src \
           $(VM_CI_SRC_DIR)/jdk.vm.ci.code/src \
           $(VM_CI_SRC_DIR)/jdk.vm.ci.common/src \
           $(VM_CI_SRC_DIR)/jdk.vm.ci.meta/src \
--- a/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/make/gensrc/Gensrc-jdk.internal.vm.compiler.gmk	Thu Apr 06 21:14:07 2017 +0000
@@ -37,7 +37,6 @@
 
 PROC_SRC_SUBDIRS := \
     org.graalvm.compiler.code \
-    org.graalvm.compiler.common \
     org.graalvm.compiler.core \
     org.graalvm.compiler.core.aarch64 \
     org.graalvm.compiler.core.amd64 \
@@ -81,6 +80,7 @@
 PROCESSOR_PATH := $(call PathList, $(PROCESSOR_JARS))
 
 ADD_EXPORTS := \
+    --add-modules jdk.internal.vm.ci \
     --add-exports jdk.internal.vm.ci/jdk.vm.ci.aarch64=ALL-UNNAMED \
     --add-exports jdk.internal.vm.ci/jdk.vm.ci.amd64=ALL-UNNAMED \
     --add-exports jdk.internal.vm.ci/jdk.vm.ci.code=ALL-UNNAMED \
--- a/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/cpu/s390/vm/methodHandles_s390.cpp	Thu Apr 06 21:14:07 2017 +0000
@@ -73,7 +73,7 @@
                                  const char* error_message) {
 
   InstanceKlass** klass_addr = SystemDictionary::well_known_klass_addr(klass_id);
-  KLass* klass = SystemDictionary::well_known_klass(klass_id);
+  Klass* klass = SystemDictionary::well_known_klass(klass_id);
 
   assert(temp_reg != Z_R0 && // Is used as base register!
          temp_reg != noreg && temp2_reg != noreg, "need valid registers!");
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Thu Apr 06 21:14:07 2017 +0000
@@ -40,14 +40,15 @@
 import jdk.tools.jaotc.binformat.pecoff.JPECoffRelocObject;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.options.OptionValues;
 
 /**
  * A format-agnostic container class that holds various components of a binary.
  *
  * <p>
  * This class holds information necessary to create platform-specific binary containers such as
- * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac
- * OS or PEContainer for MS Windows operating systems.
+ * ELFContainer for Linux and Solaris operating systems or MachOContainer for Mac OS or PEContainer
+ * for MS Windows operating systems.
  *
  * <p>
  * Method APIs provided by this class are used to construct and populate platform-independent
@@ -58,6 +59,7 @@
  * Methods to record and access code section contents, symbols and relocations are provided.
  */
 public class BinaryContainer implements SymbolTable {
+    private final OptionValues graalOptions;
 
     private final int codeSegmentSize;
 
@@ -259,8 +261,12 @@
      * Allocates a {@code BinaryContainer} object whose content will be generated in a file with the
      * prefix {@code prefix}. It also initializes internal code container, symbol table and
      * relocation tables.
+     *
+     * @param graalOptions
      */
-    public BinaryContainer(GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
+    public BinaryContainer(OptionValues graalOptions, GraalHotSpotVMConfig graalHotSpotVMConfig, GraphBuilderConfiguration graphBuilderConfig, String jvmVersion) {
+        this.graalOptions = graalOptions;
+
         this.codeSegmentSize = graalHotSpotVMConfig.codeSegmentSize;
         this.codeEntryAlignment = graalHotSpotVMConfig.codeEntryAlignment;
 
@@ -305,17 +311,17 @@
                                    graalHotSpotVMConfig.useCMSGC,
                                    graalHotSpotVMConfig.useTLAB,
                                    graalHotSpotVMConfig.useBiasedLocking,
-                                   TieredAOT.getValue(),
+                                   TieredAOT.getValue(graalOptions),
                                    graalHotSpotVMConfig.enableContended,
                                    graalHotSpotVMConfig.restrictContended,
                                    graphBuilderConfig.omitAssertions()
         };
 
-        int[] intFlags         = { graalHotSpotVMConfig.getOopEncoding().shift,
-                                   graalHotSpotVMConfig.getKlassEncoding().shift,
+        int[] intFlags         = { graalHotSpotVMConfig.getOopEncoding().getShift(),
+                                   graalHotSpotVMConfig.getKlassEncoding().getShift(),
                                    graalHotSpotVMConfig.contendedPaddingWidth,
                                    graalHotSpotVMConfig.fieldsAllocationStyle,
-                                   1 << graalHotSpotVMConfig.getOopEncoding().alignment,
+                                   1 << graalHotSpotVMConfig.logMinObjAlignment(),
                                    graalHotSpotVMConfig.codeSegmentSize,
         };
         // @formatter:on
@@ -511,8 +517,7 @@
                     JPECoffRelocObject pecoffobj = new JPECoffRelocObject(this, outputFileName, aotVersion);
                     pecoffobj.createPECoffRelocObject(relocationTable, symbolTable.values());
                     break;
-                }
-                else
+                } else
                     throw new InternalError("Unsupported platform: " + osName);
         }
     }
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTBackend.java	Thu Apr 06 21:14:07 2017 +0000
@@ -23,17 +23,12 @@
 
 package jdk.tools.jaotc;
 
-import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
-import static org.graalvm.compiler.core.common.GraalOptions.ImmutableCode;
-
 import java.util.ListIterator;
 
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.core.GraalCompiler;
-import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.debug.Debug;
 import org.graalvm.compiler.debug.Debug.Scope;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.HotSpotCompiledCodeBuilder;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -43,8 +38,7 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
-import org.graalvm.compiler.options.OptionValue;
-import org.graalvm.compiler.options.OptionValue.OverrideScope;
+import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.BasePhase;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.PhaseSuite;
@@ -62,6 +56,7 @@
 public class AOTBackend {
 
     private final Main main;
+    private final OptionValues graalOptions;
 
     private final HotSpotBackend backend;
 
@@ -71,8 +66,9 @@
     private final HighTierContext highTierContext;
     private final GraalFilters filters;
 
-    public AOTBackend(Main main, HotSpotBackend backend, GraalFilters filters) {
+    public AOTBackend(Main main, OptionValues graalOptions, HotSpotBackend backend, GraalFilters filters) {
         this.main = main;
+        this.graalOptions = graalOptions;
         this.backend = backend;
         this.filters = filters;
         providers = backend.getProviders();
@@ -87,23 +83,21 @@
 
     private Suites getSuites() {
         // create suites every time, as we modify options for the compiler
-        return backend.getSuites().getDefaultSuites();
+        return backend.getSuites().getDefaultSuites(graalOptions);
     }
 
     private LIRSuites getLirSuites() {
         // create suites every time, as we modify options for the compiler
-        return backend.getSuites().getDefaultLIRSuites();
+        return backend.getSuites().getDefaultLIRSuites(graalOptions);
     }
 
     @SuppressWarnings("try")
     public CompilationResult compileMethod(ResolvedJavaMethod resolvedMethod) {
-        try (OverrideScope s = OptionValue.override(ImmutableCode, true, GeneratePIC, true)) {
-            StructuredGraph graph = buildStructuredGraph(resolvedMethod);
-            if (graph != null) {
-                return compileGraph(resolvedMethod, graph);
-            }
-            return null;
+        StructuredGraph graph = buildStructuredGraph(resolvedMethod);
+        if (graph != null) {
+            return compileGraph(resolvedMethod, graph);
         }
+        return null;
     }
 
     /**
@@ -115,7 +109,7 @@
     @SuppressWarnings("try")
     private StructuredGraph buildStructuredGraph(ResolvedJavaMethod javaMethod) {
         try (Scope s = Debug.scope("AOTParseMethod")) {
-            StructuredGraph graph = new StructuredGraph(javaMethod, StructuredGraph.AllowAssumptions.NO, false, CompilationIdentifier.INVALID_COMPILATION_ID);
+            StructuredGraph graph = new StructuredGraph.Builder(graalOptions).method(javaMethod).useProfilingInfo(false).build();
             graphBuilderSuite.apply(graph, highTierContext);
             return graph;
         } catch (Throwable e) {
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Thu Apr 06 21:14:07 2017 +0000
@@ -33,6 +33,7 @@
 import org.graalvm.compiler.debug.Management;
 import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.debug.internal.DebugScope;
+import org.graalvm.compiler.options.OptionValues;
 
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -54,6 +55,8 @@
 
     private final Main main;
 
+    private OptionValues graalOptions;
+
     /**
      * The compilation id of this task.
      */
@@ -73,8 +76,9 @@
      */
     private CompiledMethodInfo result;
 
-    public AOTCompilationTask(Main main, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) {
+    public AOTCompilationTask(Main main, OptionValues graalOptions, AOTCompiledClass holder, ResolvedJavaMethod method, AOTBackend aotBackend) {
         this.main = main;
+        this.graalOptions = graalOptions;
         this.id = ids.getAndIncrement();
         this.holder = holder;
         this.method = method;
@@ -91,14 +95,14 @@
 
         // Ensure a debug configuration for this thread is initialized
         if (Debug.isEnabled() && DebugScope.getConfig() == null) {
-            DebugEnvironment.initialize(TTY.out);
+            DebugEnvironment.ensureInitialized(graalOptions);
         }
         AOTCompiler.logCompilation(MiscUtils.uniqueMethodName(method), "Compiling");
 
         final long threadId = Thread.currentThread().getId();
 
-        final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue() && !TTY.isSuppressed();
-        final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue() && !TTY.isSuppressed();
+        final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed();
+        final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue(graalOptions) && !TTY.isSuppressed();
         if (printCompilation) {
             TTY.println(getMethodDescription() + "...");
         }
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompiler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -31,12 +31,16 @@
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.graalvm.compiler.options.OptionValues;
+
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 public class AOTCompiler {
 
     private final Main main;
 
+    private final OptionValues graalOptions;
+
     private CompileQueue compileQueue;
 
     private final AOTBackend backend;
@@ -102,11 +106,13 @@
 
     /**
      * @param main
+     * @param graalOptions
      * @param aotBackend
      * @param threads number of compilation threads
      */
-    public AOTCompiler(Main main, AOTBackend aotBackend, final int threads) {
+    public AOTCompiler(Main main, OptionValues graalOptions, AOTBackend aotBackend, final int threads) {
         this.main = main;
+        this.graalOptions = graalOptions;
         this.compileQueue = new CompileQueue(threads);
         this.backend = aotBackend;
     }
@@ -146,7 +152,7 @@
      * @param method method to be enqueued
      */
     private void enqueueMethod(AOTCompiledClass aotClass, ResolvedJavaMethod method) {
-        AOTCompilationTask task = new AOTCompilationTask(main, aotClass, method, backend);
+        AOTCompilationTask task = new AOTCompilationTask(main, graalOptions, aotClass, method, backend);
         try {
             compileQueue.execute(task);
         } catch (RejectedExecutionException e) {
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/DataBuilder.java	Thu Apr 06 21:14:07 2017 +0000
@@ -36,6 +36,7 @@
 import org.graalvm.compiler.debug.Debug;
 import org.graalvm.compiler.debug.Debug.Scope;
 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
+import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
 import org.graalvm.compiler.hotspot.stubs.Stub;
 
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
@@ -180,7 +181,8 @@
     @SuppressWarnings("try")
     private AOTCompiledClass retrieveStubCode() {
         ArrayList<CompiledMethodInfo> stubs = new ArrayList<>();
-        for (Stub stub : Stub.getStubs()) {
+        HotSpotForeignCallsProvider foreignCallsProvider = backend.getProviders().getForeignCalls();
+        for (Stub stub : foreignCallsProvider.getStubs()) {
             try (Scope scope = Debug.scope("CompileStubs")) {
                 CompilationResult result = stub.getCompilationResult(backend);
                 CompiledMethodInfo cm = new CompiledMethodInfo(result, new AOTStub(stub, backend));
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Apr 06 21:14:07 2017 +0000
@@ -60,11 +60,15 @@
 import jdk.tools.jaotc.utils.Timer;
 
 import org.graalvm.compiler.api.runtime.GraalJVMCICompiler;
+import org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory;
+import org.graalvm.compiler.hotspot.HotSpotGraalOptionValues;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotHostBackend;
 import org.graalvm.compiler.java.GraphBuilderPhase;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.BasePhase;
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
@@ -76,11 +80,6 @@
 import jdk.vm.ci.runtime.JVMCI;
 
 public class Main implements LogPrinter {
-    static {
-        GeneratePIC.setValue(true);
-        ImmutableCode.setValue(true);
-    }
-
     static class BadArgs extends Exception {
         private static final long serialVersionUID = 1L;
         final String key;
@@ -132,7 +131,7 @@
         abstract void process(Main task, String opt, String arg) throws BadArgs;
     }
 
-    static Option[] recognizedOptions = { new Option("  --output <file>            Output file name", true, "--output") {
+    static Option[] recognizedOptions = {new Option("  --output <file>            Output file name", true, "--output") {
         @Override
         void process(Main task, String opt, String arg) {
             String name = arg;
@@ -172,7 +171,7 @@
     }, new Option("  --compile-for-tiered       Generate profiling code for tiered compilation", false, "--compile-for-tiered") {
         @Override
         void process(Main task, String opt, String arg) {
-            TieredAOT.setValue(true);
+            task.options.tiered = true;
         }
     }, new Option("  --compile-with-assertions  Compile with java assertions", false, "--compile-with-assertions") {
         @Override
@@ -265,6 +264,7 @@
         public boolean help;
         public boolean version;
         public boolean compileWithAssertions;
+        public boolean tiered;
     }
 
     /* package */final Options options = new Options();
@@ -307,7 +307,7 @@
             printlnInfo("Compiling " + options.outputName + "...");
             final long start = System.currentTimeMillis();
             if (!run()) {
-              return EXIT_ABNORMAL;
+                return EXIT_ABNORMAL;
             }
             final long end = System.currentTimeMillis();
             printlnInfo("Total time: " + (end - start) + " ms");
@@ -351,8 +351,7 @@
     }
 
     /**
-     * Visual Studio supported versions
-     * Search Order is:  VS2013, VS2015, VS2012
+     * Visual Studio supported versions Search Order is: VS2013, VS2015, VS2012
      */
     public enum VSVERSIONS {
         VS2013("VS120COMNTOOLS", "C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\bin\\amd64\\link.exe"),
@@ -367,20 +366,23 @@
             this.wkp = wellknownpath;
         }
 
-        String EnvVariable()   { return envvariable; }
-        String WellKnownPath() { return wkp; }
+        String EnvVariable() {
+            return envvariable;
+        }
+
+        String WellKnownPath() {
+            return wkp;
+        }
     }
 
     /**
-     * Search for Visual Studio link.exe
-     * Search Order is:  VS2013, VS2015, VS2012
+     * Search for Visual Studio link.exe Search Order is: VS2013, VS2015, VS2012
      */
     private static String getWindowsLinkPath() {
         String link = "\\VC\\bin\\amd64\\link.exe";
 
         /**
-         * First try searching the paths pointed to by
-         * the VS environment variables.
+         * First try searching the paths pointed to by the VS environment variables.
          */
         for (VSVERSIONS vs : VSVERSIONS.values()) {
             String vspath = System.getenv(vs.EnvVariable());
@@ -388,13 +390,13 @@
                 File commonTools = new File(vspath);
                 File vsRoot = commonTools.getParentFile().getParentFile();
                 File linkPath = new File(vsRoot, link);
-                if (linkPath.exists()) return linkPath.getPath();
+                if (linkPath.exists())
+                    return linkPath.getPath();
             }
         }
 
         /**
-         * If we didn't find via the VS environment variables,
-         * try the well known paths
+         * If we didn't find via the VS environment variables, try the well known paths
          */
         for (VSVERSIONS vs : VSVERSIONS.values()) {
             String wkp = vs.WellKnownPath();
@@ -438,7 +440,13 @@
                 printInfo(classesToCompile.size() + " classes found");
             }
 
-            GraalJVMCICompiler graalCompiler = (GraalJVMCICompiler) JVMCI.getRuntime().getCompiler();
+            OptionValues graalOptions = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
+            // Setting -Dgraal.TieredAOT overrides --compile-for-tiered
+            if (!TieredAOT.hasBeenSet(graalOptions)) {
+                graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
+            }
+            graalOptions = new OptionValues(HotSpotGraalOptionValues.HOTSPOT_OPTIONS, GeneratePIC, true, ImmutableCode, true);
+            GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
             HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
             HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
             MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
@@ -458,8 +466,8 @@
                 System.gc();
             }
 
-            AOTBackend aotBackend = new AOTBackend(this, backend, filters);
-            AOTCompiler compiler = new AOTCompiler(this, aotBackend, options.threads);
+            AOTBackend aotBackend = new AOTBackend(this, graalOptions, backend, filters);
+            AOTCompiler compiler = new AOTCompiler(this, graalOptions, aotBackend, options.threads);
             classes = compiler.compileClasses(classes);
 
             GraalHotSpotVMConfig graalHotSpotVMConfig = runtime.getVMConfig();
@@ -475,7 +483,7 @@
                 System.gc();
             }
 
-            BinaryContainer binaryContainer = new BinaryContainer(graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
+            BinaryContainer binaryContainer = new BinaryContainer(graalOptions, graalHotSpotVMConfig, graphBuilderConfig, JVM_VERSION);
             DataBuilder dataBuilder = new DataBuilder(this, backend, classes, binaryContainer);
             dataBuilder.prepareData();
 
@@ -524,11 +532,9 @@
 
             if (name.endsWith(".so")) {
                 objectFileName = name.substring(0, name.length() - ".so".length());
-            }
-            else if (name.endsWith(".dylib")) {
+            } else if (name.endsWith(".dylib")) {
                 objectFileName = name.substring(0, name.length() - ".dylib".length());
-            }
-            else if (name.endsWith(".dll")) {
+            } else if (name.endsWith(".dll")) {
                 objectFileName = name.substring(0, name.length() - ".dll".length());
             }
 
@@ -536,34 +542,32 @@
                 case "Linux":
                     // libraryFileName = options.outputName + ".so";
                     objectFileName = objectFileName + ".o";
-                    linkerPath = (options.linkerpath != null) ?  options.linkerpath : "ld";
+                    linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
                     linkerCmd = linkerPath + " -shared -z noexecstack -o " + libraryFileName + " " + objectFileName;
                     break;
                 case "SunOS":
                     // libraryFileName = options.outputName + ".so";
                     objectFileName = objectFileName + ".o";
-                    linkerPath = (options.linkerpath != null) ?  options.linkerpath : "ld";
+                    linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
                     linkerCmd = linkerPath + " -shared -o " + libraryFileName + " " + objectFileName;
                     break;
                 case "Mac OS X":
                     // libraryFileName = options.outputName + ".dylib";
                     objectFileName = objectFileName + ".o";
-                    linkerPath = (options.linkerpath != null) ?  options.linkerpath : "ld";
+                    linkerPath = (options.linkerpath != null) ? options.linkerpath : "ld";
                     linkerCmd = linkerPath + " -dylib -o " + libraryFileName + " " + objectFileName;
                     break;
                 default:
                     if (osName.startsWith("Windows")) {
                         // libraryFileName = options.outputName + ".dll";
                         objectFileName = objectFileName + ".obj";
-                        linkerPath = (options.linkerpath != null) ?
-                            options.linkerpath : getWindowsLinkPath();
+                        linkerPath = (options.linkerpath != null) ? options.linkerpath : getWindowsLinkPath();
                         if (linkerPath == null) {
                             throw new InternalError("Can't locate Microsoft Visual Studio amd64 link.exe");
                         }
                         linkerCmd = linkerPath + " /DLL /OPT:NOREF /NOLOGO /NOENTRY" + " /OUT:" + libraryFileName + " " + objectFileName;
                         break;
-                    }
-                    else
+                    } else
                         throw new InternalError("Unsupported platform: " + osName);
             }
 
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/collect/ClassSource.java	Thu Apr 06 21:14:07 2017 +0000
@@ -31,6 +31,20 @@
         return fileName.endsWith(".class") && !fileName.endsWith("module-info.class");
     }
 
+    static String stripRoot(Path path) {
+      if (path.getRoot() != null) {
+        String root = path.getRoot().toString();
+        String filename = path.toString().substring(root.length());
+        String separator = path.getFileSystem().getSeparator();
+        while (filename.startsWith(separator)) {
+          filename = filename.substring(separator.length());
+        }
+        return filename;
+      }
+
+      return path.toString();
+    }
+
     static String makeClassName(Path path) {
         String fileName = path.toString();
 
@@ -38,13 +52,10 @@
             throw new IllegalArgumentException("File doesn't end with .class: '" + fileName + "'");
         }
 
-        int start = 0;
-        if (fileName.startsWith("/")) {
-            start = 1;
-        }
+        fileName = stripRoot(path);
 
-        String className = fileName.substring(start, fileName.length() - ".class".length());
-        className = className.replace('/', '.');
+        String className = fileName.substring(0, fileName.length() - ".class".length());
+        className = className.replace(path.getFileSystem().getSeparator(), ".");
         return className;
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Thu Apr 06 21:14:07 2017 +0000
@@ -17,18 +17,22 @@
       "sha1" : "476d9a44cd19d6b55f81571077dfa972a4f8a083",
       "bootClassPathAgent" : "true",
     },
+
+    "ASM5" : {
+      "sha1" : "0da08b8cce7bbf903602a25a3a163ae252435795",
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-5.0.4.jar"],
+    },
+
+    "ASM_TREE5" : {
+      "sha1" : "396ce0c07ba2b481f25a70195c7c94922f0d1b0b",
+      "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/asm-tree-5.0.4.jar"],
+      "dependencies" : ["ASM5"],
+    },
   },
 
   "projects" : {
 
     # ------------- Graal -------------
-    "org.graalvm.compiler.common" : {
-      "subDir" : "share/classes",
-      "sourceDirs" : ["src"],
-      "checkstyle" : "org.graalvm.compiler.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "API,Graal",
-    },
 
     "org.graalvm.compiler.serviceprovider" : {
       "subDir" : "share/classes",
@@ -50,7 +54,9 @@
     "org.graalvm.compiler.options" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : ["org.graalvm.util"],
       "checkstyle" : "org.graalvm.compiler.graph",
+      "uses" : ["org.graalvm.compiler.options.OptionDescriptors"],
       "javaCompliance" : "1.8",
       "workingSets" : "Graal",
     },
@@ -82,6 +88,11 @@
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
       "checkstyle" : "org.graalvm.compiler.graph",
+      "uses" : [
+        "org.graalvm.compiler.debug.DebugConfigCustomizer",
+        "org.graalvm.compiler.debug.DebugInitializationParticipant",
+        "org.graalvm.compiler.debug.TTYStreamProvider",
+      ],
       "dependencies" : [
         "org.graalvm.compiler.serviceprovider",
         "org.graalvm.compiler.options"
@@ -108,7 +119,6 @@
       "sourceDirs" : ["src"],
       "dependencies" : [
         "org.graalvm.compiler.graph",
-        "org.graalvm.compiler.common",
       ],
       "annotationProcessors" : ["GRAAL_SERVICEPROVIDER_PROCESSOR"],
       "checkstyle" : "org.graalvm.compiler.graph",
@@ -116,7 +126,7 @@
       "workingSets" : "Graal",
     },
 
-    "org.graalvm.compiler.api.collections" : {
+    "org.graalvm.util" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
       "checkstyle" : "org.graalvm.compiler.graph",
@@ -124,6 +134,18 @@
       "workingSets" : "API,Graal",
     },
 
+    "org.graalvm.util.test" : {
+      "subDir" : "share/classes",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "mx:JUNIT",
+        "org.graalvm.util",
+      ],
+      "checkstyle" : "org.graalvm.compiler.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,Graal",
+    },
+
     "org.graalvm.compiler.api.directives" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
@@ -179,6 +201,11 @@
         "org.graalvm.compiler.replacements",
         "org.graalvm.compiler.runtime",
       ],
+      "imports" : [
+        # All other internal packages are exported dynamically -
+        # see org.graalvm.compiler.hotspot.HotSpotGraalJVMCIServiceLocator
+        "jdk.internal.module",
+      ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "annotationProcessors" : [
         "GRAAL_NODEINFO_PROCESSOR",
@@ -320,7 +347,6 @@
       "dependencies" : [
         "org.graalvm.compiler.nodeinfo",
         "org.graalvm.compiler.core.common",
-        "org.graalvm.compiler.api.collections",
       ],
       "javaCompliance" : "1.8",
       "annotationProcessors" : [
@@ -347,6 +373,9 @@
     "org.graalvm.compiler.asm" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
+      "dependencies" : [
+        "org.graalvm.compiler.core.common"
+      ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
       "workingSets" : "Graal,Assembler",
@@ -356,7 +385,6 @@
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "org.graalvm.compiler.debug",
         "org.graalvm.compiler.asm",
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
@@ -379,9 +407,7 @@
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "org.graalvm.compiler.debug",
         "org.graalvm.compiler.asm",
-        "org.graalvm.compiler.common"
       ],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -711,6 +737,18 @@
       "workingSets" : "Graal",
     },
 
+    "org.graalvm.compiler.loop.test" : {
+      "subDir" : "share/classes",
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "org.graalvm.compiler.loop",
+        "org.graalvm.compiler.core.test"
+      ],
+      "checkstyle" : "org.graalvm.compiler.graph",
+      "javaCompliance" : "1.8",
+      "workingSets" : "Graal,Test",
+    },
+
     "org.graalvm.compiler.loop.phases" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
@@ -731,6 +769,7 @@
         "org.graalvm.compiler.virtual",
         "org.graalvm.compiler.loop.phases",
       ],
+      "uses" : ["org.graalvm.compiler.core.match.MatchStatementSet"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
       "annotationProcessors" : [
@@ -908,7 +947,9 @@
         "org.graalvm.compiler.graph.test",
         "org.graalvm.compiler.printer",
         "JAVA_ALLOCATION_INSTRUMENTER",
+        "ASM_TREE5",
       ],
+      "uses" : ["org.graalvm.compiler.options.OptionDescriptors"],
       "annotationProcessors" : ["GRAAL_NODEINFO_PROCESSOR"],
       "checkstyle" : "org.graalvm.compiler.graph",
       "javaCompliance" : "1.8",
@@ -929,21 +970,6 @@
       "findbugs" : "false",
     },
 
-    # ------------- Salver -------------
-
-    "org.graalvm.compiler.salver" : {
-      "subDir" : "share/classes",
-      "sourceDirs" : ["src"],
-      "dependencies" : ["org.graalvm.compiler.phases"],
-      "annotationProcessors" : [
-        "GRAAL_OPTIONS_PROCESSOR",
-        "GRAAL_SERVICEPROVIDER_PROCESSOR",
-      ],
-      "checkstyle" : "org.graalvm.compiler.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "Graal",
-    },
-
     # ------------- AOT -------------
 
     "jdk.tools.jaotc" : {
@@ -1073,7 +1099,6 @@
         "org.graalvm.compiler.replacements.amd64",
         "org.graalvm.compiler.core.sparc",
         "org.graalvm.compiler.replacements.sparc",
-        "org.graalvm.compiler.salver",
       ],
       "distDependencies" : [
         "GRAAL_API",
@@ -1197,7 +1222,6 @@
         "org.graalvm.compiler.replacements.amd64",
         "org.graalvm.compiler.core.sparc",
         "org.graalvm.compiler.replacements.sparc",
-        "org.graalvm.compiler.salver",
         "org.graalvm.compiler.hotspot.aarch64",
         "org.graalvm.compiler.hotspot.amd64",
         "org.graalvm.compiler.hotspot.sparc",
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/module-info.java	Thu Apr 06 21:14:07 2017 +0000
@@ -39,6 +39,7 @@
     uses org.graalvm.compiler.debug.TTYStreamProvider;
     uses org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
     uses org.graalvm.compiler.hotspot.HotSpotBackendFactory;
+    uses org.graalvm.compiler.options.OptionValuesAccess;
     uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
 
     exports org.graalvm.compiler.api.directives         to jdk.aot;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/CollectionsProvider.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.collections;
-
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A factory for creating collections.
- */
-public interface CollectionsProvider {
-
-    /**
-     * Creates a set that uses reference-equality in place of object-equality when comparing
-     * entries.
-     */
-    <E> Set<E> newIdentitySet();
-
-    /**
-     * Creates a map that uses reference-equality in place of object-equality when comparing keys.
-     */
-    <K, V> Map<K, V> newIdentityMap();
-
-    /**
-     * Creates a map that uses reference-equality in place of object-equality when comparing keys.
-     *
-     * @param expectedMaxSize the expected maximum size of the map
-     */
-    <K, V> Map<K, V> newIdentityMap(int expectedMaxSize);
-
-    /**
-     * Creates a map that uses reference-equality in place of object-equality when comparing keys.
-     *
-     * @param initFrom the returned map is populated with the entries in this map
-     */
-    <K, V> Map<K, V> newIdentityMap(Map<K, V> initFrom);
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.collections/src/org/graalvm/compiler/api/collections/DefaultCollectionsProvider.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.collections;
-
-import java.util.Collections;
-import java.util.IdentityHashMap;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * A default implementation of {@link CollectionsProvider} that creates standard JDK collection
- * class objects.
- */
-public class DefaultCollectionsProvider implements CollectionsProvider {
-
-    @Override
-    public <E> Set<E> newIdentitySet() {
-        return Collections.newSetFromMap(newIdentityMap());
-    }
-
-    @Override
-    public <K, V> Map<K, V> newIdentityMap() {
-        return new IdentityHashMap<>();
-    }
-
-    @Override
-    public <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
-        return new IdentityHashMap<>(expectedMaxSize);
-    }
-
-    @Override
-    public <K, V> Map<K, V> newIdentityMap(Map<K, V> initFrom) {
-        return new IdentityHashMap<>(initFrom);
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/AllocationInstrumentationTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.directives.test;
-
-import java.io.IOException;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.graalvm.compiler.api.directives.GraalDirectives;
-import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.options.OptionValue;
-import org.graalvm.compiler.options.OptionValue.OverrideScope;
-
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-@SuppressWarnings("try")
-public class AllocationInstrumentationTest extends GraalCompilerTest {
-
-    private TinyInstrumentor instrumentor;
-
-    public AllocationInstrumentationTest() {
-        HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod");
-        method.setNotInlineable();
-
-        try {
-            instrumentor = new TinyInstrumentor(AllocationInstrumentationTest.class, "instrumentation");
-        } catch (IOException e) {
-            Assert.fail("unable to initialize the instrumentor: " + e);
-        }
-    }
-
-    public static class ClassA {
-        // This method should be marked as not inlineable
-        public void notInlinedMethod() {
-        }
-    }
-
-    public static boolean allocationWasExecuted;
-
-    private static void resetFlag() {
-        allocationWasExecuted = false;
-    }
-
-    static void instrumentation() {
-        GraalDirectives.instrumentationBeginForPredecessor();
-        allocationWasExecuted = true;
-        GraalDirectives.instrumentationEnd();
-    }
-
-    public static void notEscapeSnippet() {
-        @SuppressWarnings("unused")
-        ClassA a = new ClassA(); // a does not escape
-    }
-
-    @Test
-    public void testNotEscape() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            Class<?> clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "notEscapeSnippet", Opcodes.NEW);
-            ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "notEscapeSnippet");
-            executeExpected(method, null); // ensure the method is fully resolved
-            resetFlag();
-            // The allocation in the snippet does not escape and will be optimized away. We expect
-            // the instrumentation is removed.
-            InstalledCode code = getCode(method);
-            code.executeVarargs();
-            Assert.assertFalse("allocation should not take place", allocationWasExecuted);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public static void mustEscapeSnippet() {
-        ClassA a = new ClassA();
-        a.notInlinedMethod(); // a escapses
-    }
-
-    @Test
-    public void testMustEscape() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            Class<?> clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "mustEscapeSnippet", Opcodes.NEW);
-            ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "mustEscapeSnippet");
-            executeExpected(method, null); // ensure the method is fully resolved
-            resetFlag();
-            // The allocation in the snippet escapes. We expect the instrumentation is preserved.
-            InstalledCode code = getCode(method);
-            code.executeVarargs();
-            Assert.assertTrue("allocation should take place", allocationWasExecuted);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public static void partialEscapeSnippet(boolean condition) {
-        ClassA a = new ClassA();
-
-        if (condition) {
-            a.notInlinedMethod(); // a escapes in the then-clause
-        }
-    }
-
-    @Test
-    public void testPartialEscape() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            Class<?> clazz = instrumentor.instrument(AllocationInstrumentationTest.class, "partialEscapeSnippet", Opcodes.NEW);
-            ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "partialEscapeSnippet");
-            executeExpected(method, null, true); // ensure the method is fully resolved
-            resetFlag();
-            // The allocation in the snippet escapes in the then-clause, and will be relocated to
-            // this branch. We expect the instrumentation follows and will only be effective when
-            // the then-clause is taken.
-            InstalledCode code = getCode(method);
-            code.executeVarargs(false);
-            Assert.assertFalse("allocation should not take place", allocationWasExecuted);
-            code.executeVarargs(true);
-            Assert.assertTrue("allocation should take place", allocationWasExecuted);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java	Thu Apr 06 21:14:07 2017 +0000
@@ -70,7 +70,7 @@
         Result actual;
         try {
             actual = new Result(code.executeVarargs(), null);
-        } catch (Throwable e) {
+        } catch (Exception e) {
             actual = new Result(null, e);
         }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/IsMethodInlineDirectiveTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.directives.test;
-
-import org.junit.Test;
-
-import org.graalvm.compiler.api.directives.GraalDirectives;
-import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.options.OptionValue;
-import org.graalvm.compiler.options.OptionValue.OverrideScope;
-
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-public class IsMethodInlineDirectiveTest extends GraalCompilerTest {
-
-    public IsMethodInlineDirectiveTest() {
-        HotSpotResolvedJavaMethod calleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeSnippet");
-        calleeSnippet.shouldBeInlined();
-
-        HotSpotResolvedJavaMethod calleeWithInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(IsMethodInlineDirectiveTest.class, "calleeWithInstrumentationSnippet");
-        calleeWithInstrumentationSnippet.shouldBeInlined();
-    }
-
-    public static boolean rootMethodSnippet() {
-        return GraalDirectives.isMethodInlined();
-    }
-
-    @SuppressWarnings("try")
-    @Test
-    public void testRootMethod() {
-        ResolvedJavaMethod method = getResolvedJavaMethod("rootMethodSnippet");
-        executeExpected(method, null); // ensure the method is fully resolved
-        // The target method is not inlined. We expect the result to be false.
-        InstalledCode code = getCode(method);
-        try {
-            Result result = new Result(code.executeVarargs(), null);
-            assertEquals(new Result(false, null), result);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public static boolean calleeSnippet() {
-        return GraalDirectives.isMethodInlined();
-    }
-
-    public static boolean callerSnippet() {
-        return calleeSnippet();
-    }
-
-    @Test
-    public void testInlinedCallee() {
-        ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet");
-        executeExpected(method, null); // ensure the method is fully resolved
-        // calleeSnippet will be inlined. We expect the result to be true.
-        InstalledCode code = getCode(method);
-        try {
-            Result result = new Result(code.executeVarargs(), null);
-            assertEquals(new Result(true, null), result);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    static boolean isCalleeInlined;
-    static boolean isCallerInlined;
-
-    public static void calleeWithInstrumentationSnippet() {
-        GraalDirectives.instrumentationBegin();
-        isCalleeInlined = GraalDirectives.isMethodInlined();
-        GraalDirectives.instrumentationEnd();
-    }
-
-    public static void callerSnippet1() {
-        calleeWithInstrumentationSnippet();
-
-        GraalDirectives.instrumentationBegin();
-        isCallerInlined = GraalDirectives.isMethodInlined();
-        GraalDirectives.instrumentationEnd();
-    }
-
-    @SuppressWarnings("try")
-    @Test
-    public void testInlinedCalleeWithInstrumentation() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1");
-            executeExpected(method, null); // ensure the method is fully resolved
-            isCalleeInlined = false;
-            isCallerInlined = false;
-            // calleeWithInstrumentationSnippet will be inlined. We expect the flag1 set in
-            // calleeWithInstrumentationSnippet to be true, and the flag2 set in callerSnippet1 to
-            // be false.
-            InstalledCode code = getCode(method);
-            code.executeVarargs();
-            assertTrue("calleWithInstrumentationSnippet should be inlined", isCalleeInlined);
-            assertFalse("callerSnippet1 should not be inlined", isCallerInlined);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/LockInstrumentationTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.directives.test;
-
-import java.io.IOException;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import org.graalvm.compiler.api.directives.GraalDirectives;
-import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.options.OptionValue;
-import org.graalvm.compiler.options.OptionValue.OverrideScope;
-
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-@SuppressWarnings("try")
-public class LockInstrumentationTest extends GraalCompilerTest {
-
-    private TinyInstrumentor instrumentor;
-
-    public LockInstrumentationTest() {
-        HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(ClassA.class, "notInlinedMethod");
-        method.setNotInlineable();
-
-        try {
-            instrumentor = new TinyInstrumentor(LockInstrumentationTest.class, "instrumentation");
-        } catch (IOException e) {
-            Assert.fail("unable to initialize the instrumentor: " + e);
-        }
-    }
-
-    public static class ClassA {
-
-        // This method should be marked as not inlineable
-        public void notInlinedMethod() {
-        }
-
-    }
-
-    public static final Object lock = new Object();
-    public static boolean lockAfterCheckPoint;
-    public static boolean checkpoint;
-
-    private static void resetFlags() {
-        lockAfterCheckPoint = false;
-        checkpoint = false;
-    }
-
-    static void instrumentation() {
-        GraalDirectives.instrumentationBeginForPredecessor();
-        lockAfterCheckPoint = checkpoint;
-        GraalDirectives.instrumentationEnd();
-    }
-
-    public static void lockSnippet() {
-        synchronized (lock) {
-            checkpoint = true;
-            ClassA a = new ClassA();
-            a.notInlinedMethod();
-        }
-    }
-
-    @Test
-    public void testLock() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            Class<?> clazz = instrumentor.instrument(LockInstrumentationTest.class, "lockSnippet", Opcodes.MONITORENTER);
-            ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "lockSnippet");
-            executeExpected(method, null); // ensure the method is fully resolved
-            resetFlags();
-            // The monitorenter anchors. We expect the instrumentation set the flag before passing
-            // the checkpoint.
-            InstalledCode code = getCode(method);
-            code.executeVarargs();
-            Assert.assertFalse("expected lock was performed before checkpoint", lockAfterCheckPoint);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public static void postponeLockSnippet() {
-        ClassA a = new ClassA();
-
-        synchronized (a) {
-            checkpoint = true;
-            a.notInlinedMethod();
-        }
-
-    }
-
-    @Test
-    public void testNonEscapeLock() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            Class<?> clazz = instrumentor.instrument(LockInstrumentationTest.class, "postponeLockSnippet", Opcodes.MONITORENTER);
-            ResolvedJavaMethod method = getResolvedJavaMethod(clazz, "postponeLockSnippet");
-            executeExpected(method, null); // ensure the method is fully resolved
-            resetFlags();
-            // The lock in the snippet will be relocated before the invocation to
-            // notInlinedMethod(), i.e., after the checkpoint. We expect the instrumentation follows
-            // and flag will be set to true.
-            InstalledCode code = getCode(method);
-            code.executeVarargs();
-            Assert.assertTrue("expected lock was performed after checkpoint", lockAfterCheckPoint);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/RootNameDirectiveTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.directives.test;
-
-import java.io.ByteArrayOutputStream;
-import java.lang.reflect.Method;
-import java.util.Formatter;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import com.google.monitoring.runtime.instrumentation.common.com.google.common.base.Objects;
-import org.graalvm.compiler.api.directives.GraalDirectives;
-import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.debug.Debug;
-import org.graalvm.compiler.debug.Debug.Scope;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.options.OptionValue;
-import org.graalvm.compiler.options.OptionValue.OverrideScope;
-import org.graalvm.compiler.printer.IdealGraphPrinter;
-
-import jdk.vm.ci.code.CodeCacheProvider;
-import jdk.vm.ci.code.InstalledCode;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-public class RootNameDirectiveTest extends GraalCompilerTest {
-
-    public RootNameDirectiveTest() {
-        HotSpotResolvedJavaMethod rootNameAtCalleeSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameAtCalleeSnippet");
-        rootNameAtCalleeSnippet.shouldBeInlined();
-
-        HotSpotResolvedJavaMethod rootNameWithinInstrumentationSnippet = (HotSpotResolvedJavaMethod) getResolvedJavaMethod(RootNameDirectiveTest.class, "rootNameWithinInstrumentationSnippet");
-        rootNameWithinInstrumentationSnippet.shouldBeInlined();
-    }
-
-    private static String toString(ResolvedJavaMethod method) {
-        return method.getDeclaringClass().toJavaName() + "." + method.getName() + method.getSignature().toMethodDescriptor();
-    }
-
-    public static String rootNameSnippet() {
-        return GraalDirectives.rootName();
-    }
-
-    @Test
-    public void testRootName() {
-        ResolvedJavaMethod method = getResolvedJavaMethod("rootNameSnippet");
-        executeExpected(method, null); // ensure the method is fully resolved
-        // The target snippet is already the root method. We expect the name of the target snippet
-        // is returned.
-        InstalledCode code = getCode(method);
-        try {
-            Result result = new Result(code.executeVarargs(), null);
-            assertEquals(new Result(toString(method), null), result);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    public static String rootNameAtCalleeSnippet() {
-        return GraalDirectives.rootName();
-    }
-
-    public static String callerSnippet() {
-        return rootNameAtCalleeSnippet();
-    }
-
-    @Test
-    public void testRootNameAtCallee() {
-        ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet");
-        executeExpected(method, null); // ensure the method is fully resolved
-        // The target snippet is the compilation root of rootNameAtCalleeSnippet() because the later
-        // will be inlined. We expect the name of the target snippet is returned.
-        InstalledCode code = getCode(method);
-        try {
-            Result result = new Result(code.executeVarargs(), null);
-            assertEquals(new Result(toString(method), null), result);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-    static String rootNameInCallee;
-    static String rootNameInCaller;
-
-    @BytecodeParserForceInline
-    public static void rootNameWithinInstrumentationSnippet() {
-        GraalDirectives.instrumentationBegin();
-        rootNameInCallee = GraalDirectives.rootName();
-        GraalDirectives.instrumentationEnd();
-    }
-
-    public static void callerSnippet1() {
-        rootNameWithinInstrumentationSnippet();
-
-        GraalDirectives.instrumentationBegin();
-        rootNameInCaller = GraalDirectives.rootName();
-        GraalDirectives.instrumentationEnd();
-    }
-
-    @SuppressWarnings("try")
-    private void assertEquals(StructuredGraph graph, InstalledCode code, Object expected, Object actual) {
-        if (!Objects.equal(expected, actual)) {
-            Formatter buf = new Formatter();
-
-            try (Scope s = Debug.sandbox("PrintingGraph", null)) {
-                Map<Object, Object> properties = new HashMap<>();
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                IdealGraphPrinter printer = new IdealGraphPrinter(baos, true, getSnippetReflection());
-                printer.beginGroup("RootNameDirectiveTest", "RootNameDirectiveTest", graph.method(), -1, null);
-                properties.put("graph", graph.toString());
-                properties.put("scope", Debug.currentScope());
-                printer.print(graph, graph.method().format("%H.%n(%p)"), properties);
-                printer.endGroup();
-                printer.close();
-                buf.format("-- Graph -- %n%s", baos.toString());
-            } catch (Throwable e) {
-                buf.format("%nError printing graph: %s", e);
-            }
-            try {
-                CodeCacheProvider codeCache = getCodeCache();
-                Method disassemble = codeCache.getClass().getMethod("disassemble", InstalledCode.class);
-                buf.format("%n-- Code -- %n%s", disassemble.invoke(codeCache, code));
-            } catch (NoSuchMethodException e) {
-                // Not a HotSpotCodeCacheProvider
-            } catch (Exception e) {
-                buf.format("%nError disassembling code: %s", e);
-            }
-            Assert.assertEquals(buf.toString(), expected, actual);
-        }
-    }
-
-    @SuppressWarnings("try")
-    @Test
-    public void testRootNameWithinInstrumentationAtCallee() {
-        try (OverrideScope s = OptionValue.override(GraalOptions.UseGraalInstrumentation, true)) {
-            ResolvedJavaMethod method = getResolvedJavaMethod("callerSnippet1");
-            executeExpected(method, null); // ensure the method is fully resolved
-            rootNameInCallee = null;
-            rootNameInCaller = null;
-            // We expect both rootName1 and rootName2 are set to the name of the target snippet.
-            StructuredGraph graph = parseForCompile(method);
-            InstalledCode code = getCode(method, graph);
-            code.executeVarargs();
-            assertEquals(graph, code, toString(method), rootNameInCallee);
-            assertEquals(graph, code, rootNameInCallee, rootNameInCaller);
-        } catch (Throwable e) {
-            throw new AssertionError(e);
-        }
-    }
-
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/TinyInstrumentor.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,242 +0,0 @@
-/*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.api.directives.test;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.graalvm.compiler.test.ExportingClassLoader;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.IincInsnNode;
-import jdk.internal.org.objectweb.asm.tree.InsnList;
-import jdk.internal.org.objectweb.asm.tree.JumpInsnNode;
-import jdk.internal.org.objectweb.asm.tree.LabelNode;
-import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.VarInsnNode;
-
-/**
- * The {@code TinyInstrumentor} is a bytecode instrumentor using ASM bytecode manipulation
- * framework. It injects given code snippet into a target method and creates a temporary class as
- * the container. Because the target method is cloned into the temporary class, it is required that
- * the target method is public static. Any referred method/field in the target method or the
- * instrumentation snippet should be made public as well.
- */
-public class TinyInstrumentor implements Opcodes {
-
-    private InsnList instrumentationInstructions;
-    private int instrumentationMaxLocal;
-
-    /**
-     * Create a instrumentor with a instrumentation snippet. The snippet is specified with the given
-     * class {@code instrumentationClass} and the given method name {@code methodName}.
-     */
-    public TinyInstrumentor(Class<?> instrumentationClass, String methodName) throws IOException {
-        MethodNode instrumentationMethod = getMethodNode(instrumentationClass, methodName);
-        assert instrumentationMethod != null;
-        assert (instrumentationMethod.access | ACC_STATIC) != 0;
-        assert "()V".equals(instrumentationMethod.desc);
-        instrumentationInstructions = cloneInstructions(instrumentationMethod.instructions);
-        instrumentationMaxLocal = instrumentationMethod.maxLocals;
-        // replace return instructions with a goto unless there is a single return at the end. In
-        // that case, simply remove the return.
-        List<AbstractInsnNode> returnInstructions = new ArrayList<>();
-        for (AbstractInsnNode instruction : selectAll(instrumentationInstructions)) {
-            if (instruction instanceof LineNumberNode) {
-                instrumentationInstructions.remove(instruction);
-            } else if (instruction.getOpcode() == RETURN) {
-                returnInstructions.add(instruction);
-            }
-        }
-        LabelNode exit = new LabelNode();
-        if (returnInstructions.size() == 1) {
-            AbstractInsnNode returnInstruction = returnInstructions.get(0);
-            if (instrumentationInstructions.getLast() != returnInstruction) {
-                instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit));
-            }
-            instrumentationInstructions.remove(returnInstruction);
-        } else {
-            for (AbstractInsnNode returnInstruction : returnInstructions) {
-                instrumentationInstructions.insertBefore(returnInstruction, new JumpInsnNode(GOTO, exit));
-                instrumentationInstructions.remove(returnInstruction);
-            }
-        }
-        instrumentationInstructions.add(exit);
-    }
-
-    /**
-     * @return a {@link MethodNode} called {@code methodName} in the given class.
-     */
-    private static MethodNode getMethodNode(Class<?> clazz, String methodName) throws IOException {
-        ClassReader classReader = new ClassReader(clazz.getName());
-        ClassNode classNode = new ClassNode();
-        classReader.accept(classNode, ClassReader.SKIP_FRAMES);
-
-        for (MethodNode methodNode : classNode.methods) {
-            if (methodNode.name.equals(methodName)) {
-                return methodNode;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Create a {@link ClassNode} with empty constructor.
-     */
-    private static ClassNode emptyClass(String name) {
-        ClassNode classNode = new ClassNode();
-        classNode.visit(52, ACC_SUPER | ACC_PUBLIC, name.replace('.', '/'), null, "java/lang/Object", new String[]{});
-
-        MethodVisitor mv = classNode.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
-        mv.visitCode();
-        Label l0 = new Label();
-        mv.visitLabel(l0);
-        mv.visitVarInsn(ALOAD, 0);
-        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
-        mv.visitInsn(RETURN);
-        Label l1 = new Label();
-        mv.visitLabel(l1);
-        mv.visitMaxs(1, 1);
-        mv.visitEnd();
-
-        return classNode;
-    }
-
-    /**
-     * Helper method for iterating the given {@link InsnList}.
-     */
-    private static Iterable<AbstractInsnNode> selectAll(InsnList instructions) {
-        return new Iterable<AbstractInsnNode>() {
-            @Override
-            public Iterator<AbstractInsnNode> iterator() {
-                return instructions.iterator();
-            }
-        };
-    }
-
-    /**
-     * Make a clone of the given {@link InsnList}.
-     */
-    private static InsnList cloneInstructions(InsnList instructions) {
-        Map<LabelNode, LabelNode> labelMap = new HashMap<>();
-        for (AbstractInsnNode instruction : selectAll(instructions)) {
-            if (instruction instanceof LabelNode) {
-                LabelNode clone = new LabelNode(new Label());
-                LabelNode original = (LabelNode) instruction;
-                labelMap.put(original, clone);
-            }
-        }
-        InsnList clone = new InsnList();
-        for (AbstractInsnNode insn : selectAll(instructions)) {
-            clone.add(insn.clone(labelMap));
-        }
-        return clone;
-    }
-
-    /**
-     * Shifts all local variable slot references by a specified amount.
-     */
-    private static void shiftLocalSlots(InsnList instructions, int offset) {
-        for (AbstractInsnNode insn : selectAll(instructions)) {
-            if (insn instanceof VarInsnNode) {
-                VarInsnNode varInsn = (VarInsnNode) insn;
-                varInsn.var += offset;
-
-            } else if (insn instanceof IincInsnNode) {
-                IincInsnNode iincInsn = (IincInsnNode) insn;
-                iincInsn.var += offset;
-            }
-        }
-    }
-
-    /**
-     * Instrument the target method specified by the class {@code targetClass} and the method name
-     * {@code methodName}. For each occurrence of the {@code opcode}, the instrumentor injects a
-     * copy of the instrumentation snippet.
-     */
-    public Class<?> instrument(Class<?> targetClass, String methodName, int opcode) throws IOException, ClassNotFoundException {
-        return instrument(targetClass, methodName, opcode, true);
-    }
-
-    public Class<?> instrument(Class<?> targetClass, String methodName, int opcode, boolean insertAfter) throws IOException, ClassNotFoundException {
-        // create a container class
-        String className = targetClass.getName() + "$$" + methodName;
-        ClassNode classNode = emptyClass(className);
-        // duplicate the target method and add to the container class
-        MethodNode methodNode = getMethodNode(targetClass, methodName);
-        MethodNode newMethodNode = new MethodNode(methodNode.access, methodNode.name, methodNode.desc, methodNode.signature, methodNode.exceptions.toArray(new String[methodNode.exceptions.size()]));
-        methodNode.accept(newMethodNode);
-        classNode.methods.add(newMethodNode);
-        // perform bytecode instrumentation
-        for (AbstractInsnNode instruction : selectAll(newMethodNode.instructions)) {
-            if (instruction.getOpcode() == opcode) {
-                InsnList instrumentation = cloneInstructions(instrumentationInstructions);
-                shiftLocalSlots(instrumentation, newMethodNode.maxLocals);
-                newMethodNode.maxLocals += instrumentationMaxLocal;
-                if (insertAfter) {
-                    newMethodNode.instructions.insert(instruction, instrumentation);
-                } else {
-                    newMethodNode.instructions.insertBefore(instruction, instrumentation);
-                }
-            }
-        }
-        // dump a byte array and load the class with a dedicated loader to separate the namespace
-        ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
-        classNode.accept(classWriter);
-        byte[] bytes = classWriter.toByteArray();
-        return new Loader(className, bytes).findClass(className);
-    }
-
-    private static class Loader extends ExportingClassLoader {
-
-        private String className;
-        private byte[] bytes;
-
-        Loader(String className, byte[] bytes) {
-            super(TinyInstrumentor.class.getClassLoader());
-            this.className = className;
-            this.bytes = bytes;
-        }
-
-        @Override
-        protected Class<?> findClass(String name) throws ClassNotFoundException {
-            if (name.equals(className)) {
-                return defineClass(name, bytes, 0, bytes.length);
-            } else {
-                return super.findClass(name);
-            }
-        }
-    }
-
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives/src/org/graalvm/compiler/api/directives/GraalDirectives.java	Thu Apr 06 21:14:07 2017 +0000
@@ -22,8 +22,6 @@
  */
 package org.graalvm.compiler.api.directives;
 
-import java.nio.charset.Charset;
-
 // JaCoCo Exclude
 
 /**
@@ -367,67 +365,4 @@
      */
     public static void ensureVirtualizedHere(@SuppressWarnings("unused") Object object) {
     }
-
-    /**
-     * Marks the beginning of an instrumentation boundary. The instrumentation code will be folded
-     * during compilation and will not affect inlining heuristics regarding graph size except one on
-     * compiled low-level graph size (e.g., {@code GraalOptions.SmallCompiledLowLevelGraphSize}).
-     */
-    public static void instrumentationBegin() {
-    }
-
-    /**
-     * Marks the beginning of an instrumentation boundary and associates the instrumentation with
-     * the preceding bytecode. If the instrumented instruction is {@code new}, then instrumentation
-     * will adapt to optimizations concerning allocation, and only be executed if allocation really
-     * happens.
-     *
-     * Example (the instrumentation is associated with {@code new}):
-     *
-     * <blockquote>
-     *
-     * <pre>
-     *  0  new java.lang.Object
-     *  3  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationBeginForPredecessor() : void
-     *  6  invokestatic AllocationProfiler.countActualAllocation() : void
-     *  9  invokestatic org.graalvm.compiler.api.directives.GraalDirectives.instrumentationEnd() : void
-     * 12  invokespecial java.lang.Object()
-     * </pre>
-     *
-     * </blockquote>
-     *
-     * @see #instrumentationBegin()
-     */
-    public static void instrumentationBeginForPredecessor() {
-    }
-
-    /**
-     * Marks the end of the instrumentation boundary.
-     *
-     * @see #instrumentationBegin()
-     */
-    public static void instrumentationEnd() {
-    }
-
-    /**
-     * @return true if the enclosing method is inlined.
-     */
-    public static boolean isMethodInlined() {
-        return false;
-    }
-
-    private static final Charset UTF8 = Charset.forName("UTF-8");
-
-    /**
-     * @return the name of the root method for the current compilation task. If the enclosing method
-     *         is inlined, it returns the name of the method into which it is inlined.
-     */
-    public static String rootName() {
-        return new String(rawRootName(), UTF8);
-    }
-
-    public static byte[] rawRootName() {
-        return new byte[0];
-    }
-
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.replacements/src/org/graalvm/compiler/api/replacements/Snippet.java	Thu Apr 06 21:14:07 2017 +0000
@@ -54,4 +54,13 @@
     @Target(ElementType.PARAMETER)
     public @interface ConstantParameter {
     }
+
+    /**
+     * Denotes a snippet parameter that will bound to a non-null value during snippet template
+     * instantiation.
+     */
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target(ElementType.PARAMETER)
+    public @interface NonNullParameter {
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/AArch64MacroAssemblerTest.java	Thu Apr 06 21:14:07 2017 +0000
@@ -31,7 +31,7 @@
 import org.junit.Before;
 import org.junit.Test;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.aarch64.AArch64Address;
 import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -226,12 +226,12 @@
     }
 
     @Override
-    protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
+    public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
         super.adds(size, dst, src1, src2, shiftType, imm);
     }
 
     @Override
-    protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
+    public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
         super.subs(size, dst, src1, src2, shiftType, imm);
     }
 
@@ -261,7 +261,7 @@
     }
 
     @Override
-    protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
+    public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
         super.subs(size, dst, src1, src2, extendType, shiftAmt);
     }
 
@@ -336,7 +336,7 @@
     }
 
     @Override
-    protected void rbit(int size, Register dst, Register src) {
+    public void rbit(int size, Register dst, Register src) {
         super.rbit(size, dst, src);
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Address.java	Thu Apr 06 21:14:07 2017 +0000
@@ -25,7 +25,7 @@
 import static jdk.vm.ci.aarch64.AArch64.zr;
 
 import org.graalvm.compiler.asm.AbstractAddress;
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.debug.GraalError;
 
 import jdk.vm.ci.aarch64.AArch64;
@@ -274,7 +274,7 @@
     /**
      * @return immediate in correct representation for the given addressing mode. For example in
      *         case of <code>addressingMode ==IMMEDIATE_UNSCALED </code> the value will be returned
-     *         as the 9bit signed representation.
+     *         as the 9-bit signed representation.
      */
     public int getImmediate() {
         switch (addressingMode) {
@@ -282,12 +282,15 @@
             case IMMEDIATE_POST_INDEXED:
             case IMMEDIATE_PRE_INDEXED:
                 // 9-bit signed value
+                assert NumUtil.isSignedNbit(9, immediate);
                 return immediate & NumUtil.getNbitNumberInt(9);
             case IMMEDIATE_SCALED:
                 // Unsigned value can be returned as-is.
+                assert NumUtil.isUnsignedNbit(9, immediate);
                 return immediate;
             case PC_LITERAL:
                 // 21-bit signed value, but lower 2 bits are always 0 and are shifted out.
+                assert NumUtil.isSignedNbit(19, immediate >> 2);
                 return (immediate >> 2) & NumUtil.getNbitNumberInt(19);
             default:
                 throw GraalError.shouldNotReachHere("Should only be called for addressing modes that use immediate values.");
@@ -356,4 +359,29 @@
         }
     }
 
+    /**
+     * Loads an address into Register r.
+     *
+     * @param masm the macro assembler.
+     * @param r general purpose register. May not be null.
+     */
+    public void lea(AArch64MacroAssembler masm, Register r) {
+        switch (addressingMode) {
+            case IMMEDIATE_UNSCALED:
+                if (immediate == 0 && base.equals(r)) { // it's a nop
+                    break;
+                }
+                masm.add(64, r, base, immediate);
+                break;
+            case REGISTER_OFFSET:
+                masm.add(64, r, base, offset);
+                break;
+            case PC_LITERAL: {
+                masm.mov(r, getImmediate());
+                break;
+            }
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -111,7 +111,7 @@
 import java.util.Arrays;
 
 import org.graalvm.compiler.asm.Assembler;
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
 import org.graalvm.compiler.debug.GraalError;
 
@@ -347,6 +347,11 @@
         return reg.encoding << RnOffset;
     }
 
+    private static int maskField(int sizeInBits, int n) {
+        assert NumUtil.isSignedNbit(sizeInBits, n);
+        return n & NumUtil.getNbitNumberInt(sizeInBits);
+    }
+
     /**
      * Enumeration of all different instruction kinds: General32/64 are the general instructions
      * (integer, branch, etc.), for 32-, respectively 64-bit operands. FP32/64 is the encoding for
@@ -448,7 +453,7 @@
     private static final int LoadStoreFpFlagOffset = 26;
     private static final int LoadLiteralImmeOffset = 5;
 
-    private static final int LoadStorePairOp = 0b101_0_010 << 23;
+    private static final int LoadStorePairOp = 0b101_0 << 26;
     @SuppressWarnings("unused") private static final int LoadStorePairPostIndexOp = 0b101_0_001 << 23;
     @SuppressWarnings("unused") private static final int LoadStorePairPreIndexOp = 0b101_0_011 << 23;
     private static final int LoadStorePairImm7Offset = 15;
@@ -978,7 +983,9 @@
     }
 
     /**
-     *
+     * Load Pair of Registers calculates an address from a base register value and an immediate
+     * offset, and stores two 32-bit words or two 64-bit doublewords to the calculated address, from
+     * two registers.
      */
     public void ldp(int size, Register rt, Register rt2, AArch64Address address) {
         assert size == 32 || size == 64;
@@ -996,10 +1003,18 @@
     }
 
     private void loadStorePairInstruction(Instruction instr, Register rt, Register rt2, AArch64Address address, InstructionType type) {
-        int memop = type.encoding | instr.encoding | address.getImmediate() << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt);
+        int scaledOffset = maskField(7, address.getImmediateRaw());  // LDP/STP use a 7-bit scaled
+                                                                     // offset
+        int memop = type.encoding | instr.encoding | scaledOffset << LoadStorePairImm7Offset | rt2(rt2) | rn(address.getBase()) | rt(rt);
         switch (address.getAddressingMode()) {
-            case IMMEDIATE_UNSCALED:
-                emitInt(memop | LoadStorePairOp);
+            case IMMEDIATE_SCALED:
+                emitInt(memop | LoadStorePairOp | (0b010 << 23));
+                break;
+            case IMMEDIATE_POST_INDEXED:
+                emitInt(memop | LoadStorePairOp | (0b001 << 23));
+                break;
+            case IMMEDIATE_PRE_INDEXED:
+                emitInt(memop | LoadStorePairOp | (0b011 << 23));
                 break;
             default:
                 throw GraalError.shouldNotReachHere("Unhandled addressing mode: " + address.getAddressingMode());
@@ -1471,7 +1486,7 @@
      * @param shiftType any type but ROR.
      * @param imm must be in range 0 to size - 1.
      */
-    protected void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
+    public void adds(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
         addSubShiftedInstruction(ADDS, dst, src1, src2, shiftType, imm, generalFromSize(size));
     }
 
@@ -1499,7 +1514,7 @@
      * @param shiftType any type but ROR.
      * @param imm must be in range 0 to size - 1.
      */
-    protected void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
+    public void subs(int size, Register dst, Register src1, Register src2, ShiftType shiftType, int imm) {
         addSubShiftedInstruction(SUBS, dst, src1, src2, shiftType, imm, generalFromSize(size));
     }
 
@@ -1571,7 +1586,7 @@
      * @param extendType defines how src2 is extended to the same size as src1.
      * @param shiftAmt must be in range 0 to 4.
      */
-    protected void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
+    public void subs(int size, Register dst, Register src1, Register src2, ExtendType extendType, int shiftAmt) {
         assert !dst.equals(sp);
         assert !src1.equals(zr);
         assert !src2.equals(sp);
@@ -1786,7 +1801,7 @@
      * @param dst general purpose register. May not be null, zero-register or the stackpointer.
      * @param src source register. May not be null, zero-register or the stackpointer.
      */
-    protected void rbit(int size, Register dst, Register src) {
+    public void rbit(int size, Register dst, Register src) {
         dataProcessing1SourceOp(RBIT, dst, src, generalFromSize(size));
     }
 
@@ -1934,7 +1949,7 @@
      * @param src2 general purpose register. May not be null or the stackpointer.
      * @param src3 general purpose register. May not be null or the stackpointer.
      */
-    protected void smaddl(Register dst, Register src1, Register src2, Register src3) {
+    public void smaddl(Register dst, Register src1, Register src2, Register src3) {
         assert !dst.equals(sp);
         assert !src1.equals(sp);
         assert !src2.equals(sp);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64MacroAssembler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -39,7 +39,7 @@
 
 import org.graalvm.compiler.asm.AbstractAddress;
 import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.debug.GraalError;
 
 import jdk.vm.ci.aarch64.AArch64;
@@ -196,6 +196,7 @@
                 break;
             case ADD_TO_INDEX:
                 newIndex = allowOverwrite ? index : additionalReg;
+                assert !newIndex.equals(sp) && !newIndex.equals(zr);
                 if (plan.needsScratch) {
                     mov(additionalReg, scaledDisplacement);
                     add(signExtendIndex ? 32 : 64, newIndex, index, additionalReg);
@@ -206,6 +207,7 @@
                 break;
             case ADD_TO_BASE:
                 newBase = allowOverwrite ? base : additionalReg;
+                assert !newBase.equals(sp) && !newBase.equals(zr);
                 if (plan.needsScratch) {
                     mov(additionalReg, displacement);
                     add(64, newBase, base, additionalReg);
@@ -412,6 +414,19 @@
     }
 
     /**
+     * Generates a 32-bit immediate move code sequence. The immediate may later be updated by
+     * HotSpot.
+     *
+     * @param dst general purpose register. May not be null, stackpointer or zero-register.
+     * @param imm
+     */
+    public void movNarrowAddress(Register dst, long imm) {
+        assert (imm & 0xFFFF_FFFF_0000_0000L) == 0;
+        movz(64, dst, (int) (imm >>> 16), 16);
+        movk(64, dst, (int) (imm & 0xffff), 0);
+    }
+
+    /**
      * @return Number of instructions necessary to load immediate into register.
      */
     public static int nrInstructionsToMoveImmediate(long imm) {
@@ -456,6 +471,19 @@
     }
 
     /**
+     * Loads a srcSize value from address into rt zero-extending it if necessary.
+     *
+     * @param srcSize size of memory read in bits. Must be 8, 16 or 32 and smaller or equal to
+     *            targetSize.
+     * @param rt general purpose register. May not be null or stackpointer.
+     * @param address all addressing modes allowed. May not be null.
+     */
+    @Override
+    public void ldr(int srcSize, Register rt, AArch64Address address) {
+        super.ldr(srcSize, rt, address);
+    }
+
+    /**
      * Conditional move. dst = src1 if condition else src2.
      *
      * @param size register size. Has to be 32 or 64.
@@ -482,52 +510,47 @@
      * dst = src1 + src2.
      *
      * @param size register size. Has to be 32 or 64.
-     * @param dst general purpose register. May not be null or stackpointer.
-     * @param src1 general purpose register. May not be null or stackpointer.
+     * @param dst general purpose register. May not be null.
+     * @param src1 general purpose register. May not be null.
      * @param src2 general purpose register. May not be null or stackpointer.
      */
     public void add(int size, Register dst, Register src1, Register src2) {
-        super.add(size, dst, src1, src2, ShiftType.LSL, 0);
+        if (dst.equals(sp) || src1.equals(sp)) {
+            super.add(size, dst, src1, src2, ExtendType.UXTX, 0);
+        } else {
+            super.add(size, dst, src1, src2, ShiftType.LSL, 0);
+        }
     }
 
     /**
      * dst = src1 + src2 and sets condition flags.
      *
      * @param size register size. Has to be 32 or 64.
-     * @param dst general purpose register. May not be null or stackpointer.
-     * @param src1 general purpose register. May not be null or stackpointer.
+     * @param dst general purpose register. May not be null.
+     * @param src1 general purpose register. May not be null.
      * @param src2 general purpose register. May not be null or stackpointer.
      */
     public void adds(int size, Register dst, Register src1, Register src2) {
-        super.adds(size, dst, src1, src2, getNopExtendType(size), 0);
+        if (dst.equals(sp) || src1.equals(sp)) {
+            super.adds(size, dst, src1, src2, ExtendType.UXTX, 0);
+        } else {
+            super.adds(size, dst, src1, src2, ShiftType.LSL, 0);
+        }
     }
 
     /**
      * dst = src1 - src2 and sets condition flags.
      *
      * @param size register size. Has to be 32 or 64.
-     * @param dst general purpose register. May not be null or stackpointer.
-     * @param src1 general purpose register. May not be null or stackpointer.
+     * @param dst general purpose register. May not be null.
+     * @param src1 general purpose register. May not be null.
      * @param src2 general purpose register. May not be null or stackpointer.
      */
     public void subs(int size, Register dst, Register src1, Register src2) {
-        super.subs(size, dst, src1, src2, getNopExtendType(size), 0);
-    }
-
-    /**
-     * Returns the ExtendType for the given size that corresponds to a no-op.
-     *
-     * I.e. when doing add X0, X1, X2, the actual instruction has the form add X0, X1, X2 UXTX.
-     *
-     * @param size
-     */
-    private static ExtendType getNopExtendType(int size) {
-        if (size == 64) {
-            return ExtendType.UXTX;
-        } else if (size == 32) {
-            return ExtendType.UXTW;
+        if (dst.equals(sp) || src1.equals(sp)) {
+            super.subs(size, dst, src1, src2, ExtendType.UXTX, 0);
         } else {
-            throw GraalError.shouldNotReachHere("No-op ");
+            super.subs(size, dst, src1, src2, ShiftType.LSL, 0);
         }
     }
 
@@ -535,12 +558,16 @@
      * dst = src1 - src2.
      *
      * @param size register size. Has to be 32 or 64.
-     * @param dst general purpose register. May not be null or stackpointer.
-     * @param src1 general purpose register. May not be null or stackpointer.
+     * @param dst general purpose register. May not be null.
+     * @param src1 general purpose register. May not be null.
      * @param src2 general purpose register. May not be null or stackpointer.
      */
     public void sub(int size, Register dst, Register src1, Register src2) {
-        super.sub(size, dst, src1, src2, ShiftType.LSL, 0);
+        if (dst.equals(sp) || src1.equals(sp)) {
+            super.sub(size, dst, src1, src2, ExtendType.UXTX, 0);
+        } else {
+            super.sub(size, dst, src1, src2, ShiftType.LSL, 0);
+        }
     }
 
     /**
@@ -590,16 +617,26 @@
      * dst = src + immediate.
      *
      * @param size register size. Has to be 32 or 64.
-     * @param dst general purpose register. May not be null or stackpointer.
-     * @param src general purpose register. May not be null or stackpointer.
-     * @param immediate arithmetic immediate
+     * @param dst general purpose register. May not be null or zero-register.
+     * @param src general purpose register. May not be null or zero-register.
+     * @param immediate 32-bit signed int
      */
     @Override
     public void add(int size, Register dst, Register src, int immediate) {
+        assert (!dst.equals(zr) && !src.equals(zr));
         if (immediate < 0) {
             sub(size, dst, src, -immediate);
-        } else if (!(dst.equals(src) && immediate == 0)) {
-            super.add(size, dst, src, immediate);
+        } else if (isAimm(immediate)) {
+            if (!(dst.equals(src) && immediate == 0)) {
+                super.add(size, dst, src, immediate);
+            }
+        } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) {
+            super.add(size, dst, src, immediate & -(1 << 12));
+            super.add(size, dst, dst, immediate & ((1 << 12) - 1));
+        } else {
+            assert !dst.equals(src);
+            mov(dst, immediate);
+            add(size, src, dst, dst);
         }
     }
 
@@ -613,6 +650,7 @@
      */
     @Override
     public void adds(int size, Register dst, Register src, int immediate) {
+        assert (!dst.equals(sp) && !src.equals(zr));
         if (immediate < 0) {
             subs(size, dst, src, -immediate);
         } else if (!(dst.equals(src) && immediate == 0)) {
@@ -624,16 +662,26 @@
      * dst = src - immediate.
      *
      * @param size register size. Has to be 32 or 64.
-     * @param dst general purpose register. May not be null or stackpointer.
-     * @param src general purpose register. May not be null or stackpointer.
-     * @param immediate arithmetic immediate
+     * @param dst general purpose register. May not be null or zero-register.
+     * @param src general purpose register. May not be null or zero-register.
+     * @param immediate 32-bit signed int
      */
     @Override
     public void sub(int size, Register dst, Register src, int immediate) {
+        assert (!dst.equals(zr) && !src.equals(zr));
         if (immediate < 0) {
             add(size, dst, src, -immediate);
-        } else if (!dst.equals(src) || immediate != 0) {
-            super.sub(size, dst, src, immediate);
+        } else if (isAimm(immediate)) {
+            if (!(dst.equals(src) && immediate == 0)) {
+                super.sub(size, dst, src, immediate);
+            }
+        } else if (immediate >= -(1 << 24) && immediate < (1 << 24)) {
+            super.sub(size, dst, src, immediate & -(1 << 12));
+            super.sub(size, dst, dst, immediate & ((1 << 12) - 1));
+        } else {
+            assert !dst.equals(src);
+            mov(dst, immediate);
+            sub(size, src, dst, dst);
         }
     }
 
@@ -647,10 +695,11 @@
      */
     @Override
     public void subs(int size, Register dst, Register src, int immediate) {
+        assert (!dst.equals(sp) && !src.equals(zr));
         if (immediate < 0) {
             adds(size, dst, src, -immediate);
         } else if (!dst.equals(src) || immediate != 0) {
-            super.sub(size, dst, src, immediate);
+            super.subs(size, dst, src, immediate);
         }
     }
 
@@ -675,6 +724,7 @@
      * @param src2 general purpose register. May not be null or the stackpointer.
      */
     public void umulh(int size, Register dst, Register src1, Register src2) {
+        assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp));
         assert size == 32 || size == 64;
         if (size == 64) {
             super.umulh(dst, src1, src2);
@@ -695,6 +745,7 @@
      * @param src2 general purpose register. May not be null or the stackpointer.
      */
     public void smulh(int size, Register dst, Register src1, Register src2) {
+        assert (!dst.equals(sp) && !src1.equals(sp) && !src2.equals(sp));
         assert size == 32 || size == 64;
         if (size == 64) {
             super.smulh(dst, src1, src2);
@@ -715,6 +766,7 @@
      * @param d denominator. General purpose register. Divisor May not be null or the stackpointer.
      */
     public void rem(int size, Register dst, Register n, Register d) {
+        assert (!dst.equals(sp) && !n.equals(sp) && !d.equals(sp));
         // There is no irem or similar instruction. Instead we use the relation:
         // n % d = n - Floor(n / d) * d if nd >= 0
         // n % d = n - Ceil(n / d) * d else
@@ -940,16 +992,14 @@
     /**
      * Sign-extend value from src into dst.
      *
-     * @param destSize destination register size. Has to be 32 or 64.
-     * @param srcSize source register size. May be 8, 16 or 32 and smaller than destSize.
+     * @param destSize destination register size. Must be 32 or 64.
+     * @param srcSize source register size. Must be smaller than destSize.
      * @param dst general purpose register. May not be null, stackpointer or zero-register.
      * @param src general purpose register. May not be null, stackpointer or zero-register.
      */
     public void sxt(int destSize, int srcSize, Register dst, Register src) {
-        assert (destSize == 32 || destSize == 64) && srcSize < destSize;
-        assert srcSize == 8 || srcSize == 16 || srcSize == 32;
-        int[] srcSizeValues = {7, 15, 31};
-        super.sbfm(destSize, dst, src, 0, srcSizeValues[NumUtil.log2Ceil(srcSize / 8)]);
+        assert (srcSize < destSize && srcSize > 0);
+        super.sbfm(destSize, dst, src, 0, srcSize - 1);
     }
 
     /**
@@ -1078,6 +1128,7 @@
      * @param y general purpose register. May not be null or stackpointer.
      */
     public void cmp(int size, Register x, Register y) {
+        assert size == 32 || size == 64;
         super.subs(size, zr, x, y, ShiftType.LSL, 0);
     }
 
@@ -1089,6 +1140,7 @@
      * @param y comparison immediate, {@link #isComparisonImmediate(long)} has to be true for it.
      */
     public void cmp(int size, Register x, int y) {
+        assert size == 32 || size == 64;
         if (y < 0) {
             super.adds(size, zr, x, -y);
         } else {
@@ -1109,6 +1161,54 @@
     }
 
     /**
+     * Sets overflow flag according to result of x * y.
+     *
+     * @param size register size. Has to be 32 or 64.
+     * @param dst general purpose register. May not be null or stack-pointer.
+     * @param x general purpose register. May not be null or stackpointer.
+     * @param y general purpose register. May not be null or stackpointer.
+     */
+    public void mulvs(int size, Register dst, Register x, Register y) {
+        try (ScratchRegister sc1 = getScratchRegister();
+                        ScratchRegister sc2 = getScratchRegister()) {
+            switch (size) {
+                case 64: {
+                    // Be careful with registers: it's possible that x, y, and dst are the same
+                    // register.
+                    Register rscratch1 = sc1.getRegister();
+                    Register rscratch2 = sc2.getRegister();
+                    mul(64, rscratch1, x, y);     // Result bits 0..63
+                    smulh(64, rscratch2, x, y);  // Result bits 64..127
+                    // Top is pure sign ext
+                    subs(64, zr, rscratch2, rscratch1, ShiftType.ASR, 63);
+                    // Copy all 64 bits of the result into dst
+                    mov(64, dst, rscratch1);
+                    mov(rscratch1, 0x80000000);
+                    // Develop 0 (EQ), or 0x80000000 (NE)
+                    cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE);
+                    cmp(32, rscratch1, 1);
+                    // 0x80000000 - 1 => VS
+                    break;
+                }
+                case 32: {
+                    Register rscratch1 = sc1.getRegister();
+                    smaddl(rscratch1, x, y, zr);
+                    // Copy the low 32 bits of the result into dst
+                    mov(32, dst, rscratch1);
+                    subs(64, zr, rscratch1, rscratch1, ExtendType.SXTW, 0);
+                    // NE => overflow
+                    mov(rscratch1, 0x80000000);
+                    // Develop 0 (EQ), or 0x80000000 (NE)
+                    cmov(32, rscratch1, rscratch1, zr, ConditionFlag.NE);
+                    cmp(32, rscratch1, 1);
+                    // 0x80000000 - 1 => VS
+                    break;
+                }
+            }
+        }
+    }
+
+    /**
      * When patching up Labels we have to know what kind of code to generate.
      */
     public enum PatchLabelKind {
@@ -1353,7 +1453,8 @@
                 super.b(branchOffset, branch);
                 break;
             case JUMP_ADDRESS:
-                emitInt(jumpTarget, branch);
+                int offset = instruction >>> PatchLabelKind.INFORMATION_OFFSET;
+                emitInt(jumpTarget - offset, branch);
                 break;
             case BRANCH_NONZERO:
             case BRANCH_ZERO: {
@@ -1404,4 +1505,14 @@
     public AbstractAddress getPlaceholder(int instructionStartPosition) {
         return AArch64Address.PLACEHOLDER;
     }
+
+    /**
+     * Loads an address into Register d.
+     *
+     * @param d general purpose register. May not be null.
+     * @param a AArch64Address the address of an operand.
+     */
+    public void lea(Register d, AArch64Address a) {
+        a.lea(this, d);
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Address.java	Thu Apr 06 21:14:07 2017 +0000
@@ -66,6 +66,18 @@
     }
 
     /**
+     * Creates an {@link AMD64Address} with given base and index registers, scaling and 0
+     * displacement.
+     *
+     * @param base the base register
+     * @param index the index register
+     * @param scale the scaling factor
+     */
+    public AMD64Address(Register base, Register index, Scale scale) {
+        this(base, index, scale, 0, -1);
+    }
+
+    /**
      * Creates an {@link AMD64Address} with given base and index registers, scaling and
      * displacement. This is the most general constructor.
      *
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64Assembler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -22,10 +22,10 @@
  */
 package org.graalvm.compiler.asm.amd64;
 
-import static org.graalvm.compiler.asm.NumUtil.isByte;
-import static org.graalvm.compiler.asm.NumUtil.isInt;
-import static org.graalvm.compiler.asm.NumUtil.isShiftCount;
-import static org.graalvm.compiler.asm.NumUtil.isUByte;
+import static org.graalvm.compiler.core.common.NumUtil.isByte;
+import static org.graalvm.compiler.core.common.NumUtil.isInt;
+import static org.graalvm.compiler.core.common.NumUtil.isShiftCount;
+import static org.graalvm.compiler.core.common.NumUtil.isUByte;
 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseAddressNop;
 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseNormalNop;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.ADD;
@@ -58,7 +58,7 @@
 
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
 
 import jdk.vm.ci.amd64.AMD64;
@@ -2494,6 +2494,24 @@
         emitByte(0xC0 | encode);
     }
 
+    void pcmpestri(Register dst, AMD64Address src, int imm8) {
+        assert supports(CPUFeature.SSE4_2);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+        simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes);
+        emitByte(0x61);
+        emitOperandHelper(dst, src, 0);
+        emitByte(imm8);
+    }
+
+    void pcmpestri(Register dst, Register src, int imm8) {
+        assert supports(CPUFeature.SSE4_2);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+        int encode = simdPrefixAndEncode(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F_3A, attributes);
+        emitByte(0x61);
+        emitByte(0xC0 | encode);
+        emitByte(imm8);
+    }
+
     public final void push(Register src) {
         int encode = prefixAndEncode(src.encoding);
         emitByte(0x50 | encode);
@@ -2633,6 +2651,16 @@
         emitByte(imm8);
     }
 
+    public final void psrldq(Register dst, int imm8) {
+        assert isUByte(imm8) : "invalid value";
+        assert dst.getRegisterCategory().equals(AMD64.XMM);
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+        int encode = simdPrefixAndEncode(AMD64.xmm3, dst, dst, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+        emitByte(0x73);
+        emitByte(0xC0 | encode);
+        emitByte(imm8);
+    }
+
     public final void pshufd(Register dst, Register src, int imm8) {
         assert isUByte(imm8) : "invalid value";
         assert dst.getRegisterCategory().equals(AMD64.XMM) && src.getRegisterCategory().equals(AMD64.XMM);
@@ -3322,6 +3350,13 @@
         }
     }
 
+    public final void movdl(Register dst, AMD64Address src) {
+        AMD64InstructionAttr attributes = new AMD64InstructionAttr(AvxVectorLen.AVX_128bit, /* rexVexW */ false, /* legacyMode */ false, /* noMaskReg */ false, /* usesVl */ false, target);
+        simdPrefix(dst, Register.None, src, VexSimdPrefix.VEX_SIMD_66, VexOpcode.VEX_OPCODE_0F, attributes);
+        emitByte(0x6E);
+        emitOperandHelper(dst, src, 0);
+    }
+
     public final void movddup(Register dst, Register src) {
         assert supports(CPUFeature.SSE3);
         assert dst.getRegisterCategory().equals(AMD64.XMM);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.amd64/src/org/graalvm/compiler/asm/amd64/AMD64MacroAssembler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -22,11 +22,17 @@
  */
 package org.graalvm.compiler.asm.amd64;
 
+import static jdk.vm.ci.amd64.AMD64.rax;
+import static jdk.vm.ci.amd64.AMD64.rcx;
+import static jdk.vm.ci.amd64.AMD64.rdx;
+import static jdk.vm.ci.amd64.AMD64.rsp;
 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseIncDec;
 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmLoadAndClearUpper;
 import static org.graalvm.compiler.asm.amd64.AMD64AsmOptions.UseXmmRegToRegMoveAll;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
 
 import jdk.vm.ci.amd64.AMD64;
 import jdk.vm.ci.amd64.AMD64Kind;
@@ -138,6 +144,10 @@
         cmpq(src1, src2);
     }
 
+    public final void decrementl(Register reg) {
+        decrementl(reg, 1);
+    }
+
     public final void decrementl(Register reg, int value) {
         if (value == Integer.MIN_VALUE) {
             subl(reg, value);
@@ -321,4 +331,434 @@
         movdbl(dest, tmp);
         addq(AMD64.rsp, AMD64Kind.DOUBLE.getSizeInBytes());
     }
+
+    // IndexOf for constant substrings with size >= 8 chars
+    // which don't need to be loaded through stack.
+    public void stringIndexofC8(Register str1, Register str2,
+                    Register cnt1, Register cnt2,
+                    int intCnt2, Register result,
+                    Register vec, Register tmp) {
+        // assert(UseSSE42Intrinsics, "SSE4.2 is required");
+
+        // This method uses pcmpestri inxtruction with bound registers
+        // inputs:
+        // xmm - substring
+        // rax - substring length (elements count)
+        // mem - scanned string
+        // rdx - string length (elements count)
+        // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
+        // outputs:
+        // rcx - matched index in string
+        assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
+
+        Label reloadSubstr = new Label();
+        Label scanToSubstr = new Label();
+        Label scanSubstr = new Label();
+        Label retFound = new Label();
+        Label retNotFound = new Label();
+        Label exit = new Label();
+        Label foundSubstr = new Label();
+        Label matchSubstrHead = new Label();
+        Label reloadStr = new Label();
+        Label foundCandidate = new Label();
+
+        // Note, inline_string_indexOf() generates checks:
+        // if (substr.count > string.count) return -1;
+        // if (substr.count == 0) return 0;
+        assert intCnt2 >= 8 : "this code isused only for cnt2 >= 8 chars";
+
+        // Load substring.
+        movdqu(vec, new AMD64Address(str2, 0));
+        movl(cnt2, intCnt2);
+        movq(result, str1); // string addr
+
+        if (intCnt2 > 8) {
+            jmpb(scanToSubstr);
+
+            // Reload substr for rescan, this code
+            // is executed only for large substrings (> 8 chars)
+            bind(reloadSubstr);
+            movdqu(vec, new AMD64Address(str2, 0));
+            negq(cnt2); // Jumped here with negative cnt2, convert to positive
+
+            bind(reloadStr);
+            // We came here after the beginning of the substring was
+            // matched but the rest of it was not so we need to search
+            // again. Start from the next element after the previous match.
+
+            // cnt2 is number of substring reminding elements and
+            // cnt1 is number of string reminding elements when cmp failed.
+            // Restored cnt1 = cnt1 - cnt2 + int_cnt2
+            subl(cnt1, cnt2);
+            addl(cnt1, intCnt2);
+            movl(cnt2, intCnt2); // Now restore cnt2
+
+            decrementl(cnt1, 1);     // Shift to next element
+            cmpl(cnt1, cnt2);
+            jccb(ConditionFlag.Negative, retNotFound);  // Left less then substring
+
+            addq(result, 2);
+
+        } // (int_cnt2 > 8)
+
+        // Scan string for start of substr in 16-byte vectors
+        bind(scanToSubstr);
+        pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
+        jccb(ConditionFlag.Below, foundCandidate);   // CF == 1
+        subl(cnt1, 8);
+        jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string
+        cmpl(cnt1, cnt2);
+        jccb(ConditionFlag.Negative, retNotFound);  // Left less then substring
+        addq(result, 16);
+        jmpb(scanToSubstr);
+
+        // Found a potential substr
+        bind(foundCandidate);
+        // Matched whole vector if first element matched (tmp(rcx) == 0).
+        if (intCnt2 == 8) {
+            jccb(ConditionFlag.Overflow, retFound);    // OF == 1
+        } else { // int_cnt2 > 8
+            jccb(ConditionFlag.Overflow, foundSubstr);
+        }
+        // After pcmpestri tmp(rcx) contains matched element index
+        // Compute start addr of substr
+        leaq(result, new AMD64Address(result, tmp, Scale.Times2, 0));
+
+        // Make sure string is still long enough
+        subl(cnt1, tmp);
+        cmpl(cnt1, cnt2);
+        if (intCnt2 == 8) {
+            jccb(ConditionFlag.GreaterEqual, scanToSubstr);
+        } else { // int_cnt2 > 8
+            jccb(ConditionFlag.GreaterEqual, matchSubstrHead);
+        }
+        // Left less then substring.
+
+        bind(retNotFound);
+        movl(result, -1);
+        jmpb(exit);
+
+        if (intCnt2 > 8) {
+            // This code is optimized for the case when whole substring
+            // is matched if its head is matched.
+            bind(matchSubstrHead);
+            pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
+            // Reload only string if does not match
+            jccb(ConditionFlag.NoOverflow, reloadStr); // OF == 0
+
+            Label contScanSubstr = new Label();
+            // Compare the rest of substring (> 8 chars).
+            bind(foundSubstr);
+            // First 8 chars are already matched.
+            negq(cnt2);
+            addq(cnt2, 8);
+
+            bind(scanSubstr);
+            subl(cnt1, 8);
+            cmpl(cnt2, -8); // Do not read beyond substring
+            jccb(ConditionFlag.LessEqual, contScanSubstr);
+            // Back-up strings to avoid reading beyond substring:
+            // cnt1 = cnt1 - cnt2 + 8
+            addl(cnt1, cnt2); // cnt2 is negative
+            addl(cnt1, 8);
+            movl(cnt2, 8);
+            negq(cnt2);
+            bind(contScanSubstr);
+            if (intCnt2 < 1024 * 1024 * 1024) {
+                movdqu(vec, new AMD64Address(str2, cnt2, Scale.Times2, intCnt2 * 2));
+                pcmpestri(vec, new AMD64Address(result, cnt2, Scale.Times2, intCnt2 * 2), 0x0d);
+            } else {
+                // calculate index in register to avoid integer overflow (int_cnt2*2)
+                movl(tmp, intCnt2);
+                addq(tmp, cnt2);
+                movdqu(vec, new AMD64Address(str2, tmp, Scale.Times2, 0));
+                pcmpestri(vec, new AMD64Address(result, tmp, Scale.Times2, 0), 0x0d);
+            }
+            // Need to reload strings pointers if not matched whole vector
+            jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0
+            addq(cnt2, 8);
+            jcc(ConditionFlag.Negative, scanSubstr);
+            // Fall through if found full substring
+
+        } // (int_cnt2 > 8)
+
+        bind(retFound);
+        // Found result if we matched full small substring.
+        // Compute substr offset
+        subq(result, str1);
+        shrl(result, 1); // index
+        bind(exit);
+
+    } // string_indexofC8
+
+    // Small strings are loaded through stack if they cross page boundary.
+    public void stringIndexOf(Register str1, Register str2,
+                    Register cnt1, Register cnt2,
+                    int intCnt2, Register result,
+                    Register vec, Register tmp, int vmPageSize) {
+        //
+        // int_cnt2 is length of small (< 8 chars) constant substring
+        // or (-1) for non constant substring in which case its length
+        // is in cnt2 register.
+        //
+        // Note, inline_string_indexOf() generates checks:
+        // if (substr.count > string.count) return -1;
+        // if (substr.count == 0) return 0;
+        //
+        assert intCnt2 == -1 || (0 < intCnt2 && intCnt2 < 8) : "should be != 0";
+
+        // This method uses pcmpestri instruction with bound registers
+        // inputs:
+        // xmm - substring
+        // rax - substring length (elements count)
+        // mem - scanned string
+        // rdx - string length (elements count)
+        // 0xd - mode: 1100 (substring search) + 01 (unsigned shorts)
+        // outputs:
+        // rcx - matched index in string
+        assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
+
+        Label reloadSubstr = new Label();
+        Label scanToSubstr = new Label();
+        Label scanSubstr = new Label();
+        Label adjustStr = new Label();
+        Label retFound = new Label();
+        Label retNotFound = new Label();
+        Label cleanup = new Label();
+        Label foundSubstr = new Label();
+        Label foundCandidate = new Label();
+
+        int wordSize = 8;
+        // We don't know where these strings are located
+        // and we can't read beyond them. Load them through stack.
+        Label bigStrings = new Label();
+        Label checkStr = new Label();
+        Label copySubstr = new Label();
+        Label copyStr = new Label();
+
+        movq(tmp, rsp); // save old SP
+
+        if (intCnt2 > 0) {     // small (< 8 chars) constant substring
+            if (intCnt2 == 1) {  // One char
+                movzwl(result, new AMD64Address(str2, 0));
+                movdl(vec, result); // move 32 bits
+            } else if (intCnt2 == 2) { // Two chars
+                movdl(vec, new AMD64Address(str2, 0)); // move 32 bits
+            } else if (intCnt2 == 4) { // Four chars
+                movq(vec, new AMD64Address(str2, 0));  // move 64 bits
+            } else { // cnt2 = { 3, 5, 6, 7 }
+                // Array header size is 12 bytes in 32-bit VM
+                // + 6 bytes for 3 chars == 18 bytes,
+                // enough space to load vec and shift.
+                movdqu(vec, new AMD64Address(str2, (intCnt2 * 2) - 16));
+                psrldq(vec, 16 - (intCnt2 * 2));
+            }
+        } else { // not constant substring
+            cmpl(cnt2, 8);
+            jccb(ConditionFlag.AboveEqual, bigStrings); // Both strings are big enough
+
+            // We can read beyond string if str+16 does not cross page boundary
+            // since heaps are aligned and mapped by pages.
+            assert vmPageSize < 1024 * 1024 * 1024 : "default page should be small";
+            movl(result, str2); // We need only low 32 bits
+            andl(result, (vmPageSize - 1));
+            cmpl(result, (vmPageSize - 16));
+            jccb(ConditionFlag.BelowEqual, checkStr);
+
+            // Move small strings to stack to allow load 16 bytes into vec.
+            subq(rsp, 16);
+            int stackOffset = wordSize - 2;
+            push(cnt2);
+
+            bind(copySubstr);
+            movzwl(result, new AMD64Address(str2, cnt2, Scale.Times2, -2));
+            movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
+            decrementl(cnt2, 1);
+            jccb(ConditionFlag.NotZero, copySubstr);
+
+            pop(cnt2);
+            movq(str2, rsp);  // New substring address
+        } // non constant
+
+        bind(checkStr);
+        cmpl(cnt1, 8);
+        jccb(ConditionFlag.AboveEqual, bigStrings);
+
+        // Check cross page boundary.
+        movl(result, str1); // We need only low 32 bits
+        andl(result, (vmPageSize - 1));
+        cmpl(result, (vmPageSize - 16));
+        jccb(ConditionFlag.BelowEqual, bigStrings);
+
+        subq(rsp, 16);
+        int stackOffset = -2;
+        if (intCnt2 < 0) { // not constant
+            push(cnt2);
+            stackOffset += wordSize;
+        }
+        movl(cnt2, cnt1);
+
+        bind(copyStr);
+        movzwl(result, new AMD64Address(str1, cnt2, Scale.Times2, -2));
+        movw(new AMD64Address(rsp, cnt2, Scale.Times2, stackOffset), result);
+        decrementl(cnt2, 1);
+        jccb(ConditionFlag.NotZero, copyStr);
+
+        if (intCnt2 < 0) { // not constant
+            pop(cnt2);
+        }
+        movq(str1, rsp);  // New string address
+
+        bind(bigStrings);
+        // Load substring.
+        if (intCnt2 < 0) { // -1
+            movdqu(vec, new AMD64Address(str2, 0));
+            push(cnt2);       // substr count
+            push(str2);       // substr addr
+            push(str1);       // string addr
+        } else {
+            // Small (< 8 chars) constant substrings are loaded already.
+            movl(cnt2, intCnt2);
+        }
+        push(tmp);  // original SP
+        // Finished loading
+
+        // ========================================================
+        // Start search
+        //
+
+        movq(result, str1); // string addr
+
+        if (intCnt2 < 0) {  // Only for non constant substring
+            jmpb(scanToSubstr);
+
+            // SP saved at sp+0
+            // String saved at sp+1*wordSize
+            // Substr saved at sp+2*wordSize
+            // Substr count saved at sp+3*wordSize
+
+            // Reload substr for rescan, this code
+            // is executed only for large substrings (> 8 chars)
+            bind(reloadSubstr);
+            movq(str2, new AMD64Address(rsp, 2 * wordSize));
+            movl(cnt2, new AMD64Address(rsp, 3 * wordSize));
+            movdqu(vec, new AMD64Address(str2, 0));
+            // We came here after the beginning of the substring was
+            // matched but the rest of it was not so we need to search
+            // again. Start from the next element after the previous match.
+            subq(str1, result); // Restore counter
+            shrl(str1, 1);
+            addl(cnt1, str1);
+            decrementl(cnt1);   // Shift to next element
+            cmpl(cnt1, cnt2);
+            jccb(ConditionFlag.Negative, retNotFound);  // Left less then substring
+
+            addq(result, 2);
+        } // non constant
+
+        // Scan string for start of substr in 16-byte vectors
+        bind(scanToSubstr);
+        assert cnt1.equals(rdx) && cnt2.equals(rax) && tmp.equals(rcx) : "pcmpestri";
+        pcmpestri(vec, new AMD64Address(result, 0), 0x0d);
+        jccb(ConditionFlag.Below, foundCandidate);   // CF == 1
+        subl(cnt1, 8);
+        jccb(ConditionFlag.LessEqual, retNotFound); // Scanned full string
+        cmpl(cnt1, cnt2);
+        jccb(ConditionFlag.Negative, retNotFound);  // Left less then substring
+        addq(result, 16);
+
+        bind(adjustStr);
+        cmpl(cnt1, 8); // Do not read beyond string
+        jccb(ConditionFlag.GreaterEqual, scanToSubstr);
+        // Back-up string to avoid reading beyond string.
+        leaq(result, new AMD64Address(result, cnt1, Scale.Times2, -16));
+        movl(cnt1, 8);
+        jmpb(scanToSubstr);
+
+        // Found a potential substr
+        bind(foundCandidate);
+        // After pcmpestri tmp(rcx) contains matched element index
+
+        // Make sure string is still long enough
+        subl(cnt1, tmp);
+        cmpl(cnt1, cnt2);
+        jccb(ConditionFlag.GreaterEqual, foundSubstr);
+        // Left less then substring.
+
+        bind(retNotFound);
+        movl(result, -1);
+        jmpb(cleanup);
+
+        bind(foundSubstr);
+        // Compute start addr of substr
+        leaq(result, new AMD64Address(result, tmp, Scale.Times2));
+
+        if (intCnt2 > 0) { // Constant substring
+            // Repeat search for small substring (< 8 chars)
+            // from new point without reloading substring.
+            // Have to check that we don't read beyond string.
+            cmpl(tmp, 8 - intCnt2);
+            jccb(ConditionFlag.Greater, adjustStr);
+            // Fall through if matched whole substring.
+        } else { // non constant
+            assert intCnt2 == -1 : "should be != 0";
+
+            addl(tmp, cnt2);
+            // Found result if we matched whole substring.
+            cmpl(tmp, 8);
+            jccb(ConditionFlag.LessEqual, retFound);
+
+            // Repeat search for small substring (<= 8 chars)
+            // from new point 'str1' without reloading substring.
+            cmpl(cnt2, 8);
+            // Have to check that we don't read beyond string.
+            jccb(ConditionFlag.LessEqual, adjustStr);
+
+            Label checkNext = new Label();
+            Label contScanSubstr = new Label();
+            Label retFoundLong = new Label();
+            // Compare the rest of substring (> 8 chars).
+            movq(str1, result);
+
+            cmpl(tmp, cnt2);
+            // First 8 chars are already matched.
+            jccb(ConditionFlag.Equal, checkNext);
+
+            bind(scanSubstr);
+            pcmpestri(vec, new AMD64Address(str1, 0), 0x0d);
+            // Need to reload strings pointers if not matched whole vector
+            jcc(ConditionFlag.NoOverflow, reloadSubstr); // OF == 0
+
+            bind(checkNext);
+            subl(cnt2, 8);
+            jccb(ConditionFlag.LessEqual, retFoundLong); // Found full substring
+            addq(str1, 16);
+            addq(str2, 16);
+            subl(cnt1, 8);
+            cmpl(cnt2, 8); // Do not read beyond substring
+            jccb(ConditionFlag.GreaterEqual, contScanSubstr);
+            // Back-up strings to avoid reading beyond substring.
+            leaq(str2, new AMD64Address(str2, cnt2, Scale.Times2, -16));
+            leaq(str1, new AMD64Address(str1, cnt2, Scale.Times2, -16));
+            subl(cnt1, cnt2);
+            movl(cnt2, 8);
+            addl(cnt1, 8);
+            bind(contScanSubstr);
+            movdqu(vec, new AMD64Address(str2, 0));
+            jmpb(scanSubstr);
+
+            bind(retFoundLong);
+            movq(str1, new AMD64Address(rsp, wordSize));
+        } // non constant
+
+        bind(retFound);
+        // Compute substr offset
+        subq(result, str1);
+        shrl(result, 1); // index
+
+        bind(cleanup);
+        pop(rsp); // restore SP
+
+    }
+
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.sparc/src/org/graalvm/compiler/asm/sparc/SPARCAssembler.java	Thu Apr 06 21:14:07 2017 +0000
@@ -135,8 +135,8 @@
 
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.asm.Label;
-import org.graalvm.compiler.asm.NumUtil;
-import org.graalvm.compiler.common.PermanentBailoutException;
+import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.debug.GraalError;
 
 import jdk.vm.ci.code.Register;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.test/src/org/graalvm/compiler/asm/test/AssemblerTest.java	Thu Apr 06 21:14:07 2017 +0000
@@ -26,8 +26,6 @@
 
 import java.lang.reflect.Method;
 
-import org.junit.Assert;
-
 import org.graalvm.compiler.api.test.Graal;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.code.DisassemblerProvider;
@@ -36,10 +34,12 @@
 import org.graalvm.compiler.debug.Debug;
 import org.graalvm.compiler.debug.Debug.Scope;
 import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.runtime.RuntimeProvider;
 import org.graalvm.compiler.serviceprovider.GraalServices;
+import org.graalvm.compiler.test.AddExports;
 import org.graalvm.compiler.test.GraalTest;
+import org.junit.Assert;
 
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CodeCacheProvider;
@@ -52,6 +52,7 @@
 import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.runtime.JVMCIBackend;
 
+@AddExports("jdk.internal.vm.ci/jdk.vm.ci.runtime")
 public abstract class AssemblerTest extends GraalTest {
 
     private final MetaAccessProvider metaAccess;
@@ -62,6 +63,14 @@
         byte[] generateCode(CompilationResult compResult, TargetDescription target, RegisterConfig registerConfig, CallingConvention cc);
     }
 
+    /**
+     * Gets the initial option values provided by the Graal runtime. These are option values
+     * typically parsed from the command line.
+     */
+    public static OptionValues getInitialOptions() {
+        return Graal.getRequiredCapability(OptionValues.class);
+    }
+
     public AssemblerTest() {
         JVMCIBackend providers = JVMCI.getRuntime().getHostJVMCIBackend();
         this.metaAccess = providers.getMetaAccess();
@@ -79,7 +88,8 @@
         try (Scope s = Debug.scope("assembleMethod", method, codeCache)) {
             RegisterConfig registerConfig = codeCache.getRegisterConfig();
             CompilationIdentifier compilationId = backend.getCompilationIdentifier(method);
-            CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, new StructuredGraph(method, AllowAssumptions.NO, compilationId), null).getCallingConvention();
+            StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).compilationId(compilationId).build();
+            CallingConvention cc = backend.newLIRGenerationResult(compilationId, null, null, graph, null).getCallingConvention();
 
             CompilationResult compResult = new CompilationResult();
             byte[] targetCode = test.generateCode(compResult, codeCache.getTarget(), registerConfig, cc);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/Buffer.java	Thu Apr 06 21:14:07 2017 +0000
@@ -22,6 +22,8 @@
  */
 package org.graalvm.compiler.asm;
 
+import org.graalvm.compiler.core.common.NumUtil;
+
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Arrays;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm/src/org/graalvm/compiler/asm/NumUtil.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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.asm;
-
-// JaCoCo Exclude
-
-/**
- * A collection of static utility functions that check ranges of numbers.
- */
-public class NumUtil {
-
-    public static boolean isShiftCount(int x) {
-        return 0 <= x && x < 32;
-    }
-
-    /**
-     * Determines if a given {@code int} value is the range of unsigned byte values.
-     */
-    public static boolean isUByte(int x) {
-        return (x & 0xff) == x;
-    }
-
-    /**
-     * Determines if a given {@code int} value is the range of signed byte values.
-     */
-    public static boolean isByte(int x) {
-        return (byte) x == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of unsigned byte values.
-     */
-    public static boolean isUByte(long x) {
-        return (x & 0xffL) == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of signed byte values.
-     */
-    public static boolean isByte(long l) {
-        return (byte) l == l;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of unsigned int values.
-     */
-    public static boolean isUInt(long x) {
-        return (x & 0xffffffffL) == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of signed int values.
-     */
-    public static boolean isInt(long l) {
-        return (int) l == l;
-    }
-
-    /**
-     * Determines if a given {@code int} value is the range of signed short values.
-     */
-    public static boolean isShort(int x) {
-        return (short) x == x;
-    }
-
-    /**
-     * Determines if a given {@code long} value is the range of signed short values.
-     */
-    public static boolean isShort(long x) {
-        return (short) x == x;
-    }
-
-    public static boolean isUShort(int s) {
-        return s == (s & 0xFFFF);
-    }
-
-    public static boolean isUShort(long s) {
-        return s == (s & 0xFFFF);
-    }
-
-    public static boolean is32bit(long x) {
-        return -0x80000000L <= x && x < 0x80000000L;
-    }
-
-    public static short safeToShort(int v) {
-        assert isShort(v);
-        return (short) v;
-    }
-
-    public static int roundUp(int number, int mod) {
-        return ((number + mod - 1) / mod) * mod;
-    }
-
-    public static long roundUp(long number, long mod) {
-        return ((number + mod - 1L) / mod) * mod;
-    }
-
-    public static int roundDown(int number, int mod) {
-        return number / mod * mod;
-    }
-
-    public static long roundDown(long number, long mod) {
-        return number / mod * mod;
-    }
-
-    public static int log2Ceil(int val) {
-        int x = 1;
-        int log2 = 0;
-        while (x < val) {
-            log2++;
-            x *= 2;
-        }
-        return log2;
-    }
-
-    public static boolean isUnsignedNbit(int n, int value) {
-        assert n > 0 && n < 32;
-        return 32 - Integer.numberOfLeadingZeros(value) <= n;
-    }
-
-    public static boolean isUnsignedNbit(int n, long value) {
-        assert n > 0 && n < 64;
-        return 64 - Long.numberOfLeadingZeros(value) <= n;
-    }
-
-    public static boolean isSignedNbit(int n, int value) {
-        assert n > 0 && n < 32;
-        int min = -(1 << (n - 1));
-        int max = (1 << (n - 1)) - 1;
-        return value >= min && value <= max;
-    }
-
-    public static boolean isSignedNbit(int n, long value) {
-        assert n > 0 && n < 64;
-        long min = -(1L << (n - 1));
-        long max = (1L << (n - 1)) - 1;
-        return value >= min && value <= max;
-    }
-
-    /**
-     *
-     * @param n Number of bits that should be set to 1. Must be between 0 and 32 (inclusive).
-     * @return A number with n bits set to 1.
-     */
-    public static int getNbitNumberInt(int n) {
-        assert n >= 0 && n <= 32 : "0 <= n <= 32; instead: " + n;
-        if (n < 32) {
-            return (1 << n) - 1;
-        } else {
-            return 0xFFFFFFFF;
-        }
-    }
-
-    /**
-     *
-     * @param n Number of bits that should be set to 1. Must be between 0 and 64 (inclusive).
-     * @return A number with n bits set to 1.
-     */
-    public static long getNbitNumberLong(int n) {
-        assert n >= 0 && n <= 64;
-        if (n < 64) {
-            return (1L << n) - 1;
-        } else {
-            return 0xFFFFFFFFFFFFFFFFL;
-        }
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java	Thu Apr 06 21:14:07 2017 +0000
@@ -34,6 +34,7 @@
 import java.util.Objects;
 
 import org.graalvm.compiler.graph.NodeSourcePosition;
+import org.graalvm.util.EconomicSet;
 
 import jdk.vm.ci.code.DebugInfo;
 import jdk.vm.ci.code.StackSlot;
@@ -363,9 +364,10 @@
      *
      * @param accessedFields the collected set of fields accessed during compilation
      */
-    public void setFields(Collection<ResolvedJavaField> accessedFields) {
-        assert accessedFields != null;
-        fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]);
+    public void setFields(EconomicSet<ResolvedJavaField> accessedFields) {
+        if (accessedFields != null) {
+            fields = accessedFields.toArray(new ResolvedJavaField[accessedFields.size()]);
+        }
     }
 
     /**
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java	Thu Apr 06 21:14:07 2017 +0000
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.code;
 
-import org.graalvm.compiler.common.PermanentBailoutException;
+import org.graalvm.compiler.core.common.PermanentBailoutException;
 
 /**
  * Represents a bailout exception with a stack trace in terms of the Java source being compiled
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/PermanentBailoutException.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.common;
-
-import jdk.vm.ci.code.BailoutException;
-
-public class PermanentBailoutException extends BailoutException {
-
-    private static final long serialVersionUID = -2683649650135362549L;
-
-    public PermanentBailoutException(String format, Object... args) {
-        super(true, format, args);
-    }
-
-    public PermanentBailoutException(String reason) {
-        super(true, reason);
-    }
-
-    public PermanentBailoutException(Throwable cause, String format, Object... args) {
-        super(cause, format, args);
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.common/src/org/graalvm/compiler/common/RetryableBailoutException.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.common;
-
-import jdk.vm.ci.code.BailoutException;
-
-public class RetryableBailoutException extends BailoutException {
-
-    private static final long serialVersionUID = -7145365025679144525L;
-
-    public RetryableBailoutException(String format, Object... args) {
-        super(false, format, args);
-    }
-
-    public RetryableBailoutException(String reason) {
-        super(false, reason);
-    }
-
-    public RetryableBailoutException(Throwable cause, String format) {
-        super(cause, format);
-    }
-
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java	Thu Apr 06 21:14:07 2017 +0000
@@ -90,6 +90,7 @@
         gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, displacement, scaled, addressingMode));
     }
 
+    @Override
     public ValueNode getBase() {
         return base;
     }
@@ -102,6 +103,7 @@
         this.base = base;
     }
 
+    @Override
     public ValueNode getIndex() {
         return index;
     }
@@ -121,4 +123,9 @@
     public void setDisplacement(int displacement) {
         this.displacement = displacement;
     }
+
+    @Override
+    public long getMaxConstantDisplacement() {
+        return Long.MAX_VALUE;
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java	Thu Apr 06 21:14:07 2017 +0000
@@ -23,13 +23,16 @@
 
 package org.graalvm.compiler.core.aarch64;
 
-import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
-import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
 import static jdk.vm.ci.aarch64.AArch64.sp;
 import static jdk.vm.ci.aarch64.AArch64Kind.DWORD;
 import static jdk.vm.ci.aarch64.AArch64Kind.QWORD;
+import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
+import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
+import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.BSR;
+import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CLZ;
+import static org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode.CTZ;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.calc.FloatConvert;
@@ -41,12 +44,12 @@
 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticLIRGeneratorTool;
 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
 import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp;
-import org.graalvm.compiler.lir.aarch64.AArch64BitManipulationOp.BitManipulationOpCode;
 import org.graalvm.compiler.lir.aarch64.AArch64Move.LoadOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreConstantOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Move.StoreOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ReinterpretOp;
 import org.graalvm.compiler.lir.aarch64.AArch64SignExtendOp;
+import org.graalvm.compiler.lir.aarch64.AArch64Unary;
 import org.graalvm.compiler.lir.gen.ArithmeticLIRGenerator;
 
 import jdk.vm.ci.aarch64.AArch64Kind;
@@ -91,11 +94,30 @@
         }
     }
 
+    protected Value emitExtendMemory(boolean isSigned, AArch64Kind memoryKind, int resultBits, AArch64AddressValue address, LIRFrameState state) {
+        // Issue a zero extending load of the proper bit size and set the result to
+        // the proper kind.
+        Variable result = getLIRGen().newVariable(LIRKind.value(resultBits == 32 ? AArch64Kind.DWORD : AArch64Kind.QWORD));
+
+        int targetSize = resultBits <= 32 ? 32 : 64;
+        switch (memoryKind) {
+            case BYTE:
+            case WORD:
+            case DWORD:
+            case QWORD:
+                getLIRGen().append(new AArch64Unary.MemoryOp(isSigned, targetSize,
+                                memoryKind.getSizeInBytes() * 8, result, address, state));
+                break;
+            default:
+                throw GraalError.shouldNotReachHere();
+        }
+        return result;
+    }
+
     @Override
     public Value emitMul(Value a, Value b, boolean setFlags) {
-        // TODO (das) setFlags handling - should be handled higher up. Ask for ideas at mailing list
-        assert !setFlags : "Set flags on multiplication is not supported";
-        return emitBinary(LIRKind.combine(a, b), getOpCode(a, AArch64ArithmeticOp.MUL, AArch64ArithmeticOp.FMUL), true, a, b);
+        AArch64ArithmeticOp intOp = setFlags ? AArch64ArithmeticOp.MULVS : AArch64ArithmeticOp.MUL;
+        return emitBinary(LIRKind.combine(a, b), getOpCode(a, intOp, AArch64ArithmeticOp.FMUL), true, a, b);
     }
 
     @Override
@@ -223,7 +245,7 @@
 
     @Override
     public Value emitZeroExtend(Value inputVal, int fromBits, int toBits) {
-        assert fromBits <= toBits && (toBits == 32 || toBits == 64);
+        assert fromBits <= toBits && toBits <= 64;
         if (fromBits == toBits) {
             return inputVal;
         }
@@ -235,11 +257,21 @@
 
     @Override
     public Value emitSignExtend(Value inputVal, int fromBits, int toBits) {
-        assert fromBits <= toBits && (toBits == 32 || toBits == 64);
+        LIRKind resultKind = getResultLirKind(toBits, inputVal);
+        assert fromBits <= toBits && toBits <= 64;
         if (fromBits == toBits) {
             return inputVal;
+        } else if (isJavaConstant(inputVal)) {
+            JavaConstant javaConstant = asJavaConstant(inputVal);
+            long constant;
+            if (javaConstant.isNull()) {
+                constant = 0;
+            } else {
+                constant = javaConstant.asLong();
+            }
+            int shiftCount = QWORD.getSizeInBytes() * 8 - fromBits;
+            return new ConstantValue(resultKind, JavaConstant.forLong((constant << shiftCount) >> shiftCount));
         }
-        LIRKind resultKind = getResultLirKind(toBits, inputVal);
         Variable result = getLIRGen().newVariable(resultKind);
         getLIRGen().append(new AArch64SignExtendOp(result, getLIRGen().asAllocatable(inputVal), fromBits, toBits));
         return result;
@@ -249,7 +281,8 @@
         if (resultBitSize == 64) {
             return LIRKind.combine(inputValues).changeType(QWORD);
         } else {
-            assert resultBitSize == 32;
+            // FIXME: I have no idea what this assert was ever for
+            // assert resultBitSize == 32;
             return LIRKind.combine(inputValues).changeType(DWORD);
         }
     }
@@ -352,8 +385,8 @@
     }
 
     @Override
-    public Value emitBitScanForward(Value inputVal) {
-        return emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode.BSF, inputVal);
+    public Variable emitBitScanForward(Value value) {
+        throw GraalError.unimplemented();
     }
 
     @Override
@@ -362,27 +395,23 @@
     }
 
     @Override
-    public Value emitBitScanReverse(Value inputVal) {
-        // TODO (das) old implementation said to use emitCountLeadingZeros instead - need extra node
-        // for that though
-        return emitBitManipulation(BitManipulationOpCode.BSR, inputVal);
+    public Value emitBitScanReverse(Value value) {
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
+        getLIRGen().append(new AArch64BitManipulationOp(BSR, result, getLIRGen().asAllocatable(value)));
+        return result;
     }
 
     @Override
     public Value emitCountLeadingZeros(Value value) {
-        return emitBitManipulation(BitManipulationOpCode.CLZ, value);
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
+        getLIRGen().append(new AArch64BitManipulationOp(CLZ, result, getLIRGen().asAllocatable(value)));
+        return result;
     }
 
     @Override
     public Value emitCountTrailingZeros(Value value) {
-        throw GraalError.unimplemented();
-    }
-
-    private Variable emitBitManipulation(AArch64BitManipulationOp.BitManipulationOpCode op, Value inputVal) {
-        assert isNumericInteger(inputVal.getPlatformKind());
-        AllocatableValue input = getLIRGen().asAllocatable(inputVal);
-        Variable result = getLIRGen().newVariable(LIRKind.combine(input));
-        getLIRGen().append(new AArch64BitManipulationOp(op, result, input));
+        Variable result = getLIRGen().newVariable(LIRKind.combine(value).changeType(AArch64Kind.DWORD));
+        getLIRGen().append(new AArch64BitManipulationOp(CTZ, result, getLIRGen().asAllocatable(value)));
         return result;
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Thu Apr 06 21:14:07 2017 +0000
@@ -42,11 +42,14 @@
 import org.graalvm.compiler.lir.Variable;
 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ArrayEqualsOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Compare;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.BranchOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.CondMoveOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Move;
 import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
@@ -56,6 +59,7 @@
 import org.graalvm.compiler.phases.util.Providers;
 
 import jdk.vm.ci.aarch64.AArch64Kind;
+import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.RegisterValue;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.JavaConstant;
@@ -121,8 +125,19 @@
     }
 
     @Override
-    public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+    public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+        Variable prevValue = newVariable(expectedValue.getValueKind());
+        Variable scratch = newVariable(LIRKind.value(AArch64Kind.DWORD));
+        append(new CompareAndSwapOp(prevValue, loadReg(expectedValue), loadReg(newValue), asAllocatable(address), scratch));
+        assert trueValue.getValueKind().equals(falseValue.getValueKind());
         Variable result = newVariable(trueValue.getValueKind());
+        append(new CondMoveOp(result, ConditionFlag.EQ, asAllocatable(trueValue), asAllocatable(falseValue)));
+        return result;
+    }
+
+    @Override
+    public Variable emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) {
+        Variable result = newVariable(newValue.getValueKind());
         Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD));
         append(new CompareAndSwapOp(result, loadNonCompareConst(expectedValue), loadReg(newValue), asAllocatable(address), scratch));
         return result;
@@ -271,13 +286,25 @@
         boolean mirrored;
         AArch64Kind kind = (AArch64Kind) cmpKind;
         if (kind.isInteger()) {
-            if (LIRValueUtil.isVariable(b)) {
-                left = load(b);
-                right = loadNonConst(a);
+            Value aExt = a;
+            Value bExt = b;
+
+            int compareBytes = cmpKind.getSizeInBytes();
+            // AArch64 compares 32 or 64 bits: sign extend a and b as required.
+            if (compareBytes < a.getPlatformKind().getSizeInBytes()) {
+                aExt = arithmeticLIRGen.emitSignExtend(a, compareBytes * 8, 64);
+            }
+            if (compareBytes < b.getPlatformKind().getSizeInBytes()) {
+                bExt = arithmeticLIRGen.emitSignExtend(b, compareBytes * 8, 64);
+            }
+
+            if (LIRValueUtil.isVariable(bExt)) {
+                left = load(bExt);
+                right = loadNonConst(aExt);
                 mirrored = true;
             } else {
-                left = load(a);
-                right = loadNonConst(b);
+                left = load(aExt);
+                right = loadNonConst(bExt);
                 mirrored = false;
             }
             append(new AArch64Compare.CompareOp(left, loadNonCompareConst(right)));
@@ -367,7 +394,7 @@
     public Variable emitIntegerTestMove(Value left, Value right, Value trueValue, Value falseValue) {
         assert ((AArch64Kind) left.getPlatformKind()).isInteger() && ((AArch64Kind) right.getPlatformKind()).isInteger();
         assert ((AArch64Kind) trueValue.getPlatformKind()).isInteger() && ((AArch64Kind) falseValue.getPlatformKind()).isInteger();
-        ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(trueValue.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right);
+        ((AArch64ArithmeticLIRGenerator) getArithmetic()).emitBinary(left.getValueKind(), AArch64ArithmeticOp.ANDS, true, left, right);
         Variable result = newVariable(trueValue.getValueKind());
         append(new CondMoveOp(result, ConditionFlag.EQ, load(trueValue), load(falseValue)));
         return result;
@@ -385,22 +412,21 @@
 
     @Override
     protected void emitTableSwitch(int lowKey, LabelRef defaultTarget, LabelRef[] targets, Value key) {
-        // Make copy of key since the TableSwitch destroys its input.
-        Variable tmp = emitMove(key);
-        Variable scratch = newVariable(LIRKind.value(AArch64Kind.WORD));
-        append(new AArch64ControlFlow.TableSwitchOp(lowKey, defaultTarget, targets, tmp, scratch));
+        append(new TableSwitchOp(lowKey, defaultTarget, targets, key, newVariable(LIRKind.value(target().arch.getWordKind())), newVariable(key.getValueKind())));
     }
 
     @Override
-    public Variable emitByteSwap(Value operand) {
-        // TODO (das) Do not generate until we support vector instructions
-        throw GraalError.unimplemented("Do not generate until we support vector instructions");
+    public Variable emitByteSwap(Value input) {
+        Variable result = newVariable(LIRKind.combine(input));
+        append(new AArch64ByteSwapOp(result, input));
+        return result;
     }
 
     @Override
     public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
-        // TODO (das) Do not generate until we support vector instructions
-        throw GraalError.unimplemented("Do not generate until we support vector instructions");
+        Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD));
+        append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
+        return result;
     }
 
     @Override
@@ -443,4 +469,6 @@
     public void emitPause() {
         append(new AArch64PauseOp());
     }
+
+    public abstract void emitCCall(long address, CallingConvention nativeCallingConvention, Value[] args);
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java	Thu Apr 06 21:14:07 2017 +0000
@@ -86,21 +86,25 @@
     }
 
     @Override
-    public boolean canInlineConstant(JavaConstant c) {
-        switch (c.getJavaKind()) {
-            case Boolean:
-            case Byte:
-            case Char:
-            case Short:
-            case Int:
-                return AArch64MacroAssembler.isMovableImmediate(c.asInt());
-            case Long:
-                return AArch64MacroAssembler.isMovableImmediate(c.asLong());
-            case Object:
-                return c.isNull();
-            default:
-                return false;
+    public boolean canInlineConstant(Constant con) {
+        if (con instanceof JavaConstant) {
+            JavaConstant c = (JavaConstant) con;
+            switch (c.getJavaKind()) {
+                case Boolean:
+                case Byte:
+                case Char:
+                case Short:
+                case Int:
+                    return AArch64MacroAssembler.isMovableImmediate(c.asInt());
+                case Long:
+                    return AArch64MacroAssembler.isMovableImmediate(c.asLong());
+                case Object:
+                    return c.isNull();
+                default:
+                    return false;
+            }
         }
+        return false;
     }
 
     @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64NodeMatchRules.java	Thu Apr 06 21:14:07 2017 +0000
@@ -24,9 +24,14 @@
 package org.graalvm.compiler.core.aarch64;
 
 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.lir.LIRFrameState;
+import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodes.DeoptimizingNode;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
 import org.graalvm.compiler.nodes.memory.Access;
 
 import jdk.vm.ci.aarch64.AArch64Kind;
@@ -56,4 +61,18 @@
     protected AArch64ArithmeticLIRGenerator getArithmeticLIRGenerator() {
         return (AArch64ArithmeticLIRGenerator) getLIRGeneratorTool().getArithmetic();
     }
+
+    @MatchRule("(ZeroExtend Read=access)")
+    @MatchRule("(ZeroExtend FloatingRead=access)")
+    public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) {
+        AArch64Kind memoryKind = getMemoryKind(access);
+        return builder -> getArithmeticLIRGenerator().emitExtendMemory(false, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access));
+    }
+
+    @MatchRule("(SignExtend Read=access)")
+    @MatchRule("(SignExtend FloatingRead=access)")
+    public ComplexMatchResult signExtend(SignExtendNode root, Access access) {
+        AArch64Kind memoryKind = getMemoryKind(access);
+        return builder -> getArithmeticLIRGenerator().emitExtendMemory(true, memoryKind, root.getResultBits(), (AArch64AddressValue) operand(access.getAddress()), getState(access));
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/AMD64AllocatorTest.java	Thu Apr 06 21:14:07 2017 +0000
@@ -38,8 +38,8 @@
     @Before
     public void checkAMD64() {
         assumeTrue("skipping AMD64 specific test", getTarget().arch instanceof AMD64);
-        assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue() == null);
-        assumeTrue("TraceRA is set -> skip", !TraceRA.getValue());
+        assumeTrue("RegisterPressure is set -> skip", RegisterPressure.getValue(getInitialOptions()) == null);
+        assumeTrue("TraceRA is set -> skip", !TraceRA.getValue(getInitialOptions()));
     }
 
     @Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64.test/src/org/graalvm/compiler/core/amd64/test/MatchRuleTest.java	Thu Apr 06 21:14:07 2017 +0000
@@ -24,22 +24,23 @@
 
 import static org.junit.Assume.assumeTrue;
 
-import org.junit.Before;
-import org.junit.Test;
-
 import org.graalvm.compiler.lir.LIR;
 import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer.MemoryConstOp;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.jtt.LIRTest;
 import org.graalvm.compiler.lir.phases.LIRPhase;
+import org.graalvm.compiler.lir.phases.LIRSuites;
 import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
+import org.graalvm.compiler.options.OptionValues;
+import org.junit.Before;
+import org.junit.Test;
 
 import jdk.vm.ci.amd64.AMD64;
 import jdk.vm.ci.code.TargetDescription;
 
 public class MatchRuleTest extends LIRTest {
-    private static LIR lir;
+    private LIR lir;
 
     @Before
     public void checkAMD64() {
@@ -54,13 +55,19 @@
         }
     }
 
+    @Override
+    protected LIRSuites createLIRSuites(OptionValues options) {
+        LIRSuites suites = super.createLIRSuites(options);
+        suites.getPreAllocationOptimizationStage().appendPhase(new CheckPhase());
+        return suites;
+    }
+
     /**
      * Verifies, if the match rules in AMD64NodeMatchRules do work on the graphs by compiling and
      * checking if the expected LIR instruction show up.
      */
     @Test
     public void test1() {
-        getLIRSuites().getPreAllocationOptimizationStage().appendPhase(new CheckPhase());
         compile(getResolvedJavaMethod("test1Snippet"), null);
         boolean found = false;
         for (LIRInstruction ins : lir.getLIRforBlock(lir.codeEmittingOrder()[0])) {
@@ -83,7 +90,7 @@
         }
     }
 
-    public static class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> {
+    public class CheckPhase extends LIRPhase<PreAllocationOptimizationContext> {
         @Override
         protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreAllocationOptimizationContext context) {
             lir = lirGenRes.getLIR();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressLowering.java	Thu Apr 06 21:14:07 2017 +0000
@@ -25,7 +25,7 @@
 
 import jdk.vm.ci.meta.JavaConstant;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.nodes.ValueNode;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64AddressNode.java	Thu Apr 06 21:14:07 2017 +0000
@@ -87,6 +87,7 @@
         gen.setResult(this, new AMD64AddressValue(kind, baseValue, indexValue, scale, displacement));
     }
 
+    @Override
     public ValueNode getBase() {
         return base;
     }
@@ -99,6 +100,7 @@
         this.base = base;
     }
 
+    @Override
     public ValueNode getIndex() {
         return index;
     }
@@ -126,4 +128,9 @@
     public void setDisplacement(int displacement) {
         this.displacement = displacement;
     }
+
+    @Override
+    public long getMaxConstantDisplacement() {
+        return displacement;
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java	Thu Apr 06 21:14:07 2017 +0000
@@ -74,7 +74,7 @@
 import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicUnaryOp.UnaryIntrinsicOpcode.EXP;
 import static org.graalvm.compiler.lir.amd64.AMD64MathIntrinsicBinaryOp.BinaryIntrinsicOpcode.POW;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MOp;
@@ -1234,7 +1234,7 @@
                 return;
             } else if (c instanceof VMConstant) {
                 VMConstant vc = (VMConstant) c;
-                if (size == DWORD && !GeneratePIC.getValue()) {
+                if (size == DWORD && !GeneratePIC.getValue(getOptions())) {
                     getLIRGen().append(new AMD64BinaryConsumer.VMConstOp(CMP.getMIOpcode(DWORD, false), left, vc));
                 } else {
                     getLIRGen().append(new AMD64BinaryConsumer.DataOp(CMP.getRMOpcode(size), size, left, vc));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64LIRGenerator.java	Thu Apr 06 21:14:07 2017 +0000
@@ -23,6 +23,7 @@
 
 package org.graalvm.compiler.core.amd64;
 
+import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64BinaryArithmetic.CMP;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.DWORD;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.PD;
@@ -31,10 +32,10 @@
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.lir.LIRValueUtil.asConstantValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.asJavaConstant;
+import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isJavaConstant;
-import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.ConditionFlag;
@@ -72,6 +73,7 @@
 import org.graalvm.compiler.lir.amd64.AMD64Move.MembarOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move.StackLeaOp;
 import org.graalvm.compiler.lir.amd64.AMD64PauseOp;
+import org.graalvm.compiler.lir.amd64.AMD64StringIndexOfOp;
 import org.graalvm.compiler.lir.amd64.AMD64ZapRegistersOp;
 import org.graalvm.compiler.lir.amd64.AMD64ZapStackOp;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
@@ -112,10 +114,8 @@
     protected static final boolean canStoreConstant(JavaConstant c) {
         // there is no immediate move of 64-bit constants on Intel
         switch (c.getJavaKind()) {
-            case Long: {
-                long l = c.asLong();
-                return (int) l == l;
-            }
+            case Long:
+                return NumUtil.isInt(c.asLong());
             case Double:
                 return false;
             case Object:
@@ -183,7 +183,7 @@
     }
 
     @Override
-    public Variable emitCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
+    public Variable emitLogicCompareAndSwap(Value address, Value expectedValue, Value newValue, Value trueValue, Value falseValue) {
         ValueKind<?> kind = newValue.getValueKind();
         assert kind.equals(expectedValue.getValueKind());
         AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind();
@@ -200,6 +200,33 @@
     }
 
     @Override
+    public Value emitValueCompareAndSwap(Value address, Value expectedValue, Value newValue) {
+        ValueKind<?> kind = newValue.getValueKind();
+        assert kind.equals(expectedValue.getValueKind());
+        AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind();
+
+        AMD64AddressValue addressValue = asAddressValue(address);
+        RegisterValue raxRes = AMD64.rax.asValue(kind);
+        emitMove(raxRes, expectedValue);
+        append(new CompareAndSwapOp(memKind, raxRes, addressValue, raxRes, asAllocatable(newValue)));
+        Variable result = newVariable(kind);
+        emitMove(result, raxRes);
+        return result;
+    }
+
+    public void emitCompareAndSwapBranch(ValueKind<?> kind, AMD64AddressValue address, Value expectedValue, Value newValue, Condition condition, LabelRef trueLabel, LabelRef falseLabel,
+                    double trueLabelProbability) {
+        assert kind.equals(expectedValue.getValueKind());
+        assert kind.equals(newValue.getValueKind());
+        assert condition == Condition.EQ || condition == Condition.NE;
+        AMD64Kind memKind = (AMD64Kind) kind.getPlatformKind();
+        RegisterValue raxValue = AMD64.rax.asValue(kind);
+        emitMove(raxValue, expectedValue);
+        append(new CompareAndSwapOp(memKind, raxValue, address, raxValue, asAllocatable(newValue)));
+        append(new BranchOp(condition, trueLabel, falseLabel, trueLabelProbability));
+    }
+
+    @Override
     public Value emitAtomicReadAndAdd(Value address, Value delta) {
         ValueKind<?> kind = delta.getValueKind();
         Variable result = newVariable(kind);
@@ -329,7 +356,7 @@
                 throw GraalError.shouldNotReachHere("unexpected kind: " + cmpKind);
         }
 
-        if (isJavaConstant(a)) {
+        if (isConstantValue(a)) {
             return emitCompareMemoryConOp(size, asConstantValue(a), b, state);
         } else {
             return emitCompareRegMemoryOp(size, asAllocatable(a), b, state);
@@ -399,7 +426,7 @@
     @Override
     protected void emitForeignCallOp(ForeignCallLinkage linkage, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
         long maxOffset = linkage.getMaxCallTargetOffset();
-        if (maxOffset != (int) maxOffset && !GeneratePIC.getValue()) {
+        if (maxOffset != (int) maxOffset && !GeneratePIC.getValue(getResult().getLIR().getOptions())) {
             append(new AMD64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info));
         } else {
             append(new AMD64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info));
@@ -420,6 +447,24 @@
         return result;
     }
 
+    /**
+     * Return a conservative estimate of the page size for use by the String.indexOf intrinsic.
+     */
+    protected int getVMPageSize() {
+        return 4096;
+    }
+
+    @Override
+    public Variable emitStringIndexOf(Value source, Value sourceCount, Value target, Value targetCount, int constantTargetCount) {
+        Variable result = newVariable(LIRKind.value(AMD64Kind.DWORD));
+        RegisterValue cnt1 = AMD64.rdx.asValue(sourceCount.getValueKind());
+        emitMove(cnt1, sourceCount);
+        RegisterValue cnt2 = AMD64.rax.asValue(targetCount.getValueKind());
+        emitMove(cnt2, targetCount);
+        append(new AMD64StringIndexOfOp(this, result, source, target, cnt1, cnt2, AMD64.rcx.asValue(), AMD64.xmm0.asValue(), constantTargetCount, getVMPageSize()));
+        return result;
+    }
+
     @Override
     public void emitReturn(JavaKind kind, Value input) {
         AllocatableValue operand = Value.ILLEGAL;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java	Thu Apr 06 21:14:07 2017 +0000
@@ -28,7 +28,7 @@
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
 import static jdk.vm.ci.code.ValueUtil.isRegister;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.type.DataPointerConstant;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
@@ -54,15 +54,19 @@
     }
 
     @Override
-    public boolean canInlineConstant(JavaConstant c) {
-        switch (c.getJavaKind()) {
-            case Long:
-                return NumUtil.isInt(c.asLong());
-            case Object:
-                return c.isNull();
-            default:
-                return true;
+    public boolean canInlineConstant(Constant con) {
+        if (con instanceof JavaConstant) {
+            JavaConstant c = (JavaConstant) con;
+            switch (c.getJavaKind()) {
+                case Long:
+                    return NumUtil.isInt(c.asLong());
+                case Object:
+                    return c.isNull();
+                default:
+                    return true;
+            }
         }
+        return false;
     }
 
     @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java	Thu Apr 06 21:14:07 2017 +0000
@@ -26,15 +26,14 @@
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.lir.VirtualStackSlot;
 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
 import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64PushPopStackMove;
 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
+import org.graalvm.util.Equivalence;
+import org.graalvm.util.EconomicMap;
 
 import jdk.vm.ci.amd64.AMD64Kind;
 import jdk.vm.ci.code.Architecture;
@@ -61,7 +60,7 @@
     public static final class BackupSlotProvider {
 
         private final FrameMapBuilder frameMapBuilder;
-        private Map<PlatformKind.Key, RegisterBackupPair> categorized;
+        private EconomicMap<PlatformKind.Key, RegisterBackupPair> categorized;
 
         public BackupSlotProvider(FrameMapBuilder frameMapBuilder) {
             this.frameMapBuilder = frameMapBuilder;
@@ -70,7 +69,7 @@
         protected RegisterBackupPair getScratchRegister(PlatformKind kind) {
             PlatformKind.Key key = kind.getKey();
             if (categorized == null) {
-                categorized = new HashMap<>();
+                categorized = EconomicMap.create(Equivalence.DEFAULT);
             } else if (categorized.containsKey(key)) {
                 return categorized.get(key);
             }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64NodeMatchRules.java	Thu Apr 06 21:14:07 2017 +0000
@@ -36,13 +36,13 @@
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SD;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.SS;
 
-import org.graalvm.compiler.asm.NumUtil;
+import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64MIOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RMOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.AMD64RRMOp;
+import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize;
 import org.graalvm.compiler.asm.amd64.AMD64Assembler.SSEOp;
-import org.graalvm.compiler.asm.amd64.AMD64Assembler.AVXOp;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.gen.NodeLIRBuilder;
@@ -52,6 +52,7 @@
 import org.graalvm.compiler.debug.Debug;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.lir.LIRFrameState;
+import org.graalvm.compiler.lir.LIRValueUtil;
 import org.graalvm.compiler.lir.LabelRef;
 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
 import org.graalvm.compiler.lir.amd64.AMD64BinaryConsumer;
@@ -69,18 +70,22 @@
 import org.graalvm.compiler.nodes.calc.SignExtendNode;
 import org.graalvm.compiler.nodes.calc.UnsignedRightShiftNode;
 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.java.LogicCompareAndSwapNode;
+import org.graalvm.compiler.nodes.java.ValueCompareAndSwapNode;
 import org.graalvm.compiler.nodes.memory.Access;
+import org.graalvm.compiler.nodes.memory.LIRLowerableAccess;
 import org.graalvm.compiler.nodes.memory.WriteNode;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 
 import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.amd64.AMD64.CPUFeature;
 import jdk.vm.ci.amd64.AMD64Kind;
-import jdk.vm.ci.amd64.AMD64.CPUFeature;
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.PlatformKind;
 import jdk.vm.ci.meta.Value;
+import jdk.vm.ci.meta.ValueKind;
 
 public class AMD64NodeMatchRules extends NodeMatchRules {
 
@@ -95,11 +100,15 @@
         return null;
     }
 
-    protected AMD64Kind getMemoryKind(Access access) {
-        return (AMD64Kind) gen.getLIRKind(access.asNode().stamp()).getPlatformKind();
+    protected AMD64Kind getMemoryKind(LIRLowerableAccess access) {
+        return (AMD64Kind) getLirKind(access).getPlatformKind();
     }
 
-    protected OperandSize getMemorySize(Access access) {
+    protected LIRKind getLirKind(LIRLowerableAccess access) {
+        return gen.getLIRKind(access.getAccessStamp());
+    }
+
+    protected OperandSize getMemorySize(LIRLowerableAccess access) {
         switch (getMemoryKind(access)) {
             case BYTE:
                 return OperandSize.BYTE;
@@ -118,25 +127,36 @@
         }
     }
 
-    protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, Access access) {
+    protected ComplexMatchResult emitCompareBranchMemory(IfNode ifNode, CompareNode compare, ValueNode value, LIRLowerableAccess access) {
         Condition cond = compare.condition();
         AMD64Kind kind = getMemoryKind(access);
+        boolean matchedAsConstant = false; // For assertion checking
 
         if (value.isConstant()) {
             JavaConstant constant = value.asJavaConstant();
-            if (constant != null && kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) {
-                // Only imm32 as long
-                return null;
+            if (constant != null) {
+                if (kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && !NumUtil.isInt(constant.asLong())) {
+                    // Only imm32 as long
+                    return null;
+                }
+                // A QWORD that can be encoded as int can be embedded as a constant
+                matchedAsConstant = kind == AMD64Kind.QWORD && !constant.getJavaKind().isObject() && NumUtil.isInt(constant.asLong());
+            }
+            if (kind == AMD64Kind.DWORD) {
+                // Any DWORD value should be embeddable as a constant
+                matchedAsConstant = true;
             }
             if (kind.isXMM()) {
                 Debug.log("Skipping constant compares for float kinds");
                 return null;
             }
         }
+        boolean matchedAsConstantFinal = matchedAsConstant;
 
-        // emitCompareBranchMemory expects the memory on the right, so mirror the condition if
-        // that's not true. It might be mirrored again the actual compare is emitted but that's
-        // ok.
+        /*
+         * emitCompareBranchMemory expects the memory on the right, so mirror the condition if
+         * that's not true. It might be mirrored again the actual compare is emitted but that's ok.
+         */
         Condition finalCondition = GraphUtil.unproxify(compare.getX()) == access ? cond.mirror() : cond;
         return new ComplexMatchResult() {
             @Override
@@ -146,6 +166,11 @@
                 boolean unorderedIsTrue = compare.unorderedIsTrue();
                 double trueLabelProbability = ifNode.probability(ifNode.trueSuccessor());
                 Value other = operand(value);
+                /*
+                 * Check that patterns which were matched as a constant actually end up seeing a
+                 * constant in the LIR.
+                 */
+                assert !matchedAsConstantFinal || !LIRValueUtil.isVariable(other) : "expected constant value " + value;
                 AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress());
                 getLIRGeneratorTool().emitCompareBranchMemory(kind, other, address, getState(access), finalCondition, unorderedIsTrue, trueLabel, falseLabel, trueLabelProbability);
                 return null;
@@ -153,7 +178,7 @@
         };
     }
 
-    private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, Access access) {
+    private ComplexMatchResult emitIntegerTestBranchMemory(IfNode x, ValueNode value, LIRLowerableAccess access) {
         LabelRef trueLabel = getLIRBlock(x.trueSuccessor());
         LabelRef falseLabel = getLIRBlock(x.falseSuccessor());
         double trueLabelProbability = x.probability(x.trueSuccessor());
@@ -181,15 +206,22 @@
         }
     }
 
-    protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) {
+    protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access, ValueKind<?> addressKind) {
         return builder -> {
             AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress());
             LIRFrameState state = getState(access);
+            if (addressKind != null) {
+                address = address.withKind(addressKind);
+            }
             return getArithmeticLIRGenerator().emitConvertMemoryOp(kind, op, size, address, state);
         };
     }
 
-    private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits) {
+    protected ComplexMatchResult emitConvertMemoryOp(PlatformKind kind, AMD64RMOp op, OperandSize size, Access access) {
+        return emitConvertMemoryOp(kind, op, size, access, null);
+    }
+
+    private ComplexMatchResult emitSignExtendMemory(Access access, int fromBits, int toBits, ValueKind<?> addressKind) {
         assert fromBits <= toBits && toBits <= 64;
         AMD64Kind kind = null;
         AMD64RMOp op;
@@ -231,7 +263,7 @@
             }
         }
         if (kind != null && op != null) {
-            return emitConvertMemoryOp(kind, op, size, access);
+            return emitConvertMemoryOp(kind, op, size, access, addressKind);
         }
         return null;
     }
@@ -244,7 +276,7 @@
 
     @MatchRule("(If (IntegerTest Read=access value))")
     @MatchRule("(If (IntegerTest FloatingRead=access value))")
-    public ComplexMatchResult integerTestBranchMemory(IfNode root, Access access, ValueNode value) {
+    public ComplexMatchResult integerTestBranchMemory(IfNode root, LIRLowerableAccess access, ValueNode value) {
         return emitIntegerTestBranchMemory(root, value, access);
     }
 
@@ -262,7 +294,67 @@
     @MatchRule("(If (PointerEquals=compare value FloatingRead=access))")
     @MatchRule("(If (ObjectEquals=compare value Read=access))")
     @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))")
-    public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, Access access) {
+    public ComplexMatchResult ifCompareMemory(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) {
+        return emitCompareBranchMemory(root, compare, value, access);
+    }
+
+    @MatchRule("(If (ObjectEquals=compare value ValueCompareAndSwap=cas))")
+    @MatchRule("(If (PointerEquals=compare value ValueCompareAndSwap=cas))")
+    @MatchRule("(If (FloatEquals=compare value ValueCompareAndSwap=cas))")
+    @MatchRule("(If (IntegerEquals=compare value ValueCompareAndSwap=cas))")
+    public ComplexMatchResult ifCompareValueCas(IfNode root, CompareNode compare, ValueNode value, ValueCompareAndSwapNode cas) {
+        assert compare.condition() == Condition.EQ;
+        if (value == cas.getExpectedValue() && cas.usages().count() == 1) {
+            return builder -> {
+                LIRKind kind = getLirKind(cas);
+                LabelRef trueLabel = getLIRBlock(root.trueSuccessor());
+                LabelRef falseLabel = getLIRBlock(root.falseSuccessor());
+                double trueLabelProbability = root.probability(root.trueSuccessor());
+                Value expectedValue = operand(cas.getExpectedValue());
+                Value newValue = operand(cas.getNewValue());
+                AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress());
+                getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, Condition.EQ, trueLabel, falseLabel, trueLabelProbability);
+                return null;
+            };
+        }
+        return null;
+    }
+
+    @MatchRule("(If (ObjectEquals=compare value LogicCompareAndSwap=cas))")
+    @MatchRule("(If (PointerEquals=compare value LogicCompareAndSwap=cas))")
+    @MatchRule("(If (FloatEquals=compare value LogicCompareAndSwap=cas))")
+    @MatchRule("(If (IntegerEquals=compare value LogicCompareAndSwap=cas))")
+    public ComplexMatchResult ifCompareLogicCas(IfNode root, CompareNode compare, ValueNode value, LogicCompareAndSwapNode cas) {
+        JavaConstant constant = value.asJavaConstant();
+        assert compare.condition() == Condition.EQ;
+        if (constant != null && cas.usages().count() == 1) {
+            long constantValue = constant.asLong();
+            boolean successIsTrue;
+            if (constantValue == 0) {
+                successIsTrue = false;
+            } else if (constantValue == 1) {
+                successIsTrue = true;
+            } else {
+                return null;
+            }
+            return builder -> {
+                LIRKind kind = getLirKind(cas);
+                LabelRef trueLabel = getLIRBlock(root.trueSuccessor());
+                LabelRef falseLabel = getLIRBlock(root.falseSuccessor());
+                double trueLabelProbability = root.probability(root.trueSuccessor());
+                Value expectedValue = operand(cas.getExpectedValue());
+                Value newValue = operand(cas.getNewValue());
+                AMD64AddressValue address = (AMD64AddressValue) operand(cas.getAddress());
+                Condition condition = successIsTrue ? Condition.EQ : Condition.NE;
+                getLIRGeneratorTool().emitCompareAndSwapBranch(kind, address, expectedValue, newValue, condition, trueLabel, falseLabel, trueLabelProbability);
+                return null;
+            };
+        }
+        return null;
+    }
+
+    @MatchRule("(If (ObjectEquals=compare value FloatingRead=access))")
+    public ComplexMatchResult ifLogicCas(IfNode root, CompareNode compare, ValueNode value, LIRLowerableAccess access) {
         return emitCompareBranchMemory(root, compare, value, access);
     }
 
@@ -290,19 +382,19 @@
         return null;
     }
 
-    private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, Access access) {
+    private ComplexMatchResult binaryRead(AMD64RMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) {
         return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()),
                         getState(access));
     }
 
-    private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, Access access) {
+    private ComplexMatchResult binaryRead(AMD64RRMOp op, OperandSize size, ValueNode value, LIRLowerableAccess access) {
         return builder -> getArithmeticLIRGenerator().emitBinaryMemory(op, size, getLIRGeneratorTool().asAllocatable(operand(value)), (AMD64AddressValue) operand(access.getAddress()),
                         getState(access));
     }
 
     @MatchRule("(Add value Read=access)")
     @MatchRule("(Add value FloatingRead=access)")
-    public ComplexMatchResult addMemory(ValueNode value, Access access) {
+    public ComplexMatchResult addMemory(ValueNode value, LIRLowerableAccess access) {
         OperandSize size = getMemorySize(access);
         if (size.isXmmType()) {
             TargetDescription target = getLIRGeneratorTool().target();
@@ -319,7 +411,7 @@
 
     @MatchRule("(Sub value Read=access)")
     @MatchRule("(Sub value FloatingRead=access)")
-    public ComplexMatchResult subMemory(ValueNode value, Access access) {
+    public ComplexMatchResult subMemory(ValueNode value, LIRLowerableAccess access) {
         OperandSize size = getMemorySize(access);
         if (size.isXmmType()) {
             TargetDescription target = getLIRGeneratorTool().target();
@@ -336,7 +428,7 @@
 
     @MatchRule("(Mul value Read=access)")
     @MatchRule("(Mul value FloatingRead=access)")
-    public ComplexMatchResult mulMemory(ValueNode value, Access access) {
+    public ComplexMatchResult mulMemory(ValueNode value, LIRLowerableAccess access) {
         OperandSize size = getMemorySize(access);
         if (size.isXmmType()) {
             TargetDescription target = getLIRGeneratorTool().target();
@@ -353,7 +445,7 @@
 
     @MatchRule("(And value Read=access)")
     @MatchRule("(And value FloatingRead=access)")
-    public ComplexMatchResult andMemory(ValueNode value, Access access) {
+    public ComplexMatchResult andMemory(ValueNode value, LIRLowerableAccess access) {
         OperandSize size = getMemorySize(access);
         if (size.isXmmType()) {
             return null;
@@ -364,7 +456,7 @@
 
     @MatchRule("(Or value Read=access)")
     @MatchRule("(Or value FloatingRead=access)")
-    public ComplexMatchResult orMemory(ValueNode value, Access access) {
+    public ComplexMatchResult orMemory(ValueNode value, LIRLowerableAccess access) {
         OperandSize size = getMemorySize(access);
         if (size.isXmmType()) {
             return null;
@@ -375,7 +467,7 @@
 
     @MatchRule("(Xor value Read=access)")
     @MatchRule("(Xor value FloatingRead=access)")
-    public ComplexMatchResult xorMemory(ValueNode value, Access access) {
+    public ComplexMatchResult xorMemory(ValueNode value, LIRLowerableAccess access) {
         OperandSize size = getMemorySize(access);
         if (size.isXmmType()) {
             return null;
@@ -395,20 +487,44 @@
 
     @MatchRule("(SignExtend Read=access)")
     @MatchRule("(SignExtend FloatingRead=access)")
-    public ComplexMatchResult signExtend(SignExtendNode root, Access access) {
-        return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits());
+    public ComplexMatchResult signExtend(SignExtendNode root, LIRLowerableAccess access) {
+        return emitSignExtendMemory(access, root.getInputBits(), root.getResultBits(), null);
     }
 
     @MatchRule("(ZeroExtend Read=access)")
     @MatchRule("(ZeroExtend FloatingRead=access)")
-    public ComplexMatchResult zeroExtend(ZeroExtendNode root, Access access) {
+    public ComplexMatchResult zeroExtend(ZeroExtendNode root, LIRLowerableAccess access) {
         AMD64Kind memoryKind = getMemoryKind(access);
         return builder -> getArithmeticLIRGenerator().emitZeroExtendMemory(memoryKind, root.getResultBits(), (AMD64AddressValue) operand(access.getAddress()), getState(access));
     }
 
+    @MatchRule("(Narrow Read=access)")
+    @MatchRule("(Narrow FloatingRead=access)")
+    public ComplexMatchResult narrowRead(NarrowNode root, LIRLowerableAccess access) {
+        return new ComplexMatchResult() {
+            @Override
+            public Value evaluate(NodeLIRBuilder builder) {
+                AMD64AddressValue address = (AMD64AddressValue) operand(access.getAddress());
+                LIRKind addressKind = LIRKind.combineDerived(getLIRGeneratorTool().getLIRKind(root.asNode().stamp()),
+                                address.getBase(), address.getIndex());
+                AMD64AddressValue newAddress = address.withKind(addressKind);
+                LIRKind readKind = getLIRGeneratorTool().getLIRKind(root.stamp());
+                return getArithmeticLIRGenerator().emitZeroExtendMemory((AMD64Kind) readKind.getPlatformKind(),
+                                root.getResultBits(), newAddress, getState(access));
+            }
+        };
+    }
+
+    @MatchRule("(SignExtend (Narrow=narrow Read=access))")
+    @MatchRule("(SignExtend (Narrow=narrow FloatingRead=access))")
+    public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode narrow, LIRLowerableAccess access) {
+        LIRKind kind = getLIRGeneratorTool().getLIRKind(narrow.stamp());
+        return emitSignExtendMemory(access, narrow.getResultBits(), root.getResultBits(), kind);
+    }
+
     @MatchRule("(FloatConvert Read=access)")
     @MatchRule("(FloatConvert FloatingRead=access)")
-    public ComplexMatchResult floatConvert(FloatConvertNode root, Access access) {
+    public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) {
         switch (root.getFloatConvert()) {
             case D2F:
                 return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSD2SS, SD, access);
@@ -437,7 +553,7 @@
 
     @MatchRule("(Reinterpret Read=access)")
     @MatchRule("(Reinterpret FloatingRead=access)")
-    public ComplexMatchResult reinterpret(ReinterpretNode root, Access access) {
+    public ComplexMatchResult reinterpret(ReinterpretNode root, LIRLowerableAccess access) {
         return builder -> {
             LIRKind kind = getLIRGeneratorTool().getLIRKind(root.stamp());
             return emitReinterpretMemory(kind, access);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java	Thu Apr 06 21:14:07 2017 +0000
@@ -26,6 +26,7 @@
 import org.graalvm.compiler.lir.amd64.phases.StackMoveOptimizationPhase;
 import org.graalvm.compiler.lir.phases.LIRSuites;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 
 public class AMD64SuitesProvider extends DefaultSuitesProvider {
@@ -35,9 +36,9 @@
     }
 
     @Override
-    public LIRSuites createLIRSuites() {
-        LIRSuites lirSuites = super.createLIRSuites();
-        if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue()) {
+    public LIRSuites createLIRSuites(OptionValues options) {
+        LIRSuites lirSuites = super.createLIRSuites(options);
+        if (StackMoveOptimizationPhase.Options.LIROptStackMoveOptimizer.getValue(options)) {
             /* Note: this phase must be inserted <b>after</b> RedundantMoveElimination */
             lirSuites.getPostAllocationOptimizationStage().appendPhase(new StackMoveOptimizationPhase());
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CancellationBailoutException.java	Thu Apr 06 21:14:07 2017 +0000
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.common;
+
+/**
+ * A {@linkplain RetryableBailoutException} that will be thrown if an on-going compilation in the
+ * compiler was cancelled.
+ */
+public final class CancellationBailoutException extends RetryableBailoutException {
+
+    private static final long serialVersionUID = 6551793589275293360L;
+
+    public CancellationBailoutException() {
+        super("Compilation cancelled.");
+    }
+
+    public static void cancelCompilation() {
+        throw new CancellationBailoutException();
+    }
+
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CollectionsFactory.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,132 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.common;
-
-import static org.graalvm.compiler.core.common.CollectionsFactory.Mode.STANDARD;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * Factory for creating collection objects used during compilation.
- */
-public class CollectionsFactory {
-
-    private static final ThreadLocal<Mode> tl = new ThreadLocal<>();
-
-    public static class ModeScope implements AutoCloseable {
-        private final Mode previousMode;
-
-        public ModeScope(Mode previousMode) {
-            this.previousMode = previousMode;
-        }
-
-        @Override
-        public void close() {
-            tl.set(previousMode);
-        }
-    }
-
-    /**
-     * Constants denoting what type of collections are {@link CollectionsFactory#getMode()
-     * currently} returned by the factory.
-     */
-    public enum Mode {
-        /**
-         * Denotes standard collections such as {@link HashSet} and {@link HashMap}.
-         */
-        STANDARD,
-
-        /**
-         * Denotes collections that have a deterministic iteration order over their keys/entries.
-         */
-        DETERMINISTIC_ITERATION_ORDER;
-    }
-
-    /**
-     * Gets the current mode determining the type of collection objects created by this factory.
-     */
-    public static Mode getMode() {
-        Mode mode = tl.get();
-        return mode == null ? Mode.STANDARD : mode;
-    }
-
-    /**
-     * Updates the mode for the current thread.
-     *
-     * @return an object which when {@linkplain ModeScope#close() closed} will revert the mode of
-     *         the current thread to the state before calling this method
-     */
-    public static ModeScope changeMode(Mode mode) {
-        Mode previousMode = tl.get();
-        tl.set(mode);
-        return new ModeScope(previousMode);
-    }
-
-    public static <K, V> HashMap<K, V> newMap() {
-        return getMode() == STANDARD ? new HashMap<>() : new LinkedHashMap<>();
-    }
-
-    public static <K, V> HashMap<K, V> newMap(Map<K, V> m) {
-        return getMode() == STANDARD ? new HashMap<>(m) : new LinkedHashMap<>(m);
-    }
-
-    public static <K, V> HashMap<K, V> newMap(int initialCapacity) {
-        return getMode() == STANDARD ? new HashMap<>(initialCapacity) : new LinkedHashMap<>(initialCapacity);
-    }
-
-    public static <K, V> Map<K, V> newIdentityMap() {
-        return getMode() == STANDARD ? new IdentityHashMap<>() : new LinkedIdentityHashMap<>();
-    }
-
-    public static <K, V> Map<K, V> newIdentityMap(int expectedMaxSize) {
-        return getMode() == STANDARD ? new IdentityHashMap<>(expectedMaxSize) : new LinkedIdentityHashMap<>();
-    }
-
-    public static <K, V> Map<K, V> newIdentityMap(Map<K, V> m) {
-        return getMode() == STANDARD ? new IdentityHashMap<>(m) : new LinkedIdentityHashMap<>(m);
-    }
-
-    /**
-     * Creates a set. If the current thread is {@linkplain CollectionsFactory#getMode() using}
-     * {@link Mode#DETERMINISTIC_ITERATION_ORDER} collections, the returned set will have an
-     * iteration order determined by the order in which elements are inserted in the set.
-     */
-    public static <E> Set<E> newSet() {
-        return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>() : new LinkedHashSet<>();
-    }
-
-    /**
-     * @see #newSet()
-     */
-    public static <E> Set<E> newSet(Collection<? extends E> c) {
-        return CollectionsFactory.getMode() == Mode.STANDARD ? new HashSet<>(c) : new LinkedHashSet<>(c);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/CompressEncoding.java	Thu Apr 06 21:14:07 2017 +0000
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.common;
+
+/**
+ * A compact representation of the different encoding strategies for Objects and metadata.
+ */
+public final class CompressEncoding {
+    private final long base;
+    private final int shift;
+
+    public CompressEncoding(long base, int shift) {
+        this.base = base;
+        this.shift = shift;
+    }
+
+    public int compress(long ptr) {
+        if (ptr == 0L) {
+            return 0;
+        } else {
+            return (int) ((ptr - base) >>> shift);
+        }
+    }
+
+    public boolean hasBase() {
+        return base != 0;
+    }
+
+    public boolean hasShift() {
+        return shift != 0;
+    }
+
+    public long getBase() {
+        return base;
+    }
+
+    public int getShift() {
+        return shift;
+    }
+
+    public long uncompress(int ptr) {
+        if (ptr == 0) {
+            return 0L;
+        } else {
+            return ((ptr & 0xFFFFFFFFL) << shift) + base;
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "base: " + base + " shift: " + shift;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (int) (base ^ (base >>> 32));
+        result = prime * result + shift;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof CompressEncoding) {
+            CompressEncoding other = (CompressEncoding) obj;
+            return base == other.base && shift == other.shift;
+        } else {
+            return false;
+        }
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Thu Apr 06 14:07:21 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Thu Apr 06 21:14:07 2017 +0000
@@ -22,10 +22,10 @@
  */
 package org.graalvm.compiler.core.common;
 
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionType;
-import org.graalvm.compiler.options.OptionValue;
-import org.graalvm.compiler.options.StableOptionValue;
+import org.graalvm.compiler.options.OptionKey;
 
 /**
  * This class encapsulates options that control the behavior of the Graal compiler.
@@ -34,250 +34,242 @@
 public final class GraalOptions {
 
     @Option(help = "Use compiler intrinsifications.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> Intrinsify = new OptionValue<>(true);
+    public static final OptionKey<Boolean> Intrinsify = new OptionKey<>(true);
 
     @Option(help = "Inline calls with monomorphic type profile.", type = OptionType.Expert)
-    public static final OptionValue<Boolean> InlineMonomorphicCalls = new OptionValue<>(true);
+    public static final OptionKey<Boolean> InlineMonomorphicCalls = new OptionKey<>(true);
 
     @Option(help = "Inline calls with polymorphic type profile.", type = OptionType.Expert)
-    public static final OptionValue<Boolean> InlinePolymorphicCalls = new OptionValue<>(true);
+    public static final OptionKey<Boolean> InlinePolymorphicCalls = new OptionKey<>(true);
 
     @Option(help = "Inline calls with megamorphic type profile (i.e., not all types could be recorded).", type = OptionType.Expert)
-    public static final OptionValue<Boolean> InlineMegamorphicCalls = new OptionValue<>(true);
+    public static final OptionKey<Boolean> InlineMegamorphicCalls = new OptionKey<>(true);
 
     @Option(help = "Maximum desired size of the compiler graph in nodes.", type = OptionType.User)
-    public static final OptionValue<Integer> MaximumDesiredSize = new OptionValue<>(20000);
+    public static final OptionKey<Integer> MaximumDesiredSize = new OptionKey<>(20000);
 
     @Option(help = "Minimum probability for methods to be inlined for megamorphic type profiles.", type = OptionType.Expert)
-    public static final OptionValue<Double> MegamorphicInliningMinMethodProbability = new OptionValue<>(0.33D);
+    public static final OptionKey<Double> MegamorphicInliningMinMethodProbability = new OptionKey<>(0.33D);
 
     @Option(help = "Maximum level of recursive inlining.", type = OptionType.Expert)
-    public static final OptionValue<Integer> MaximumRecursiveInlining = new OptionValue<>(5);
+    public static final OptionKey<Integer> MaximumRecursiveInlining = new OptionKey<>(5);
 
     @Option(help = "Graphs with less than this number of nodes are trivial and therefore always inlined.", type = OptionType.Expert)
-    public static final OptionValue<Integer> TrivialInliningSize = new OptionValue<>(10);
+    public static final OptionKey<Integer> TrivialInliningSize = new OptionKey<>(10);
 
     @Option(help = "Inlining is explored up to this number of nodes in the graph for each call site.", type = OptionType.Expert)
-    public static final OptionValue<Integer> MaximumInliningSize = new OptionValue<>(300);
+    public static final OptionKey<Integer> MaximumInliningSize = new OptionKey<>(300);
 
     @Option(help = "If the previous low-level graph size of the method exceeds the threshold, it is not inlined.", type = OptionType.Expert)
-    public static final OptionValue<Integer> SmallCompiledLowLevelGraphSize = new OptionValue<>(300);
+    public static final OptionKey<Integer> SmallCompiledLowLevelGraphSize = new OptionKey<>(300);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Double> LimitInlinedInvokes = new OptionValue<>(5.0);
+    public static final OptionKey<Double> LimitInlinedInvokes = new OptionKey<>(5.0);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Boolean> InlineEverything = new OptionValue<>(false);
+    public static final OptionKey<Boolean> InlineEverything = new OptionKey<>(false);
 
     // escape analysis settings
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> PartialEscapeAnalysis = new OptionValue<>(true);
+    public static final OptionKey<Boolean> PartialEscapeAnalysis = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Integer> EscapeAnalysisIterations = new OptionValue<>(2);
+    public static final OptionKey<Integer> EscapeAnalysisIterations = new OptionKey<>(2);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Integer> EscapeAnalysisLoopCutoff = new OptionValue<>(20);
+    public static final OptionKey<Integer> EscapeAnalysisLoopCutoff = new OptionKey<>(20);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<String> EscapeAnalyzeOnly = new OptionValue<>(null);
+    public static final OptionKey<String> EscapeAnalyzeOnly = new OptionKey<>(null);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Integer> MaximumEscapeAnalysisArrayLength = new OptionValue<>(32);
+    public static final OptionKey<Integer> MaximumEscapeAnalysisArrayLength = new OptionKey<>(32);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> PEAInliningHints = new OptionValue<>(false);
+    public static final OptionKey<Boolean> PEAInliningHints = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Double> TailDuplicationProbability = new OptionValue<>(0.5);
+    public static final OptionKey<Double> TailDuplicationProbability = new OptionKey<>(0.5);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Integer> TailDuplicationTrivialSize = new OptionValue<>(1);
+    public static final OptionKey<Integer> TailDuplicationTrivialSize = new OptionKey<>(1);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Integer> DeoptsToDisableOptimisticOptimization = new OptionValue<>(40);
+    public static final OptionKey<Integer> DeoptsToDisableOptimisticOptimization = new OptionKey<>(40);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> LoopPeeling = new OptionValue<>(true);
+    public static final OptionKey<Boolean> LoopPeeling = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> ReassociateInvariants = new OptionValue<>(true);
+    public static final OptionKey<Boolean> ReassociateInvariants = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> FullUnroll = new OptionValue<>(true);
+    public static final OptionKey<Boolean> FullUnroll = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> LoopUnswitch = new OptionValue<>(true);
+    public static final OptionKey<Boolean> LoopUnswitch = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Float> MinimumPeelProbability = new OptionValue<>(0.35f);
+    public static final OptionKey<Float> MinimumPeelProbability = new OptionKey<>(0.35f);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Integer> LoopMaxUnswitch = new OptionValue<>(3);
+    public static final OptionKey<Integer> LoopMaxUnswitch = new OptionKey<>(3);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> UseLoopLimitChecks = new OptionValue<>(true);
+    public static final OptionKey<Boolean> UseLoopLimitChecks = new OptionKey<>(true);
 
     // debugging settings
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> ZapStackOnMethodEntry = new OptionValue<>(false);
+    public static final OptionKey<Boolean> ZapStackOnMethodEntry = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> DeoptALot = new OptionValue<>(false);
+    public static final OptionKey<Boolean> DeoptALot = new OptionKey<>(false);
 
     @Option(help = "Stress the code emitting explicit exception throwing code.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> StressExplicitExceptionCode = new OptionValue<>(false);
+    public static final OptionKey<Boolean> StressExplicitExceptionCode = new OptionKey<>(false);
 
     @Option(help = "Stress the code emitting invokes with explicit exception edges.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> StressInvokeWithExceptionNode = new OptionValue<>(false);
+    public static final OptionKey<Boolean> StressInvokeWithExceptionNode = new OptionKey<>(false);
+
+    @Option(help = "Stress the code by emitting reads at earliest instead of latest point.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> StressTestEarlyReads = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> VerifyPhases = new OptionValue<>(false);
+    public static final OptionKey<Boolean> VerifyPhases = new OptionKey<>(false);
 
     // Debug settings:
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Integer> GCDebugStartCycle = new OptionValue<>(-1);
+    public static final OptionKey<Integer> GCDebugStartCycle = new OptionKey<>(-1);
 
     @Option(help = "Perform platform dependent validation of the Java heap at returns", type = OptionType.Debug)
-    public static final OptionValue<Boolean> VerifyHeapAtReturn = new OptionValue<>(false);
+    public static final OptionKey<Boolean> VerifyHeapAtReturn = new OptionKey<>(false);
 
     // Other printing settings
     @Option(help = "Print profiling information when parsing a method's bytecode", type = OptionType.Debug)
-    public static final OptionValue<Boolean> PrintProfilingInformation = new OptionValue<>(false);
+    public static final OptionKey<Boolean> PrintProfilingInformation = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final StableOptionValue<Boolean> TraceEscapeAnalysis = new StableOptionValue<>(false);
+    public static final OptionKey<Boolean> TraceEscapeAnalysis = new OptionKey<>(false);
 
     // HotSpot command line options
     @Option(help = "Print inlining optimizations", type = OptionType.Debug)
-    public static final OptionValue<Boolean> HotSpotPrintInlining = new OptionValue<>(false);
+    public static final OptionKey<Boolean> HotSpotPrintInlining = new OptionKey<>(false);
 
     // Register allocator debugging
     @Option(help = "Comma separated list of registers that register allocation is limited to.", type = OptionType.Debug)
-    public static final OptionValue<String> RegisterPressure = new OptionValue<>(null);
+    public static final OptionKey<String> RegisterPressure = new OptionKey<>(null);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> ConditionalElimination = new OptionValue<>(true);
+    public static final OptionKey<Boolean> ConditionalElimination = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> RemoveNeverExecutedCode = new OptionValue<>(true);
+    public static final OptionKey<Boolean> RawConditionalElimination = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> UseExceptionProbability = new OptionValue<>(true);
+    public static final OptionKey<Boolean> ReplaceInputsWithConstantsBasedOnStamps = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> UseExceptionProbabilityForOperations = new OptionValue<>(true);
+    public static final OptionKey<Boolean> RemoveNeverExecutedCode = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OmitHotExceptionStacktrace = new OptionValue<>(false);
+    public static final OptionKey<Boolean> UseExceptionProbability = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> GenSafepoints = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OmitHotExceptionStacktrace = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> GenLoopSafepoints = new OptionValue<>(true);
+    public static final OptionKey<Boolean> GenSafepoints = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> UseTypeCheckHints = new OptionValue<>(true);
+    public static final OptionKey<Boolean> GenLoopSafepoints = new OptionKey<>(true);
+
+    @Option(help = "", type = OptionType.Debug)
+    public static final OptionKey<Boolean> UseTypeCheckHints = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Boolean> InlineVTableStubs = new OptionValue<>(true);
+    public static final OptionKey<Boolean> InlineVTableStubs = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Boolean> AlwaysInlineVTableStubs = new OptionValue<>(false);
+    public static final OptionKey<Boolean> AlwaysInlineVTableStubs = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> ResolveClassBeforeStaticInvoke = new OptionValue<>(false);
+    public static final OptionKey<Boolean> ResolveClassBeforeStaticInvoke = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> CanOmitFrame = new OptionValue<>(true);
+    public static final OptionKey<Boolean> CanOmitFrame = new OptionKey<>(true);
 
     // Ahead of time compilation
     @Option(help = "Try to avoid emitting code where patching is required", type = OptionType.Expert)
-    public static final OptionValue<Boolean> ImmutableCode = new OptionValue<>(false);
+    public static final OptionKey<Boolean> ImmutableCode = new OptionKey<>(false);
 
     @Option(help = "Generate position independent code", type = OptionType.Expert)
-    public static final OptionValue<Boolean> GeneratePIC = new OptionValue<>(false);
+    public static final OptionKey<Boolean> GeneratePIC = new OptionKey<>(false);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Boolean> CallArrayCopy = new OptionValue<>(true);
+    public static final OptionKey<Boolean> CallArrayCopy = new OptionKey<>(true);
 
     // Runtime settings
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Boolean> SupportJsrBytecodes = new OptionValue<>(true);
+    public static final OptionKey<Boolean> SupportJsrBytecodes = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Expert)
-    public static final OptionValue<Boolean> OptAssumptions = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptAssumptions = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptConvertDeoptsToGuards = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptConvertDeoptsToGuards = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptReadElimination = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptReadElimination = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Integer> ReadEliminationMaxLoopVisits = new OptionValue<>(5);
+    public static final OptionKey<Integer> ReadEliminationMaxLoopVisits = new OptionKey<>(5);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptDeoptimizationGrouping = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptDeoptimizationGrouping = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptScheduleOutOfLoops = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptScheduleOutOfLoops = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptEliminateGuards = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptEliminateGuards = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptImplicitNullChecks = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptImplicitNullChecks = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptClearNonLiveLocals = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptClearNonLiveLocals = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptLoopTransform = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptLoopTransform = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptFloatingReads = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptFloatingReads = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptEliminatePartiallyRedundantGuards = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptEliminatePartiallyRedundantGuards = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptFilterProfiledTypes = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptFilterProfiledTypes = new OptionKey<>(true);
 
     @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptDevirtualizeInvokesOptimistically = new OptionValue<>(true);
-
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionValue<Boolean> OptPushThroughPi = new OptionValue<>(true);
+    public static final OptionKey<Boolean> OptDevirtualizeInvokesOptimistically = new OptionKey<>(true);
 
     @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> MatchExpressions = new OptionValue<>(true);
+    public static final OptionKey<Boolean> MatchExpressions = new OptionKey<>(true);
 
     @Option(help = "Enable counters for various paths in snippets.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> SnippetCounters = new OptionValue<>(false);
+    public static final OptionKey<Boolean> SnippetCounters = new OptionKey<>(false);
 
     @Option(help = "Eagerly construct extra snippet info.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> EagerSnippets = new OptionValue<>(false);
+    public static final OptionKey<Boolean> EagerSnippets = new OptionKey<>(false);
 
     @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> UseSnippetGraphCache = new OptionValue<>(true);
+    public static final OptionKey<Boolean> UseSnippetGraphCache = new OptionKey<>(true);
 
-    @Option(help = "Enable expensive assertions", type = OptionType.Debug)
-    public static final OptionValue<Boolean> DetailedAsserts = new StableOptionValue<Boolean>() {
-        @Override
-        protected Boolean defaultValue() {
-            boolean enabled = false;
-            // turn detailed assertions on when the general assertions are on (misusing the assert keyword for this)
-            assert (enabled = true) == true;
-            return enabled;
-        }
-    };
-
-    @Option(help = "Enable Graal instrumentation")
-    public static final OptionValue<Boolean> UseGraalInstrumentation = new OptionValue<>(false);
+    @Option(help = "Enable expensive assertions.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> DetailedAsserts = new OptionKey<>(Assertions.ENABLED);
 
     @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug)
-    public static final OptionValue<Boolean> TraceRA = new OptionValue<>(false);
+    public static final OptionKey<Boolean> TraceRA = new OptionKey<>(false);
 
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/LinkedIdentityHashMap.java	Thu Apr 06 14:07:21 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.common;
-
-import java.util.AbstractSet;
-import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.Spliterator;
-import java.util.Spliterators;
-import java.util.function.Consumer;
-
-/**
- * A map that combines {@link IdentityHashMap} with {@link LinkedHashMap} for the purpose of
- * ensuring a deterministic execution order during a capturing compilation.
- */
-final class LinkedIdentityHashMap<K, V> implements Map<K, V> {
-
-    private final LinkedHashMap<Id<K>, V> map;
-
-    LinkedIdentityHashMap() {
-        map = new LinkedHashMap<>();
-    }
-
-    LinkedIdentityHashMap(Map<K, V> m) {
-        map = new LinkedHashMap<>(m.size());
-        putAll(m);
-    }
-
-    LinkedIdentityHashMap(int expectedMaxSize) {
-        map = new LinkedHashMap<>(expectedMaxSize);
-    }
-
-    /**
-     * Wrapper for an object that gives uses the object's identity for the purpose of equality
-     * comparisons and computing a hash code.
-     */
-    static final class Id<T> {
-        final T object;
-
-        Id(T object) {
-            assert object != null;
-            this.object = object;
-        }
-
-        @SuppressWarnings("unchecked")
-        @Override
-        public boolean equals(Object obj) {
-            return obj instanceof Id && ((Id<T>) obj).object == object;
-        }
-
-        @Override
-        public int hashCode() {
-            return System.identityHashCode(object);
-        }
-    }
-
-    @Override
-    public int size() {
-        return map.size();
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return map.isEmpty();
-    }
-
-    @Override
-    public boolean containsKey(Object key) {
-        return map.containsKey(id(key));
-    }
-
-    @SuppressWarnings("unchecked")
-    private Id<K> id(Object key) {
-        if (key == null) {
-            return null;
-        }
-        return new Id<>((K) key);
-    }
-
-    @Override
-    public boolean containsValue(Object value) {
-        return map.containsValue(value);
-    }
-
-    @Override
-    public V get(Object key) {
-        return map.get(id(key));
-    }
-
-    @Override
-    public V put(K key, V value) {
-        return map.put(id(key), value);
-    }
-
-    @Override
-    public V remove(Object key) {
-        return map.remove(id(key));
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    public void putAll(Map<? extends K, ? extends V> m) {
-        if (m == null) {
-            throw new NullPointerException();
-        }
-        if (m.getClass() == getClass()) {
-            LinkedIdentityHashMap<K, V> that = (LinkedIdentityHashMap<K, V>) m;
-            map.putAll(that.map);
-
-        } else {
-            for (K key : m.keySet()) {
-                map.put(id(key), m.get(key));
-            }
-        }
-    }
-