changeset 46536:79d8dffda212

8182018: Update Graal Reviewed-by: kvn
author iveresov
date Tue, 13 Jun 2017 09:19:35 -0700
parents 025dfc75204d
children 8f9a3ff618bd
files hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/AtomicUnsigned.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/AtomicWord.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/ComparableWord.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/LocationIdentity.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Pointer.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/PointerBase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/PointerUtils.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Signed.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Unsigned.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/UnsignedUtils.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/WordBase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/WordFactory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolver.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AbstractInliningPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/IdealGraphPrinter.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java
diffstat 90 files changed, 3053 insertions(+), 616 deletions(-) [+]
line wrap: on
line diff
--- a/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/.mx.graal/suite.py	Tue Jun 13 09:19:35 2017 -0700
@@ -61,6 +61,27 @@
   },
 
   "projects" : {
+    # -------------- SDK --------------
+    "org.graalvm.options" : {
+      "subDir" : "share/classes",
+      "sourceDirs" : ["src"],
+      "dependencies" : [],
+      "uses" : [],
+      "exports" : [
+        "<package-info>",  # exports all packages containing package-info.java
+      ],
+      "checkstyle" : "org.graalvm.api.word",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,SDK",
+    },
+    "org.graalvm.api.word" : {
+      "subDir" : "share/classes",
+      "sourceDirs" : ["src"],
+      "dependencies" : [],
+      "checkstyle" : "org.graalvm.api.word",
+      "javaCompliance" : "1.8",
+      "workingSets" : "API,SDK",
+    },
 
     # ------------- Graal -------------
 
@@ -84,7 +105,7 @@
 
     "org.graalvm.compiler.options" : {
       "subDir" : "share/classes",
-      "dependencies" : ["JVMCI_SERVICES", "JVMCI_API"],
+      "dependencies" : ["JVMCI_SERVICES", "JVMCI_API", "org.graalvm.util"],
       "sourceDirs" : ["src"],
       "dependencies" : ["org.graalvm.util"],
       "checkstyle" : "org.graalvm.compiler.graph",
@@ -594,15 +615,6 @@
       "workingSets" : "Graal,LIR,SPARC",
     },
 
-    "org.graalvm.api.word" : {
-      "subDir" : "share/classes",
-      "sourceDirs" : ["src"],
-      "dependencies" : [],
-      "checkstyle" : "org.graalvm.compiler.graph",
-      "javaCompliance" : "1.8",
-      "workingSets" : "API",
-    },
-
     "org.graalvm.compiler.word" : {
       "subDir" : "share/classes",
       "sourceDirs" : ["src"],
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/AtomicUnsigned.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/AtomicUnsigned.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/AtomicWord.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/AtomicWord.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/ComparableWord.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/ComparableWord.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/LocationIdentity.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/LocationIdentity.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Pointer.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Pointer.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/PointerBase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/PointerBase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/PointerUtils.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/PointerUtils.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Signed.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Signed.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Unsigned.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/Unsigned.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/UnsignedUtils.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/UnsignedUtils.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/WordBase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/WordBase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/WordFactory.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.api.word/src/org/graalvm/api/word/WordFactory.java	Tue Jun 13 09:19:35 2017 -0700
@@ -4,7 +4,9 @@
  *
  * 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.
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
  *
  * This code is distributed in the hope that it will be useful, but WITHOUT
  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLowering.java	Tue Jun 13 07:30:11 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2015, 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.core.aarch64;
-
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering;
-
-public class AArch64AddressLowering extends AddressLowering {
-
-    @Override
-    public AddressNode lower(ValueNode address) {
-        return lower(address, null);
-    }
-
-    @Override
-    public AddressNode lower(ValueNode base, ValueNode offset) {
-        AArch64AddressNode ret = new AArch64AddressNode(base, offset);
-        // TODO improve
-        return base.graph().unique(ret);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressLoweringByUse.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 2017, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.graalvm.compiler.core.aarch64;
+
+import jdk.vm.ci.aarch64.AArch64Kind;
+import jdk.vm.ci.meta.JavaConstant;
+import org.graalvm.compiler.asm.aarch64.AArch64Address;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.core.common.NumUtil;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.AddNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.memory.address.RawAddressNode;
+import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
+
+public class AArch64AddressLoweringByUse extends AddressLoweringByUsePhase.AddressLoweringByUse {
+    private AArch64LIRKindTool kindtool;
+
+    public AArch64AddressLoweringByUse(AArch64LIRKindTool kindtool) {
+        this.kindtool = kindtool;
+    }
+
+    @Override
+    public AddressNode lower(ValueNode use, Stamp stamp, AddressNode address) {
+        if (address instanceof RawAddressNode) {
+            return doLower(stamp, address.getBase(), null);
+        } else if (address instanceof OffsetAddressNode) {
+            OffsetAddressNode offsetAddress = (OffsetAddressNode) address;
+            return doLower(stamp, offsetAddress.getBase(), offsetAddress.getOffset());
+        } else {
+            // must be an already transformed AArch64AddressNode
+            return address;
+        }
+    }
+
+    @Override
+    public AddressNode lower(AddressNode address) {
+        return lower(null, null, address);
+    }
+
+    private AddressNode doLower(Stamp stamp, ValueNode base, ValueNode index) {
+        AArch64AddressNode ret = new AArch64AddressNode(base, index);
+        AArch64Kind aarch64Kind = (stamp == null ? null : getAArch64Kind(stamp));
+
+        // improve the address as much as possible
+        boolean changed;
+        do {
+            changed = improve(aarch64Kind, ret);
+        } while (changed);
+
+        // avoid duplicates
+        return base.graph().unique(ret);
+    }
+
+    protected boolean improve(AArch64Kind kind, AArch64AddressNode ret) {
+        AArch64Address.AddressingMode mode = ret.getAddressingMode();
+        // if we have already set a displacement or set to base only mode then we are done
+        if (isDisplacementMode(mode) || isBaseOnlyMode(mode)) {
+            return false;
+        }
+        ValueNode base = ret.getBase();
+        ValueNode index = ret.getIndex();
+
+        // avoid a constant or null base if possible
+        if (base == null) {
+            ret.setBase(index);
+            ret.setIndex(base);
+            return true;
+        }
+        // make sure any integral JavaConstant
+        // is the index rather than the base
+        // strictly we don't need the conditions on index
+        // as we ought not to see two JavaConstant values
+        if (base.isJavaConstant() && base.asJavaConstant().getJavaKind().isNumericInteger() &&
+                        index != null && !index.isJavaConstant()) {
+            ret.setBase(index);
+            ret.setIndex(base);
+            return true;
+        }
+
+        // if the base is an add then move it up
+        if (index == null && base instanceof AddNode) {
+            AddNode add = (AddNode) base;
+            ret.setBase(add.getX());
+            ret.setIndex(add.getY());
+            return true;
+        }
+
+        // we can try to fold a JavaConstant index into a displacement
+        if (index != null && index.isJavaConstant()) {
+            JavaConstant javaConstant = index.asJavaConstant();
+            if (javaConstant.getJavaKind().isNumericInteger()) {
+                long disp = javaConstant.asLong();
+                mode = immediateMode(kind, disp);
+                if (isDisplacementMode(mode)) {
+                    index = null;
+                    // we can fold this in as a displacement
+                    // but first see if we can pull up any additional
+                    // constants added into the base
+                    boolean tryNextBase = (base instanceof AddNode);
+                    while (tryNextBase) {
+                        AddNode add = (AddNode) base;
+                        tryNextBase = false;
+                        ValueNode child = add.getX();
+                        if (child.isJavaConstant() && child.asJavaConstant().getJavaKind().isNumericInteger()) {
+                            long newDisp = disp + child.asJavaConstant().asLong();
+                            AArch64Address.AddressingMode newMode = immediateMode(kind, newDisp);
+                            if (newMode != AArch64Address.AddressingMode.REGISTER_OFFSET) {
+                                disp = newDisp;
+                                mode = newMode;
+                                base = add.getY();
+                                ret.setBase(base);
+                                tryNextBase = (base instanceof AddNode);
+                            }
+                        } else {
+                            child = add.getY();
+                            if (child.isJavaConstant() && child.asJavaConstant().getJavaKind().isNumericInteger()) {
+                                long newDisp = disp + child.asJavaConstant().asLong();
+                                AArch64Address.AddressingMode newMode = immediateMode(kind, newDisp);
+                                if (newMode != AArch64Address.AddressingMode.REGISTER_OFFSET) {
+                                    disp = newDisp;
+                                    mode = newMode;
+                                    base = add.getX();
+                                    ret.setBase(base);
+                                    tryNextBase = (base instanceof AddNode);
+                                }
+                            }
+                        }
+                    }
+                    if (disp != 0) {
+                        // ok now set the displacement in place of an index
+                        ret.setIndex(null);
+                        int scaleFactor = computeScaleFactor(kind, mode);
+                        ret.setDisplacement(disp, scaleFactor, mode);
+                    } else {
+                        // reset to base register only
+                        ret.setIndex(null);
+                        ret.setDisplacement(0, 1, AArch64Address.AddressingMode.BASE_REGISTER_ONLY);
+                    }
+                    return true;
+                }
+            }
+        }
+        // nope cannot improve this any more
+        return false;
+    }
+
+    private AArch64Kind getAArch64Kind(Stamp stamp) {
+        LIRKind lirKind = stamp.getLIRKind(kindtool);
+        if (!lirKind.isValue()) {
+            if (!lirKind.isReference(0) || lirKind.getReferenceCount() != 1) {
+                return null;
+            }
+        }
+
+        return (AArch64Kind) lirKind.getPlatformKind();
+    }
+
+    private static AArch64Address.AddressingMode immediateMode(AArch64Kind kind, long value) {
+        if (kind != null) {
+            int size = kind.getSizeInBytes();
+            // this next test should never really fail
+            if ((value & (size - 1)) == 0) {
+                long encodedValue = value / size;
+                // assert value % size == 0
+                // we can try for a 12 bit scaled offset
+                if (NumUtil.isUnsignedNbit(12, encodedValue)) {
+                    return AArch64Address.AddressingMode.IMMEDIATE_SCALED;
+                }
+            }
+        }
+
+        // we can try for a 9 bit unscaled offset
+        if (NumUtil.isSignedNbit(9, value)) {
+            return AArch64Address.AddressingMode.IMMEDIATE_UNSCALED;
+        }
+
+        // nope this index needs to be passed via offset register
+        return AArch64Address.AddressingMode.REGISTER_OFFSET;
+    }
+
+    private static int computeScaleFactor(AArch64Kind kind, AArch64Address.AddressingMode mode) {
+        if (mode == AArch64Address.AddressingMode.IMMEDIATE_SCALED) {
+            return kind.getSizeInBytes();
+        }
+        return 1;
+    }
+
+    boolean isBaseOnlyMode(AArch64Address.AddressingMode addressingMode) {
+        return addressingMode == AArch64Address.AddressingMode.BASE_REGISTER_ONLY;
+    }
+
+    private static boolean isDisplacementMode(AArch64Address.AddressingMode addressingMode) {
+        switch (addressingMode) {
+            case IMMEDIATE_POST_INDEXED:
+            case IMMEDIATE_PRE_INDEXED:
+            case IMMEDIATE_SCALED:
+            case IMMEDIATE_UNSCALED:
+                return true;
+        }
+        return false;
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64AddressNode.java	Tue Jun 13 09:19:35 2017 -0700
@@ -26,7 +26,6 @@
 import org.graalvm.compiler.asm.aarch64.AArch64Address;
 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
 import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
@@ -40,7 +39,7 @@
 import jdk.vm.ci.meta.Value;
 
 /**
- * Represents an address of the form... TODO.
+ * Represents an AArch64 address in the graph.
  */
 @NodeInfo
 public class AArch64AddressNode extends AddressNode implements LIRLowerable {
@@ -52,7 +51,8 @@
     @OptionalInput private ValueNode index;
     private AArch64Address.AddressingMode addressingMode;
 
-    private int displacement;
+    private long displacement;
+    private int scaleFactor;
 
     public AArch64AddressNode(ValueNode base) {
         this(base, null);
@@ -63,6 +63,8 @@
         this.base = base;
         this.index = index;
         this.addressingMode = AddressingMode.REGISTER_OFFSET;
+        this.displacement = 0;
+        this.scaleFactor = 1;
     }
 
     @Override
@@ -76,7 +78,6 @@
         AllocatableValue indexReference;
         if (addressingMode.equals(AddressingMode.IMMEDIATE_UNSCALED)) {
             indexReference = LIRKind.derivedBaseFromValue(indexValue);
-            throw GraalError.unimplemented();
         } else {
             if (LIRKind.isValue(indexValue.getValueKind())) {
                 indexReference = null;
@@ -86,8 +87,7 @@
         }
 
         LIRKind kind = LIRKind.combineDerived(tool.getLIRKind(stamp()), baseReference, indexReference);
-        final boolean scaled = false;
-        gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, displacement, scaled, addressingMode));
+        gen.setResult(this, new AArch64AddressValue(kind, baseValue, indexValue, (int) displacement, scaleFactor, addressingMode));
     }
 
     @Override
@@ -116,16 +116,22 @@
         this.index = index;
     }
 
-    public int getDisplacement() {
+    public long getDisplacement() {
         return displacement;
     }
 
-    public void setDisplacement(int displacement) {
+    public void setDisplacement(long displacement, int scaleFactor, AArch64Address.AddressingMode addressingMode) {
         this.displacement = displacement;
+        this.scaleFactor = scaleFactor;
+        this.addressingMode = addressingMode;
     }
 
     @Override
     public long getMaxConstantDisplacement() {
-        return Long.MAX_VALUE;
+        return displacement;
+    }
+
+    public AddressingMode getAddressingMode() {
+        return addressingMode;
     }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -120,7 +120,7 @@
         if (address instanceof AArch64AddressValue) {
             return (AArch64AddressValue) address;
         } else {
-            return new AArch64AddressValue(address.getValueKind(), asAllocatable(address), Value.ILLEGAL, 0, false, AddressingMode.BASE_REGISTER_ONLY);
+            return new AArch64AddressValue(address.getValueKind(), asAllocatable(address), Value.ILLEGAL, 0, 1, AddressingMode.BASE_REGISTER_ONLY);
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.aarch64;
+
+import org.graalvm.compiler.java.DefaultSuitesCreator;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+
+public class AArch64SuitesCreator extends DefaultSuitesCreator {
+
+    public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+        super(compilerConfiguration, plugins);
+    }
+
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.aarch64;
-
-import org.graalvm.compiler.java.DefaultSuitesProvider;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-
-public class AArch64SuitesProvider extends DefaultSuitesProvider {
-
-    public AArch64SuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        super(compilerConfiguration, plugins);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesCreator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.amd64;
+
+import org.graalvm.compiler.java.DefaultSuitesCreator;
+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 AMD64SuitesCreator extends DefaultSuitesCreator {
+
+    public AMD64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+        super(compilerConfiguration, plugins);
+    }
+
+    @Override
+    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());
+        }
+        return lirSuites;
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64SuitesProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.amd64;
-
-import org.graalvm.compiler.java.DefaultSuitesProvider;
-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 {
-
-    public AMD64SuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        super(compilerConfiguration, plugins);
-    }
-
-    @Override
-    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());
-        }
-        return lirSuites;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesCreator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2015, 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.core.sparc;
+
+import java.util.ListIterator;
+
+import org.graalvm.compiler.java.DefaultSuitesCreator;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.common.ExpandLogicPhase;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.Suites;
+
+public class SPARCSuitesCreator extends DefaultSuitesCreator {
+
+    public SPARCSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+        super(compilerConfiguration, plugins);
+    }
+
+    @Override
+    public Suites createSuites(OptionValues options) {
+        Suites s = super.createSuites(options);
+        ListIterator<BasePhase<? super LowTierContext>> l = s.getLowTier().findPhase(ExpandLogicPhase.class);
+        while (PhaseSuite.findNextPhase(l, ExpandLogicPhase.class)) {
+            // Search for last occurrence of ExpandLogicPhase
+        }
+        l.previous();
+        l.add(new SPARCIntegerCompareCanonicalizationPhase());
+        return s;
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCSuitesProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2015, 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.core.sparc;
-
-import java.util.ListIterator;
-
-import org.graalvm.compiler.java.DefaultSuitesProvider;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.PhaseSuite;
-import org.graalvm.compiler.phases.common.ExpandLogicPhase;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.phases.tiers.LowTierContext;
-import org.graalvm.compiler.phases.tiers.Suites;
-
-public class SPARCSuitesProvider extends DefaultSuitesProvider {
-    public SPARCSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        super(compilerConfiguration, plugins);
-    }
-
-    @Override
-    public Suites createSuites(OptionValues options) {
-        Suites s = super.createSuites(options);
-        ListIterator<BasePhase<? super LowTierContext>> l = s.getLowTier().findPhase(ExpandLogicPhase.class);
-        while (PhaseSuite.findNextPhase(l, ExpandLogicPhase.class)) {
-            // Search for last occurrence of ExpandLogicPhase
-        }
-        l.previous();
-        l.add(new SPARCIntegerCompareCanonicalizationPhase());
-        return s;
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Tue Jun 13 09:19:35 2017 -0700
@@ -310,7 +310,7 @@
             LIRGenerationContext context = new LIRGenerationContext(lirGen, nodeLirGen, graph, schedule);
             new LIRGenerationPhase().apply(backend.getTarget(), lirGenRes, context);
 
-            try (Scope s = Debug.scope("LIRStages", nodeLirGen, lir)) {
+            try (Scope s = Debug.scope("LIRStages", nodeLirGen, lirGenRes, lir)) {
                 // Dump LIR along with HIR (the LIR is looked up from context)
                 Debug.dump(Debug.BASIC_LEVEL, graph.getLastSchedule(), "After LIR generation");
                 LIRGenerationResult result = emitLowLevel(backend.getTarget(), lirGenRes, lirGen, lirSuites, backend.newRegisterAllocationConfig(registerConfig, allocationRestrictedTo));
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Tue Jun 13 09:19:35 2017 -0700
@@ -27,8 +27,9 @@
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
-import org.graalvm.compiler.core.aarch64.AArch64AddressLowering;
-import org.graalvm.compiler.core.aarch64.AArch64SuitesProvider;
+import org.graalvm.compiler.core.aarch64.AArch64AddressLoweringByUse;
+import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
+import org.graalvm.compiler.core.aarch64.AArch64SuitesCreator;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
@@ -176,7 +177,7 @@
     }
 
     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        return new HotSpotSuitesProvider(new AArch64SuitesProvider(compilerConfiguration, plugins), config, runtime, new AArch64AddressLowering());
+        return new AArch64HotSpotSuitesProvider(new AArch64SuitesCreator(compilerConfiguration, plugins), config, runtime, new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
     }
 
     protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -36,7 +36,6 @@
 import org.graalvm.compiler.core.aarch64.AArch64LIRKindTool;
 import org.graalvm.compiler.core.common.CompressEncoding;
 import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
 import org.graalvm.compiler.core.common.spi.LIRKindTool;
@@ -321,8 +320,7 @@
         LIRKind wordKind = LIRKind.value(target().arch.getWordKind());
         RegisterValue thread = getProviders().getRegisters().getThreadRegister().asValue(wordKind);
         final int transferSize = value.getValueKind().getPlatformKind().getSizeInBytes();
-        final int scaledDisplacement = offset >> NumUtil.log2Ceil(transferSize);
-        AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, scaledDisplacement, true, AddressingMode.IMMEDIATE_SCALED);
+        AArch64AddressValue address = new AArch64AddressValue(value.getValueKind(), thread, Value.ILLEGAL, offset, transferSize, AddressingMode.IMMEDIATE_SCALED);
         append(new StoreOp((AArch64Kind) value.getPlatformKind(), address, loadReg(value), null));
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.aarch64;
+
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
+import org.graalvm.compiler.phases.common.ExpandLogicPhase;
+import org.graalvm.compiler.phases.common.FixReadsPhase;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.Suites;
+import org.graalvm.compiler.phases.tiers.SuitesCreator;
+
+import java.util.ListIterator;
+
+/**
+ * Subclass to factor out management of address lowering.
+ */
+public class AArch64HotSpotSuitesProvider extends HotSpotSuitesProvider {
+
+    private final AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse;
+
+    public AArch64HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime,
+                    AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse) {
+        super(defaultSuitesCreator, config, runtime);
+        this.addressLoweringByUse = addressLoweringByUse;
+    }
+
+    @Override
+    public Suites createSuites(OptionValues options) {
+        Suites suites = super.createSuites(options);
+
+        ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class);
+        if (findPhase == null) {
+            findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
+        }
+        findPhase.add(new AddressLoweringByUsePhase(addressLoweringByUse));
+
+        return suites;
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Tue Jun 13 09:19:35 2017 -0700
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
+import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotGraphBuilderPlugins;
@@ -182,7 +183,7 @@
      */
     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
                     HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) {
-        return new HotSpotSuitesProvider(new AMD64HotSpotSuitesProvider(compilerConfiguration, plugins), config, runtime,
+        return new AddressLoweringHotSpotSuitesProvider(new AMD64HotSpotSuitesCreator(compilerConfiguration, plugins), config, runtime,
                         new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options));
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesCreator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,47 @@
+/*
+ * 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.hotspot.amd64;
+
+import org.graalvm.compiler.core.amd64.AMD64SuitesCreator;
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase;
+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 AMD64HotSpotSuitesCreator extends AMD64SuitesCreator {
+
+    public AMD64HotSpotSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+        super(compilerConfiguration, plugins);
+    }
+
+    @Override
+    public LIRSuites createLIRSuites(OptionValues options) {
+        LIRSuites lirSuites = super.createLIRSuites(options);
+        if (GraalOptions.DetailedAsserts.getValue(options)) {
+            lirSuites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase());
+        }
+        return lirSuites;
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotSuitesProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +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.hotspot.amd64;
-
-import org.graalvm.compiler.core.amd64.AMD64SuitesProvider;
-import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.hotspot.lir.HotSpotZapRegistersPhase;
-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 AMD64HotSpotSuitesProvider extends AMD64SuitesProvider {
-
-    public AMD64HotSpotSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        super(compilerConfiguration, plugins);
-    }
-
-    @Override
-    public LIRSuites createLIRSuites(OptionValues options) {
-        LIRSuites lirSuites = super.createLIRSuites(options);
-        if (GraalOptions.DetailedAsserts.getValue(options)) {
-            lirSuites.getPostAllocationOptimizationStage().appendPhase(new HotSpotZapRegistersPhase());
-        }
-        return lirSuites;
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java	Tue Jun 13 09:19:35 2017 -0700
@@ -27,12 +27,13 @@
 
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.core.sparc.SPARCAddressLowering;
-import org.graalvm.compiler.core.sparc.SPARCSuitesProvider;
+import org.graalvm.compiler.core.sparc.SPARCSuitesCreator;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
+import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
@@ -123,7 +124,7 @@
      */
     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
                     Replacements replacements) {
-        return new HotSpotSuitesProvider(new SPARCSuitesProvider(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering());
+        return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering());
     }
 
     protected SPARCHotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Tue Jun 13 09:19:35 2017 -0700
@@ -22,14 +22,34 @@
  */
 package org.graalvm.compiler.hotspot.test;
 
+import java.lang.annotation.Annotation;
 import java.lang.management.ManagementFactory;
 import java.lang.reflect.Field;
+import java.lang.reflect.Type;
 import javax.management.Attribute;
 import javax.management.MBeanAttributeInfo;
 import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
 import javax.management.MBeanServer;
 import javax.management.ObjectInstance;
 import javax.management.ObjectName;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.Assumptions;
+import jdk.vm.ci.meta.Constant;
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ExceptionHandler;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.LineNumberTable;
+import jdk.vm.ci.meta.LocalVariableTable;
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.ResolvedJavaField;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.meta.Signature;
+import jdk.vm.ci.meta.SpeculationLog;
+import org.graalvm.compiler.debug.GraalDebugConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.util.EconomicMap;
@@ -57,7 +77,7 @@
         }
         assertNull("The platformMBeanServer isn't initialized now", field.get(null));
 
-        HotSpotGraalMBean bean = HotSpotGraalMBean.create();
+        HotSpotGraalMBean bean = HotSpotGraalMBean.create(null);
         assertNotNull("Bean created", bean);
 
         assertNull("It is not registered yet", bean.ensureRegistered(true));
@@ -82,7 +102,7 @@
 
         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 
-        HotSpotGraalMBean realBean = HotSpotGraalMBean.create();
+        HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
         assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
         final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
 
@@ -124,7 +144,7 @@
 
         assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
 
-        HotSpotGraalMBean realBean = HotSpotGraalMBean.create();
+        HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
 
         OptionValues original = new OptionValues(EconomicMap.create());
 
@@ -153,4 +173,533 @@
 
     }
 
+    @Test
+    public void dumpOperation() throws Exception {
+        Field field = null;
+        try {
+            field = stopMBeanServer();
+        } catch (Exception ex) {
+            if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
+                // skip on JDK9
+                return;
+            }
+        }
+        assertNull("The platformMBeanServer isn't initialized now", field.get(null));
+
+        ObjectName name;
+
+        assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
+
+        HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
+
+        assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
+        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+        ObjectInstance bean = server.getObjectInstance(name);
+        assertNotNull("Bean is registered", bean);
+
+        MBeanInfo info = server.getMBeanInfo(name);
+        assertNotNull("Info is found", info);
+
+        final MBeanOperationInfo[] arr = info.getOperations();
+        assertEquals("Currently three overloads", 3, arr.length);
+        MBeanOperationInfo dumpOp = null;
+        for (int i = 0; i < arr.length; i++) {
+            assertEquals("dumpMethod", arr[i].getName());
+            if (arr[i].getSignature().length == 3) {
+                dumpOp = arr[i];
+            }
+        }
+        assertNotNull("three args variant found", dumpOp);
+
+        server.invoke(name, "dumpMethod", new Object[]{
+                        "java.util.Arrays", "asList", ":3"
+        }, null);
+
+        MBeanAttributeInfo dump = findAttributeInfo("Dump", info);
+        Attribute dumpTo1 = new Attribute(dump.getName(), "");
+        server.setAttribute(name, dumpTo1);
+        Object after = server.getAttribute(name, dump.getName());
+        assertEquals("", after);
+
+        OptionValues empty = new OptionValues(EconomicMap.create());
+        OptionValues unsetDump = realBean.optionsFor(empty, null);
+
+        final OptionValues forMethod = realBean.optionsFor(unsetDump, new MockResolvedJavaMethod());
+        assertNotSame(unsetDump, forMethod);
+        Object nothing = unsetDump.getMap().get(GraalDebugConfig.Options.Dump);
+        assertEquals("Empty string", "", nothing);
+
+        Object specialValue = forMethod.getMap().get(GraalDebugConfig.Options.Dump);
+        assertEquals(":3", specialValue);
+
+        OptionValues normalMethod = realBean.optionsFor(unsetDump, null);
+        Object noSpecialValue = normalMethod.getMap().get(GraalDebugConfig.Options.Dump);
+        assertEquals("Empty string", "", noSpecialValue);
+    }
+
+    private static class MockResolvedJavaMethod implements HotSpotResolvedJavaMethod {
+        MockResolvedJavaMethod() {
+        }
+
+        @Override
+        public boolean isCallerSensitive() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public HotSpotResolvedObjectType getDeclaringClass() {
+            return new MockResolvedObjectType();
+        }
+
+        @Override
+        public boolean isForceInline() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean hasReservedStackAccess() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void setNotInlineable() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean ignoredBySecurityStackWalk() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType receiver) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean hasCompiledCode() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean hasCompiledCodeAtLevel(int level) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int vtableEntryOffset(ResolvedJavaType resolved) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int intrinsicId() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int allocateCompileId(int entryBCI) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean hasCodeAtLevel(int entryBCI, int level) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public byte[] getCode() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getCodeSize() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getMaxLocals() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getMaxStackSize() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isSynthetic() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isVarArgs() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isBridge() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isClassInitializer() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isConstructor() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean canBeStaticallyBound() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public ExceptionHandler[] getExceptionHandlers() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public StackTraceElement asStackTraceElement(int bci) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void reprofile() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public ConstantPool getConstantPool() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Annotation[][] getParameterAnnotations() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Type[] getGenericParameterTypes() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean canBeInlined() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean hasNeverInlineDirective() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean shouldBeInlined() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public LineNumberTable getLineNumberTable() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public LocalVariableTable getLocalVariableTable() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Constant getEncoding() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isInVirtualMethodTable(ResolvedJavaType resolved) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public SpeculationLog getSpeculationLog() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public String getName() {
+            return "asList";
+        }
+
+        @Override
+        public Signature getSignature() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public int getModifiers() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Annotation[] getAnnotations() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Annotation[] getDeclaredAnnotations() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isIntrinsicCandidate() {
+            return true;
+        }
+
+        private static class MockResolvedObjectType implements HotSpotResolvedObjectType {
+            MockResolvedObjectType() {
+            }
+
+            @Override
+            public long getFingerprint() {
+                return 0L;
+            }
+
+            @Override
+            public HotSpotResolvedObjectType getArrayClass() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaType getComponentType() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Assumptions.AssumptionResult<ResolvedJavaType> findLeafConcreteSubtype() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public HotSpotResolvedObjectType getSuperclass() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public HotSpotResolvedObjectType[] getInterfaces() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public HotSpotResolvedObjectType getSupertype() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ConstantPool getConstantPool() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int instanceSize() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int getVtableLength() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Assumptions.AssumptionResult<ResolvedJavaMethod> findUniqueConcreteMethod(ResolvedJavaMethod method) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Constant klass() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isPrimaryType() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int superCheckOffset() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public long prototypeMarkWord() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int layoutHelper() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public HotSpotResolvedObjectType getEnclosingType() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaMethod getClassInitializer() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean hasFinalizer() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Assumptions.AssumptionResult<Boolean> hasFinalizableSubclass() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isInterface() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isInstanceClass() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isInitialized() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public void initialize() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isLinked() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isAssignableFrom(ResolvedJavaType other) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isInstance(JavaConstant obj) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaType getSingleImplementor() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaField[] getStaticFields() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public String getSourceFileName() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isLocal() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isMember() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaMethod[] getDeclaredConstructors() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public ResolvedJavaMethod[] getDeclaredMethods() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public boolean isCloneableWithAllocation() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public String getName() {
+                return "Ljava/util/Arrays;";
+            }
+
+            @Override
+            public ResolvedJavaType resolve(ResolvedJavaType accessingClass) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public int getModifiers() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Annotation[] getAnnotations() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public Annotation[] getDeclaredAnnotations() {
+                throw new UnsupportedOperationException();
+            }
+        }
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/ReplaceConstantNodesPhaseTest.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,162 @@
+/*
+ * 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.hotspot.test;
+
+import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
+import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
+import org.graalvm.compiler.hotspot.nodes.aot.LoadConstantIndirectlyNode;
+import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
+import org.graalvm.compiler.hotspot.phases.LoadJavaMirrorWithKlassPhase;
+import org.graalvm.compiler.hotspot.phases.aot.EliminateRedundantInitializationPhase;
+import org.graalvm.compiler.hotspot.phases.aot.ReplaceConstantNodesPhase;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.nodes.spi.LoweringTool;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.common.CanonicalizerPhase;
+import org.graalvm.compiler.phases.common.LoweringPhase;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReplaceConstantNodesPhaseTest extends HotSpotGraalCompilerTest {
+    private final GraalHotSpotVMConfig config = runtime().getVMConfig();
+
+    @Override
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        Plugins plugins = super.getDefaultGraphBuilderPlugins();
+        plugins.setClassInitializationPlugin(new HotSpotClassInitializationPlugin());
+        return plugins;
+    }
+
+    public static class X {
+        public static int x;
+        public static int y;
+        public static int z;
+        public static Object o;
+    }
+
+    public static class Y extends X {
+        public static int a;
+        public static int b;
+    }
+
+    public static int a;
+
+    public static void assignFields() {
+        X.x = 1;
+        X.y = 2;
+        X.z = 3;
+    }
+
+    public static void assignFieldsInBranches(boolean x) {
+        if (x) {
+            X.y = 1;
+        } else {
+            X.z = 2;
+        }
+    }
+
+    public static void assignFieldsWithDominatingInit(boolean x) {
+        X.x = 1;
+        if (x) {
+            X.y = 2;
+        } else {
+            X.z = 3;
+        }
+    }
+
+    public static void assignString() {
+        X.o = "foo";
+    }
+
+    public static void assignToParentAndChild() {
+        Y.a = 1;
+        X.x = 2;
+    }
+
+    public static void assignToThis() {
+        a = 1;
+    }
+
+    public static void assignFieldsWithDominatingInitOfParent(boolean x) {
+        Y.a = 1;
+        if (x) {
+            X.y = 2;
+        } else {
+            X.z = 3;
+        }
+        Y.b = 4;
+    }
+
+    private void test(String name, int expectedInits, int expectedResolves, int expectedLoads) {
+        StructuredGraph graph = parseEager(name, AllowAssumptions.NO, new OptionValues(getInitialOptions(), GraalOptions.GeneratePIC, true));
+        HighTierContext highTierContext = getDefaultHighTierContext();
+        CanonicalizerPhase canonicalizer = new CanonicalizerPhase();
+        new EliminateRedundantInitializationPhase().apply(graph, highTierContext);
+        new LoweringPhase(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER).apply(graph, highTierContext);
+        new LoadJavaMirrorWithKlassPhase(config).apply(graph, highTierContext);
+        new ReplaceConstantNodesPhase(false).apply(graph, highTierContext);
+        Assert.assertEquals(expectedInits, graph.getNodes().filter(InitializeKlassNode.class).count());
+        Assert.assertEquals(expectedResolves, graph.getNodes().filter(ResolveConstantNode.class).count());
+        Assert.assertEquals(expectedLoads, graph.getNodes().filter(LoadConstantIndirectlyNode.class).count());
+    }
+
+    @Test
+    public void test1() {
+        test("assignFields", 1, 0, 0);
+    }
+
+    @Test
+    public void test2() {
+        test("assignFieldsWithDominatingInit", 1, 0, 0);
+    }
+
+    @Test
+    public void test3() {
+        test("assignString", 1, 1, 0);
+    }
+
+    @Test
+    public void test4() {
+        test("assignToParentAndChild", 1, 1, 0);
+    }
+
+    @Test
+    public void test5() {
+        test("assignToThis", 0, 0, 1);
+    }
+
+    @Test
+    public void test6() {
+        test("assignFieldsWithDominatingInitOfParent", 1, 1, 0);
+    }
+
+    @Test
+    public void test7() {
+        test("assignFieldsInBranches", 2, 1, 0);
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Tue Jun 13 09:19:35 2017 -0700
@@ -295,11 +295,13 @@
         // Log a compilation event.
         EventProvider.CompilationEvent compilationEvent = eventProvider.newCompilationEvent();
 
-        // If there is already compiled code for this method on our level we simply return.
-        // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we
-        // only need to check for that value.
-        if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) {
-            return null;
+        if (installAsDefault) {
+            // If there is already compiled code for this method on our level we simply return.
+            // JVMCI compiles are always at the highest compile level, even in non-tiered mode so we
+            // only need to check for that value.
+            if (method.hasCodeAtLevel(entryBCI, config.compilationLevelFullOptimization)) {
+                return HotSpotCompilationRequestResult.failure("Already compiled", false);
+            }
         }
 
         RetryableCompilation compilation = new RetryableCompilation(compilationEvent);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCodeCacheListener.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015, 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.hotspot;
+
+import jdk.vm.ci.code.CompiledCode;
+import jdk.vm.ci.code.InstalledCode;
+import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
+
+public interface HotSpotCodeCacheListener {
+    /**
+     * Notifies this object on successful install into the CodeCache.
+     *
+     * @param codeCache the code cache into which the code was installed
+     * @param installedCode the code that was installed
+     * @param compiledCode the compiled code from which {@code installedCode} was produced
+     */
+    default void notifyInstall(HotSpotCodeCacheProvider codeCache, InstalledCode installedCode, CompiledCode compiledCode) {
+
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Tue Jun 13 09:19:35 2017 -0700
@@ -81,11 +81,10 @@
     private final CompilationCounters compilationCounters;
     private final BootstrapWatchDog bootstrapWatchDog;
 
-    HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime) {
+    HotSpotGraalCompiler(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, OptionValues options) {
         this.jvmciRuntime = jvmciRuntime;
         this.graalRuntime = graalRuntime;
         // It is sufficient to have one compilation counter object per Graal compiler object.
-        OptionValues options = graalRuntime.getOptions();
         this.compilationCounters = Options.CompilationCountLimit.getValue(options) > 0 ? new CompilationCounters(options) : null;
         this.bootstrapWatchDog = graalRuntime.isBootstrapping() && !GraalDebugConfig.Options.BootstrapInitializeOnly.getValue(options) ? BootstrapWatchDog.maybeCreate(graalRuntime) : null;
     }
@@ -96,8 +95,12 @@
     }
 
     @Override
+    public CompilationRequestResult compileMethod(CompilationRequest request) {
+        return compileMethod(request, true);
+    }
+
     @SuppressWarnings("try")
-    public CompilationRequestResult compileMethod(CompilationRequest request) {
+    CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault) {
         if (graalRuntime.isShutdown()) {
             return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
         }
@@ -124,8 +127,8 @@
             }
             // Ensure a debug configuration for this thread is initialized
             DebugEnvironment.ensureInitialized(options, graalRuntime.getHostProviders().getSnippetReflection());
-            CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, true, options);
-            CompilationRequestResult r = null;
+            CompilationTask task = new CompilationTask(jvmciRuntime, this, hsRequest, true, installAsDefault, options);
+            CompilationRequestResult r;
             try (DebugConfigScope dcs = Debug.setConfig(new TopLevelDebugConfig());
                             Debug.Scope s = Debug.methodMetricsScope("HotSpotGraalCompiler", MethodMetricsRootScopeInfo.create(method), true, method)) {
                 r = task.runCompilation();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Tue Jun 13 09:19:35 2017 -0700
@@ -128,7 +128,7 @@
         HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime;
         try (InitTimer t = timer("HotSpotGraalRuntime.<init>")) {
             HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options);
-            return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime);
+            return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions());
         }
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Tue Jun 13 09:19:35 2017 -0700
@@ -23,9 +23,13 @@
 package org.graalvm.compiler.hotspot;
 
 import java.lang.management.ManagementFactory;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import javax.management.Attribute;
 import javax.management.AttributeList;
 import javax.management.AttributeNotFoundException;
@@ -34,31 +38,51 @@
 import javax.management.MBeanAttributeInfo;
 import javax.management.MBeanException;
 import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
 import javax.management.MalformedObjectNameException;
 import javax.management.NotCompliantMBeanException;
 import javax.management.ObjectName;
 import javax.management.ReflectionException;
+import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
+import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
+import org.graalvm.compiler.debug.GraalDebugConfig;
 import org.graalvm.compiler.options.OptionDescriptor;
 import org.graalvm.compiler.options.OptionDescriptors;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.options.OptionsParser;
 import org.graalvm.util.EconomicMap;
+import org.graalvm.util.EconomicSet;
+import org.graalvm.util.Equivalence;
 import org.graalvm.util.UnmodifiableEconomicMap;
 
 public final class HotSpotGraalMBean implements DynamicMBean {
     private static Object mBeanServerField;
+    private final HotSpotGraalCompiler compiler;
     private final OptionValues options;
     private final EconomicMap<OptionKey<?>, Object> changes;
+    private final EconomicSet<Dump> methodDumps;
+    private volatile EconomicSet<Reference<ClassLoader>> loaders;
     private ObjectName registered;
     private OptionValues cachedOptions;
 
-    private HotSpotGraalMBean(OptionValues options) {
+    private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) {
+        this.compiler = compiler;
         this.options = options;
         this.changes = EconomicMap.create();
+        this.methodDumps = EconomicSet.create();
+        EconomicSet<Reference<ClassLoader>> systemLoaderSet = EconomicSet.create(RefEquivalence.INSTANCE);
+        systemLoaderSet.add(new WeakReference<>(ClassLoader.getSystemClassLoader()));
+        this.loaders = systemLoaderSet;
     }
 
     private static boolean isMXServerOn() {
@@ -82,9 +106,9 @@
         }
     }
 
-    public static HotSpotGraalMBean create() {
+    public static HotSpotGraalMBean create(HotSpotGraalCompiler compiler) {
         OptionValues options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
-        HotSpotGraalMBean mbean = new HotSpotGraalMBean(options);
+        HotSpotGraalMBean mbean = new HotSpotGraalMBean(compiler, options);
         return mbean;
     }
 
@@ -111,14 +135,25 @@
         return registered;
     }
 
-    @SuppressWarnings("unused")
     public OptionValues optionsFor(OptionValues initialValues, ResolvedJavaMethod forMethod) {
         ensureRegistered(true);
-        return currentMap(initialValues);
+        if (forMethod instanceof HotSpotResolvedJavaMethod) {
+            HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) forMethod).getDeclaringClass();
+            if (type instanceof HotSpotResolvedJavaType) {
+                Class<?> clazz = ((HotSpotResolvedJavaType) type).mirror();
+                Reference<ClassLoader> addNewRef = new WeakReference<>(clazz.getClassLoader());
+                if (!loaders.contains(addNewRef)) {
+                    EconomicSet<Reference<ClassLoader>> newLoaders = EconomicSet.create(RefEquivalence.INSTANCE, loaders);
+                    newLoaders.add(addNewRef);
+                    this.loaders = newLoaders;
+                }
+            }
+        }
+        return currentMap(initialValues, forMethod);
     }
 
-    private OptionValues currentMap(OptionValues initialValues) {
-        if (changes.isEmpty()) {
+    private OptionValues currentMap(OptionValues initialValues, ResolvedJavaMethod method) {
+        if (changes.isEmpty() && methodDumps.isEmpty()) {
             return initialValues;
         }
         OptionValues current = cachedOptions;
@@ -126,12 +161,23 @@
             current = new OptionValues(initialValues, changes);
             cachedOptions = current;
         }
+        if (method != null) {
+            for (Dump request : methodDumps) {
+                final String clazzName = method.getDeclaringClass().getName();
+                if (method.getName().equals(request.method) && clazzName.equals(request.clazz)) {
+                    current = new OptionValues(current, GraalDebugConfig.Options.Dump, request.filter,
+                                    GraalDebugConfig.Options.PrintGraphHost, request.host,
+                                    GraalDebugConfig.Options.PrintBinaryGraphPort, request.port);
+                    break;
+                }
+            }
+        }
         return current;
     }
 
     @Override
     public Object getAttribute(String attribute) {
-        UnmodifiableEconomicMap<OptionKey<?>, Object> map = currentMap(options).getMap();
+        UnmodifiableEconomicMap<OptionKey<?>, Object> map = currentMap(options, null).getMap();
         for (OptionKey<?> k : map.getKeys()) {
             if (k.getName().equals(attribute)) {
                 return map.get(k);
@@ -185,9 +231,71 @@
 
     @Override
     public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+        if ("dumpMethod".equals(actionName)) {
+            try {
+                String className = param(params, 0, "className", String.class, null);
+                String methodName = param(params, 1, "methodName", String.class, null);
+                String filter = param(params, 2, "filter", String.class, ":3");
+                String host = param(params, 3, "host", String.class, "localhost");
+                Number port = param(params, 4, "port", Number.class, 4445);
+                dumpMethod(className, methodName, filter, host, port.intValue());
+            } catch (Exception ex) {
+                throw new ReflectionException(ex);
+            }
+        }
         return null;
     }
 
+    private static <T> T param(Object[] arr, int index, String name, Class<T> type, T defaultValue) {
+        Object value = arr.length > index ? arr[index] : null;
+        if (value == null || (value instanceof String && ((String) value).isEmpty())) {
+            if (defaultValue == null) {
+                throw new IllegalArgumentException(name + " must be specified");
+            }
+            value = defaultValue;
+        }
+        if (type.isInstance(value)) {
+            return type.cast(value);
+        }
+        throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
+    }
+
+    public void dumpMethod(String className, String methodName, String filter, String host, int port) throws MBeanException {
+        String jvmName = MetaUtil.toInternalName(className);
+        methodDumps.add(new Dump(host, port, jvmName, methodName, filter));
+
+        ClassNotFoundException last = null;
+        EconomicSet<Class<?>> found = EconomicSet.create();
+        Iterator<Reference<ClassLoader>> it = loaders.iterator();
+        while (it.hasNext()) {
+            Reference<ClassLoader> ref = it.next();
+            ClassLoader loader = ref.get();
+            if (loader == null) {
+                it.remove();
+                continue;
+            }
+            try {
+                Class<?> clazz = Class.forName(className, false, loader);
+                if (found.add(clazz)) {
+                    ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz);
+                    if (compiler != null) {
+                        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+                            if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) {
+                                HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method;
+                                compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false);
+                            }
+                        }
+                    }
+                }
+            } catch (ClassNotFoundException ex) {
+                last = ex;
+            }
+        }
+        if (found.isEmpty()) {
+            throw new MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
+        }
+    }
+
     @Override
     public MBeanInfo getMBeanInfo() {
         List<MBeanAttributeInfo> attrs = new ArrayList<>();
@@ -196,11 +304,30 @@
                 attrs.add(new MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
             }
         }
+        MBeanOperationInfo[] ops = {
+                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                        }, "void", MBeanOperationInfo.ACTION),
+                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                        }, "void", MBeanOperationInfo.ACTION),
+                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                                        new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
+                                        new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
+                        }, "void", MBeanOperationInfo.ACTION)
+        };
+
         return new MBeanInfo(
                         HotSpotGraalMBean.class.getName(),
                         "Graal",
                         attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
-                        null, null, null);
+                        null, ops, null);
     }
 
     private static Iterable<OptionDescriptor> allOptionDescriptors() {
@@ -213,4 +340,41 @@
         return arr;
     }
 
+    private static final class Dump {
+        final String host;
+        final int port;
+        final String clazz;
+        final String method;
+        final String filter;
+
+        Dump(String host, int port, String clazz, String method, String filter) {
+            this.host = host;
+            this.port = port;
+            this.clazz = clazz;
+            this.method = method;
+            this.filter = filter;
+        }
+    }
+
+    private static final class RefEquivalence extends Equivalence {
+        static final Equivalence INSTANCE = new RefEquivalence();
+
+        private RefEquivalence() {
+        }
+
+        @Override
+        public boolean equals(Object a, Object b) {
+            Reference<?> refA = (Reference<?>) a;
+            Reference<?> refB = (Reference<?>) b;
+            return Objects.equals(refA.get(), refB.get());
+        }
+
+        @Override
+        public int hashCode(Object o) {
+            Reference<?> ref = (Reference<?>) o;
+            Object obj = ref.get();
+            return obj == null ? 0 : obj.hashCode();
+        }
+
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Tue Jun 13 09:19:35 2017 -0700
@@ -130,10 +130,12 @@
             options = initialOptions;
         }
 
-        this.mBean = HotSpotGraalMBean.create();
-
         snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
+
+        HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
+        this.mBean = HotSpotGraalMBean.create(compiler);
+
         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
 
         JVMCIBackend hostJvmciBackend = jvmciRuntime.getHostJVMCIBackend();
@@ -261,12 +263,12 @@
 
     @Override
     public OptionValues getOptions() {
-        return mBean == null ? options : mBean.optionsFor(options, null);
+        return mBean.optionsFor(options, null);
     }
 
     @Override
     public OptionValues getOptions(ResolvedJavaMethod forMethod) {
-        return mBean == null ? options : mBean.optionsFor(options, forMethod);
+        return mBean.optionsFor(options, forMethod);
     }
 
     @Override
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalVMEventListener.java	Tue Jun 13 09:19:35 2017 -0700
@@ -22,21 +22,29 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import org.graalvm.compiler.code.CompilationResult;
-import org.graalvm.compiler.debug.Debug;
-import org.graalvm.compiler.debug.GraalDebugConfig;
-
 import jdk.vm.ci.code.CompiledCode;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotVMEventListener;
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.debug.Debug;
+import org.graalvm.compiler.debug.GraalDebugConfig;
+import org.graalvm.compiler.serviceprovider.GraalServices;
+
+import java.util.ArrayList;
+import java.util.List;
 
 public class HotSpotGraalVMEventListener implements HotSpotVMEventListener {
 
     private final HotSpotGraalRuntime runtime;
+    private List<HotSpotCodeCacheListener> listeners;
 
     HotSpotGraalVMEventListener(HotSpotGraalRuntime runtime) {
         this.runtime = runtime;
+        listeners = new ArrayList<>();
+        for (HotSpotCodeCacheListener listener : GraalServices.load(HotSpotCodeCacheListener.class)) {
+            listeners.add(listener);
+        }
     }
 
     @Override
@@ -54,6 +62,9 @@
         if (Debug.isLogEnabled()) {
             Debug.log("%s", codeCache.disassemble(installedCode));
         }
+        for (HotSpotCodeCacheListener listener : listeners) {
+            listener.notifyInstall(codeCache, installedCode, compiledCode);
+        }
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.meta;
+
+import java.util.ListIterator;
+
+import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.common.AddressLoweringPhase;
+import org.graalvm.compiler.phases.common.ExpandLogicPhase;
+import org.graalvm.compiler.phases.common.FixReadsPhase;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.Suites;
+import org.graalvm.compiler.phases.tiers.SuitesCreator;
+
+/**
+ * Subclass to factor out management of address lowering.
+ */
+public class AddressLoweringHotSpotSuitesProvider extends HotSpotSuitesProvider {
+
+    private final AddressLoweringPhase.AddressLowering addressLowering;
+
+    public AddressLoweringHotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime,
+                    AddressLoweringPhase.AddressLowering addressLowering) {
+        super(defaultSuitesCreator, config, runtime);
+        this.addressLowering = addressLowering;
+    }
+
+    @Override
+    public Suites createSuites(OptionValues options) {
+        Suites suites = super.createSuites(options);
+
+        ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class);
+        if (findPhase == null) {
+            findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
+        }
+        findPhase.add(new AddressLoweringPhase(addressLowering));
+
+        return suites;
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Tue Jun 13 09:19:35 2017 -0700
@@ -364,11 +364,17 @@
         } else if (n instanceof IdentityHashCodeNode) {
             hashCodeSnippets.lower((IdentityHashCodeNode) n, tool);
         } else if (n instanceof ResolveConstantNode) {
-            resolveConstantSnippets.lower((ResolveConstantNode) n, tool);
+            if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
+                resolveConstantSnippets.lower((ResolveConstantNode) n, tool);
+            }
         } else if (n instanceof ResolveMethodAndLoadCountersNode) {
-            resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool);
+            if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
+                resolveConstantSnippets.lower((ResolveMethodAndLoadCountersNode) n, tool);
+            }
         } else if (n instanceof InitializeKlassNode) {
-            resolveConstantSnippets.lower((InitializeKlassNode) n, tool);
+            if (graph.getGuardsStage().areFrameStatesAtDeopts()) {
+                resolveConstantSnippets.lower((InitializeKlassNode) n, tool);
+            }
         } else if (n instanceof ProfileNode) {
             profileSnippets.lower((ProfileNode) n, tool);
         } else {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotSuitesProvider.java	Tue Jun 13 09:19:35 2017 -0700
@@ -52,16 +52,11 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.BasePhase;
 import org.graalvm.compiler.phases.PhaseSuite;
-import org.graalvm.compiler.phases.common.AddressLoweringPhase;
-import org.graalvm.compiler.phases.common.AddressLoweringPhase.AddressLowering;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
-import org.graalvm.compiler.phases.common.ExpandLogicPhase;
-import org.graalvm.compiler.phases.common.FixReadsPhase;
-import org.graalvm.compiler.phases.common.LoopSafepointInsertionPhase;
 import org.graalvm.compiler.phases.common.LoweringPhase;
 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.MidTierContext;
 import org.graalvm.compiler.phases.tiers.Suites;
 import org.graalvm.compiler.phases.tiers.SuitesCreator;
 
@@ -73,14 +68,12 @@
     protected final GraalHotSpotVMConfig config;
     protected final HotSpotGraalRuntimeProvider runtime;
 
-    private final AddressLowering addressLowering;
     private final SuitesCreator defaultSuitesCreator;
 
-    public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, AddressLowering addressLowering) {
+    public HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime) {
         this.defaultSuitesCreator = defaultSuitesCreator;
         this.config = config;
         this.runtime = runtime;
-        this.addressLowering = addressLowering;
         this.defaultGraphBuilderSuite = createGraphBuilderSuite();
     }
 
@@ -95,14 +88,14 @@
                 ret.getHighTier().appendPhase(new AheadOfTimeVerificationPhase());
             }
             if (GeneratePIC.getValue(options)) {
-                // EliminateRedundantInitializationPhase must happen before the first lowering.
                 ListIterator<BasePhase<? super HighTierContext>> highTierLowering = ret.getHighTier().findPhase(LoweringPhase.class);
                 highTierLowering.previous();
                 highTierLowering.add(new EliminateRedundantInitializationPhase());
                 if (HotSpotAOTProfilingPlugin.Options.TieredAOT.getValue(options)) {
                     highTierLowering.add(new FinalizeProfileNodesPhase(HotSpotAOTProfilingPlugin.Options.TierAInvokeInlineeNotifyFreqLog.getValue(options)));
                 }
-                ret.getMidTier().findPhase(LoopSafepointInsertionPhase.class).add(new ReplaceConstantNodesPhase());
+                ListIterator<BasePhase<? super MidTierContext>> midTierLowering = ret.getMidTier().findPhase(LoweringPhase.class);
+                midTierLowering.add(new ReplaceConstantNodesPhase());
 
                 // Replace inlining policy
                 ListIterator<BasePhase<? super HighTierContext>> iter = ret.getHighTier().findPhase(InliningPhase.class);
@@ -117,12 +110,6 @@
             ret.getMidTier().appendPhase(new WriteBarrierVerificationPhase(config));
         }
 
-        ListIterator<BasePhase<? super LowTierContext>> findPhase = ret.getLowTier().findPhase(FixReadsPhase.class);
-        if (findPhase == null) {
-            findPhase = ret.getLowTier().findPhase(ExpandLogicPhase.class);
-        }
-        findPhase.add(new AddressLoweringPhase(addressLowering));
-
         return ret;
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java	Tue Jun 13 09:19:35 2017 -0700
@@ -22,18 +22,21 @@
  */
 package org.graalvm.compiler.hotspot.nodes.aot;
 
+import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16;
 
+import org.graalvm.api.word.LocationIdentity;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
 import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 
-@NodeInfo(cycles = CYCLES_4, size = SIZE_16)
-public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable {
+@NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {Memory})
+public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable, MemoryCheckpoint.Single {
     public static final NodeClass<InitializeKlassNode> TYPE = NodeClass.create(InitializeKlassNode.class);
 
     @Input ValueNode value;
@@ -56,4 +59,9 @@
     public boolean canDeoptimize() {
         return true;
     }
+
+    @Override
+    public LocationIdentity getLocationIdentity() {
+        return LocationIdentity.any();
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantNode.java	Tue Jun 13 09:19:35 2017 -0700
@@ -28,13 +28,13 @@
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.calc.FloatingNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 
 @NodeInfo(cycles = CYCLES_4, size = SIZE_16)
-public class ResolveConstantNode extends FloatingNode implements Lowerable {
+public class ResolveConstantNode extends DeoptimizingFixedWithNextNode implements Lowerable {
     public static final NodeClass<ResolveConstantNode> TYPE = NodeClass.create(ResolveConstantNode.class);
 
     @Input ValueNode value;
@@ -64,4 +64,9 @@
     public HotSpotConstantLoadAction action() {
         return action;
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveConstantStubCall.java	Tue Jun 13 09:19:35 2017 -0700
@@ -110,5 +110,4 @@
         }
         gen.setResult(this, result);
     }
-
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveMethodAndLoadCountersNode.java	Tue Jun 13 09:19:35 2017 -0700
@@ -28,15 +28,15 @@
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.hotspot.nodes.type.MethodCountersPointerStamp;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.DeoptimizingFixedWithNextNode;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.calc.FloatingNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 @NodeInfo(cycles = CYCLES_4, size = SIZE_16)
-public class ResolveMethodAndLoadCountersNode extends FloatingNode implements Lowerable {
+public class ResolveMethodAndLoadCountersNode extends DeoptimizingFixedWithNextNode implements Lowerable {
     public static final NodeClass<ResolveMethodAndLoadCountersNode> TYPE = NodeClass.create(ResolveMethodAndLoadCountersNode.class);
 
     ResolvedJavaMethod method;
@@ -60,4 +60,9 @@
     public ValueNode getHub() {
         return hub;
     }
+
+    @Override
+    public boolean canDeoptimize() {
+        return true;
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -22,10 +22,12 @@
  */
 package org.graalvm.compiler.hotspot.phases.aot;
 
+import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates;
 import static org.graalvm.compiler.hotspot.nodes.aot.LoadMethodCountersNode.getLoadMethodCountersNodes;
 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
 
 import java.util.HashSet;
+import java.util.List;
 
 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
@@ -35,11 +37,13 @@
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
+import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.graph.NodeMap;
 import org.graalvm.compiler.hotspot.FingerprintUtil;
 import org.graalvm.compiler.hotspot.meta.HotSpotConstantLoadAction;
 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
@@ -49,14 +53,21 @@
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveMethodAndLoadCountersNode;
 import org.graalvm.compiler.nodes.ConstantNode;
+import org.graalvm.compiler.nodes.FixedWithNextNode;
 import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
 import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.cfg.Block;
 import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
+import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
+import org.graalvm.util.EconomicMap;
 
 public class ReplaceConstantNodesPhase extends BasePhase<PhaseContext> {
 
     private static final HashSet<Class<?>> builtIns = new HashSet<>();
+    private final boolean verifyFingerprints;
 
     static {
         builtIns.add(Boolean.class);
@@ -91,6 +102,14 @@
         // @formatter:on
     }
 
+    private static boolean anyUsagesNeedReplacement(ConstantNode node) {
+        return node.usages().filter(n -> !isReplacementNode(n)).isNotEmpty();
+    }
+
+    private static boolean anyUsagesNeedReplacement(LoadMethodCountersNode node) {
+        return node.usages().filter(n -> !(n instanceof ResolveMethodAndLoadCountersNode)).isNotEmpty();
+    }
+
     private static boolean checkForBadFingerprint(HotSpotResolvedJavaType type) {
         if (type.isArray()) {
             if (type.getElementalType().isPrimitive()) {
@@ -101,80 +120,223 @@
         return FingerprintUtil.getFingerprint((HotSpotResolvedObjectType) type) == 0;
     }
 
-    private static void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) {
+    /**
+     * Replace {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} with indirection.
+     *
+     * @param graph
+     * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
+     *            resolution.
+     */
+    private void handleHotSpotMetaspaceConstant(StructuredGraph graph, ConstantNode node) {
         HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
 
         if (type != null) {
-            if (checkForBadFingerprint(type)) {
+            if (verifyFingerprints && checkForBadFingerprint(type)) {
                 throw new GraalError("Type with bad fingerprint: " + type);
             }
-
             assert !metaspaceConstant.isCompressed() : "No support for replacing compressed metaspace constants";
-            ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass();
-            ValueNode replacement;
-
-            if (type.isArray() && type.getComponentType().isPrimitive()) {
-                // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may
-                // omit the resolution call.
-                replacement = new LoadConstantIndirectlyNode(node);
-            } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) {
-                // If it's a supertype of or the same class that declares the top method, we are
-                // guaranteed to have it resolved already. If it's an interface, we just test for
-                // equality.
-                replacement = new LoadConstantIndirectlyNode(node);
-            } else if (builtIns.contains(type.mirror())) {
-                // Special case of klass constants that come from {@link BoxingSnippets}.
-                replacement = new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE);
-            } else {
-                replacement = new ResolveConstantNode(node);
+            replaceWithInitialization(graph, node);
+            if (anyUsagesNeedReplacement(node)) {
+                replaceWithResolution(graph, node);
             }
-
-            node.replaceAtUsages(graph.addOrUnique(replacement), n -> !isReplacementNode(n));
         } else {
             throw new GraalError("Unsupported metaspace constant type: " + type);
         }
     }
 
+    /**
+     * Find the lowest dominating {@link FixedWithNextNode} before given node.
+     *
+     * @param graph
+     * @param node
+     * @return the last {@link FixedWithNextNode} that is scheduled before node.
+     */
+    private static FixedWithNextNode findFixedWithNextBefore(StructuredGraph graph, Node node) {
+        ScheduleResult schedule = graph.getLastSchedule();
+        NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
+        BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
+
+        Block block = nodeToBlock.get(node);
+        FixedWithNextNode result = null;
+        for (Node n : blockToNodes.get(block)) {
+            if (n instanceof FixedWithNextNode) {
+                result = (FixedWithNextNode) n;
+            }
+            if (n.equals(node)) {
+                break;
+            }
+        }
+        assert result != null;
+        return result;
+    }
+
+    /**
+     * Try to find dominating {@link InitializeKlassNode} that can be reused.
+     *
+     * @param graph
+     * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
+     *            resolution.
+     */
+    private static void replaceWithInitialization(StructuredGraph graph, ConstantNode node) {
+        ScheduleResult schedule = graph.getLastSchedule();
+        NodeMap<Block> nodeToBlock = schedule.getNodeToBlockMap();
+        BlockMap<List<Node>> blockToNodes = schedule.getBlockToNodesMap();
+
+        EconomicMap<Block, Node> blockToInit = EconomicMap.create();
+        for (Node n : node.usages().filter(InitializeKlassNode.class)) {
+            blockToInit.put(nodeToBlock.get(n), n);
+        }
+        for (Node use : node.usages().filter(n -> !isReplacementNode(n)).snapshot()) {
+            boolean replaced = false;
+            Block b = nodeToBlock.get(use);
+            InitializeKlassNode i = (InitializeKlassNode) blockToInit.get(b);
+            if (i != null) {
+                // There is an initialization in the same block as the use, look if the use is
+                // scheduled after it.
+                for (Node n : blockToNodes.get(b)) {
+                    if (n.equals(use)) {
+                        // Usage is before initialization, can't use it
+                        break;
+                    }
+                    if (n.equals(i)) {
+                        use.replaceFirstInput(node, i);
+                        replaced = true;
+                        break;
+                    }
+                }
+            }
+            if (!replaced) {
+                // Look for dominating blocks that have initializations
+                for (Block d : blockToInit.getKeys()) {
+                    if (strictlyDominates(d, b)) {
+                        use.replaceFirstInput(node, blockToInit.get(d));
+                        break;
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Replace the uses of a constant with either {@link LoadConstantIndirectlyNode} or
+     * {@link ResolveConstantNode}.
+     *
+     * @param graph
+     * @param node {@link ConstantNode} containing a {@link HotSpotResolvedJavaType} that needs
+     *            resolution.
+     */
+    private static void replaceWithResolution(StructuredGraph graph, ConstantNode node) {
+        HotSpotMetaspaceConstant metaspaceConstant = (HotSpotMetaspaceConstant) node.asConstant();
+        HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) metaspaceConstant.asResolvedJavaType();
+        ResolvedJavaType topMethodHolder = graph.method().getDeclaringClass();
+        ValueNode replacement;
+
+        if (type.isArray() && type.getComponentType().isPrimitive()) {
+            // Special case for primitive arrays. The AOT runtime pre-resolves them, so we may
+            // omit the resolution call.
+            replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
+        } else if (type.equals(topMethodHolder) || (type.isAssignableFrom(topMethodHolder) && !type.isInterface())) {
+            // If it's a supertype of or the same class that declares the top method, we are
+            // guaranteed to have it resolved already. If it's an interface, we just test for
+            // equality.
+            replacement = graph.addOrUnique(new LoadConstantIndirectlyNode(node));
+        } else {
+            FixedWithNextNode fixedReplacement;
+            if (builtIns.contains(type.mirror())) {
+                // Special case of klass constants that come from {@link BoxingSnippets}.
+                fixedReplacement = graph.add(new ResolveConstantNode(node, HotSpotConstantLoadAction.INITIALIZE));
+            } else {
+                fixedReplacement = graph.add(new ResolveConstantNode(node));
+            }
+            graph.addAfterFixed(findFixedWithNextBefore(graph, node), fixedReplacement);
+            replacement = fixedReplacement;
+        }
+        node.replaceAtUsages(replacement, n -> !isReplacementNode(n));
+    }
+
+    /**
+     * Replace an object constant with an indirect load {@link ResolveConstantNode}. Currently we
+     * support only strings.
+     *
+     * @param graph
+     * @param node {@link ConstantNode} containing a {@link HotSpotObjectConstant} that needs
+     *            resolution.
+     */
     private static void handleHotSpotObjectConstant(StructuredGraph graph, ConstantNode node) {
         HotSpotObjectConstant constant = (HotSpotObjectConstant) node.asJavaConstant();
         HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) constant.getType();
         if (type.mirror().equals(String.class)) {
             assert !constant.isCompressed() : "No support for replacing compressed oop constants";
-            ValueNode replacement = graph.unique(new ResolveConstantNode(node));
+            FixedWithNextNode replacement = graph.add(new ResolveConstantNode(node));
+            graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement);
             node.replaceAtUsages(replacement, n -> !(n instanceof ResolveConstantNode));
         } else {
             throw new GraalError("Unsupported object constant type: " + type);
         }
     }
 
+    /**
+     * Replace {@link LoadMethodCountersNode} with indirect load
+     * {@link ResolveMethodAndLoadCountersNode}, expose a klass constant of the holder.
+     *
+     * @param graph
+     * @param node
+     * @param context
+     */
     private static void handleLoadMethodCounters(StructuredGraph graph, LoadMethodCountersNode node, PhaseContext context) {
         ResolvedJavaType type = node.getMethod().getDeclaringClass();
         Stamp hubStamp = context.getStampProvider().createHubStamp((ObjectStamp) StampFactory.objectNonNull());
         ConstantReflectionProvider constantReflection = context.getConstantReflection();
         ConstantNode klassHint = ConstantNode.forConstant(hubStamp, constantReflection.asObjectHub(type), context.getMetaAccess(), graph);
-        ValueNode replacement = graph.unique(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint));
+        FixedWithNextNode replacement = graph.add(new ResolveMethodAndLoadCountersNode(node.getMethod(), klassHint));
+        graph.addAfterFixed(findFixedWithNextBefore(graph, node), replacement);
         node.replaceAtUsages(replacement, n -> !(n instanceof ResolveMethodAndLoadCountersNode));
     }
 
+    /**
+     * Replace {@link LoadMethodCountersNode} with {@link ResolveMethodAndLoadCountersNode}, expose
+     * klass constants.
+     *
+     * @param graph
+     * @param context
+     */
+    private static void replaceLoadMethodCounters(StructuredGraph graph, PhaseContext context) {
+        new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
+        for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) {
+            if (anyUsagesNeedReplacement(node)) {
+                handleLoadMethodCounters(graph, node, context);
+            }
+        }
+    }
+
+    /**
+     * Replace object and klass constants with resolution nodes or reuse preceding initializations.
+     *
+     * @param graph
+     */
+    private void replaceKlassesAndObjects(StructuredGraph graph) {
+        new SchedulePhase(SchedulingStrategy.LATEST_OUT_OF_LOOPS, true).apply(graph, false);
+
+        for (ConstantNode node : getConstantNodes(graph)) {
+            Constant constant = node.asConstant();
+            if (constant instanceof HotSpotMetaspaceConstant && anyUsagesNeedReplacement(node)) {
+                handleHotSpotMetaspaceConstant(graph, node);
+            } else if (constant instanceof HotSpotObjectConstant && anyUsagesNeedReplacement(node)) {
+                handleHotSpotObjectConstant(graph, node);
+            }
+        }
+    }
+
     @Override
     protected void run(StructuredGraph graph, PhaseContext context) {
         // Replace LoadMethodCountersNode with ResolveMethodAndLoadCountersNode, expose klass
         // constants.
-        for (LoadMethodCountersNode node : getLoadMethodCountersNodes(graph)) {
-            handleLoadMethodCounters(graph, node, context);
-        }
+        replaceLoadMethodCounters(graph, context);
 
         // Replace object and klass constants (including the ones added in the previous pass) with
         // resolution nodes.
-        for (ConstantNode node : getConstantNodes(graph)) {
-            Constant constant = node.asConstant();
-            if (constant instanceof HotSpotMetaspaceConstant) {
-                handleHotSpotMetaspaceConstant(graph, node);
-            } else if (constant instanceof HotSpotObjectConstant) {
-                handleHotSpotObjectConstant(graph, node);
-            }
-        }
+        replaceKlassesAndObjects(graph);
     }
 
     @Override
@@ -182,4 +344,11 @@
         return false;
     }
 
+    public ReplaceConstantNodesPhase() {
+        this(true);
+    }
+
+    public ReplaceConstantNodesPhase(boolean verifyFingerprints) {
+        this.verifyFingerprints = verifyFingerprints;
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/InstanceOfSnippets.java	Tue Jun 13 09:19:35 2017 -0700
@@ -49,7 +49,6 @@
 import org.graalvm.compiler.hotspot.nodes.type.KlassPointerStamp;
 import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Counters;
 import org.graalvm.compiler.hotspot.replacements.TypeCheckSnippetUtils.Hints;
-import org.graalvm.compiler.hotspot.replacements.aot.ResolveConstantSnippets;
 import org.graalvm.compiler.hotspot.word.KlassPointer;
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.nodes.DeoptimizeNode;
@@ -147,12 +146,6 @@
         return trueValue;
     }
 
-    @Snippet
-    public static Object instanceofExactPIC(Object object, KlassPointer exactHub, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
-        KlassPointer exactHubPIC = ResolveConstantSnippets.resolveKlassConstant(exactHub);
-        return instanceofExact(object, exactHubPIC, trueValue, falseValue, counters);
-    }
-
     /**
      * A test against a primary type.
      */
@@ -172,12 +165,6 @@
         return trueValue;
     }
 
-    @Snippet
-    public static Object instanceofPrimaryPIC(KlassPointer hub, Object object, @ConstantParameter int superCheckOffset, Object trueValue, Object falseValue, @ConstantParameter Counters counters) {
-        KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub);
-        return instanceofPrimary(resolvedHub, object, superCheckOffset, trueValue, falseValue, counters);
-    }
-
     /**
      * A test against a restricted secondary type type.
      */
@@ -207,13 +194,6 @@
         return trueValue;
     }
 
-    @Snippet
-    public static Object instanceofSecondaryPIC(KlassPointer hub, Object object, @VarargsParameter KlassPointer[] hints, @VarargsParameter boolean[] hintIsPositive, Object trueValue,
-                    Object falseValue, @ConstantParameter Counters counters) {
-        KlassPointer resolvedHub = ResolveConstantSnippets.resolveKlassConstant(hub);
-        return instanceofSecondary(resolvedHub, object, hints, hintIsPositive, trueValue, falseValue, counters);
-    }
-
     /**
      * Type test used when the type being tested against is not known at compile time.
      */
@@ -272,11 +252,8 @@
 
         private final SnippetInfo instanceofWithProfile = snippet(InstanceOfSnippets.class, "instanceofWithProfile");
         private final SnippetInfo instanceofExact = snippet(InstanceOfSnippets.class, "instanceofExact");
-        private final SnippetInfo instanceofExactPIC = snippet(InstanceOfSnippets.class, "instanceofExactPIC");
         private final SnippetInfo instanceofPrimary = snippet(InstanceOfSnippets.class, "instanceofPrimary");
-        private final SnippetInfo instanceofPrimaryPIC = snippet(InstanceOfSnippets.class, "instanceofPrimaryPIC");
         private final SnippetInfo instanceofSecondary = snippet(InstanceOfSnippets.class, "instanceofSecondary", SECONDARY_SUPER_CACHE_LOCATION);
-        private final SnippetInfo instanceofSecondaryPIC = snippet(InstanceOfSnippets.class, "instanceofSecondaryPIC", SECONDARY_SUPER_CACHE_LOCATION);
         private final SnippetInfo instanceofDynamic = snippet(InstanceOfSnippets.class, "instanceofDynamic", SECONDARY_SUPER_CACHE_LOCATION);
         private final SnippetInfo isAssignableFrom = snippet(InstanceOfSnippets.class, "isAssignableFrom", SECONDARY_SUPER_CACHE_LOCATION);
 
@@ -316,20 +293,17 @@
                     args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs);
                     args.addVarargs("hintIsPositive", boolean.class, StampFactory.forKind(JavaKind.Boolean), hints.isPositive);
                 } else if (hintInfo.exact != null) {
-                    SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? instanceofExactPIC : instanceofExact;
-                    args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
+                    args = new Arguments(instanceofExact, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("object", object);
                     args.add("exactHub", ConstantNode.forConstant(KlassPointerStamp.klassNonNull(), ((HotSpotResolvedObjectType) hintInfo.exact).klass(), providers.getMetaAccess(), graph));
                 } else if (type.isPrimaryType()) {
-                    SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? instanceofPrimaryPIC : instanceofPrimary;
-                    args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
+                    args = new Arguments(instanceofPrimary, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("hub", hub);
                     args.add("object", object);
                     args.addConst("superCheckOffset", type.superCheckOffset());
                 } else {
                     Hints hints = createHints(hintInfo, providers.getMetaAccess(), false, graph);
-                    SnippetInfo snippet = GeneratePIC.getValue(localOptions) ? instanceofSecondaryPIC : instanceofSecondary;
-                    args = new Arguments(snippet, graph.getGuardsStage(), tool.getLoweringStage());
+                    args = new Arguments(instanceofSecondary, graph.getGuardsStage(), tool.getLoweringStage());
                     args.add("hub", hub);
                     args.add("object", object);
                     args.addVarargs("hints", KlassPointer.class, KlassPointerStamp.klassNonNull(), hints.hubs);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/aot/ResolveConstantSnippets.java	Tue Jun 13 09:19:35 2017 -0700
@@ -149,7 +149,7 @@
             args.add("constant", value);
 
             SnippetTemplate template = template(args);
-            template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, tool, args);
+            template.instantiate(providers.getMetaAccess(), resolveConstantNode, DEFAULT_REPLACER, args);
 
             assert resolveConstantNode.hasNoUsages();
             if (!resolveConstantNode.isDeleted()) {
@@ -187,7 +187,7 @@
             args.add("method", method);
             args.add("klassHint", resolveMethodAndLoadCountersNode.getHub());
             SnippetTemplate template = template(args);
-            template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, tool, args);
+            template.instantiate(providers.getMetaAccess(), resolveMethodAndLoadCountersNode, DEFAULT_REPLACER, args);
 
             assert resolveMethodAndLoadCountersNode.hasNoUsages();
             if (!resolveMethodAndLoadCountersNode.isDeleted()) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Tue Jun 13 09:19:35 2017 -0700
@@ -1422,7 +1422,7 @@
     @Override
     public void handleReplacedInvoke(CallTargetNode callTarget, JavaKind resultType) {
         BytecodeParser intrinsicCallSiteParser = getNonIntrinsicAncestor();
-        boolean withExceptionEdge = intrinsicCallSiteParser == null ? false : intrinsicCallSiteParser.omitInvokeExceptionEdge(null);
+        boolean withExceptionEdge = intrinsicCallSiteParser == null ? !omitInvokeExceptionEdge(null) : !intrinsicCallSiteParser.omitInvokeExceptionEdge(null);
         createNonInlinedInvoke(withExceptionEdge, bci(), callTarget, resultType);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesCreator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.java;
+
+import org.graalvm.compiler.lir.phases.LIRSuites;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.graalvm.compiler.phases.tiers.Suites;
+
+public class DefaultSuitesCreator extends SuitesProviderBase {
+
+    private final CompilerConfiguration compilerConfiguration;
+
+    public DefaultSuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+        super();
+        this.defaultGraphBuilderSuite = createGraphBuilderSuite(plugins);
+        this.compilerConfiguration = compilerConfiguration;
+    }
+
+    @Override
+    public Suites createSuites(OptionValues options) {
+        return Suites.createSuites(compilerConfiguration, options);
+    }
+
+    protected PhaseSuite<HighTierContext> createGraphBuilderSuite(Plugins plugins) {
+        PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
+        suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault(plugins)));
+        return suite;
+    }
+
+    @Override
+    public LIRSuites createLIRSuites(OptionValues options) {
+        return Suites.createLIRSuites(compilerConfiguration, options);
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/DefaultSuitesProvider.java	Tue Jun 13 07:30:11 2017 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.java;
-
-import org.graalvm.compiler.lir.phases.LIRSuites;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
-import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.PhaseSuite;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.Suites;
-
-public class DefaultSuitesProvider extends SuitesProviderBase {
-
-    private final CompilerConfiguration compilerConfiguration;
-
-    public DefaultSuitesProvider(CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        super();
-        this.defaultGraphBuilderSuite = createGraphBuilderSuite(plugins);
-        this.compilerConfiguration = compilerConfiguration;
-    }
-
-    @Override
-    public Suites createSuites(OptionValues options) {
-        return Suites.createSuites(compilerConfiguration, options);
-    }
-
-    protected PhaseSuite<HighTierContext> createGraphBuilderSuite(Plugins plugins) {
-        PhaseSuite<HighTierContext> suite = new PhaseSuite<>();
-        suite.appendPhase(new GraphBuilderPhase(GraphBuilderConfiguration.getDefault(plugins)));
-        return suite;
-    }
-
-    @Override
-    public LIRSuites createLIRSuites(OptionValues options) {
-        return Suites.createLIRSuites(compilerConfiguration, options);
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AddressValue.java	Tue Jun 13 09:19:35 2017 -0700
@@ -46,20 +46,20 @@
 
     @Component({OperandFlag.REG, OperandFlag.ILLEGAL}) protected AllocatableValue base;
     @Component({OperandFlag.REG, OperandFlag.ILLEGAL}) protected AllocatableValue offset;
-    private final int immediate;
+    private final int displacement;
 
     /**
      * Whether register offset should be scaled or not.
      */
-    private final boolean scaled;
+    private final int scaleFactor;
     private final AddressingMode addressingMode;
 
-    public AArch64AddressValue(ValueKind<?> kind, AllocatableValue base, AllocatableValue offset, int immediate, boolean scaled, AddressingMode addressingMode) {
+    public AArch64AddressValue(ValueKind<?> kind, AllocatableValue base, AllocatableValue offset, int displacement, int scaleFactor, AddressingMode addressingMode) {
         super(kind);
         this.base = base;
         this.offset = offset;
-        this.immediate = immediate;
-        this.scaled = scaled;
+        this.displacement = displacement;
+        this.scaleFactor = scaleFactor;
         this.addressingMode = addressingMode;
     }
 
@@ -79,12 +79,16 @@
         return offset;
     }
 
-    public int getImmediate() {
-        return immediate;
+    public int getDisplacement() {
+        return displacement;
     }
 
     public boolean isScaled() {
-        return scaled;
+        return scaleFactor != 1;
+    }
+
+    public int getScaleFactor() {
+        return scaleFactor;
     }
 
     public AddressingMode getAddressingMode() {
@@ -95,7 +99,7 @@
         Register baseReg = toRegister(base);
         Register offsetReg = toRegister(offset);
         AArch64Assembler.ExtendType extendType = addressingMode == AddressingMode.EXTENDED_REGISTER_OFFSET ? ExtendType.SXTW : null;
-        return AArch64Address.createAddress(addressingMode, baseReg, offsetReg, immediate, scaled, extendType);
+        return AArch64Address.createAddress(addressingMode, baseReg, offsetReg, displacement / scaleFactor, isScaled(), extendType);
     }
 
     @Override
@@ -103,7 +107,7 @@
         AllocatableValue newBase = (AllocatableValue) proc.doValue(inst, base, mode, flags);
         AllocatableValue newOffset = (AllocatableValue) proc.doValue(inst, offset, mode, flags);
         if (!base.identityEquals(newBase) || !offset.identityEquals(newOffset)) {
-            return new AArch64AddressValue(getValueKind(), newBase, newOffset, immediate, scaled, addressingMode);
+            return new AArch64AddressValue(getValueKind(), newBase, newOffset, displacement, scaleFactor, addressingMode);
         }
         return this;
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Tue Jun 13 09:19:35 2017 -0700
@@ -145,7 +145,7 @@
         public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
             Register dst = asRegister(result);
             AArch64Address adr = address.toAddress();
-            masm.loadAddress(dst, adr, address.getPlatformKind().getSizeInBytes());
+            masm.loadAddress(dst, adr, address.getScaleFactor());
         }
     }
 
@@ -241,8 +241,8 @@
 
         @Override
         public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) {
-            int immediate = addressValue.getImmediate();
-            if (state == null && value.equals(addressValue.getBase()) && addressValue.getOffset().equals(Value.ILLEGAL) && immediate >= 0 && immediate < implicitNullCheckLimit) {
+            int displacement = addressValue.getDisplacement();
+            if (state == null && value.equals(addressValue.getBase()) && addressValue.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) {
                 state = nullCheckState;
                 return true;
             }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Unary.java	Tue Jun 13 09:19:35 2017 -0700
@@ -84,8 +84,8 @@
 
         @Override
         public boolean makeNullCheckFor(Value value, LIRFrameState nullCheckState, int implicitNullCheckLimit) {
-            int immediate = input.getImmediate();
-            if (state == null && value.equals(input.getBase()) && input.getOffset().equals(Value.ILLEGAL) && immediate >= 0 && immediate < implicitNullCheckLimit) {
+            int displacement = input.getDisplacement();
+            if (state == null && value.equals(input.getBase()) && input.getOffset().equals(Value.ILLEGAL) && displacement >= 0 && displacement < implicitNullCheckLimit) {
                 state = nullCheckState;
                 return true;
             }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRInstruction.java	Tue Jun 13 09:19:35 2017 -0700
@@ -51,6 +51,7 @@
 import org.graalvm.compiler.lir.StandardOp.MoveOp;
 import org.graalvm.compiler.lir.StandardOp.ValueMoveOp;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 
 import jdk.vm.ci.code.RegisterValue;
 import jdk.vm.ci.code.StackSlot;
@@ -414,6 +415,20 @@
     public void verify() {
     }
 
+    /**
+     * Adds a comment to this instruction.
+     */
+    public final void setComment(LIRGenerationResult res, String comment) {
+        res.setComment(this, comment);
+    }
+
+    /**
+     * Gets the comment attached to this instruction.
+     */
+    public final String getComment(LIRGenerationResult res) {
+        return res.getComment(this);
+    }
+
     public final String toStringWithIdPrefix() {
         if (id != -1) {
             return String.format("%4d %s", id, toString());
@@ -426,6 +441,18 @@
         return instructionClass.toString(this);
     }
 
+    public String toString(LIRGenerationResult res) {
+        String toString = toString();
+        if (res == null) {
+            return toString;
+        }
+        String comment = getComment(res);
+        if (comment == null) {
+            return toString;
+        }
+        return String.format("%s // %s", toString, comment);
+    }
+
     public LIRInstructionClass<?> getLIRInstructionClass() {
         return instructionClass;
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/SaveCalleeSaveRegisters.java	Tue Jun 13 09:19:35 2017 -0700
@@ -54,19 +54,19 @@
             return;
         }
         LIR lir = lirGenRes.getLIR();
-        RegisterMap<Variable> savedRegisters = saveAtEntry(lir, context.lirGen, calleeSaveRegisters, target.arch);
+        RegisterMap<Variable> savedRegisters = saveAtEntry(lir, context.lirGen, lirGenRes, calleeSaveRegisters, target.arch);
 
         for (AbstractBlockBase<?> block : lir.codeEmittingOrder()) {
             if (block == null) {
                 continue;
             }
             if (block.getSuccessorCount() == 0) {
-                restoreAtExit(lir, context.lirGen.getSpillMoveFactory(), savedRegisters, block);
+                restoreAtExit(lir, context.lirGen.getSpillMoveFactory(), lirGenRes, savedRegisters, block);
             }
         }
     }
 
-    private static RegisterMap<Variable> saveAtEntry(LIR lir, LIRGeneratorTool lirGen, RegisterArray calleeSaveRegisters, Architecture arch) {
+    private static RegisterMap<Variable> saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, RegisterArray calleeSaveRegisters, Architecture arch) {
         AbstractBlockBase<?> startBlock = lir.getControlFlowGraph().getStartBlock();
         ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(startBlock);
         int insertionIndex = 1;
@@ -83,6 +83,7 @@
             Variable saveVariable = lirGen.newVariable(lirKind);
             LIRInstruction save = lirGen.getSpillMoveFactory().createMove(saveVariable, registerValue);
             buffer.append(insertionIndex, save);
+            save.setComment(lirGenRes, "SaveCalleeSavedRegisters: saveAtEntry");
             saveMap.put(register, saveVariable);
             savedRegisterValues[savedRegisterValueIndex++] = registerValue;
         }
@@ -91,7 +92,7 @@
         return saveMap;
     }
 
-    private static void restoreAtExit(LIR lir, LIRGeneratorTool.MoveFactory moveFactory, RegisterMap<Variable> calleeSaveRegisters, AbstractBlockBase<?> block) {
+    private static void restoreAtExit(LIR lir, LIRGeneratorTool.MoveFactory moveFactory, LIRGenerationResult lirGenRes, RegisterMap<Variable> calleeSaveRegisters, AbstractBlockBase<?> block) {
         ArrayList<LIRInstruction> instructions = lir.getLIRforBlock(block);
         int insertionIndex = instructions.size() - 1;
         LIRInsertionBuffer buffer = new LIRInsertionBuffer();
@@ -100,6 +101,7 @@
         calleeSaveRegisters.forEach((Register register, Variable saved) -> {
             LIRInstruction restore = moveFactory.createMove(register.asValue(saved.getValueKind()), saved);
             buffer.append(insertionIndex, restore);
+            restore.setComment(lirGenRes, "SaveCalleeSavedRegisters: restoreAtExit");
         });
         buffer.finish();
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java	Tue Jun 13 09:19:35 2017 -0700
@@ -185,10 +185,12 @@
     protected final Interval intervalEndMarker;
     public final Range rangeEndMarker;
     public final boolean detailedAsserts;
+    private final LIRGenerationResult res;
 
     protected LinearScan(TargetDescription target, LIRGenerationResult res, MoveFactory spillMoveFactory, RegisterAllocationConfig regAllocConfig, AbstractBlockBase<?>[] sortedBlocks,
                     boolean neverSpillConstants) {
         this.ir = res.getLIR();
+        this.res = res;
         this.moveFactory = spillMoveFactory;
         this.frameMapBuilder = res.getFrameMapBuilder();
         this.sortedBlocks = sortedBlocks;
@@ -206,6 +208,10 @@
         this.detailedAsserts = DetailedAsserts.getValue(ir.getOptions());
     }
 
+    public LIRGenerationResult getLIRGenerationResult() {
+        return res;
+    }
+
     public Interval intervalEndMarker() {
         return intervalEndMarker;
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanEliminateSpillMovePhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -75,12 +75,12 @@
 
     @Override
     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
-        eliminateSpillMoves();
+        eliminateSpillMoves(lirGenRes);
     }
 
     /**
      * @return the index of the first instruction that is of interest for
-     *         {@link #eliminateSpillMoves()}
+     *         {@link #eliminateSpillMoves}
      */
     protected int firstInstructionOfInterest() {
         // skip the first because it is always a label
@@ -89,7 +89,7 @@
 
     // called once before assignment of register numbers
     @SuppressWarnings("try")
-    void eliminateSpillMoves() {
+    void eliminateSpillMoves(LIRGenerationResult res) {
         try (Indent indent = Debug.logAndIndent("Eliminating unnecessary spill moves")) {
 
             /*
@@ -168,6 +168,7 @@
 
                                         LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
                                         insertionBuffer.append(j + 1, move);
+                                        move.setComment(res, "LSRAEliminateSpillMove: store at definition");
 
                                         if (Debug.isLogEnabled()) {
                                             Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -55,16 +55,16 @@
 
     @Override
     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
-        optimizeSpillPosition();
+        optimizeSpillPosition(lirGenRes);
         allocator.printIntervals("After optimize spill position");
     }
 
     @SuppressWarnings("try")
-    private void optimizeSpillPosition() {
+    private void optimizeSpillPosition(LIRGenerationResult res) {
         try (Indent indent0 = Debug.logAndIndent("OptimizeSpillPositions")) {
             LIRInsertionBuffer[] insertionBuffers = new LIRInsertionBuffer[allocator.getLIR().linearScanOrder().length];
             for (Interval interval : allocator.intervals()) {
-                optimizeInterval(insertionBuffers, interval);
+                optimizeInterval(insertionBuffers, interval, res);
             }
             for (LIRInsertionBuffer insertionBuffer : insertionBuffers) {
                 if (insertionBuffer != null) {
@@ -76,7 +76,7 @@
     }
 
     @SuppressWarnings("try")
-    private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval interval) {
+    private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval interval, LIRGenerationResult res) {
         if (interval == null || !interval.isSplitParent() || interval.spillState() != SpillState.SpillInDominator) {
             return;
         }
@@ -165,6 +165,7 @@
             AllocatableValue fromLocation = interval.getSplitChildAtOpId(spillOpId, OperandMode.DEF, allocator).location();
             AllocatableValue toLocation = LinearScan.canonicalSpillOpr(interval);
             LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
+            move.setComment(res, "LSRAOptimizeSpillPos: optimize spill pos");
             Debug.log(Debug.VERBOSE_LEVEL, "Insert spill move %s", move);
             move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID);
             /*
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java	Tue Jun 13 09:19:35 2017 -0700
@@ -36,6 +36,7 @@
 import org.graalvm.compiler.lir.LIRInsertionBuffer;
 import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.LIRValueUtil;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.util.Equivalence;
 import org.graalvm.util.EconomicSet;
 
@@ -60,6 +61,8 @@
     private boolean multipleReadsAllowed;
     private final int[] registerBlocked;
 
+    private final LIRGenerationResult res;
+
     protected void setValueBlocked(Value location, int direction) {
         assert direction == 1 || direction == -1 : "out of bounds";
         if (isRegister(location)) {
@@ -101,7 +104,6 @@
     }
 
     protected MoveResolver(LinearScan allocator) {
-
         this.allocator = allocator;
         this.multipleReadsAllowed = false;
         this.mappingFrom = new ArrayList<>(8);
@@ -110,6 +112,7 @@
         this.insertIdx = -1;
         this.insertionBuffer = new LIRInsertionBuffer();
         this.registerBlocked = new int[allocator.getRegisters().size()];
+        this.res = allocator.getLIRGenerationResult();
     }
 
     protected boolean checkEmpty() {
@@ -265,16 +268,18 @@
         insertIdx = -1;
     }
 
-    private void insertMove(Interval fromInterval, Interval toInterval) {
+    private LIRInstruction insertMove(Interval fromInterval, Interval toInterval) {
         assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval;
         assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : "move between different types";
         assert insertIdx != -1 : "must setup insert position first";
 
-        insertionBuffer.append(insertIdx, createMove(fromInterval.operand, toInterval.operand, fromInterval.location(), toInterval.location()));
+        LIRInstruction move = createMove(fromInterval.operand, toInterval.operand, fromInterval.location(), toInterval.location());
+        insertionBuffer.append(insertIdx, move);
 
         if (Debug.isLogEnabled()) {
             Debug.log("insert move from %s to %s at %d", fromInterval, toInterval, insertIdx);
         }
+        return move;
     }
 
     /**
@@ -287,7 +292,7 @@
         return getAllocator().getSpillMoveFactory().createMove(toOpr, fromOpr);
     }
 
-    private void insertMove(Constant fromOpr, Interval toInterval) {
+    private LIRInstruction insertMove(Constant fromOpr, Interval toInterval) {
         assert insertIdx != -1 : "must setup insert position first";
 
         AllocatableValue toOpr = toInterval.operand;
@@ -297,6 +302,7 @@
         if (Debug.isLogEnabled()) {
             Debug.log("insert move from value %s to %s at %d", fromOpr, toInterval, insertIdx);
         }
+        return move;
     }
 
     @SuppressWarnings("try")
@@ -329,12 +335,14 @@
 
                     if (safeToProcessMove(fromInterval, toInterval)) {
                         // this interval can be processed because target is free
+                        final LIRInstruction move;
                         if (fromInterval != null) {
-                            insertMove(fromInterval, toInterval);
+                            move = insertMove(fromInterval, toInterval);
                             unblockRegisters(fromInterval);
                         } else {
-                            insertMove(mappingFromOpr.get(i), toInterval);
+                            move = insertMove(mappingFromOpr.get(i), toInterval);
                         }
+                        move.setComment(res, "MoveResolver resolve mapping");
                         if (LIRValueUtil.isStackSlotValue(toInterval.location())) {
                             if (busySpillSlots == null) {
                                 busySpillSlots = new ArrayList<>(2);
@@ -404,9 +412,10 @@
         blockRegisters(spillInterval);
 
         // insert a move from register to stack and update the mapping
-        insertMove(fromInterval, spillInterval);
+        LIRInstruction move = insertMove(fromInterval, spillInterval);
         mappingFrom.set(spillCandidate, spillInterval);
         unblockRegisters(fromInterval);
+        move.setComment(res, "MoveResolver break cycle");
     }
 
     @SuppressWarnings("try")
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolver.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceGlobalMoveResolver.java	Tue Jun 13 09:19:35 2017 -0700
@@ -81,6 +81,7 @@
     private final FrameMapBuilder frameMapBuilder;
     private final OptionValues options;
     private final RegisterAllocationConfig registerAllocationConfig;
+    private final LIRGenerationResult res;
 
     private void setValueBlocked(Value location, int direction) {
         assert direction == 1 || direction == -1 : "out of bounds";
@@ -157,6 +158,7 @@
         FrameMap frameMap = frameMapBuilderTool.getFrameMap();
         this.firstVirtualStackIndex = !frameMap.frameNeedsAllocating() ? 0 : frameMap.currentFrameSize() + 1;
         this.options = res.getLIR().getOptions();
+        this.res = res;
     }
 
     private boolean checkEmpty() {
@@ -314,16 +316,18 @@
         insertIdx = -1;
     }
 
-    private void insertMove(Value fromOperand, AllocatableValue toOperand) {
+    private LIRInstruction insertMove(Value fromOperand, AllocatableValue toOperand) {
         assert !fromOperand.equals(toOperand) : "from and to are equal: " + fromOperand + " vs. " + toOperand;
         assert LIRKind.verifyMoveKinds(fromOperand.getValueKind(), fromOperand.getValueKind(), registerAllocationConfig) : "move between different types";
         assert insertIdx != -1 : "must setup insert position first";
 
-        insertionBuffer.append(insertIdx, createMove(fromOperand, toOperand));
+        LIRInstruction move = createMove(fromOperand, toOperand);
+        insertionBuffer.append(insertIdx, move);
 
         if (Debug.isLogEnabled()) {
             Debug.log("insert move from %s to %s at %d", fromOperand, toOperand, insertIdx);
         }
+        return move;
     }
 
     /**
@@ -363,7 +367,8 @@
                     AllocatableValue toLocation = mappingTo.get(i);
                     if (safeToProcessMove(fromLocation, toLocation)) {
                         // this interval can be processed because target is free
-                        insertMove(fromLocation, toLocation);
+                        LIRInstruction move = insertMove(fromLocation, toLocation);
+                        move.setComment(res, "TraceGlobalMoveResolver: resolveMapping");
                         unblock(fromLocation);
                         if (isStackSlotValue(toLocation)) {
                             if (busySpillSlots == null) {
@@ -422,7 +427,8 @@
                 cycleBreakingSlotsAllocated.increment();
                 Debug.log("created new slot for spilling: %s", spillSlot);
                 // insert a move from register to stack and update the mapping
-                insertMove(from, spillSlot);
+                LIRInstruction move = insertMove(from, spillSlot);
+                move.setComment(res, "TraceGlobalMoveResolver: breakCycle");
             }
             block(spillSlot);
             mappingFrom.set(spillCandidate, spillSlot);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/bu/BottomUpAllocator.java	Tue Jun 13 09:19:35 2017 -0700
@@ -308,6 +308,7 @@
         private void insertSpillMoveBefore(AllocatableValue dst, Value src) {
             LIRInstruction move = spillMoveFactory.createMove(dst, src);
             insertInstructionsBefore.add(move);
+            move.setComment(lirGenRes, "BottomUp: spill move before");
             Debug.log("insert before %s", move);
         }
 
@@ -316,6 +317,7 @@
             if (!(inst instanceof BlockEndOp)) {
                 LIRInstruction move = spillMoveFactory.createMove(dst, src);
                 insertInstructionsAfter.add(move);
+                move.setComment(lirGenRes, "BottomUp: spill move after");
                 Debug.log("insert after %s", move);
             } else {
                 Debug.log("Block end op. No from %s to %s necessary.", src, dst);
@@ -409,6 +411,7 @@
                 move = spillMoveFactory.createMove(dest, asVariable(phiOut));
             }
             Debug.log("Inserting load %s", move);
+            move.setComment(lirGenRes, "BottomUp: phi resolution");
             phiResolutionMoves.add(move);
         }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/lsra/TraceLinearScanEliminateSpillMovePhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -65,7 +65,7 @@
     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, Trace trace, MoveFactory spillMoveFactory, RegisterAllocationConfig registerAllocationConfig,
                     TraceBuilderResult traceBuilderResult, TraceLinearScan allocator) {
         boolean shouldEliminateSpillMoves = shouldEliminateSpillMoves(traceBuilderResult, allocator);
-        eliminateSpillMoves(allocator, shouldEliminateSpillMoves, traceBuilderResult);
+        eliminateSpillMoves(allocator, shouldEliminateSpillMoves, traceBuilderResult, lirGenRes);
     }
 
     private static boolean shouldEliminateSpillMoves(TraceBuilderResult traceBuilderResult, TraceLinearScan allocator) {
@@ -74,7 +74,7 @@
 
     // called once before assignment of register numbers
     @SuppressWarnings("try")
-    private static void eliminateSpillMoves(TraceLinearScan allocator, boolean shouldEliminateSpillMoves, TraceBuilderResult traceBuilderResult) {
+    private static void eliminateSpillMoves(TraceLinearScan allocator, boolean shouldEliminateSpillMoves, TraceBuilderResult traceBuilderResult, LIRGenerationResult res) {
         try (Indent indent = Debug.logAndIndent("Eliminating unnecessary spill moves: Trace%d", traceBuilderResult.getTraceForBlock(allocator.blockAt(0)).getId())) {
             allocator.sortIntervalsBySpillPos();
 
@@ -166,6 +166,7 @@
 
                                             LIRInstruction move = allocator.getSpillMoveFactory().createMove(toLocation, fromLocation);
                                             insertionBuffer.append(j + 1, move);
+                                            move.setComment(res, "TraceLSRAEliminateSpillMove: spill def pos");
 
                                             if (Debug.isLogEnabled()) {
                                                 Debug.log("inserting move after definition of interval %d to stack slot %s at opId %d", interval.operandNumber, interval.spillSlot(), opId);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java	Tue Jun 13 09:19:35 2017 -0700
@@ -24,9 +24,13 @@
 
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
+import org.graalvm.compiler.debug.Debug;
 import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.framemap.FrameMap;
 import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
+import org.graalvm.util.EconomicMap;
+import org.graalvm.util.Equivalence;
 
 import jdk.vm.ci.code.CallingConvention;
 
@@ -43,7 +47,12 @@
     /**
      * Unique identifier of this compilation.
      */
-    private final CompilationIdentifier compilationId;
+    private CompilationIdentifier compilationId;
+
+    /**
+     * Stores comments about a {@link LIRInstruction} , e.g., which phase created it.
+     */
+    private EconomicMap<LIRInstruction, String> comments;
 
     public LIRGenerationResult(CompilationIdentifier compilationId, LIR lir, FrameMapBuilder frameMapBuilder, CallingConvention callingConvention) {
         this.lir = lir;
@@ -53,6 +62,28 @@
     }
 
     /**
+     * Adds a comment to a {@link LIRInstruction}. Existing comments are replaced.
+     */
+    public final void setComment(LIRInstruction op, String comment) {
+        if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) {
+            if (comments == null) {
+                comments = EconomicMap.create(Equivalence.IDENTITY);
+            }
+            comments.put(op, comment);
+        }
+    }
+
+    /**
+     * Gets the comment attached to a {@link LIRInstruction}.
+     */
+    public final String getComment(LIRInstruction op) {
+        if (comments == null) {
+            return null;
+        }
+        return comments.get(op);
+    }
+
+    /**
      * Returns the incoming calling convention for the parameters of the method that is compiled.
      */
     public CallingConvention getCallingConvention() {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/SimplifyingGraphDecoder.java	Tue Jun 13 09:19:35 2017 -0700
@@ -190,13 +190,20 @@
 
     @Override
     protected void handleFixedNode(MethodScope methodScope, LoopScope loopScope, int nodeOrderId, FixedNode node) {
-        Node canonical = canonicalizeFixedNode(node);
+        Node canonical = canonicalizeFixedNode(methodScope, node);
         if (canonical != node) {
             handleCanonicalization(loopScope, nodeOrderId, node, canonical);
         }
     }
 
-    private Node canonicalizeFixedNode(FixedNode node) {
+    /**
+     * Canonicalizes the provided node, which was originally a {@link FixedNode} but can already be
+     * canonicalized (and therefore be a non-fixed node).
+     *
+     * @param methodScope The current method.
+     * @param node The node to be canonicalized.
+     */
+    protected Node canonicalizeFixedNode(MethodScope methodScope, Node node) {
         if (node instanceof LoadFieldNode) {
             LoadFieldNode loadFieldNode = (LoadFieldNode) node;
             return loadFieldNode.canonical(canonicalizerTool);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java	Tue Jun 13 09:19:35 2017 -0700
@@ -57,7 +57,11 @@
      * This constructor exists for node intrinsics that need a stamp based on {@code accessKind}.
      */
     public RawLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity) {
-        super(TYPE, StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity, false);
+        this(object, offset, accessKind, locationIdentity, false);
+    }
+
+    public RawLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, LocationIdentity locationIdentity, boolean forceAnyLocation) {
+        super(TYPE, StampFactory.forKind(accessKind.getStackKind()), object, offset, accessKind, locationIdentity, forceAnyLocation);
     }
 
     /**
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AbstractInliningPhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AbstractInliningPhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -29,8 +29,4 @@
  * Common superclass for phases that perform inlining.
  */
 public abstract class AbstractInliningPhase extends BasePhase<HighTierContext> {
-    @Override
-    protected boolean isInliningPhase() {
-        return true;
-    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * 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.phases.common;
+
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.extended.JavaReadNode;
+import org.graalvm.compiler.nodes.memory.AbstractWriteNode;
+import org.graalvm.compiler.nodes.memory.FloatingReadNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
+import org.graalvm.compiler.nodes.memory.address.RawAddressNode;
+import org.graalvm.compiler.nodes.util.GraphUtil;
+import org.graalvm.compiler.phases.Phase;
+
+/**
+ * Created by adinn on 09/05/17.
+ */
+public class AddressLoweringByUsePhase extends Phase {
+    public abstract static class AddressLoweringByUse {
+
+        public abstract AddressNode lower(ValueNode use, Stamp stamp, AddressNode address);
+
+        public abstract AddressNode lower(AddressNode address);
+    }
+
+    private final AddressLoweringByUse lowering;
+
+    public AddressLoweringByUsePhase(AddressLoweringByUse lowering) {
+        this.lowering = lowering;
+        assert lowering != null;
+    }
+
+    @Override
+    protected void run(StructuredGraph graph) {
+        // first replace address nodes hanging off known usages
+        for (Node node : graph.getNodes()) {
+            AddressNode address;
+            AddressNode lowered;
+            if (node instanceof ReadNode) {
+                ReadNode readNode = (ReadNode) node;
+                Stamp stamp = readNode.stamp();
+                address = readNode.getAddress();
+                lowered = lowering.lower(readNode, stamp, address);
+            } else if (node instanceof JavaReadNode) {
+                JavaReadNode javaReadNode = (JavaReadNode) node;
+                Stamp stamp = javaReadNode.stamp();
+                address = javaReadNode.getAddress();
+                lowered = lowering.lower(javaReadNode, stamp, address);
+            } else if (node instanceof FloatingReadNode) {
+                FloatingReadNode floatingReadNode = (FloatingReadNode) node;
+                Stamp stamp = floatingReadNode.stamp();
+                address = floatingReadNode.getAddress();
+                lowered = lowering.lower(floatingReadNode, stamp, address);
+            } else if (node instanceof AbstractWriteNode) {
+                AbstractWriteNode abstractWriteNode = (AbstractWriteNode) node;
+                Stamp stamp = abstractWriteNode.value().stamp();
+                address = abstractWriteNode.getAddress();
+                lowered = lowering.lower(abstractWriteNode, stamp, address);
+                // TODO -- PrefetchAllocateNode is not yet implemented for AArch64
+                // } else if (node instanceof PrefetchAllocateNode) {
+                // PrefetchAllocateNode prefetchAllocateNode = (PrefetchAllocateNode) node;
+                // Stamp stamp = prefetchAllocateNode.value().stamp();
+                // n.b.this getter is not provided!
+                // address = prefetchAllocateNode.getAddress();
+                // lowered = lowering.lower(prefetchAllocateNode, stamp, address);
+            } else {
+                continue;
+            }
+            // the lowered address amy already be a replacement
+            // in which case we want to use it not delete it!
+            if (lowered != address) {
+                address.replaceAtUsages(lowered);
+                GraphUtil.killWithUnusedFloatingInputs(address);
+            }
+        }
+
+        // now replace any remaining unlowered address nodes
+        for (Node node : graph.getNodes()) {
+            AddressNode lowered;
+            if (node instanceof RawAddressNode || node instanceof OffsetAddressNode) {
+                AddressNode address = (AddressNode) node;
+                lowered = lowering.lower(address);
+            } else {
+                continue;
+            }
+            // will always be a new AddresNode
+            node.replaceAtUsages(lowered);
+            GraphUtil.killWithUnusedFloatingInputs(node);
+        }
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -225,6 +225,11 @@
         this.loweringStage = loweringStage;
     }
 
+    @Override
+    protected boolean shouldDumpBeforeAtBasicLevel() {
+        return loweringStage == LoweringTool.StandardLoweringStage.HIGH_TIER;
+    }
+
     /**
      * Checks that second lowering of a given graph did not introduce any new nodes.
      *
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java	Tue Jun 13 09:19:35 2017 -0700
@@ -101,6 +101,7 @@
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Consumer;
 
 import static jdk.vm.ci.meta.DeoptimizationAction.InvalidateReprofile;
 import static jdk.vm.ci.meta.DeoptimizationReason.NullCheckException;
@@ -408,6 +409,12 @@
      */
     @SuppressWarnings("try")
     public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod) {
+        return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, null);
+    }
+
+    @SuppressWarnings("try")
+    public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod,
+                    Consumer<UnmodifiableEconomicMap<Node, Node>> duplicatesConsumer) {
         HashSetNodeEventListener listener = new HashSetNodeEventListener();
         /*
          * This code relies on the fact that Graph.addDuplicates doesn't trigger the
@@ -415,7 +422,10 @@
          * the graph into the current graph.
          */
         try (NodeEventScope nes = invoke.asNode().graph().trackNodeEvents(listener)) {
-            InliningUtil.inline(invoke, inlineGraph, receiverNullCheck, inlineeMethod);
+            UnmodifiableEconomicMap<Node, Node> duplicates = InliningUtil.inline(invoke, inlineGraph, receiverNullCheck, inlineeMethod);
+            if (duplicatesConsumer != null) {
+                duplicatesConsumer.accept(duplicates);
+            }
         }
         return listener.getNodes();
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Tue Jun 13 09:19:35 2017 -0700
@@ -277,7 +277,7 @@
         // do the actual inlining for every invoke
         for (int i = 0; i < numberOfMethods; i++) {
             Invoke invokeForInlining = (Invoke) successors[i].next();
-            canonicalizeNodes.addAll(inline(invokeForInlining, methodAt(i), inlineableElementAt(i), false));
+            canonicalizeNodes.addAll(doInline(i, invokeForInlining));
         }
         if (returnValuePhi != null) {
             canonicalizeNodes.add(returnValuePhi);
@@ -285,6 +285,10 @@
         return canonicalizeNodes;
     }
 
+    protected EconomicSet<Node> doInline(int index, Invoke invokeForInlining) {
+        return inline(invokeForInlining, methodAt(index), inlineableElementAt(index), false);
+    }
+
     private int getTypeCount(int concreteMethodIndex) {
         int count = 0;
         for (int i = 0; i < typesToConcretes.size(); i++) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/BasePhase.java	Tue Jun 13 09:19:35 2017 -0700
@@ -150,8 +150,12 @@
     }
 
     private boolean dumpBefore(final StructuredGraph graph, final C context, boolean isTopLevel) {
-        if (isTopLevel && Debug.isDumpEnabled(Debug.VERBOSE_LEVEL)) {
-            Debug.dump(Debug.VERBOSE_LEVEL, graph, "Before phase %s", getName());
+        if (isTopLevel && (Debug.isDumpEnabled(Debug.VERBOSE_LEVEL) || shouldDumpBeforeAtBasicLevel() && Debug.isDumpEnabled(Debug.BASIC_LEVEL))) {
+            if (shouldDumpBeforeAtBasicLevel()) {
+                Debug.dump(Debug.BASIC_LEVEL, graph, "Before phase %s", getName());
+            } else {
+                Debug.dump(Debug.VERBOSE_LEVEL, graph, "Before phase %s", getName());
+            }
         } else if (!isTopLevel && Debug.isDumpEnabled(Debug.VERBOSE_LEVEL + 1)) {
             Debug.dump(Debug.VERBOSE_LEVEL + 1, graph, "Before subphase %s", getName());
         } else if (Debug.isDumpEnabled(Debug.ENABLED_LEVEL) && shouldDump(graph, context)) {
@@ -161,7 +165,11 @@
         return false;
     }
 
-    protected boolean isInliningPhase() {
+    protected boolean shouldDumpBeforeAtBasicLevel() {
+        return false;
+    }
+
+    protected boolean shouldDumpAfterAtBasicLevel() {
         return false;
     }
 
@@ -207,7 +215,7 @@
     private void dumpAfter(final StructuredGraph graph, boolean isTopLevel, boolean dumpedBefore) {
         boolean dumped = false;
         if (isTopLevel) {
-            if (isInliningPhase()) {
+            if (shouldDumpAfterAtBasicLevel()) {
                 if (Debug.isDumpEnabled(Debug.BASIC_LEVEL)) {
                     Debug.dump(Debug.BASIC_LEVEL, graph, "After phase %s", getName());
                     dumped = true;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyDebugUsage.java	Tue Jun 13 09:19:35 2017 -0700
@@ -150,6 +150,7 @@
      */
     private static final Set<String> BasicLevelStructuredGraphDumpWhitelist = new HashSet<>(Arrays.asList(
                     "org.graalvm.compiler.phases.BasePhase.dumpAfter",
+                    "org.graalvm.compiler.phases.BasePhase.dumpBefore",
                     "org.graalvm.compiler.core.GraalCompiler.emitFrontEnd",
                     "org.graalvm.compiler.truffle.PartialEvaluator.fastPartialEvaluation",
                     "org.graalvm.compiler.truffle.PartialEvaluator$PerformanceInformationHandler.reportPerformanceWarnings",
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Tue Jun 13 09:19:35 2017 -0700
@@ -175,7 +175,7 @@
     @Override
     public void print(Graph graph, Map<Object, Object> properties, int id, String format, Object... args) throws IOException {
         writeByte(BEGIN_GRAPH);
-        if (CURRENT_MAJOR_VERSION == 3) {
+        if (CURRENT_MAJOR_VERSION >= 3) {
             writeInt(id);
             writeString(format);
             writeInt(args.length);
@@ -183,7 +183,7 @@
                 writePropertyObject(a);
             }
         } else {
-            writePoolObject(String.format(format, args));
+            writePoolObject(formatTitle(id, format, args));
         }
         writeGraph(graph, properties);
         flush();
@@ -386,12 +386,14 @@
         } else if (object instanceof NodeClass) {
             NodeClass<?> nodeClass = (NodeClass<?>) object;
             writeByte(POOL_NODE_CLASS);
-            if (CURRENT_MAJOR_VERSION == 3) {
+            if (CURRENT_MAJOR_VERSION >= 3) {
                 writePoolObject(nodeClass.getJavaClass());
+                writeString(nodeClass.getNameTemplate());
             } else {
                 writeString(nodeClass.getJavaClass().getSimpleName());
+                String nameTemplate = nodeClass.getNameTemplate();
+                writeString(nameTemplate.isEmpty() ? nodeClass.shortName() : nameTemplate);
             }
-            writeString(nodeClass.getNameTemplate());
             writeEdgesInfo(nodeClass, Inputs);
             writeEdgesInfo(nodeClass, Successors);
         } else if (object instanceof ResolvedJavaMethod || object instanceof Bytecode) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java	Tue Jun 13 09:19:35 2017 -0700
@@ -50,6 +50,7 @@
 import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessInfo;
 import org.graalvm.compiler.lir.debug.IntervalDumper;
 import org.graalvm.compiler.lir.debug.IntervalDumper.IntervalVisitor;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.nodeinfo.Verbosity;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractEndNode;
@@ -85,6 +86,7 @@
     protected ScheduleResult schedule;
     protected ResolvedJavaMethod method;
     protected GlobalLivenessInfo livenessInfo;
+    protected LIRGenerationResult res;
 
     /**
      * Creates a control flow graph printer.
@@ -555,7 +557,7 @@
                 out.adjustIndentation(level);
             }
 
-            out.print(" instruction ").print(inst.toString()).print(COLUMN_END);
+            out.print(" instruction ").print(inst.toString(res)).print(COLUMN_END);
             out.println(COLUMN_END);
         }
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java	Tue Jun 13 09:19:35 2017 -0700
@@ -51,6 +51,7 @@
 import org.graalvm.compiler.lir.LIR;
 import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessInfo;
 import org.graalvm.compiler.lir.debug.IntervalDumper;
+import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
 import org.graalvm.compiler.nodes.cfg.ControlFlowGraph;
@@ -173,6 +174,7 @@
             }
             cfgPrinter.nodeLirGenerator = Debug.contextLookup(NodeLIRBuilder.class);
             cfgPrinter.livenessInfo = Debug.contextLookup(GlobalLivenessInfo.class);
+            cfgPrinter.res = Debug.contextLookup(LIRGenerationResult.class);
             if (cfgPrinter.nodeLirGenerator != null) {
                 cfgPrinter.target = cfgPrinter.nodeLirGenerator.getLIRGeneratorTool().target();
             }
@@ -238,6 +240,7 @@
         } finally {
             cfgPrinter.target = null;
             cfgPrinter.lir = null;
+            cfgPrinter.res = null;
             cfgPrinter.nodeLirGenerator = null;
             cfgPrinter.livenessInfo = null;
             cfgPrinter.cfg = null;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CanonicalStringGraphPrinter.java	Tue Jun 13 09:19:35 2017 -0700
@@ -267,7 +267,7 @@
                 TTY.println("Dumping string graphs in %s", this.root);
                 this.root = null;
             }
-            String title = id + ": " + String.format(format, args);
+            String title = formatTitle(id, format, args);
             Path filePath = currentDirectory.resolve(escapeFileName(title));
             try (PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(filePath.toFile())))) {
                 switch (PrintCanonicalGraphStringFlavor.getValue(options)) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java	Tue Jun 13 09:19:35 2017 -0700
@@ -36,6 +36,7 @@
 
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.runtime.JVMCI;
@@ -141,6 +142,22 @@
         }
     }
 
+    default String formatTitle(int id, String format, Object... args) {
+        /*
+         * If an argument is a Class, replace it with the simple name.
+         */
+        Object[] newArgs = new Object[args.length];
+        for (int i = 0; i < newArgs.length; i++) {
+            Object arg = args[i];
+            if (arg instanceof JavaType) {
+                newArgs[i] = ((JavaType) arg).getUnqualifiedName();
+            } else {
+                newArgs[i] = arg;
+            }
+        }
+        return id + ": " + String.format(format, newArgs);
+    }
+
     static String truncate(String s) {
         if (s.length() > MAX_CONSTANT_TO_STRING_LENGTH) {
             return s.substring(0, MAX_CONSTANT_TO_STRING_LENGTH - 3) + "...";
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/IdealGraphPrinter.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/IdealGraphPrinter.java	Tue Jun 13 09:19:35 2017 -0700
@@ -115,7 +115,7 @@
      */
     @Override
     public void print(Graph graph, Map<Object, Object> properties, int id, String format, Object... args) {
-        String title = id + ": " + String.format(format, args);
+        String title = formatTitle(id, format, args);
         beginGraph(title);
         EconomicSet<Node> noBlockNodes = EconomicSet.create(Equivalence.IDENTITY);
         ScheduleResult schedule = null;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Tue Jun 13 09:19:35 2017 -0700
@@ -68,6 +68,7 @@
     private static final String IN_INTERPRETED_HANDLER_MARKER = "*** in interpreted handler ***";
 
     private InlineInvokePlugin.InlineInfo inlineInvokeDecision;
+    private String inlineInvokeMethodName = null;
 
     @SuppressWarnings("serial")
     static class CustomError extends Error {
@@ -351,12 +352,15 @@
         test(options, "callStringize", Boolean.TRUE);
         String standardReturnValue = IN_INTERPRETED_HANDLER_MARKER;
         String compiledReturnValue = IN_COMPILED_HANDLER_MARKER;
-        for (int i = 0; i < 1000; i++) {
-            // Ensures 'exception seen' bit is set for call to stringize
-            callStringize(THROW_EXCEPTION_MARKER);
+        forceCompileOverride = true;
+        inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
+        inlineInvokeMethodName = "stringizeId";
+        try {
+            testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringize", THROW_EXCEPTION_MARKER);
+        } finally {
+            inlineInvokeDecision = null;
+            inlineInvokeMethodName = null;
         }
-        forceCompileOverride = true;
-        testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringize", THROW_EXCEPTION_MARKER);
     }
 
     @Test
@@ -378,14 +382,17 @@
         test(options, "callStringizeId", new TestObject("a string"));
         test(options, "callStringizeId", new TestObject(Boolean.TRUE));
         TestObject exceptionTestObject = new TestObject(THROW_EXCEPTION_MARKER);
-        for (int i = 0; i < 1000; i++) {
-            // Ensures 'exception seen' bit is set for call to stringizeId
-            callStringizeId(exceptionTestObject);
-        }
         String standardReturnValue = IN_INTERPRETED_HANDLER_MARKER;
         String compiledReturnValue = IN_COMPILED_HANDLER_MARKER;
         forceCompileOverride = true;
-        testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringizeId", exceptionTestObject);
+        inlineInvokeDecision = InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
+        inlineInvokeMethodName = "stringizeId";
+        try {
+            testWithDifferentReturnValues(options, standardReturnValue, compiledReturnValue, "callStringizeId", exceptionTestObject);
+        } finally {
+            inlineInvokeDecision = null;
+            inlineInvokeMethodName = null;
+        }
     }
 
     public static Object callStringize(Object obj) {
@@ -474,7 +481,10 @@
 
     @Override
     protected InlineInvokePlugin.InlineInfo bytecodeParserShouldInlineInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
-        return inlineInvokeDecision;
+        if (inlineInvokeMethodName == null || inlineInvokeMethodName.equals(method.getName())) {
+            return inlineInvokeDecision;
+        }
+        return null;
     }
 
     @Test
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Tue Jun 13 07:30:11 2017 -0400
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Tue Jun 13 09:19:35 2017 -0700
@@ -94,6 +94,7 @@
 import org.graalvm.compiler.nodes.java.StoreFieldNode;
 import org.graalvm.compiler.nodes.java.StoreIndexedNode;
 import org.graalvm.compiler.nodes.spi.StampProvider;
+import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
@@ -375,56 +376,6 @@
         }
     }
 
-    /**
-     * A graph builder context that allows appending one node to the graph. If a node is appended,
-     * the target fixed node is replaced with the new node, and clients must afterwards call commit
-     * to complete the replacement.
-     *
-     * This graph builder context is intended to be used with the {@link NodePlugin} objects passed
-     * to the graph decoder.
-     */
-    protected class PEOnDemandAppendGraphBuilderContext extends PEAppendGraphBuilderContext {
-        private final FixedNode targetNode;
-        private FixedWithNextNode predecessor;
-
-        public PEOnDemandAppendGraphBuilderContext(PEMethodScope inlineScope, FixedNode targetNode) {
-            super(inlineScope, targetNode.predecessor() instanceof FixedWithNextNode ? (FixedWithNextNode) targetNode.predecessor() : null);
-            this.targetNode = targetNode;
-            this.predecessor = targetNode.predecessor() instanceof FixedWithNextNode ? (FixedWithNextNode) targetNode.predecessor() : null;
-        }
-
-        @Override
-        public void push(JavaKind kind, ValueNode value) {
-            super.push(kind, value);
-        }
-
-        private void checkPopLastInstruction() {
-            if (predecessor != null) {
-                targetNode.replaceAtPredecessor(null);
-                lastInstr = predecessor;
-                predecessor = null;
-            }
-        }
-
-        @Override
-        public <T extends ValueNode> T append(T v) {
-            checkPopLastInstruction();
-            return super.append(v);
-        }
-
-        public FixedNode commit(LoopScope loopScope, int nodeOrderId, FixedWithNextNode oldAsFixedWithNextNode) {
-            registerNode(loopScope, nodeOrderId, pushedNode, true, false);
-            targetNode.replaceAtUsages(pushedNode);
-            if (oldAsFixedWithNextNode != null) {
-                FixedNode successor = oldAsFixedWithNextNode.next();
-                successor.replaceAtPredecessor(null);
-                lastInstr.setNext(successor);
-                deleteFixedNode(targetNode);
-            }
-            return lastInstr;
-        }
-    }
-
     @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
     static class ExceptionPlaceholderNode extends ValueNode {
         public static final NodeClass<ExceptionPlaceholderNode> TYPE = NodeClass.create(ExceptionPlaceholderNode.class);
@@ -737,6 +688,26 @@
         PEMethodScope inlineScope = new PEMethodScope(graph, methodScope, loopScope, graphToInline, inlineMethod, invokeData, methodScope.inliningDepth + 1,
                         loopExplosionPlugin, arguments);
 
+        if (!inlineMethod.isStatic()) {
+            if (StampTool.isPointerAlwaysNull(arguments[0])) {
+                /*
+                 * The receiver is null, so we can unconditionally throw a NullPointerException
+                 * instead of performing any inlining.
+                 */
+                DeoptimizeNode deoptimizeNode = graph.add(new DeoptimizeNode(DeoptimizationAction.InvalidateReprofile, DeoptimizationReason.NullCheckException));
+                predecessor.setNext(deoptimizeNode);
+                finishInlining(inlineScope);
+                /* Continue decoding in the caller. */
+                return loopScope;
+
+            } else if (!StampTool.isPointerNonNull(arguments[0])) {
+                /* The receiver might be null, so we need to insert a null check. */
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(inlineScope, predecessor);
+                arguments[0] = graphBuilderContext.nullCheckedValue(arguments[0]);
+                predecessor = graphBuilderContext.lastInstr;
+            }
+        }
+
         /*
          * Do the actual inlining by returning the initial loop scope for the inlined method scope.
          */
@@ -926,26 +897,35 @@
 
     protected abstract EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodeProvider intrinsicBytecodeProvider);
 
-    @SuppressWarnings("try")
     @Override
     protected void handleFixedNode(MethodScope s, LoopScope loopScope, int nodeOrderId, FixedNode node) {
         PEMethodScope methodScope = (PEMethodScope) s;
-        FixedNode replacedNode = node;
 
         if (node instanceof ForeignCallNode) {
             ForeignCallNode foreignCall = (ForeignCallNode) node;
             if (foreignCall.getBci() == BytecodeFrame.UNKNOWN_BCI && methodScope.invokeData != null) {
                 foreignCall.setBci(methodScope.invokeData.invoke.bci());
             }
-        } else if (nodePlugins != null && nodePlugins.length > 0) {
+        }
+
+        super.handleFixedNode(methodScope, loopScope, nodeOrderId, node);
+    }
+
+    @SuppressWarnings("try")
+    @Override
+    protected Node canonicalizeFixedNode(MethodScope s, Node node) {
+        PEMethodScope methodScope = (PEMethodScope) s;
+
+        Node replacedNode = node;
+        if (nodePlugins != null && nodePlugins.length > 0) {
             if (node instanceof LoadFieldNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 LoadFieldNode loadFieldNode = (LoadFieldNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, loadFieldNode);
                 ResolvedJavaField field = loadFieldNode.field();
                 if (loadFieldNode.isStatic()) {
                     for (NodePlugin nodePlugin : nodePlugins) {
                         if (nodePlugin.handleLoadStaticField(graphBuilderContext, field)) {
-                            replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, loadFieldNode);
+                            replacedNode = graphBuilderContext.pushedNode;
                             break;
                         }
                     }
@@ -953,20 +933,20 @@
                     ValueNode object = loadFieldNode.object();
                     for (NodePlugin nodePlugin : nodePlugins) {
                         if (nodePlugin.handleLoadField(graphBuilderContext, object, field)) {
-                            replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, loadFieldNode);
+                            replacedNode = graphBuilderContext.pushedNode;
                             break;
                         }
                     }
                 }
             } else if (node instanceof StoreFieldNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 StoreFieldNode storeFieldNode = (StoreFieldNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, storeFieldNode);
                 ResolvedJavaField field = storeFieldNode.field();
                 if (storeFieldNode.isStatic()) {
                     ValueNode value = storeFieldNode.value();
                     for (NodePlugin nodePlugin : nodePlugins) {
                         if (nodePlugin.handleStoreStaticField(graphBuilderContext, field, value)) {
-                            replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, storeFieldNode);
+                            replacedNode = graphBuilderContext.pushedNode;
                             break;
                         }
                     }
@@ -975,93 +955,70 @@
                     ValueNode value = storeFieldNode.value();
                     for (NodePlugin nodePlugin : nodePlugins) {
                         if (nodePlugin.handleStoreField(graphBuilderContext, object, field, value)) {
-                            replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, storeFieldNode);
+                            replacedNode = graphBuilderContext.pushedNode;
                             break;
                         }
                     }
                 }
             } else if (node instanceof LoadIndexedNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 LoadIndexedNode loadIndexedNode = (LoadIndexedNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, loadIndexedNode);
                 ValueNode array = loadIndexedNode.array();
                 ValueNode index = loadIndexedNode.index();
                 for (NodePlugin nodePlugin : nodePlugins) {
                     if (nodePlugin.handleLoadIndexed(graphBuilderContext, array, index, loadIndexedNode.elementKind())) {
-                        replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, loadIndexedNode);
+                        replacedNode = graphBuilderContext.pushedNode;
                         break;
                     }
                 }
             } else if (node instanceof StoreIndexedNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 StoreIndexedNode storeIndexedNode = (StoreIndexedNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, storeIndexedNode);
                 ValueNode array = storeIndexedNode.array();
                 ValueNode index = storeIndexedNode.index();
                 ValueNode value = storeIndexedNode.value();
                 for (NodePlugin nodePlugin : nodePlugins) {
                     if (nodePlugin.handleStoreIndexed(graphBuilderContext, array, index, storeIndexedNode.elementKind(), value)) {
-                        replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, storeIndexedNode);
+                        replacedNode = graphBuilderContext.pushedNode;
                         break;
                     }
                 }
             } else if (node instanceof NewInstanceNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 NewInstanceNode newInstanceNode = (NewInstanceNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, newInstanceNode);
                 ResolvedJavaType type = newInstanceNode.instanceClass();
                 for (NodePlugin nodePlugin : nodePlugins) {
                     if (nodePlugin.handleNewInstance(graphBuilderContext, type)) {
-                        replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, newInstanceNode);
+                        replacedNode = graphBuilderContext.pushedNode;
                         break;
                     }
                 }
             } else if (node instanceof NewArrayNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 NewArrayNode newArrayNode = (NewArrayNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, newArrayNode);
                 ResolvedJavaType elementType = newArrayNode.elementType();
                 ValueNode length = newArrayNode.length();
                 for (NodePlugin nodePlugin : nodePlugins) {
                     if (nodePlugin.handleNewArray(graphBuilderContext, elementType, length)) {
-                        replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, newArrayNode);
+                        replacedNode = graphBuilderContext.pushedNode;
                         break;
                     }
                 }
             } else if (node instanceof NewMultiArrayNode) {
-                PEOnDemandAppendGraphBuilderContext graphBuilderContext = new PEOnDemandAppendGraphBuilderContext(methodScope, node);
                 NewMultiArrayNode newArrayNode = (NewMultiArrayNode) node;
+                PEAppendGraphBuilderContext graphBuilderContext = new PEAppendGraphBuilderContext(methodScope, newArrayNode);
                 ResolvedJavaType elementType = newArrayNode.type();
                 ValueNode[] dimensions = newArrayNode.dimensions().toArray(new ValueNode[0]);
                 for (NodePlugin nodePlugin : nodePlugins) {
                     if (nodePlugin.handleNewMultiArray(graphBuilderContext, elementType, dimensions)) {
-                        replacedNode = graphBuilderContext.commit(loopScope, nodeOrderId, newArrayNode);
+                        replacedNode = graphBuilderContext.pushedNode;
                         break;
                     }
                 }
             }
         }
 
-        NodeSourcePosition pos = replacedNode.getNodeSourcePosition();
-        if (pos != null && methodScope.isInlinedMethod()) {
-            NodeSourcePosition newPosition = pos.addCaller(methodScope.getCallerBytecodePosition());
-            try (DebugCloseable scope = replacedNode.graph().withNodeSourcePosition(newPosition)) {
-                super.handleFixedNode(s, loopScope, nodeOrderId, replacedNode);
-            }
-            if (replacedNode.isAlive()) {
-                replacedNode.setNodeSourcePosition(newPosition);
-            }
-        } else {
-            super.handleFixedNode(s, loopScope, nodeOrderId, replacedNode);
-        }
-
-    }
-
-    private static void deleteFixedNode(FixedNode node) {
-        FrameState frameState = null;
-        if (node instanceof StateSplit) {
-            frameState = ((StateSplit) node).stateAfter();
-        }
-        node.safeDelete();
-        if (frameState != null && frameState.hasNoUsages()) {
-            frameState.safeDelete();
-        }
+        return super.canonicalizeFixedNode(methodScope, replacedNode);
     }
 
     @Override
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.options;
+
+/**
+ * Classifies options in several categories depending on who this option is relevant for.
+ *
+ * @since 1.0
+ */
+public enum OptionCategory {
+
+    /**
+     * An option common for users to apply.
+     *
+     * @since 1.0
+     */
+    USER,
+
+    /**
+     * An option only relevant in corner cases and for fine-tuning.
+     *
+     * @since 1.0
+     */
+    EXPERT,
+
+    /**
+     * An option only relevant when debugging language or instrument implementations.
+     *
+     * @since 1.0
+     */
+    DEBUG
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,173 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.options;
+
+/**
+ * Represents meta-data for a single option.
+ *
+ * @since 1.0
+ */
+public final class OptionDescriptor {
+
+    private final OptionKey<?> key;
+    private final String name;
+    private final String help;
+    private final OptionCategory kind;
+    private final boolean deprecated;
+
+    OptionDescriptor(OptionKey<?> key, String name, String help, OptionCategory kind, boolean deprecated) {
+        this.key = key;
+        this.name = name;
+        this.help = help;
+        this.kind = kind;
+        this.deprecated = deprecated;
+    }
+
+    /**
+     * Returns the option name of the option represented by this descriptor.
+     *
+     * @since 1.0
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns the key for this option.
+     *
+     * @since 1.0
+     */
+    public OptionKey<?> getKey() {
+        return key;
+    }
+
+    /**
+     * Returns <code>true</code> if this option was marked deprecated. This indicates that the
+     * option is going to be removed in a future release or its use is not recommended.
+     *
+     * @since 1.0
+     */
+    public boolean isDeprecated() {
+        return deprecated;
+    }
+
+    /**
+     * Returns the user category of this option.
+     *
+     * @since 1.0
+     */
+    public OptionCategory getCategory() {
+        return kind;
+    }
+
+    /**
+     * Returns a human-readable description on how to use the option.
+     *
+     * @since 1.0
+     */
+    public String getHelp() {
+        return help;
+    }
+
+    /**
+     * @since 1.0
+     */
+    @Override
+    public String toString() {
+        return "OptionDescriptor [key=" + key + ", help=" + help + ", kind=" + kind + ", deprecated=" + deprecated + "]";
+    }
+
+    /**
+     * Creates a new option descriptor builder by key. The option group and name is inferred by the
+     * key.
+     *
+     * @since 1.0
+     */
+    public static <T> Builder newBuilder(OptionKey<T> key, String name) {
+        return new Builder(key, name);
+    }
+
+    /**
+     * Represents an option descriptor builder.
+     *
+     * @since 1.0
+     */
+    public static final class Builder {
+
+        private final OptionKey<?> key;
+        private final String name;
+        private boolean deprecated;
+        private OptionCategory category;
+        private String help;
+
+        Builder(OptionKey<?> key, String name) {
+            this.key = key;
+            this.name = name;
+        }
+
+        /**
+         * Defines the user category for this option. The default value is
+         * {@link OptionCategory#DEBUG}.
+         *
+         * @since 1.0
+         */
+        public Builder category(@SuppressWarnings("hiding") OptionCategory category) {
+            this.category = category;
+            return this;
+        }
+
+        /**
+         * Defines whether this option is deprecated. The default value for deprecated is
+         * <code>false</code>. This can be used to evolve options between releases.
+         *
+         * @since 1.0
+         */
+        public Builder deprecated(@SuppressWarnings("hiding") boolean deprecated) {
+            this.deprecated = deprecated;
+            return this;
+        }
+
+        /**
+         * Specifies a human-readable description on how to use the option.
+         *
+         * @since 1.0
+         */
+        public Builder help(@SuppressWarnings("hiding") String help) {
+            this.help = help;
+            return this;
+        }
+
+        /**
+         * Builds and returns a new option descriptor.
+         *
+         * @since 1.0
+         */
+        public OptionDescriptor build() {
+            return new OptionDescriptor(key, name, help, category, deprecated);
+        }
+
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,140 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.options;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * An interface to a set of {@link OptionDescriptor}s.
+ *
+ * @since 1.0
+ */
+public interface OptionDescriptors extends Iterable<OptionDescriptor> {
+
+    /**
+     * An empty set of option descriptors.
+     *
+     * @since 1.0
+     */
+    OptionDescriptors EMPTY = new OptionDescriptors() {
+
+        public Iterator<OptionDescriptor> iterator() {
+            return Collections.<OptionDescriptor> emptyList().iterator();
+        }
+
+        public OptionDescriptor get(String key) {
+            return null;
+        }
+    };
+
+    /**
+     * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
+     * descriptor set doesn't contain a matching option name.
+     *
+     * @since 1.0
+     */
+    OptionDescriptor get(String optionName);
+
+    /**
+     * Create a union options descriptor out of multiple given descriptors. The operation
+     * descriptors are not checked for duplicate keys. The option descriptors are iterated in
+     * declaration order.
+     *
+     * @since 1.0
+     */
+    static OptionDescriptors createUnion(OptionDescriptors... descriptors) {
+        if (descriptors.length == 0) {
+            return EMPTY;
+        } else if (descriptors.length == 1) {
+            return descriptors[0];
+        } else {
+            return new UnionOptionDescriptors(descriptors);
+        }
+    }
+}
+
+final class UnionOptionDescriptors implements OptionDescriptors {
+
+    final OptionDescriptors[] descriptorsList;
+
+    UnionOptionDescriptors(OptionDescriptors[] descriptors) {
+        // defensive copy
+        this.descriptorsList = Arrays.copyOf(descriptors, descriptors.length);
+    }
+
+    public Iterator<OptionDescriptor> iterator() {
+        return new Iterator<OptionDescriptor>() {
+
+            Iterator<OptionDescriptor> descriptors = descriptorsList[0].iterator();
+            int descriptorsIndex = 0;
+            OptionDescriptor next = null;
+
+            public boolean hasNext() {
+                return fetchNext() != null;
+            }
+
+            private OptionDescriptor fetchNext() {
+                if (next != null) {
+                    return next;
+                }
+                if (descriptors.hasNext()) {
+                    next = descriptors.next();
+                    return next;
+                } else if (descriptorsIndex < descriptorsList.length - 1) {
+                    descriptorsIndex++;
+                    descriptors = descriptorsList[descriptorsIndex].iterator();
+                    return fetchNext();
+                } else {
+                    return null;
+                }
+            }
+
+            public OptionDescriptor next() {
+                OptionDescriptor fetchedNext = fetchNext();
+                if (fetchedNext != null) {
+                    // consume next
+                    this.next = null;
+                    return fetchedNext;
+                } else {
+                    throw new NoSuchElementException();
+                }
+            }
+        };
+    }
+
+    public OptionDescriptor get(String value) {
+        for (OptionDescriptors descriptors : descriptorsList) {
+            OptionDescriptor descriptor = descriptors.get(value);
+            if (descriptor != null) {
+                return descriptor;
+            }
+        }
+        return null;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,95 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.options;
+
+import java.util.Objects;
+
+/**
+ * Represents the option key for a option specification.
+ *
+ * @since 1.0
+ */
+public final class OptionKey<T> {
+
+    private final OptionType<T> type;
+    private final T defaultValue;
+
+    /**
+     * Constructs a new option key given a default value. Throws {@link IllegalArgumentException} if
+     * no default {@link OptionType} could be {@link OptionType#defaultType(Object) resolved} for
+     * the given type. The default value must not be <code>null</code>.
+     *
+     * @since 1.0
+     */
+    public OptionKey(T defaultValue) {
+        Objects.requireNonNull(defaultValue);
+        this.defaultValue = defaultValue;
+        this.type = OptionType.defaultType(defaultValue);
+        if (type == null) {
+            throw new IllegalArgumentException("No default type specified for type " + defaultValue.getClass().getName() + ". Specify the option type explicitely to resolve this.");
+        }
+    }
+
+    /**
+     * Contructs a new option key givena default value and option key. The default value and the
+     * type must not be <code>null</code>.
+     *
+     * @since 1.0
+     */
+    public OptionKey(T defaultValue, OptionType<T> type) {
+        Objects.requireNonNull(defaultValue);
+        Objects.requireNonNull(type);
+        this.defaultValue = defaultValue;
+        this.type = type;
+    }
+
+    /**
+     * Returns the option type of this key.
+     *
+     * @since 1.0
+     */
+    public OptionType<T> getType() {
+        return type;
+    }
+
+    /**
+     * Returns the default value for this option.
+     *
+     * @since 1.0
+     */
+    public T getDefaultValue() {
+        return defaultValue;
+    }
+
+    /**
+     * Returns the value of this key given the {@link OptionValues values}.
+     *
+     * @since 1.0
+     */
+    public T getValue(OptionValues values) {
+        return values.get(this);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,211 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.options;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Consumer;
+import java.util.function.Function;
+
+/**
+ * Represents a type of an option that allows to convert string values to a java value.
+ *
+ * @since 1.0
+ */
+public final class OptionType<T> {
+
+    private final String name;
+    private final Function<String, T> stringConverter;
+    private final Consumer<T> validator;
+    private final T defaultValue;
+
+    /**
+     * Constructs a new option type with name, defaultValue and function that allows to convert a
+     * string to the option type.
+     *
+     * @param name the name of the type to identify it
+     * @param defaultValue the default value to use if no value is given
+     * @param stringConverter a function that converts a string value to the actual option value.
+     *            Can throw {@link IllegalArgumentException} to indicate an invalid string.
+     * @param validator used for validating the option value. Throws
+     *            {@link IllegalArgumentException} if the value is invalid.
+     *
+     * @since 1.0
+     */
+    public OptionType(String name, T defaultValue, Function<String, T> stringConverter, Consumer<T> validator) {
+        Objects.requireNonNull(name);
+        Objects.requireNonNull(defaultValue);
+        Objects.requireNonNull(stringConverter);
+        Objects.requireNonNull(validator);
+        this.name = name;
+        this.stringConverter = stringConverter;
+        this.defaultValue = defaultValue;
+        this.validator = validator;
+    }
+
+    /**
+     * Constructs a new option type with name, defaultValue and function that allows to convert a
+     * string to the option type.
+     *
+     * @param name the name of the type to identify it
+     * @param defaultValue the default value to use if no value is given
+     * @param stringConverter a function that converts a string value to the actual option value.
+     *            Can throw {@link IllegalArgumentException} to indicate an invalid string.
+     *
+     * @since 1.0
+     */
+    public OptionType(String name, T defaultValue, Function<String, T> stringConverter) {
+        this(name, defaultValue, stringConverter, new Consumer<T>() {
+            public void accept(T t) {
+            }
+        });
+    }
+
+    /**
+     * Returns the default value of this type, to be used if no value is available.
+     *
+     * @since 1.0
+     */
+    public T getDefaultValue() {
+        return defaultValue;
+    }
+
+    /**
+     * Returns the name of this type.
+     *
+     * @since 1.0
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Converts a string value, validates it and converts it to an object of this type.
+     *
+     * @throws IllegalArgumentException if the value is invalid or cannot be converted.
+     * @since 1.0
+     */
+    public T convert(String value) {
+        T v = stringConverter.apply(value);
+        validate(v);
+        return v;
+    }
+
+    /**
+     * Validates an option value and throws an {@link IllegalArgumentException} if it is invalid.
+     *
+     * @throws IllegalArgumentException if the value is invalid or cannot be converted.
+     * @since 1.0
+     */
+    public void validate(T value) {
+        validator.accept(value);
+    }
+
+    /**
+     * @since 1.0
+     */
+    @Override
+    public String toString() {
+        return "OptionType[name=" + name + ", defaultValue=" + defaultValue + "]";
+    }
+
+    private static Map<Class<?>, OptionType<?>> DEFAULTTYPES = new HashMap<>();
+    static {
+        DEFAULTTYPES.put(Boolean.class, new OptionType<>("Boolean", false, new Function<String, Boolean>() {
+            public Boolean apply(String t) {
+                if ("true".equals(t)) {
+                    return Boolean.TRUE;
+                } else if ("false".equals(t)) {
+                    return Boolean.FALSE;
+                } else {
+                    throw new IllegalArgumentException(String.format("Invalid boolean option value '%s'. The value of the option must be '%s' or '%s'.", t, "true", "false"));
+                }
+            }
+        }));
+        DEFAULTTYPES.put(Byte.class, new OptionType<>("Byte", (byte) 0, new Function<String, Byte>() {
+            public Byte apply(String t) {
+                try {
+                    return Byte.parseByte(t);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException(e.getMessage(), e);
+                }
+            }
+        }));
+        DEFAULTTYPES.put(Integer.class, new OptionType<>("Integer", 0, new Function<String, Integer>() {
+            public Integer apply(String t) {
+                try {
+                    return Integer.parseInt(t);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException(e.getMessage(), e);
+                }
+            }
+        }));
+        DEFAULTTYPES.put(Long.class, new OptionType<>("Long", 0L, new Function<String, Long>() {
+            public Long apply(String t) {
+                try {
+                    return Long.parseLong(t);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException(e.getMessage(), e);
+                }
+            }
+        }));
+        DEFAULTTYPES.put(Float.class, new OptionType<>("Float", 0.0f, new Function<String, Float>() {
+            public Float apply(String t) {
+                try {
+                    return Float.parseFloat(t);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException(e.getMessage(), e);
+                }
+            }
+        }));
+        DEFAULTTYPES.put(Double.class, new OptionType<>("Double", 0.0d, new Function<String, Double>() {
+            public Double apply(String t) {
+                try {
+                    return Double.parseDouble(t);
+                } catch (NumberFormatException e) {
+                    throw new IllegalArgumentException(e.getMessage(), e);
+                }
+            }
+        }));
+        DEFAULTTYPES.put(String.class, new OptionType<>("String", "0", new Function<String, String>() {
+            public String apply(String t) {
+                return t;
+            }
+        }));
+    }
+
+    /**
+     * Returns the default option type for a given value. Returns <code>null</code> if no default
+     * option type is available for this java type.
+     *
+     * @since 1.0
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> OptionType<T> defaultType(Object value) {
+        return (OptionType<T>) DEFAULTTYPES.get(value.getClass());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,55 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.options;
+
+/**
+ * Represents a set of option values based on an {@link OptionDescriptor}.
+ *
+ * @since 1.0
+ */
+public interface OptionValues {
+
+    /**
+     * Returns all available options.
+     *
+     * @since 1.0
+     */
+    OptionDescriptors getDescriptors();
+
+    /**
+     * Sets the value of {@code optionKey} to {@code value}.
+     *
+     * @since 1.0
+     */
+    <T> void set(OptionKey<T> optionKey, T value);
+
+    /**
+     * Returns the value of a given option. Returns <code>null</code> if the option does not exist.
+     *
+     * @since 1.0
+     */
+    <T> T get(OptionKey<T> optionKey);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/package-info.java	Tue Jun 13 09:19:35 2017 -0700
@@ -0,0 +1,33 @@
+/*
+ * 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+/**
+ * The Graal-SDK options package contains reusable collection classes for options.
+ *
+ * @see org.graalvm.options.OptionDescriptor
+ * @see org.graalvm.options.OptionValues
+ *
+ * @since 1.0
+ */
+package org.graalvm.options;
\ No newline at end of file