8184768: Update Graal
authoriveresov
Mon, 17 Jul 2017 16:31:51 -0700
changeset 46680 2894e4262fd6
parent 46679 05c19c4575cc
child 46681 f17cefd211b4
8184768: Update Graal Reviewed-by: kvn
hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/UniquePathUtilities.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.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/HotSpotGraalRuntime.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.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.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.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/asm/CompilationResultBuilder.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/VerifyingMoveFactory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.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/GraalDebugHandlersFactory.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.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.word/src/org/graalvm/word/AtomicUnsigned.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/AtomicWord.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Pointer.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerUtils.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Signed.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/SignedWord.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Unsigned.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedUtils.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedWord.java
hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java
--- a/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Mon Jul 17 16:31:51 2017 -0700
@@ -100,16 +100,15 @@
         final long threadId = Thread.currentThread().getId();
 
         final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed();
-        final boolean printAfterCompilation = GraalCompilerOptions.PrintAfterCompilation.getValue(graalOptions) && !TTY.isSuppressed();
         if (printCompilation) {
             TTY.println(getMethodDescription() + "...");
         }
 
         final long start;
         final long allocatedBytesBefore;
-        if (printAfterCompilation || printCompilation) {
+        if (printCompilation) {
             start = System.currentTimeMillis();
-            allocatedBytesBefore = printAfterCompilation || printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
+            allocatedBytesBefore = printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
         } else {
             start = 0L;
             allocatedBytesBefore = 0L;
@@ -123,7 +122,7 @@
         }
         final long endTime = System.currentTimeMillis();
 
-        if (printAfterCompilation || printCompilation) {
+        if (printCompilation) {
             final long stop = System.currentTimeMillis();
             final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1;
             final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.api.directives.test/src/org/graalvm/compiler/api/directives/test/DeoptimizeDirectiveTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -91,4 +91,31 @@
         boolean valid = testDeoptimizeCheckValid(method);
         Assert.assertTrue("code should still be valid", valid);
     }
+
+    public static int zeroBranchProbabilitySnippet(boolean flag) {
+        if (GraalDirectives.injectBranchProbability(0, flag)) {
+            GraalDirectives.controlFlowAnchor(); // prevent removal of the if
+            return 1;
+        } else {
+            GraalDirectives.controlFlowAnchor(); // prevent removal of the if
+            return 2;
+        }
+    }
+
+    @Test
+    public void testZeroBranchProbability() {
+        ResolvedJavaMethod method = getResolvedJavaMethod("zeroBranchProbabilitySnippet");
+        Result expected = executeExpected(method, null, true);
+
+        InstalledCode code = getCode(method);
+        Result actual;
+        try {
+            actual = new Result(code.executeVarargs(true), null);
+        } catch (Exception e) {
+            actual = new Result(null, e);
+        }
+
+        assertEquals(expected, actual);
+        assertFalse("code should be invalidated", code.isValid());
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64MoveFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -86,6 +86,11 @@
     }
 
     @Override
+    public LIRInstruction createStackLoad(AllocatableValue result, Constant input) {
+        return createLoad(result, input);
+    }
+
+    @Override
     public boolean canInlineConstant(Constant con) {
         if (con instanceof JavaConstant) {
             JavaConstant c = (JavaConstant) con;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -23,16 +23,18 @@
 
 package org.graalvm.compiler.core.amd64;
 
+import static jdk.vm.ci.code.ValueUtil.isRegister;
 import static org.graalvm.compiler.lir.LIRValueUtil.asConstant;
 import static org.graalvm.compiler.lir.LIRValueUtil.isConstantValue;
 import static org.graalvm.compiler.lir.LIRValueUtil.isStackSlotValue;
-import static jdk.vm.ci.code.ValueUtil.isRegister;
 
 import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.core.common.type.DataPointerConstant;
 import org.graalvm.compiler.debug.GraalError;
+import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.amd64.AMD64AddressValue;
 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
+import org.graalvm.compiler.lir.amd64.AMD64Move;
 import org.graalvm.compiler.lir.amd64.AMD64Move.AMD64StackMove;
 import org.graalvm.compiler.lir.amd64.AMD64Move.LeaDataOp;
 import org.graalvm.compiler.lir.amd64.AMD64Move.LeaOp;
@@ -70,6 +72,17 @@
     }
 
     @Override
+    public boolean allowConstantToStackMove(Constant constant) {
+        if (constant instanceof DataPointerConstant) {
+            return false;
+        }
+        if (constant instanceof JavaConstant && !AMD64Move.canMoveConst2Stack(((JavaConstant) constant))) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
     public AMD64LIRInstruction createMove(AllocatableValue dst, Value src) {
         if (src instanceof AMD64AddressValue) {
             return new LeaOp(dst, (AMD64AddressValue) src);
@@ -97,4 +110,13 @@
             throw GraalError.shouldNotReachHere(String.format("unsupported constant: %s", src));
         }
     }
+
+    @Override
+    public LIRInstruction createStackLoad(AllocatableValue result, Constant input) {
+        if (input instanceof JavaConstant) {
+            return new MoveFromConstOp(result, (JavaConstant) input);
+        } else {
+            throw GraalError.shouldNotReachHere(String.format("unsupported constant for stack load: %s", input));
+        }
+    }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/RetryableBailoutException.java	Mon Jul 17 16:31:51 2017 -0700
@@ -36,8 +36,8 @@
         super(false, reason);
     }
 
-    public RetryableBailoutException(Throwable cause, String format) {
-        super(cause, format);
+    public RetryableBailoutException(Throwable cause, String format, Object... args) {
+        super(cause, format, args);
     }
 
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.sparc/src/org/graalvm/compiler/core/sparc/SPARCMoveFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -91,6 +91,14 @@
     }
 
     @Override
+    public LIRInstruction createStackLoad(AllocatableValue result, Constant input) {
+        if (input instanceof DataPointerConstant) {
+            throw GraalError.shouldNotReachHere("unsupported constant for stack load: " + input);
+        }
+        return createLoad(result, input);
+    }
+
+    @Override
     public boolean canInlineConstant(Constant con) {
         if (con instanceof JavaConstant) {
             JavaConstant c = (JavaConstant) con;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Mon Jul 17 16:31:51 2017 -0700
@@ -183,6 +183,13 @@
                         String name = zipEntry.getName();
                         if (name.endsWith(".class")) {
                             String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
+                            if (isInNativeImage(className)) {
+                                /*
+                                 * Native Image is an external tool and does not need to follow the
+                                 * Graal invariants.
+                                 */
+                                continue;
+                            }
                             classNames.add(className);
                         }
                     }
@@ -293,6 +300,10 @@
         }
     }
 
+    private static boolean isInNativeImage(String className) {
+        return className.startsWith("org.graalvm.nativeimage");
+    }
+
     private static List<Class<?>> initializeClasses(InvariantsTool tool, List<String> classNames) {
         List<Class<?>> classes = new ArrayList<>(classNames.size());
         for (String className : classNames) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraalCompilerTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.core.test;
 
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
+import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
@@ -51,15 +51,16 @@
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.api.test.Graal;
 import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.CompilationPrinter;
 import org.graalvm.compiler.core.GraalCompiler;
 import org.graalvm.compiler.core.GraalCompiler.Request;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.target.Backend;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugDumpHandler;
 import org.graalvm.compiler.debug.DebugDumpScope;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.graph.Node;
@@ -941,16 +942,9 @@
             StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph;
             DebugContext debug = graphToCompile.getDebug();
             try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
-                final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed();
-                if (printCompilation) {
-                    TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s ...", id, installedCodeOwner.getDeclaringClass().getName(), installedCodeOwner.getName(),
-                                    installedCodeOwner.getSignature()));
-                }
-                long start = System.currentTimeMillis();
+                CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
                 CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(), id, options);
-                if (printCompilation) {
-                    TTY.println(String.format("@%-6s Graal %-70s %-45s %-50s | %4dms %5dB", id, "", "", "", System.currentTimeMillis() - start, compResult.getTargetCodeSize()));
-                }
+                printer.finish(compResult);
 
                 try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult);
                                 DebugContext.Activation a = debug.activate()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.test;
+
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.DebugOptions;
+import org.graalvm.compiler.debug.DebugContext.Scope;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.util.EconomicMap;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GraphResetDebugTest extends GraalCompilerTest {
+
+    public static void testSnippet() {
+    }
+
+    @SuppressWarnings("try")
+    @Test
+    public void test1() {
+        EconomicMap<OptionKey<?>, Object> map = EconomicMap.create();
+        // Configure with an option that enables scopes
+        map.put(DebugOptions.DumpOnError, true);
+        DebugContext debug = getDebugContext(new OptionValues(map));
+        StructuredGraph graph = parseEager("testSnippet", AllowAssumptions.YES, debug);
+        boolean resetSucceeded = false;
+        try (Scope scope = debug.scope("some scope")) {
+            graph.resetDebug(DebugContext.DISABLED);
+            resetSucceeded = true;
+        } catch (AssertionError expected) {
+        }
+        Assert.assertFalse(resetSucceeded);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core;
+
+import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
+
+import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.debug.Management;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.options.OptionValues;
+
+import jdk.vm.ci.meta.JavaMethod;
+import jdk.vm.ci.runtime.JVMCICompiler;
+
+/**
+ * Utility for printing an informational line to {@link TTY} upon completion of compiling a method.
+ */
+public final class CompilationPrinter {
+
+    private final CompilationIdentifier id;
+    private final JavaMethod method;
+    private final int entryBCI;
+    private final long start;
+    private final long allocatedBytesBefore;
+
+    /**
+     * Gets an object that will report statistics for a compilation if
+     * {@link GraalCompilerOptions#PrintCompilation} is enabled and {@link TTY} is not suppressed.
+     * This method should be called just before a compilation starts as it captures pre-compilation
+     * data for the purpose of {@linkplain #finish(CompilationResult) printing} the post-compilation
+     * statistics.
+     *
+     * @param options used to get the value of {@link GraalCompilerOptions#PrintCompilation}
+     * @param id the identifier for the compilation
+     * @param method the method for which code is being compiled
+     * @param entryBCI the BCI at which compilation starts
+     */
+    public static CompilationPrinter begin(OptionValues options, CompilationIdentifier id, JavaMethod method, int entryBCI) {
+        if (PrintCompilation.getValue(options) && !TTY.isSuppressed()) {
+            return new CompilationPrinter(id, method, entryBCI);
+        }
+        return DISABLED;
+    }
+
+    private static final CompilationPrinter DISABLED = new CompilationPrinter();
+
+    private CompilationPrinter() {
+        this.method = null;
+        this.id = null;
+        this.entryBCI = -1;
+        this.start = -1;
+        this.allocatedBytesBefore = -1;
+    }
+
+    private CompilationPrinter(CompilationIdentifier id, JavaMethod method, int entryBCI) {
+        this.method = method;
+        this.id = id;
+        this.entryBCI = entryBCI;
+
+        final long threadId = Thread.currentThread().getId();
+        start = System.nanoTime();
+        allocatedBytesBefore = getAllocatedBytes(threadId);
+    }
+
+    private String getMethodDescription() {
+        return String.format("%-30s %-70s %-45s %-50s %s", id.toString(CompilationIdentifier.Verbosity.ID),
+                        method.getDeclaringClass().getName(), method.getName(),
+                        method.getSignature().toMethodDescriptor(),
+                        entryBCI == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + entryBCI + ") ");
+    }
+
+    /**
+     * Notifies this object that the compilation finished and the informational line should be
+     * printed to {@link TTY}.
+     */
+    public void finish(CompilationResult result) {
+        if (id != null) {
+            final long threadId = Thread.currentThread().getId();
+            final long stop = System.nanoTime();
+            final long duration = (stop - start) / 1000000;
+            final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
+            final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
+            final long allocatedBytesAfter = getAllocatedBytes(threadId);
+            final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
+
+            TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
+        }
+    }
+
+    static com.sun.management.ThreadMXBean threadMXBean;
+
+    static long getAllocatedBytes(long threadId) {
+        if (threadMXBean == null) {
+            threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
+        }
+        return threadMXBean.getThreadAllocatedBytes(threadId);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core;
+
+import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
+import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
+import static org.graalvm.compiler.debug.DebugOptions.Dump;
+import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
+import static org.graalvm.compiler.debug.DebugOptions.MethodFilter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
+import org.graalvm.compiler.debug.PathUtilities;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.options.EnumOptionKey;
+import org.graalvm.compiler.options.OptionValues;
+
+import jdk.vm.ci.code.BailoutException;
+
+/**
+ * Wrapper for a compilation that centralizes what action to take based on
+ * {@link GraalCompilerOptions#CompilationBailoutAction} and
+ * {@link GraalCompilerOptions#CompilationFailureAction} when an uncaught exception occurs during
+ * compilation.
+ */
+public abstract class CompilationWrapper<T> {
+
+    /**
+     * Actions to take upon an exception being raised during compilation performed via
+     * {@link CompilationWrapper}. The actions are with respect to what the user sees on the
+     * console. The compilation requester determines what ultimate action is taken in
+     * {@link CompilationWrapper#handleException(Throwable)}.
+     */
+    public enum ExceptionAction {
+        /**
+         * Print nothing to the console.
+         */
+        Silent,
+        /**
+         * Print a stack trace to the console.
+         */
+        Print,
+        /**
+         * An exception causes the compilation to be retried with extra diagnostics enabled.
+         */
+        Diagnose,
+        /**
+         * Same as {@link #Diagnose} except that the VM process is exited after retrying.
+         */
+        ExitVM;
+
+        static ValueHelp HELP = new ValueHelp();
+
+        static class ValueHelp implements EnumOptionKey.ValueHelp<ExceptionAction> {
+            @Override
+            public String getHelp(Object value) {
+                ExceptionAction action = (ExceptionAction) value;
+                switch (action) {
+                    case Silent:
+                        return action + ": Print nothing to the console.";
+                    case Print:
+                        return action + ": Print a stack trace to the console.";
+                    case Diagnose:
+                        return action + ": Retry the compilation with extra diagnostics.";
+                    case ExitVM:
+                        return action + ": Same as " + Diagnose + " except that the VM process exits after retrying.";
+                }
+                return null;
+            }
+        }
+    }
+
+    private final DiagnosticsOutputDirectory outputDirectory;
+
+    /**
+     * @param outputDirectory object used to access a directory for dumping if the compilation is
+     *            re-executed
+     */
+    public CompilationWrapper(DiagnosticsOutputDirectory outputDirectory) {
+        this.outputDirectory = outputDirectory;
+    }
+
+    /**
+     * Handles an uncaught exception.
+     *
+     * @param t an exception thrown during {@link #run(DebugContext)}
+     * @return a value representing the result of a failed compilation (may be {@code null})
+     */
+    protected abstract T handleException(Throwable t);
+
+    /**
+     * Gets the action to take based on the value of {@code actionKey} in {@code options}.
+     *
+     * Subclasses can override this to choose a different action based on factors such as whether
+     * {@code actionKey} has been explicitly set in {@code options} for example.
+     */
+    protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey) {
+        if (actionKey == CompilationFailureAction) {
+            if (ExitVMOnException.getValue(options)) {
+                assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
+                assert ExitVMOnException.getDefaultValue() != true;
+                if (CompilationFailureAction.hasBeenSet(options) && CompilationFailureAction.getValue(options) != ExceptionAction.ExitVM) {
+                    TTY.printf("WARNING: Ignoring %s=%s since %s=true has been explicitly specified.%n",
+                                    CompilationFailureAction.getName(), CompilationFailureAction.getValue(options),
+                                    ExitVMOnException.getName());
+                }
+                return ExceptionAction.ExitVM;
+            }
+        }
+        return actionKey.getValue(options);
+    }
+
+    /**
+     * Perform the compilation wrapped by this object.
+     *
+     * @param debug the debug context to use for the compilation
+     */
+    protected abstract T performCompilation(DebugContext debug);
+
+    /**
+     * Gets a value that represents the input to the compilation.
+     */
+    @Override
+    public abstract String toString();
+
+    /**
+     * Creates the {@link DebugContext} to use when retrying a compilation.
+     *
+     * @param options the options for configuring the debug context
+     */
+    protected abstract DebugContext createRetryDebugContext(OptionValues options);
+
+    @SuppressWarnings("try")
+    public final T run(DebugContext initialDebug) {
+        try {
+            return performCompilation(initialDebug);
+        } catch (Throwable cause) {
+            OptionValues initialOptions = initialDebug.getOptions();
+
+            String causeType = "failure";
+            EnumOptionKey<ExceptionAction> actionKey;
+            if (cause instanceof BailoutException) {
+                actionKey = CompilationBailoutAction;
+                causeType = "bailout";
+            } else {
+                actionKey = CompilationFailureAction;
+                causeType = "failure";
+            }
+            ExceptionAction action = lookupAction(initialOptions, actionKey);
+
+            if (action == ExceptionAction.Silent) {
+                return handleException(cause);
+            }
+            if (action == ExceptionAction.Print) {
+                ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                try (PrintStream ps = new PrintStream(baos)) {
+                    ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
+                    cause.printStackTrace(ps);
+                    ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                    causeType,
+                                    actionKey.getName(), ExceptionAction.Silent,
+                                    actionKey.getName(), ExceptionAction.Silent);
+                    ps.printf("To capture more information for diagnosing or reporting a compilation %s, " +
+                                    "set %s to %s or %s (e.g., -Dgraal.%s=%s).%n",
+                                    causeType,
+                                    actionKey.getName(), ExceptionAction.Diagnose,
+                                    ExceptionAction.ExitVM,
+                                    actionKey.getName(), ExceptionAction.Diagnose);
+                }
+                synchronized (CompilationFailureAction) {
+                    // Synchronize to prevent compilation exception
+                    // messages from interleaving.
+                    TTY.println(baos.toString());
+                }
+                return handleException(cause);
+            }
+
+            // action is Diagnose or ExitVM
+
+            if (Dump.hasBeenSet(initialOptions)) {
+                // If dumping is explicitly enabled, Graal is being debugged
+                // so don't interfere with what the user is expecting to see.
+                return handleException(cause);
+            }
+
+            String dir = this.outputDirectory.getPath();
+            if (dir == null) {
+                return null;
+            }
+            String dumpName = PathUtilities.sanitizeFileName(toString());
+            File dumpPath = new File(dir, dumpName);
+            dumpPath.mkdirs();
+            if (!dumpPath.exists()) {
+                TTY.println("Warning: could not create diagnostics directory " + dumpPath);
+                return handleException(cause);
+            }
+
+            String message;
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            try (PrintStream ps = new PrintStream(baos)) {
+                ps.printf("%s: Compilation of %s failed: ", Thread.currentThread(), this);
+                cause.printStackTrace(ps);
+                ps.printf("To disable compilation %s notifications, set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                causeType,
+                                actionKey.getName(), ExceptionAction.Silent,
+                                actionKey.getName(), ExceptionAction.Silent);
+                ps.printf("To print a message for a compilation %s without retrying the compilation, " +
+                                "set %s to %s (e.g., -Dgraal.%s=%s).%n",
+                                causeType,
+                                actionKey.getName(), ExceptionAction.Print,
+                                actionKey.getName(), ExceptionAction.Print);
+                ps.println("Retrying compilation of " + this);
+                message = baos.toString();
+            }
+
+            synchronized (CompilationFailureAction) {
+                // Synchronize here to serialize retry compilations. This
+                // mitigates retry compilation storms.
+                TTY.println(message);
+                File retryLogFile = new File(dumpPath, "retry.log");
+                try (PrintStream ps = new PrintStream(new FileOutputStream(retryLogFile))) {
+                    ps.print(message);
+                } catch (IOException ioe) {
+                    TTY.printf("Error writing to %s: %s%n", retryLogFile, ioe);
+                }
+
+                OptionValues retryOptions = new OptionValues(initialOptions,
+                                Dump, ":" + VERBOSE_LEVEL,
+                                MethodFilter, null,
+                                DumpPath, dumpPath.getPath());
+
+                try (DebugContext retryDebug = createRetryDebugContext(retryOptions)) {
+                    return performCompilation(retryDebug);
+                } catch (Throwable ignore) {
+                    // Failures during retry are silent
+                    return handleException(cause);
+                } finally {
+                    if (action == ExitVM) {
+                        synchronized (ExceptionAction.class) {
+                            TTY.println("Exiting VM after retry compilation of " + this);
+                            System.exit(-1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Mon Jul 17 16:31:51 2017 -0700
@@ -22,6 +22,8 @@
  */
 package org.graalvm.compiler.core;
 
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
+import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
@@ -32,22 +34,16 @@
 public class GraalCompilerOptions {
 
     // @formatter:off
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionKey<String> PrintFilter = new OptionKey<>(null);
-    @Option(help = "", type = OptionType.Debug)
+    @Option(help = "Print an informational line to the console for each completed compilation.", type = OptionType.Debug)
     public static final OptionKey<Boolean> PrintCompilation = new OptionKey<>(false);
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionKey<Boolean> PrintAfterCompilation = new OptionKey<>(false);
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionKey<Boolean> PrintBailout = new OptionKey<>(false);
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionKey<Boolean> ExitVMOnBailout = new OptionKey<>(false);
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
-    @Option(help = "", type = OptionType.Debug)
-    public static final OptionKey<Boolean> PrintStackTraceOnException = new OptionKey<>(false);
     @Option(help = "Pattern (see MethodFilter for format) for method that will trigger an exception when compiled. " +
                    "This option exists to test handling compilation crashes gracefully.", type = OptionType.Debug)
     public static final OptionKey<String> CrashAt = new OptionKey<>(null);
+    @Option(help = "Specifies the action to take when compilation fails with a non-bailout exception.", type = OptionType.User)
+    public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose, ExceptionAction.HELP);
+    @Option(help = "Specifies the action to take when compilation fails with a bailout exception.", type = OptionType.User)
+    public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent, ExceptionAction.HELP);
+    @Option(help = "Alias for CompilationFailureAction=ExitVM.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> ExitVMOnException = new OptionKey<>(false);
     // @formatter:on
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Mon Jul 17 16:31:51 2017 -0700
@@ -712,6 +712,20 @@
         }
     }
 
+    /**
+     * Determines if scopes are enabled and this context is in a non-top-level scope.
+     */
+    public boolean inNestedScope() {
+        if (immutable.scopesEnabled) {
+            if (currentScope == null) {
+                // In an active DisabledScope
+                return true;
+            }
+            return !currentScope.isTopLevel();
+        }
+        return immutable.scopesEnabled && currentScope == null;
+    }
+
     class DisabledScope implements DebugContext.Scope {
         final boolean savedMetricsEnabled;
         final ScopeImpl savedScope;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Mon Jul 17 16:31:51 2017 -0700
@@ -180,7 +180,7 @@
     /**
      * Gets the directory in which {@link DebugDumpHandler}s can generate output. This will be the
      * directory specified by {@link #DumpPath} if it has been set otherwise it will be derived from
-     * the default value of {@link #DumpPath} and {@link UniquePathUtilities#getGlobalTimeStamp()}.
+     * the default value of {@link #DumpPath} and {@link PathUtilities#getGlobalTimeStamp()}.
      *
      * This method will ensure the returned directory exists, printing a message to {@link TTY} if
      * it creates it.
@@ -193,13 +193,14 @@
         if (DumpPath.hasBeenSet(options)) {
             dumpDir = Paths.get(DumpPath.getValue(options));
         } else {
-            dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(UniquePathUtilities.getGlobalTimeStamp()));
+            dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(PathUtilities.getGlobalTimeStamp()));
         }
+        dumpDir = dumpDir.toAbsolutePath();
         if (!Files.exists(dumpDir)) {
             synchronized (DebugConfigImpl.class) {
                 if (!Files.exists(dumpDir)) {
                     Files.createDirectories(dumpDir);
-                    TTY.println("Dumping debug output in %s", dumpDir.toAbsolutePath().toString());
+                    TTY.println("Dumping debug output in %s", dumpDir.toString());
                 }
             }
         }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugRetryableTask.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * 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.debug;
-
-/**
- * A mechanism for re-executing a task upon failure.
- */
-public abstract class DebugRetryableTask<T> {
-
-    /**
-     * Calls {@link #run} on this task and if it results in an exception, calls
-     * {@link #getRetryContext} and if that returns a non-null value,
-     * {@link #run(DebugContext, Throwable)} is called with it.
-     *
-     * @param initialDebug the debug context to be used for the initial execution
-     */
-    @SuppressWarnings("try")
-    public final T runWithRetry(DebugContext initialDebug) {
-        try {
-            return run(initialDebug, null);
-        } catch (Throwable t) {
-            DebugContext retryDebug = getRetryContext(initialDebug, t);
-            if (retryDebug != null) {
-                return run(retryDebug, t);
-            } else {
-                throw t;
-            }
-        }
-    }
-
-    /**
-     * Runs this body of this task.
-     *
-     * @param debug the debug context to use for the execution
-     * @param failure {@code null} if this is the first execution otherwise the cause of the first
-     *            execution to fail
-     */
-    protected abstract T run(DebugContext debug, Throwable failure);
-
-    /**
-     * Notifies this object that the initial execution failed with exception {@code t} and requests
-     * a debug context to be used for re-execution.
-     *
-     * @param initialDebug the debug context used for the initial execution
-     * @param t an exception that terminated the first execution of this task
-     * @return the debug context to be used for re-executing this task or {@code null} if {@code t}
-     *         should immediately be re-thrown without re-executing this task
-     */
-    protected DebugContext getRetryContext(DebugContext initialDebug, Throwable t) {
-        return null;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,191 @@
+/*
+ * 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.debug;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.zip.Deflater;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+import org.graalvm.compiler.options.OptionValues;
+
+/**
+ * Manages a directory into which diagnostics such crash reports and dumps should be written. The
+ * directory is archived and deleted when {@link #close()} is called.
+ */
+public class DiagnosticsOutputDirectory {
+
+    /**
+     * Use an illegal file name to denote that {@link #close()} has been called.
+     */
+    private static final String CLOSED = "\u0000";
+
+    public DiagnosticsOutputDirectory(OptionValues options) {
+        this.options = options;
+    }
+
+    private final OptionValues options;
+
+    private String path;
+
+    /**
+     * Gets the path to the output directory managed by this object, creating if it doesn't exist
+     * and has not been deleted.
+     *
+     * @returns the directory or {@code null} if the could not be created or has been deleted
+     */
+    public String getPath() {
+        return getPath(true);
+    }
+
+    /**
+     * Gets a unique identifier for this execution such as a process ID.
+     */
+    protected String getExecutionID() {
+        String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
+        try {
+            int index = runtimeName.indexOf('@');
+            if (index != -1) {
+                long pid = Long.parseLong(runtimeName.substring(0, index));
+                return Long.toString(pid);
+            }
+        } catch (NumberFormatException e) {
+        }
+        return runtimeName;
+    }
+
+    private synchronized String getPath(boolean createIfNull) {
+        if (path == null && createIfNull) {
+            path = createPath();
+            File dir = new File(path).getAbsoluteFile();
+            if (!dir.exists()) {
+                dir.mkdirs();
+                if (!dir.exists()) {
+                    TTY.println("Warning: could not create Graal diagnostic directory " + dir);
+                    return null;
+                }
+            }
+        }
+        return CLOSED.equals(path) ? null : path;
+    }
+
+    /**
+     * Gets the path of the directory to be created.
+     *
+     * Subclasses can override this to determine how the path name is created.
+     *
+     * @return the path to be created
+     */
+    protected String createPath() {
+        Path baseDir;
+        try {
+            baseDir = DebugOptions.getDumpDirectory(options);
+        } catch (IOException e) {
+            // Default to current directory if there was a problem creating the
+            // directory specified by the DumpPath option.
+            baseDir = Paths.get(".");
+        }
+        return baseDir.resolve("graal_diagnostics_" + getExecutionID()).toAbsolutePath().toString();
+    }
+
+    /**
+     * Archives and deletes this directory if it exists.
+     */
+    public void close() {
+        archiveAndDelete();
+    }
+
+    /**
+     * Archives and deletes the {@linkplain #getPath() output directory} if it exists.
+     */
+    private synchronized void archiveAndDelete() {
+        String outDir = getPath(false);
+        if (outDir != null) {
+            // Notify other threads calling getPath() that the directory is deleted.
+            // This attempts to mitigate other threads writing to the directory
+            // while it is being archived and deleted.
+            path = CLOSED;
+
+            Path dir = Paths.get(outDir);
+            if (dir.toFile().exists()) {
+                File zip = new File(outDir + ".zip").getAbsoluteFile();
+                List<Path> toDelete = new ArrayList<>();
+                try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
+                    zos.setLevel(Deflater.BEST_COMPRESSION);
+                    Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
+                        @Override
+                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                            if (attrs.isRegularFile()) {
+                                ZipEntry ze = new ZipEntry(file.toString());
+                                zos.putNextEntry(ze);
+                                zos.write(Files.readAllBytes(file));
+                                zos.closeEntry();
+                            }
+                            toDelete.add(file);
+                            return FileVisitResult.CONTINUE;
+                        }
+
+                        @Override
+                        public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException {
+                            toDelete.add(d);
+                            return FileVisitResult.CONTINUE;
+                        }
+                    });
+                    // Keep this in sync with the catch_files in common.hocon
+                    TTY.println("Graal diagnostic output saved in %s", zip);
+                } catch (IOException e) {
+                    TTY.printf("IO error archiving %s:%n%s. The directory will not be deleted and must be " +
+                                    "manually removed once the VM exits.%n", dir, e);
+                    toDelete.clear();
+                }
+                if (!toDelete.isEmpty()) {
+                    IOException lastDeletionError = null;
+                    for (Path p : toDelete) {
+                        try {
+                            Files.delete(p);
+                        } catch (IOException e) {
+                            lastDeletionError = e;
+                        }
+                    }
+                    if (lastDeletionError != null) {
+                        TTY.printf("IO error deleting %s:%n%s. This is most likely due to a compilation on " +
+                                        "another thread holding a handle to a file within this directory. " +
+                                        "Please delete the directory manually once the VM exits.%n", dir, lastDeletionError);
+                    }
+                }
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,165 @@
+/*
+ * 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.debug;
+
+import java.io.IOException;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionValues;
+
+/**
+ * Miscellaneous methods for modifying and generating file system paths.
+ */
+public class PathUtilities {
+
+    private static final AtomicLong globalTimeStamp = new AtomicLong();
+    /**
+     * This generates a per thread persistent id to aid mapping related dump files with each other.
+     */
+    private static final ThreadLocal<PerThreadSequence> threadDumpId = new ThreadLocal<>();
+    private static final AtomicInteger dumpId = new AtomicInteger();
+
+    static class PerThreadSequence {
+        final int threadID;
+        HashMap<String, Integer> sequences = new HashMap<>(2);
+
+        PerThreadSequence(int threadID) {
+            this.threadID = threadID;
+        }
+
+        String generateID(String extension) {
+            Integer box = sequences.get(extension);
+            if (box == null) {
+                sequences.put(extension, 1);
+                return Integer.toString(threadID);
+            } else {
+                sequences.put(extension, box + 1);
+                return Integer.toString(threadID) + '-' + box;
+            }
+        }
+    }
+
+    private static String getThreadDumpId(String extension) {
+        PerThreadSequence id = threadDumpId.get();
+        if (id == null) {
+            id = new PerThreadSequence(dumpId.incrementAndGet());
+            threadDumpId.set(id);
+        }
+        return id.generateID(extension);
+    }
+
+    /**
+     * Prepends a period (i.e., {@code '.'}) to an non-null, non-empty string representation a file
+     * extension if the string does not already start with a period.
+     *
+     * @return {@code ext} unmodified if it is null, empty or already starts with a period other
+     *         {@code "." + ext}
+     */
+    public static String formatExtension(String ext) {
+        if (ext == null || ext.length() == 0) {
+            return "";
+        }
+        return "." + ext;
+    }
+
+    /**
+     * Gets a time stamp for the current process. This method will always return the same value for
+     * the current VM execution.
+     */
+    public static long getGlobalTimeStamp() {
+        if (globalTimeStamp.get() == 0) {
+            globalTimeStamp.compareAndSet(0, System.currentTimeMillis());
+        }
+        return globalTimeStamp.get();
+    }
+
+    /**
+     * Generates a {@link Path} using the format "%s-%d_%d%s" with the {@code baseNameOption}, a
+     * {@link #getGlobalTimeStamp() global timestamp} , {@link #getThreadDumpId a per thread unique
+     * id} and an optional {@code extension}.
+     *
+     * @return the output file path or null if the flag is null
+     */
+    public static Path getPath(OptionValues options, OptionKey<String> baseNameOption, String extension) throws IOException {
+        return getPath(options, baseNameOption, extension, true);
+    }
+
+    /**
+     * Generate a {@link Path} using the format "%s-%d_%s" with the {@code baseNameOption}, a
+     * {@link #getGlobalTimeStamp() global timestamp} and an optional {@code extension} .
+     *
+     * @return the output file path or null if the flag is null
+     */
+    public static Path getPathGlobal(OptionValues options, OptionKey<String> baseNameOption, String extension) throws IOException {
+        return getPath(options, baseNameOption, extension, false);
+    }
+
+    private static Path getPath(OptionValues options, OptionKey<String> baseNameOption, String extension, boolean includeThreadId) throws IOException {
+        if (baseNameOption.getValue(options) == null) {
+            return null;
+        }
+        String ext = formatExtension(extension);
+        final String name = includeThreadId
+                        ? String.format("%s-%d_%s%s", baseNameOption.getValue(options), getGlobalTimeStamp(), getThreadDumpId(ext), ext)
+                        : String.format("%s-%d%s", baseNameOption.getValue(options), getGlobalTimeStamp(), ext);
+        Path result = Paths.get(name);
+        if (result.isAbsolute()) {
+            return result;
+        }
+        Path dumpDir = DebugOptions.getDumpDirectory(options);
+        return dumpDir.resolve(name).normalize();
+    }
+
+    /**
+     * Gets a value based on {@code name} that can be passed to {@link Paths#get(String, String...)}
+     * without causing an {@link InvalidPathException}.
+     *
+     * @return {@code name} with all characters invalid for the current file system replaced by
+     *         {@code '_'}
+     */
+    public static String sanitizeFileName(String name) {
+        try {
+            Paths.get(name);
+            return name;
+        } catch (InvalidPathException e) {
+            // fall through
+        }
+        StringBuilder buf = new StringBuilder(name.length());
+        for (int i = 0; i < name.length(); i++) {
+            char c = name.charAt(i);
+            try {
+                Paths.get(String.valueOf(c));
+            } catch (InvalidPathException e) {
+                buf.append('_');
+            }
+            buf.append(c);
+        }
+        return buf.toString();
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/ScopeImpl.java	Mon Jul 17 16:31:51 2017 -0700
@@ -165,6 +165,10 @@
         owner.lastClosedScope = this;
     }
 
+    boolean isTopLevel() {
+        return parent == null;
+    }
+
     public boolean isDumpEnabled(int dumpLevel) {
         assert dumpLevel >= 0;
         return currentDumpLevel >= dumpLevel;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/UniquePathUtilities.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +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.debug;
-
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-
-import org.graalvm.compiler.options.OptionKey;
-import org.graalvm.compiler.options.OptionValues;
-
-public class UniquePathUtilities {
-
-    private static final AtomicLong globalTimeStamp = new AtomicLong();
-    /**
-     * This generates a per thread persistent id to aid mapping related dump files with each other.
-     */
-    private static final ThreadLocal<PerThreadSequence> threadDumpId = new ThreadLocal<>();
-    private static final AtomicInteger dumpId = new AtomicInteger();
-
-    static class PerThreadSequence {
-        final int threadID;
-        HashMap<String, Integer> sequences = new HashMap<>(2);
-
-        PerThreadSequence(int threadID) {
-            this.threadID = threadID;
-        }
-
-        String generateID(String extension) {
-            Integer box = sequences.get(extension);
-            if (box == null) {
-                sequences.put(extension, 1);
-                return Integer.toString(threadID);
-            } else {
-                sequences.put(extension, box + 1);
-                return Integer.toString(threadID) + '-' + box;
-            }
-        }
-    }
-
-    private static String getThreadDumpId(String extension) {
-        PerThreadSequence id = threadDumpId.get();
-        if (id == null) {
-            id = new PerThreadSequence(dumpId.incrementAndGet());
-            threadDumpId.set(id);
-        }
-        return id.generateID(extension);
-    }
-
-    public static String formatExtension(String ext) {
-        if (ext == null || ext.length() == 0) {
-            return "";
-        }
-        return "." + ext;
-    }
-
-    public static long getGlobalTimeStamp() {
-        if (globalTimeStamp.get() == 0) {
-            globalTimeStamp.compareAndSet(0, System.currentTimeMillis());
-        }
-        return globalTimeStamp.get();
-    }
-
-    /**
-     * Generates a {@link Path} using the format "%s-%d_%d%s" with the {@code baseNameOption}, a
-     * {@link #getGlobalTimeStamp() global timestamp} , {@link #getThreadDumpId a per thread unique
-     * id} and an optional {@code extension}.
-     *
-     * @return the output file path or null if the flag is null
-     */
-    public static Path getPath(OptionValues options, OptionKey<String> option, String extension) throws IOException {
-        return getPath(options, option, extension, true);
-    }
-
-    /**
-     * Generate a {@link Path} using the format "%s-%d_%s" with the {@code baseNameOption}, a
-     * {@link #getGlobalTimeStamp() global timestamp} and an optional {@code extension} .
-     *
-     * @return the output file path or null if the flag is null
-     */
-    public static Path getPathGlobal(OptionValues options, OptionKey<String> baseNameOption, String extension) throws IOException {
-        return getPath(options, baseNameOption, extension, false);
-    }
-
-    private static Path getPath(OptionValues options, OptionKey<String> baseNameOption, String extension, boolean includeThreadId) throws IOException {
-        if (baseNameOption.getValue(options) == null) {
-            return null;
-        }
-        String ext = formatExtension(extension);
-        final String name = includeThreadId
-                        ? String.format("%s-%d_%s%s", baseNameOption.getValue(options), getGlobalTimeStamp(), getThreadDumpId(ext), ext)
-                        : String.format("%s-%d%s", baseNameOption.getValue(options), getGlobalTimeStamp(), ext);
-        Path result = Paths.get(name);
-        if (result.isAbsolute()) {
-            return result;
-        }
-        Path dumpDir = DebugOptions.getDumpDirectory(options);
-        return dumpDir.resolve(name).normalize();
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java	Mon Jul 17 16:31:51 2017 -0700
@@ -150,7 +150,7 @@
     /**
      * The {@link DebugContext} used while compiling this graph.
      */
-    private final DebugContext debug;
+    private DebugContext debug;
 
     private class NodeSourcePositionScope implements DebugCloseable {
         private final NodeSourcePosition previous;
@@ -373,6 +373,21 @@
         return debug;
     }
 
+    /**
+     * Resets the {@link DebugContext} for this graph to a new value. This is useful when a graph is
+     * "handed over" from its creating thread to another thread.
+     *
+     * This must only be done when the current thread is no longer using the graph. This is in
+     * general impossible to test due to races and since metrics can be updated at any time. As
+     * such, this method only performs a weak sanity check that at least the current debug context
+     * does not have a nested scope open (the top level scope will always be open if scopes are
+     * enabled).
+     */
+    public void resetDebug(DebugContext newDebug) {
+        assert newDebug == debug || !debug.inNestedScope() : String.format("Cannot reset the debug context for %s while it has the nested scope \"%s\" open", this, debug.getCurrentScopeName());
+        this.debug = newDebug;
+    }
+
     @Override
     public String toString() {
         return name == null ? super.toString() : "Graph " + name;
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotMoveFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -23,6 +23,7 @@
 package org.graalvm.compiler.hotspot.amd64;
 
 import org.graalvm.compiler.core.amd64.AMD64MoveFactory;
+import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
 
 import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant;
@@ -57,7 +58,7 @@
         if (value instanceof HotSpotConstant) {
             return ((HotSpotConstant) value).isCompressed();
         }
-        return true;
+        return super.allowConstantToStackMove(value);
     }
 
     @Override
@@ -72,4 +73,19 @@
             return super.createLoad(dst, src);
         }
     }
+
+    @Override
+    public LIRInstruction createStackLoad(AllocatableValue dst, Constant src) {
+        if (HotSpotCompressedNullConstant.COMPRESSED_NULL.equals(src)) {
+            return super.createStackLoad(dst, JavaConstant.INT_0);
+        } else if (src instanceof HotSpotObjectConstant) {
+            assert ((HotSpotConstant) src).isCompressed();
+            return new AMD64HotSpotMove.HotSpotLoadObjectConstantOp(dst, (HotSpotObjectConstant) src);
+        } else if (src instanceof HotSpotMetaspaceConstant) {
+            assert ((HotSpotConstant) src).isCompressed();
+            return new AMD64HotSpotMove.HotSpotLoadMetaspaceConstantOp(dst, (HotSpotMetaspaceConstant) src);
+        } else {
+            return super.createStackLoad(dst, src);
+        }
+    }
 }
--- /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/CompilationWrapperTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2013, 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.test;
+
+import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
+import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.test.SubprocessUtil;
+import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests support for dumping graphs and other info useful for debugging a compiler crash.
+ */
+public class CompilationWrapperTest extends GraalCompilerTest {
+
+    /**
+     * Tests compilation requested by the VM.
+     */
+    @Test
+    public void testVMCompilation1() throws IOException, InterruptedException {
+        testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
+                        "-XX:+UseJVMCICompiler",
+                        "-Dgraal.CompilationFailureAction=ExitVM",
+                        "-Dgraal.CrashAt=Object.*,String.*",
+                        "-version"));
+    }
+
+    /**
+     * Tests that {@code -Dgraal.ExitVMOnException=true} works as an alias for
+     * {@code -Dgraal.CompilationFailureAction=ExitVM}.
+     */
+    @Test
+    public void testVMCompilation2() throws IOException, InterruptedException {
+        testHelper(Arrays.asList("-XX:+BootstrapJVMCI",
+                        "-XX:+UseJVMCICompiler",
+                        "-Dgraal.ExitVMOnException=true",
+                        "-Dgraal.CrashAt=Object.*,String.*",
+                        "-version"));
+    }
+
+    /**
+     * Tests compilation requested by Truffle.
+     */
+    @Test
+    public void testTruffleCompilation() throws IOException, InterruptedException {
+        testHelper(Arrays.asList(
+                        "-Dgraal.CompilationFailureAction=ExitVM",
+                        "-Dgraal.CrashAt=root test1"),
+                        "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite",
+                        "test");
+    }
+
+    private static void testHelper(List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
+        final File dumpPath = new File(CompilationWrapperTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
+        List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
+        vmArgs.removeIf(a -> a.startsWith("-Dgraal."));
+        vmArgs.add("-Dgraal.DumpPath=" + dumpPath);
+        // Force output to a file even if there's a running IGV instance available.
+        vmArgs.add("-Dgraal.PrintGraphFile=true");
+        vmArgs.addAll(extraVmArgs);
+
+        Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs);
+        System.out.println(proc);
+
+        String forcedCrashString = "Forced crash after compiling";
+        String diagnosticOutputFilePrefix = "Graal diagnostic output saved in ";
+
+        boolean seenForcedCrashString = false;
+        String diagnosticOutputZip = null;
+
+        for (String line : proc.output) {
+            if (line.contains(forcedCrashString)) {
+                seenForcedCrashString = true;
+            } else if (diagnosticOutputZip == null) {
+                int index = line.indexOf(diagnosticOutputFilePrefix);
+                if (index != -1) {
+                    diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim();
+                }
+            }
+        }
+
+        if (!seenForcedCrashString) {
+            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc));
+        }
+        if (diagnosticOutputZip == null) {
+            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc));
+        }
+
+        String[] dumpPathEntries = dumpPath.list();
+
+        File zip = new File(diagnosticOutputZip).getAbsoluteFile();
+        Assert.assertTrue(zip.toString(), zip.exists());
+        Assert.assertArrayEquals(dumpPathEntries, new String[]{zip.getName()});
+        try {
+            int bgv = 0;
+            int cfg = 0;
+            ZipFile dd = new ZipFile(diagnosticOutputZip);
+            List<String> entries = new ArrayList<>();
+            for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) {
+                ZipEntry ze = e.nextElement();
+                String name = ze.getName();
+                entries.add(name);
+                if (name.endsWith(".bgv")) {
+                    bgv++;
+                } else if (name.endsWith(".cfg")) {
+                    cfg++;
+                }
+            }
+            if (bgv == 0) {
+                Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
+            }
+            if (cfg == 0) {
+                Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries));
+            }
+        } finally {
+            zip.delete();
+            dumpPath.delete();
+        }
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Mon Jul 17 16:31:51 2017 -0700
@@ -23,9 +23,9 @@
 package org.graalvm.compiler.hotspot.test;
 
 import static java.util.Collections.singletonList;
-import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException;
+import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Print;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.test.ReflectionOptionDescriptors.extractEntries;
 import static org.graalvm.compiler.debug.MemUseTrackerKey.getCurrentThreadAllocatedBytes;
 import static org.graalvm.compiler.hotspot.test.CompileTheWorld.Options.DESCRIPTORS;
@@ -209,12 +209,9 @@
         EconomicMap<OptionKey<?>, Object> compilationOptionsCopy = EconomicMap.create(initialOptions.getMap());
         compilationOptionsCopy.putAll(compilationOptions);
 
-        // We don't want the VM to exit when a method fails to compile...
-        ExitVMOnException.putIfAbsent(compilationOptionsCopy, false);
-
-        // ...but we want to see exceptions.
-        PrintBailout.putIfAbsent(compilationOptionsCopy, true);
-        PrintStackTraceOnException.putIfAbsent(compilationOptionsCopy, true);
+        // We want to see stack traces when a method fails to compile
+        CompilationBailoutAction.putIfAbsent(compilationOptionsCopy, Print);
+        CompilationFailureAction.putIfAbsent(compilationOptionsCopy, Print);
 
         // By default only report statistics for the CTW threads themselves
         DebugOptions.MetricsThreadFilter.putIfAbsent(compilationOptionsCopy, "^CompileTheWorld");
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -22,7 +22,10 @@
  */
 package org.graalvm.compiler.hotspot.test;
 
-import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
+
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
 import org.graalvm.compiler.options.OptionKey;
@@ -40,13 +43,15 @@
 
     @Test
     public void testJDK() throws Throwable {
-        boolean originalSetting = ExitVMOnException.getValue(getInitialOptions());
+        ExceptionAction originalBailoutAction = CompilationBailoutAction.getValue(getInitialOptions());
+        ExceptionAction originalFailureAction = CompilationFailureAction.getValue(getInitialOptions());
         // Compile a couple classes in rt.jar
         HotSpotJVMCIRuntimeProvider runtime = HotSpotJVMCIRuntime.runtime();
         System.setProperty("CompileTheWorld.LimitModules", "java.base");
         OptionValues initialOptions = getInitialOptions();
         EconomicMap<OptionKey<?>, Object> compilationOptions = CompileTheWorld.parseOptions("Inline=false");
         new CompileTheWorld(runtime, (HotSpotGraalCompiler) runtime.getCompiler(), CompileTheWorld.SUN_BOOT_CLASS_PATH, 1, 5, null, null, false, initialOptions, compilationOptions).compile();
-        assert ExitVMOnException.getValue(initialOptions) == originalSetting;
+        assert CompilationBailoutAction.getValue(initialOptions) == originalBailoutAction;
+        assert CompilationFailureAction.getValue(initialOptions) == originalFailureAction;
     }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/RetryableCompilationTest.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * Copyright (c) 2013, 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.test;
-
-import static org.graalvm.compiler.test.SubprocessUtil.getVMCommandLine;
-import static org.graalvm.compiler.test.SubprocessUtil.withoutDebuggerArguments;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-import org.graalvm.compiler.core.test.GraalCompilerTest;
-import org.graalvm.compiler.test.SubprocessUtil;
-import org.graalvm.compiler.test.SubprocessUtil.Subprocess;
-import org.junit.Assert;
-import org.junit.Test;
-
-/**
- * Tests support for dumping graphs and other info useful for debugging a compiler crash.
- */
-public class RetryableCompilationTest extends GraalCompilerTest {
-
-    /**
-     * Tests compilation requested by the VM.
-     */
-    @Test
-    public void testVMCompilation() throws IOException, InterruptedException {
-        testHelper(Arrays.asList("-XX:+BootstrapJVMCI", "-XX:+UseJVMCICompiler", "-Dgraal.CrashAt=Object.*,String.*", "-version"));
-    }
-
-    /**
-     * Tests compilation requested by Truffle.
-     */
-    @Test
-    public void testTruffleCompilation() throws IOException, InterruptedException {
-        testHelper(Arrays.asList("-Dgraal.CrashAt=root test1"), "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
-    }
-
-    private static void testHelper(List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
-        List<String> vmArgs = withoutDebuggerArguments(getVMCommandLine());
-        vmArgs.removeIf(a -> a.startsWith("-Dgraal."));
-        // Force output to a file even if there's a running IGV instance available.
-        vmArgs.add("-Dgraal.PrintGraphFile=true");
-        vmArgs.addAll(extraVmArgs);
-
-        Subprocess proc = SubprocessUtil.java(vmArgs, mainClassAndArgs);
-
-        String forcedCrashString = "Forced crash after compiling";
-        String diagnosticOutputFilePrefix = "Graal diagnostic output saved in ";
-
-        boolean seenForcedCrashString = false;
-        String diagnosticOutputZip = null;
-
-        for (String line : proc.output) {
-            if (line.contains(forcedCrashString)) {
-                seenForcedCrashString = true;
-            } else if (diagnosticOutputZip == null) {
-                int index = line.indexOf(diagnosticOutputFilePrefix);
-                if (index != -1) {
-                    diagnosticOutputZip = line.substring(diagnosticOutputFilePrefix.length()).trim();
-                }
-            }
-        }
-        if (!seenForcedCrashString) {
-            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", forcedCrashString, proc));
-        }
-        if (diagnosticOutputZip == null) {
-            Assert.fail(String.format("Did not find '%s' in output of command:%n%s", diagnosticOutputFilePrefix, proc));
-        }
-
-        File zip = new File(diagnosticOutputZip).getAbsoluteFile();
-        Assert.assertTrue(zip.toString(), zip.exists());
-        try {
-            int bgv = 0;
-            int cfg = 0;
-            ZipFile dd = new ZipFile(diagnosticOutputZip);
-            List<String> entries = new ArrayList<>();
-            for (Enumeration<? extends ZipEntry> e = dd.entries(); e.hasMoreElements();) {
-                ZipEntry ze = e.nextElement();
-                String name = ze.getName();
-                entries.add(name);
-                if (name.endsWith(".bgv")) {
-                    bgv++;
-                } else if (name.endsWith(".cfg")) {
-                    cfg++;
-                }
-            }
-            if (bgv == 0) {
-                Assert.fail(String.format("Expected at least one .bgv file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
-            }
-            if (cfg == 0) {
-                Assert.fail(String.format("Expected at least one .cfg file in %s: %s", diagnosticOutputZip, entries));
-            }
-        } finally {
-            zip.delete();
-        }
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Mon Jul 17 16:31:51 2017 -0700
@@ -22,13 +22,8 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnBailout;
-import static org.graalvm.compiler.core.GraalCompilerOptions.ExitVMOnException;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintAfterCompilation;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintBailout;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintFilter;
-import static org.graalvm.compiler.core.GraalCompilerOptions.PrintStackTraceOnException;
+import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.ExitVM;
+import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 import static org.graalvm.compiler.core.phases.HighTier.Options.Inline;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
 
@@ -36,16 +31,17 @@
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.code.CompilationResult;
+import org.graalvm.compiler.core.CompilationPrinter;
+import org.graalvm.compiler.core.CompilationWrapper;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugDumpScope;
 import org.graalvm.compiler.debug.GraalError;
-import org.graalvm.compiler.debug.Management;
-import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.debug.TimeSource;
 import org.graalvm.compiler.debug.TimerKey;
+import org.graalvm.compiler.options.EnumOptionKey;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
@@ -65,8 +61,6 @@
 
 public class CompilationTask {
 
-    private static final CounterKey BAILOUTS = DebugContext.counter("Bailouts");
-
     private static final EventProvider eventProvider;
 
     static {
@@ -96,81 +90,95 @@
     private final boolean useProfilingInfo;
     private final OptionValues options;
 
-    final class RetryableCompilation extends HotSpotRetryableCompilation<HotSpotCompilationRequestResult> {
+    final class HotSpotCompilationWrapper extends CompilationWrapper<HotSpotCompilationRequestResult> {
         private final EventProvider.CompilationEvent compilationEvent;
         CompilationResult result;
 
-        RetryableCompilation(EventProvider.CompilationEvent compilationEvent) {
-            super(compiler.getGraalRuntime());
+        HotSpotCompilationWrapper(EventProvider.CompilationEvent compilationEvent) {
+            super(compiler.getGraalRuntime().getOutputDirectory());
             this.compilationEvent = compilationEvent;
         }
 
         @Override
+        protected DebugContext createRetryDebugContext(OptionValues retryOptions) {
+            SnippetReflectionProvider snippetReflection = compiler.getGraalRuntime().getHostProviders().getSnippetReflection();
+            return DebugContext.create(retryOptions, new GraalDebugHandlersFactory(snippetReflection));
+        }
+
+        @Override
         public String toString() {
-            return getMethod().format("%H.%n");
+            return getMethod().format("%H.%n(%p)");
+        }
+
+        @Override
+        protected HotSpotCompilationRequestResult handleException(Throwable t) {
+            if (t instanceof BailoutException) {
+                BailoutException bailout = (BailoutException) t;
+                /*
+                 * Handling of permanent bailouts: Permanent bailouts that can happen for example
+                 * due to unsupported unstructured control flow in the bytecodes of a method must
+                 * not be retried. Hotspot compile broker will ensure that no recompilation at the
+                 * given tier will happen if retry is false.
+                 */
+                return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !bailout.isPermanent());
+            }
+            // Log a failure event.
+            EventProvider.CompilerFailureEvent event = eventProvider.newCompilerFailureEvent();
+            if (event.shouldWrite()) {
+                event.setCompileId(getId());
+                event.setMessage(t.getMessage());
+                event.commit();
+            }
+
+            /*
+             * Treat random exceptions from the compiler as indicating a problem compiling this
+             * method. Report the result of toString instead of getMessage to ensure that the
+             * exception type is included in the output in case there's no detail mesage.
+             */
+            return HotSpotCompilationRequestResult.failure(t.toString(), false);
+        }
+
+        @Override
+        protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey) {
+            /*
+             * Automatically exit VM on non-bailout during bootstrap or when asserts are enabled but
+             * respect CompilationFailureAction if it has been explicitly set.
+             */
+            if (actionKey == CompilationFailureAction && !actionKey.hasBeenSet(values)) {
+                if (Assertions.ENABLED || compiler.getGraalRuntime().isBootstrapping()) {
+                    return ExitVM;
+                }
+            }
+            return super.lookupAction(values, actionKey);
         }
 
         @SuppressWarnings("try")
         @Override
-        protected HotSpotCompilationRequestResult run(DebugContext debug, Throwable retryCause) {
+        protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) {
             HotSpotResolvedJavaMethod method = getMethod();
             int entryBCI = getEntryBCI();
             final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI;
             CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR);
-            final boolean printCompilation = PrintCompilation.getValue(options) && !TTY.isSuppressed();
-            final boolean printAfterCompilation = PrintAfterCompilation.getValue(options) && !TTY.isSuppressed();
-            if (printCompilation) {
-                TTY.println(getMethodDescription() + "...");
-            }
 
-            TTY.Filter filter = new TTY.Filter(PrintFilter.getValue(options), method);
-            final long start;
-            final long allocatedBytesBefore;
-            if (printAfterCompilation || printCompilation) {
-                final long threadId = Thread.currentThread().getId();
-                start = TimeSource.getTimeNS();
-                allocatedBytesBefore = printAfterCompilation || printCompilation ? Lazy.threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
-            } else {
-                start = 0L;
-                allocatedBytesBefore = 0L;
-            }
+            final CompilationPrinter printer = CompilationPrinter.begin(options, compilationId, method, entryBCI);
 
             try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) {
                 // Begin the compilation event.
                 compilationEvent.begin();
                 result = compiler.compile(method, entryBCI, useProfilingInfo, compilationId, options, debug);
             } catch (Throwable e) {
-                if (retryCause != null) {
-                    log("Exception during retry", e);
-                }
                 throw debug.handle(e);
             } finally {
                 // End the compilation event.
                 compilationEvent.end();
-
-                filter.remove();
-
-                if (printAfterCompilation || printCompilation) {
-                    final long threadId = Thread.currentThread().getId();
-                    final long stop = TimeSource.getTimeNS();
-                    final long duration = (stop - start) / 1000000;
-                    final int targetCodeSize = result != null ? result.getTargetCodeSize() : -1;
-                    final int bytecodeSize = result != null ? result.getBytecodeSize() : 0;
-                    final long allocatedBytesAfter = Lazy.threadMXBean.getThreadAllocatedBytes(threadId);
-                    final long allocatedKBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
-
-                    if (printAfterCompilation) {
-                        TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB %5dkB", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
-                    } else if (printCompilation) {
-                        TTY.println(String.format("%-6d JVMCI %-70s %-45s %-50s | %4dms %5dB %5dB %5dkB", getId(), "", "", "", duration, bytecodeSize, targetCodeSize, allocatedKBytes));
-                    }
-                }
             }
 
             if (result != null) {
                 try (DebugCloseable b = CodeInstallationTime.start(debug)) {
                     installMethod(debug, result);
                 }
+                // Installation is included in compilation time and memory usage reported by printer
+                printer.finish(result);
             }
             stats.finish(method, installedCode);
             if (result != null) {
@@ -180,14 +188,6 @@
         }
     }
 
-    static class Lazy {
-        /**
-         * A {@link com.sun.management.ThreadMXBean} to be able to query some information about the
-         * current compiler thread, e.g. total allocated bytes.
-         */
-        static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
-    }
-
     public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault,
                     OptionValues options) {
         this.jvmciRuntime = jvmciRuntime;
@@ -226,7 +226,7 @@
     }
 
     /**
-     * Returns the HostSpot id of this compilation.
+     * Returns the HotSpot id of this compilation.
      *
      * @return HotSpot compile id
      */
@@ -307,46 +307,9 @@
             }
         }
 
-        RetryableCompilation compilation = new RetryableCompilation(compilationEvent);
+        HotSpotCompilationWrapper compilation = new HotSpotCompilationWrapper(compilationEvent);
         try (DebugCloseable a = CompilationTime.start(debug)) {
-            return compilation.runWithRetry(debug);
-        } catch (BailoutException bailout) {
-            BAILOUTS.increment(debug);
-            if (ExitVMOnBailout.getValue(options)) {
-                TTY.out.println(method.format("Bailout in %H.%n(%p)"));
-                bailout.printStackTrace(TTY.out);
-                System.exit(-1);
-            } else if (PrintBailout.getValue(options)) {
-                TTY.out.println(method.format("Bailout in %H.%n(%p)"));
-                bailout.printStackTrace(TTY.out);
-            }
-            /*
-             * Handling of permanent bailouts: Permanent bailouts that can happen for example due to
-             * unsupported unstructured control flow in the bytecodes of a method must not be
-             * retried. Hotspot compile broker will ensure that no recompilation at the given tier
-             * will happen if retry is false.
-             */
-            final boolean permanentBailout = bailout.isPermanent();
-            if (permanentBailout && PrintBailout.getValue(options)) {
-                TTY.println("Permanent bailout %s compiling method %s %s.", bailout.getMessage(), HotSpotGraalCompiler.str(method), (isOSR ? "OSR" : ""));
-            }
-            return HotSpotCompilationRequestResult.failure(bailout.getMessage(), !permanentBailout);
-        } catch (Throwable t) {
-            // Log a failure event.
-            EventProvider.CompilerFailureEvent event = eventProvider.newCompilerFailureEvent();
-            if (event.shouldWrite()) {
-                event.setCompileId(getId());
-                event.setMessage(t.getMessage());
-                event.commit();
-            }
-
-            handleException(t);
-            /*
-             * Treat random exceptions from the compiler as indicating a problem compiling this
-             * method. Report the result of toString instead of getMessage to ensure that the
-             * exception type is included in the output in case there's no detail mesage.
-             */
-            return HotSpotCompilationRequestResult.failure(t.toString(), false);
+            return compilation.run(debug);
         } finally {
             try {
                 int compiledBytecodes = 0;
@@ -374,46 +337,11 @@
                     compilationEvent.commit();
                 }
             } catch (Throwable t) {
-                handleException(t);
+                return compilation.handleException(t);
             }
         }
     }
 
-    protected void handleException(Throwable t) {
-        /*
-         * Automatically enable ExitVMOnException during bootstrap or when asserts are enabled but
-         * respect ExitVMOnException if it's been explicitly set.
-         */
-        boolean exitVMOnException = ExitVMOnException.getValue(options);
-        if (!ExitVMOnException.hasBeenSet(options)) {
-            assert (exitVMOnException = true) == true;
-            if (!exitVMOnException) {
-                HotSpotGraalRuntimeProvider runtime = compiler.getGraalRuntime();
-                if (runtime.isBootstrapping()) {
-                    exitVMOnException = true;
-                }
-            }
-        }
-
-        if (PrintStackTraceOnException.getValue(options) || exitVMOnException) {
-            try {
-                t.printStackTrace(TTY.out);
-            } catch (Throwable throwable) {
-                // Don't let an exception here change the other control flow
-            }
-        }
-
-        if (exitVMOnException) {
-            System.exit(-1);
-        }
-    }
-
-    private String getMethodDescription() {
-        HotSpotResolvedJavaMethod method = getMethod();
-        return String.format("%-6d JVMCI %-70s %-45s %-50s %s", getId(), method.getDeclaringClass().getName(), method.getName(), method.getSignature().toMethodDescriptor(),
-                        getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI ? "" : "(OSR@" + getEntryBCI() + ") ");
-    }
-
     @SuppressWarnings("try")
     private void installMethod(DebugContext debug, final CompilationResult compResult) {
         final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Mon Jul 17 16:31:51 2017 -0700
@@ -29,32 +29,18 @@
 import static org.graalvm.compiler.core.common.GraalOptions.HotSpotPrintInlining;
 import static org.graalvm.compiler.debug.DebugContext.DEFAULT_LOG_STREAM;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.lang.management.ManagementFactory;
-import java.nio.file.FileVisitResult;
-import java.nio.file.Files;
-import java.nio.file.InvalidPathException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.zip.Deflater;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipOutputStream;
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.api.runtime.GraalRuntime;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.target.Backend;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Description;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
 import org.graalvm.compiler.debug.GlobalMetrics;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TTY;
@@ -108,6 +94,7 @@
     private final GraalHotSpotVMConfig config;
 
     private final OptionValues options;
+    private final DiagnosticsOutputDirectory outputDirectory;
     private final HotSpotGraalMBean mBean;
 
     /**
@@ -126,6 +113,7 @@
             options = initialOptions;
         }
 
+        outputDirectory = new DiagnosticsOutputDirectory(options);
         snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
 
@@ -177,17 +165,6 @@
 
         runtimeStartTime = System.nanoTime();
         bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
-
-        assert checkPathIsInvalid(DELETED_OUTPUT_DIRECTORY);
-    }
-
-    private static boolean checkPathIsInvalid(String path) {
-        try {
-            Paths.get(path);
-            return false;
-        } catch (InvalidPathException e) {
-            return true;
-        }
     }
 
     private HotSpotBackend registerBackend(HotSpotBackend backend) {
@@ -293,7 +270,7 @@
         }
         BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
 
-        archiveAndDeleteOutputDirectory();
+        outputDirectory.close();
     }
 
     void clearMetrics() {
@@ -317,98 +294,8 @@
         return shutdown;
     }
 
-    /**
-     * Gets a unique identifier for this execution such as a process ID.
-     */
-    private static String getExecutionID() {
-        String runtimeName = ManagementFactory.getRuntimeMXBean().getName();
-        try {
-            int index = runtimeName.indexOf('@');
-            if (index != -1) {
-                long pid = Long.parseLong(runtimeName.substring(0, index));
-                return Long.toString(pid);
-            }
-        } catch (NumberFormatException e) {
-        }
-        return runtimeName;
-    }
-
-    private String outputDirectory;
-
-    /**
-     * Use an illegal file name to denote that the output directory has been deleted.
-     */
-    private static final String DELETED_OUTPUT_DIRECTORY = "\u0000";
-
     @Override
-    public String getOutputDirectory() {
-        return getOutputDirectory(true);
-    }
-
-    private synchronized String getOutputDirectory(boolean createIfNull) {
-        if (outputDirectory == null && createIfNull) {
-            outputDirectory = "graal_output_" + getExecutionID();
-            File dir = new File(outputDirectory).getAbsoluteFile();
-            if (!dir.exists()) {
-                dir.mkdirs();
-                if (!dir.exists()) {
-                    TTY.println("Warning: could not create Graal diagnostic directory " + dir);
-                    return null;
-                }
-            }
-        }
-        return DELETED_OUTPUT_DIRECTORY.equals(outputDirectory) ? null : outputDirectory;
-    }
-
-    /**
-     * Archives and deletes the {@linkplain #getOutputDirectory() output directory} if it exists.
-     */
-    private void archiveAndDeleteOutputDirectory() {
-        String outDir = getOutputDirectory(false);
-        if (outDir != null) {
-            Path dir = Paths.get(outDir);
-            if (dir.toFile().exists()) {
-                try {
-                    // Give compiler threads a chance to finishing dumping
-                    Thread.sleep(1000);
-                } catch (InterruptedException e1) {
-                }
-                File zip = new File(outDir + ".zip").getAbsoluteFile();
-                List<Path> toDelete = new ArrayList<>();
-                try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zip))) {
-                    zos.setLevel(Deflater.BEST_COMPRESSION);
-                    Files.walkFileTree(dir, Collections.emptySet(), Integer.MAX_VALUE, new SimpleFileVisitor<Path>() {
-                        @Override
-                        public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-                            if (attrs.isRegularFile()) {
-                                ZipEntry ze = new ZipEntry(file.toString());
-                                zos.putNextEntry(ze);
-                                zos.write(Files.readAllBytes(file));
-                                zos.closeEntry();
-                            }
-                            toDelete.add(file);
-                            return FileVisitResult.CONTINUE;
-                        }
-
-                        @Override
-                        public FileVisitResult postVisitDirectory(Path d, IOException exc) throws IOException {
-                            toDelete.add(d);
-                            return FileVisitResult.CONTINUE;
-                        }
-                    });
-                    TTY.println("Graal diagnostic output saved in %s", zip);
-                } catch (IOException e) {
-                    TTY.printf("IO error archiving %s:%n%s%n", dir, e);
-                }
-                for (Path p : toDelete) {
-                    try {
-                        Files.delete(p);
-                    } catch (IOException e) {
-                        TTY.printf("IO error deleting %s:%n%s%n", p, e);
-                    }
-                }
-            }
-            outputDirectory = DELETED_OUTPUT_DIRECTORY;
-        }
+    public DiagnosticsOutputDirectory getOutputDirectory() {
+        return outputDirectory;
     }
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Mon Jul 17 16:31:51 2017 -0700
@@ -25,6 +25,7 @@
 import org.graalvm.compiler.api.runtime.GraalRuntime;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.options.OptionValues;
@@ -91,12 +92,7 @@
     boolean isShutdown();
 
     /**
-     * Gets a directory into which diagnostics such crash reports and dumps should be written. This
-     * method will create the directory if it doesn't exist so it should only be called if
-     * diagnostics are about to be generated.
-     *
-     * @return the directory into which diagnostics can be written or {@code null} if the directory
-     *         does not exist and could not be created or has already been deleted
+     * Gets a directory into which diagnostics such crash reports and dumps should be written.
      */
-    String getOutputDirectory();
+    DiagnosticsOutputDirectory getOutputDirectory();
 }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotRetryableCompilation.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * 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;
-
-import static org.graalvm.compiler.debug.DebugContext.VERBOSE_LEVEL;
-import static org.graalvm.compiler.debug.DebugOptions.Dump;
-import static org.graalvm.compiler.debug.DebugOptions.DumpPath;
-import static org.graalvm.compiler.debug.DebugOptions.MethodFilter;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintStream;
-
-import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
-import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.DebugRetryableTask;
-import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
-
-import jdk.vm.ci.code.BailoutException;
-
-/**
- * Utility for retrying a compilation that throws an exception where the retry enables extra logging
- * for subsequently diagnosing the failure.
- */
-public abstract class HotSpotRetryableCompilation<T> extends DebugRetryableTask<T> {
-
-    protected final HotSpotGraalRuntimeProvider runtime;
-
-    public HotSpotRetryableCompilation(HotSpotGraalRuntimeProvider runtime) {
-        this.runtime = runtime;
-    }
-
-    /**
-     * Gets a value that represents the compilation unit being compiled.
-     */
-    @Override
-    public abstract String toString();
-
-    @Override
-    protected DebugContext getRetryContext(DebugContext initialDebug, Throwable t) {
-        if (t instanceof BailoutException) {
-            return null;
-        }
-
-        OptionValues initialOptions = initialDebug.getOptions();
-        if (Dump.hasBeenSet(initialOptions)) {
-            // If dumping is explicitly enabled, Graal is being debugged
-            // so don't interfere with what the user is expecting to see.
-            return null;
-        }
-
-        String outputDirectory = runtime.getOutputDirectory();
-        if (outputDirectory == null) {
-            return null;
-        }
-        String dumpName = GraalDebugHandlersFactory.sanitizedFileName(toString());
-        File dumpPath = new File(outputDirectory, dumpName);
-        dumpPath.mkdirs();
-        if (!dumpPath.exists()) {
-            TTY.println("Warning: could not create dump directory " + dumpPath);
-            return null;
-        }
-
-        TTY.println("Retrying compilation of " + this + " due to " + t);
-        retryLogPath = new File(dumpPath, "retry.log").getPath();
-        log("Exception causing retry", t);
-        OptionValues retryOptions = new OptionValues(initialOptions,
-                        Dump, ":" + VERBOSE_LEVEL,
-                        MethodFilter, null,
-                        DumpPath, dumpPath.getPath());
-        SnippetReflectionProvider snippetReflection = runtime.getHostProviders().getSnippetReflection();
-        return DebugContext.create(retryOptions, new GraalDebugHandlersFactory(snippetReflection));
-    }
-
-    private String retryLogPath;
-
-    /**
-     * Prints a message to a retry log file.
-     *
-     * @param message the message to print
-     * @param t if non-{@code null}, the stack trace for this exception is written to the retry log
-     *            after {@code message}
-     */
-    protected void log(String message, Throwable t) {
-        if (retryLogPath != null) {
-            try (PrintStream retryLog = new PrintStream(new FileOutputStream(retryLogPath), true)) {
-                StringBuilder buf = new StringBuilder(Thread.currentThread() + ": " + message);
-                if (t != null) {
-                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                    t.printStackTrace(new PrintStream(baos));
-                    buf.append(System.lineSeparator()).append(baos.toString());
-                }
-                retryLog.println(buf);
-            } catch (FileNotFoundException e) {
-                TTY.println("Warning: could not open retry log file " + retryLogPath + " [" + e + "]");
-            }
-        }
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Mon Jul 17 16:31:51 2017 -0700
@@ -90,7 +90,7 @@
 import org.graalvm.compiler.word.Word;
 import org.graalvm.word.LocationIdentity;
 import org.graalvm.word.Pointer;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordFactory;
 
 import jdk.vm.ci.code.Register;
@@ -250,11 +250,11 @@
         // The result of the xor reveals whether the installed pointer crosses heap regions.
         // In case it does the write barrier has to be issued.
         final int logOfHeapRegionGrainBytes = GraalHotSpotVMConfigNode.logOfHeapRegionGrainBytes();
-        Unsigned xorResult = (oop.xor(writtenValue)).unsignedShiftRight(logOfHeapRegionGrainBytes);
+        UnsignedWord xorResult = (oop.xor(writtenValue)).unsignedShiftRight(logOfHeapRegionGrainBytes);
 
         // Calculate the address of the card to be enqueued to the
         // thread local card queue.
-        Unsigned cardBase = oop.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG));
+        UnsignedWord cardBase = oop.unsignedShiftRight(cardTableShift(INJECTED_VMCONFIG));
         final long startAddress = GraalHotSpotVMConfigNode.cardTableAddress();
         int displacement = 0;
         if (((int) startAddress) == startAddress && GraalHotSpotVMConfigNode.isCardTableAddressConstant()) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/UnsafeArrayCopySnippets.java	Mon Jul 17 16:31:51 2017 -0700
@@ -56,7 +56,7 @@
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.word.ObjectAccess;
 import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordFactory;
 
 import jdk.vm.ci.code.TargetDescription;
@@ -237,15 +237,15 @@
         int log2ElementSize = (layoutHelper >> layoutHelperLog2ElementSizeShift(INJECTED_VMCONFIG)) & layoutHelperLog2ElementSizeMask(INJECTED_VMCONFIG);
         int headerSize = (layoutHelper >> layoutHelperHeaderSizeShift(INJECTED_VMCONFIG)) & layoutHelperHeaderSizeMask(INJECTED_VMCONFIG);
 
-        Unsigned vectorSize = WordFactory.unsigned(VECTOR_SIZE);
-        Unsigned srcOffset = WordFactory.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize);
-        Unsigned destOffset = WordFactory.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize);
-        Unsigned destStart = destOffset;
-        Unsigned destEnd = destOffset.add(WordFactory.unsigned(length).shiftLeft(log2ElementSize));
+        UnsignedWord vectorSize = WordFactory.unsigned(VECTOR_SIZE);
+        UnsignedWord srcOffset = WordFactory.unsigned(srcPos).shiftLeft(log2ElementSize).add(headerSize);
+        UnsignedWord destOffset = WordFactory.unsigned(destPos).shiftLeft(log2ElementSize).add(headerSize);
+        UnsignedWord destStart = destOffset;
+        UnsignedWord destEnd = destOffset.add(WordFactory.unsigned(length).shiftLeft(log2ElementSize));
 
-        Unsigned destVectorEnd = null;
-        Unsigned nonVectorBytes = null;
-        Unsigned sizeInBytes = WordFactory.unsigned(length).shiftLeft(log2ElementSize);
+        UnsignedWord destVectorEnd = null;
+        UnsignedWord nonVectorBytes = null;
+        UnsignedWord sizeInBytes = WordFactory.unsigned(length).shiftLeft(log2ElementSize);
         if (supportsUnalignedMemoryAccess) {
             nonVectorBytes = sizeInBytes.unsignedRemainder(vectorSize);
             destVectorEnd = destEnd;
@@ -261,7 +261,7 @@
             destVectorEnd = destEnd.subtract(destEnd.unsignedRemainder(vectorSize));
         }
 
-        Unsigned destNonVectorEnd = destStart.add(nonVectorBytes);
+        UnsignedWord destNonVectorEnd = destStart.add(nonVectorBytes);
         while (destOffset.belowThan(destNonVectorEnd)) {
             ObjectAccess.writeByte(dest, destOffset, ObjectAccess.readByte(src, srcOffset, any()), any());
             destOffset = destOffset.add(1);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java	Mon Jul 17 16:31:51 2017 -0700
@@ -31,8 +31,8 @@
 import org.graalvm.compiler.word.Word.Operation;
 import org.graalvm.word.LocationIdentity;
 import org.graalvm.word.Pointer;
-import org.graalvm.word.Signed;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.SignedWord;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordBase;
 
 /**
@@ -50,8 +50,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -65,8 +65,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -80,8 +80,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -95,8 +95,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -110,8 +110,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -125,8 +125,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -140,8 +140,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -155,8 +155,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -170,8 +170,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -284,8 +284,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -299,8 +299,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -314,8 +314,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -329,8 +329,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -344,8 +344,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -359,8 +359,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -374,8 +374,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -389,8 +389,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -404,8 +404,8 @@
      * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
      * are in bytes. The memory must be uninitialized or zero prior to this operation.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -419,8 +419,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -533,8 +533,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -547,8 +547,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -561,8 +561,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -575,8 +575,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -589,8 +589,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -603,8 +603,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -617,8 +617,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -631,8 +631,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -645,8 +645,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -660,8 +660,8 @@
      * the VM uses compressed oops, and it can be parameterized to allow read barriers (G1 referent
      * field).
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -777,8 +777,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -791,8 +791,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -805,8 +805,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -819,8 +819,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -833,8 +833,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -847,8 +847,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -861,8 +861,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -875,8 +875,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -889,8 +889,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Mon Jul 17 16:31:51 2017 -0700
@@ -365,6 +365,7 @@
 import org.graalvm.compiler.nodes.calc.XorNode;
 import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
 import org.graalvm.compiler.nodes.extended.AnchoringNode;
+import org.graalvm.compiler.nodes.extended.BranchProbabilityNode;
 import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode;
 import org.graalvm.compiler.nodes.extended.IntegerSwitchNode;
 import org.graalvm.compiler.nodes.extended.LoadHubNode;
@@ -2959,7 +2960,7 @@
             }
 
             // Need to get probability based on current bci.
-            double probability = branchProbability();
+            double probability = branchProbability(condition);
 
             if (negate) {
                 BciBlock tmpBlock = trueBlock;
@@ -4026,12 +4027,36 @@
         return probability == 0 && optimisticOpts.removeNeverExecutedCode(getOptions());
     }
 
-    protected double branchProbability() {
+    private double rawBranchProbability(LogicNode conditionInput) {
+        if (conditionInput instanceof IntegerEqualsNode) {
+            // Propagate injected branch probability if any.
+            IntegerEqualsNode condition = (IntegerEqualsNode) conditionInput;
+            BranchProbabilityNode injectedProbability = null;
+            ValueNode other = null;
+            if (condition.getX() instanceof BranchProbabilityNode) {
+                injectedProbability = (BranchProbabilityNode) condition.getX();
+                other = condition.getY();
+            } else if (condition.getY() instanceof BranchProbabilityNode) {
+                injectedProbability = (BranchProbabilityNode) condition.getY();
+                other = condition.getX();
+            }
+
+            if (injectedProbability != null && injectedProbability.getProbability().isConstant() && other != null && other.isConstant()) {
+                double probabilityValue = injectedProbability.getProbability().asJavaConstant().asDouble();
+                return other.asJavaConstant().asInt() == 0 ? 1.0 - probabilityValue : probabilityValue;
+            }
+        }
+
         if (profilingInfo == null) {
             return 0.5;
         }
         assert assertAtIfBytecode();
-        double probability = profilingInfo.getBranchTakenProbability(bci());
+
+        return profilingInfo.getBranchTakenProbability(bci());
+    }
+
+    protected double branchProbability(LogicNode conditionInput) {
+        double probability = rawBranchProbability(conditionInput);
         if (probability < 0) {
             assert probability == -1 : "invalid probability";
             debug.log("missing probability in %s at bci %d", code, bci());
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Mon Jul 17 16:31:51 2017 -0700
@@ -435,8 +435,9 @@
             try (ScratchRegister r2 = masm.getScratchRegister()) {
                 Register rscratch1 = r1.getRegister();
                 Register rscratch2 = r2.getRegister();
+                // use the slot kind to define the operand size
                 PlatformKind kind = input.getPlatformKind();
-                final int size = kind.getSizeInBytes() <= 4 ? 32 : 64;
+                final int size = kind.getSizeInBytes() * Byte.SIZE;
 
                 // Always perform stack -> stack copies through integer registers
                 crb.blockComment("[stack -> stack copy]");
@@ -466,8 +467,9 @@
     private static void reg2stack(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) {
         AArch64Address dest = loadStackSlotAddress(crb, masm, asStackSlot(result), Value.ILLEGAL);
         Register src = asRegister(input);
-        AArch64Kind kind = (AArch64Kind) input.getPlatformKind();
-        int size = kind.getSizeInBytes() * Byte.SIZE;
+        // use the slot kind to define the operand size
+        AArch64Kind kind = (AArch64Kind) result.getPlatformKind();
+        final int size = kind.getSizeInBytes() * Byte.SIZE;
         if (kind.isInteger()) {
             masm.str(size, src, dest);
         } else {
@@ -477,6 +479,7 @@
 
     private static void stack2reg(CompilationResultBuilder crb, AArch64MacroAssembler masm, AllocatableValue result, AllocatableValue input) {
         AArch64Kind kind = (AArch64Kind) input.getPlatformKind();
+        // use the slot kind to define the operand size
         final int size = kind.getSizeInBytes() * Byte.SIZE;
         if (kind.isInteger()) {
             AArch64Address src = loadStackSlotAddress(crb, masm, asStackSlot(input), result);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64Move.java	Mon Jul 17 16:31:51 2017 -0700
@@ -669,6 +669,28 @@
         }
     }
 
+    public static boolean canMoveConst2Stack(JavaConstant input) {
+        switch (input.getJavaKind().getStackKind()) {
+            case Int:
+                break;
+            case Long:
+                break;
+            case Float:
+                break;
+            case Double:
+                break;
+            case Object:
+                if (input.isNull()) {
+                    return true;
+                } else {
+                    return false;
+                }
+            default:
+                return false;
+        }
+        return true;
+    }
+
     public static void const2stack(CompilationResultBuilder crb, AMD64MacroAssembler masm, Value result, JavaConstant input) {
         AMD64Address dest = (AMD64Address) crb.asAddress(result);
         final long imm;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.jtt/src/org/graalvm/compiler/lir/jtt/StackStoreLoadTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,147 @@
+/*
+ * 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.lir.jtt;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.lir.Variable;
+import org.graalvm.compiler.lir.VirtualStackSlot;
+import org.graalvm.compiler.lir.framemap.FrameMapBuilder;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.PlatformKind;
+import jdk.vm.ci.meta.Value;
+import jdk.vm.ci.meta.ValueKind;
+
+public class StackStoreLoadTest extends LIRTest {
+    private static PlatformKind byteKind;
+    private static PlatformKind shortKind;
+
+    @Before
+    public void setUp() {
+        byteKind = getBackend().getTarget().arch.getPlatformKind(JavaKind.Byte);
+        shortKind = getBackend().getTarget().arch.getPlatformKind(JavaKind.Short);
+    }
+
+    private static class StackStoreLoadSpec extends LIRTestSpecification {
+        @Override
+        public void generate(LIRGeneratorTool gen, Value a) {
+            FrameMapBuilder frameMapBuilder = gen.getResult().getFrameMapBuilder();
+            ValueKind<?> valueKind = getValueKind(a);
+
+            // create slots
+            VirtualStackSlot s1 = frameMapBuilder.allocateSpillSlot(valueKind);
+            VirtualStackSlot s2 = frameMapBuilder.allocateSpillSlot(valueKind);
+            VirtualStackSlot s3 = frameMapBuilder.allocateSpillSlot(valueKind);
+
+            // start emit
+            gen.emitMove(s1, a);
+            gen.emitMove(s2, a);
+            gen.emitMove(s3, a);
+            gen.append(gen.getSpillMoveFactory().createStackMove(s1, s3));
+            Variable result = gen.emitMove(s2);
+            Value slot1 = gen.emitMove(s1);
+            Value slot3 = gen.emitMove(s3);
+            // end emit
+
+            // set output and result
+            setResult(result);
+            setOutput("slot1", slot1);
+            setOutput("slot3", slot3);
+        }
+
+        protected ValueKind<?> getValueKind(Value value) {
+            return value.getValueKind();
+        }
+    }
+
+    /*
+     * short
+     */
+
+    private static final LIRTestSpecification shortStackCopy = new StackStoreLoadSpec() {
+        @Override
+        protected ValueKind<?> getValueKind(Value value) {
+            return LIRKind.value(shortKind);
+        }
+    };
+
+    @SuppressWarnings("unused")
+    @LIRIntrinsic
+    public static short copyShort(LIRTestSpecification spec, short a) {
+        return a;
+    }
+
+    public short[] testShort(short a, short[] out) {
+        out[0] = copyShort(shortStackCopy, a);
+        out[1] = getOutput(shortStackCopy, "slot1", a);
+        out[2] = getOutput(shortStackCopy, "slot3", a);
+        return out;
+    }
+
+    @Test
+    public void runShort() throws Throwable {
+        runTest("testShort", Short.MIN_VALUE, supply(() -> new short[3]));
+        runTest("testShort", (short) -1, supply(() -> new short[3]));
+        runTest("testShort", (short) 0, supply(() -> new short[3]));
+        runTest("testShort", (short) 1, supply(() -> new short[3]));
+        runTest("testShort", Short.MAX_VALUE, supply(() -> new short[3]));
+    }
+
+    /*
+     * byte
+     */
+
+    private static final LIRTestSpecification byteStackCopy = new StackStoreLoadSpec() {
+        @Override
+        protected ValueKind<?> getValueKind(Value value) {
+            return LIRKind.value(byteKind);
+        }
+    };
+
+    @SuppressWarnings("unused")
+    @LIRIntrinsic
+    public static byte copyByte(LIRTestSpecification spec, byte a) {
+        return a;
+    }
+
+    public byte[] testByte(byte a, byte[] out) {
+        out[0] = copyByte(byteStackCopy, a);
+        out[1] = getOutput(byteStackCopy, "slot1", a);
+        out[2] = getOutput(byteStackCopy, "slot3", a);
+        return out;
+    }
+
+    @Test
+    public void runByte() throws Throwable {
+        runTest("testByte", Byte.MIN_VALUE, supply(() -> new byte[3]));
+        runTest("testByte", (byte) -1, supply(() -> new byte[3]));
+        runTest("testByte", (byte) 0, supply(() -> new byte[3]));
+        runTest("testByte", (byte) 1, supply(() -> new byte[3]));
+        runTest("testByte", Byte.MAX_VALUE, supply(() -> new byte[3]));
+    }
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java	Mon Jul 17 16:31:51 2017 -0700
@@ -37,8 +37,9 @@
 import org.graalvm.compiler.lir.LIRInstruction;
 import org.graalvm.compiler.lir.LIRValueUtil;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
+import org.graalvm.util.EconomicSet;
 import org.graalvm.util.Equivalence;
-import org.graalvm.util.EconomicSet;
+
 import jdk.vm.ci.meta.AllocatableValue;
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.Value;
@@ -296,7 +297,12 @@
         assert insertIdx != -1 : "must setup insert position first";
 
         AllocatableValue toOpr = toInterval.operand;
-        LIRInstruction move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr);
+        LIRInstruction move;
+        if (LIRValueUtil.isStackSlotValue(toInterval.location())) {
+            move = getAllocator().getSpillMoveFactory().createStackLoad(toOpr, fromOpr);
+        } else {
+            move = getAllocator().getSpillMoveFactory().createLoad(toOpr, fromOpr);
+        }
         insertionBuffer.append(insertIdx, move);
 
         DebugContext debug = allocator.getDebug();
@@ -482,7 +488,8 @@
         }
 
         assert !fromInterval.operand.equals(toInterval.operand) : "from and to interval equal: " + fromInterval;
-        assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : String.format("Kind mismatch: %s vs. %s, from=%s, to=%s", fromInterval.kind(),
+        assert LIRKind.verifyMoveKinds(toInterval.kind(), fromInterval.kind(), allocator.getRegisterAllocationConfig()) : String.format("Kind mismatch: %s vs. %s, from=%s, to=%s",
+                        fromInterval.kind(),
                         toInterval.kind(), fromInterval, toInterval);
         mappingFrom.add(fromInterval);
         mappingFromOpr.add(null);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Mon Jul 17 16:31:51 2017 -0700
@@ -482,7 +482,7 @@
                     afterOp.accept(op);
                 }
             } catch (GraalError e) {
-                throw e.addContext("lir instruction", block + "@" + op.id() + " " + op + "\n" + Arrays.toString(lir.codeEmittingOrder()));
+                throw e.addContext("lir instruction", block + "@" + op.id() + " " + op.getClass().getName() + " " + op + "\n" + Arrays.toString(lir.codeEmittingOrder()));
             }
         }
     }
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGeneratorTool.java	Mon Jul 17 16:31:51 2017 -0700
@@ -80,6 +80,8 @@
         LIRInstruction createStackMove(AllocatableValue result, AllocatableValue input);
 
         LIRInstruction createLoad(AllocatableValue result, Constant input);
+
+        LIRInstruction createStackLoad(AllocatableValue result, Constant input);
     }
 
     abstract class BlockScope implements AutoCloseable {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/VerifyingMoveFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/VerifyingMoveFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -80,6 +80,13 @@
         return inst;
     }
 
+    @Override
+    public LIRInstruction createStackLoad(AllocatableValue result, Constant input) {
+        LIRInstruction inst = inner.createStackLoad(result, input);
+        assert LoadConstantOp.isLoadConstantOp(inst) && checkResult(inst, result, null);
+        return inst;
+    }
+
     /** Closure for {@link VerifyingMoveFactory#checkResult}. */
     @SuppressWarnings("unused")
     private static class CheckClosure {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Mon Jul 17 16:31:51 2017 -0700
@@ -22,7 +22,9 @@
  */
 package org.graalvm.compiler.loop;
 
+import java.util.ArrayDeque;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.Iterator;
 
 import org.graalvm.compiler.debug.GraalError;
@@ -55,6 +57,8 @@
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 import org.graalvm.util.EconomicMap;
 
+import jdk.vm.ci.meta.TriState;
+
 public abstract class LoopFragment {
 
     private final LoopEx loop;
@@ -221,6 +225,7 @@
         }
 
         final NodeBitMap nonLoopNodes = graph.createNodeBitMap();
+        Deque<WorkListEntry> worklist = new ArrayDeque<>();
         for (AbstractBeginNode b : blocks) {
             if (b.isDeleted()) {
                 continue;
@@ -229,56 +234,98 @@
             for (Node n : b.getBlockNodes()) {
                 if (n instanceof CommitAllocationNode) {
                     for (VirtualObjectNode obj : ((CommitAllocationNode) n).getVirtualObjects()) {
-                        markFloating(obj, nodes, nonLoopNodes);
+                        markFloating(worklist, obj, nodes, nonLoopNodes);
                     }
                 }
                 if (n instanceof MonitorEnterNode) {
-                    markFloating(((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
+                    markFloating(worklist, ((MonitorEnterNode) n).getMonitorId(), nodes, nonLoopNodes);
                 }
                 for (Node usage : n.usages()) {
-                    markFloating(usage, nodes, nonLoopNodes);
+                    markFloating(worklist, usage, nodes, nonLoopNodes);
                 }
             }
         }
     }
 
-    private static boolean markFloating(Node n, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
+    static class WorkListEntry {
+        final Iterator<Node> usages;
+        final Node n;
+        boolean isLoopNode;
+
+        WorkListEntry(Node n, NodeBitMap loopNodes) {
+            this.n = n;
+            this.usages = n.usages().iterator();
+            this.isLoopNode = loopNodes.isMarked(n);
+        }
+    }
+
+    static TriState isLoopNode(Node n, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
         if (loopNodes.isMarked(n)) {
-            return true;
+            return TriState.TRUE;
         }
         if (nonLoopNodes.isMarked(n)) {
-            return false;
+            return TriState.FALSE;
         }
         if (n instanceof FixedNode) {
-            return false;
+            return TriState.FALSE;
         }
         boolean mark = false;
         if (n instanceof PhiNode) {
             PhiNode phi = (PhiNode) n;
             mark = loopNodes.isMarked(phi.merge());
             if (mark) {
+                /*
+                 * This Phi is a loop node but the inputs might not be so they must be processed by
+                 * the caller.
+                 */
                 loopNodes.mark(n);
             } else {
                 nonLoopNodes.mark(n);
-                return false;
-            }
-        }
-        for (Node usage : n.usages()) {
-            if (markFloating(usage, loopNodes, nonLoopNodes)) {
-                mark = true;
+                return TriState.FALSE;
             }
         }
-        if (!mark && n instanceof GuardNode) {
-            // (gd) this is only OK if we are not going to make loop transforms based on this
-            assert !((GuardNode) n).graph().hasValueProxies();
-            mark = true;
+        return TriState.UNKNOWN;
+    }
+
+    private static void markFloating(Deque<WorkListEntry> workList, Node start, NodeBitMap loopNodes, NodeBitMap nonLoopNodes) {
+        if (isLoopNode(start, loopNodes, nonLoopNodes).isKnown()) {
+            return;
         }
-        if (mark) {
-            loopNodes.mark(n);
-            return true;
+        workList.push(new WorkListEntry(start, loopNodes));
+        while (!workList.isEmpty()) {
+            WorkListEntry currentEntry = workList.peek();
+            if (currentEntry.usages.hasNext()) {
+                Node current = currentEntry.usages.next();
+                TriState result = isLoopNode(current, loopNodes, nonLoopNodes);
+                if (result.isKnown()) {
+                    if (result.toBoolean()) {
+                        currentEntry.isLoopNode = true;
+                    }
+                } else {
+                    workList.push(new WorkListEntry(current, loopNodes));
+                }
+            } else {
+                workList.pop();
+                boolean isLoopNode = currentEntry.isLoopNode;
+                Node current = currentEntry.n;
+                if (!isLoopNode && current instanceof GuardNode) {
+                    /*
+                     * (gd) this is only OK if we are not going to make loop transforms based on
+                     * this
+                     */
+                    assert !((GuardNode) current).graph().hasValueProxies();
+                    isLoopNode = true;
+                }
+                if (isLoopNode) {
+                    loopNodes.mark(current);
+                    for (WorkListEntry e : workList) {
+                        e.isLoopNode = true;
+                    }
+                } else {
+                    nonLoopNodes.mark(current);
+                }
+            }
         }
-        nonLoopNodes.mark(n);
-        return false;
     }
 
     public static NodeIterable<AbstractBeginNode> toHirBlocks(final Iterable<Block> blocks) {
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java	Mon Jul 17 16:31:51 2017 -0700
@@ -28,10 +28,27 @@
 
 public class EnumOptionKey<T extends Enum<T>> extends OptionKey<T> {
     final Class<T> enumClass;
+    final ValueHelp<T> valueHelp;
+
+    /**
+     * Provides help text for enum values.
+     */
+    public interface ValueHelp<T extends Enum<T>> {
+        /**
+         * Gets help text for the enum {@code value} that includes the name of the value. If
+         * {@code null} is returned, {@code value.toString()} is used.
+         */
+        String getHelp(Object value);
+    }
+
+    public EnumOptionKey(T value) {
+        this(value, null);
+    }
 
     @SuppressWarnings("unchecked")
-    public EnumOptionKey(T value) {
+    public EnumOptionKey(T value, ValueHelp<T> help) {
         super(value);
+        this.valueHelp = help;
         if (value == null) {
             throw new IllegalArgumentException("Value must not be null");
         }
@@ -45,6 +62,10 @@
         return EnumSet.allOf(enumClass);
     }
 
+    public ValueHelp<T> getValueHelp() {
+        return valueHelp;
+    }
+
     Object valueOf(String name) {
         try {
             return Enum.valueOf(enumClass, name);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java	Mon Jul 17 16:31:51 2017 -0700
@@ -26,11 +26,13 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import org.graalvm.compiler.options.EnumOptionKey.ValueHelp;
 import org.graalvm.util.EconomicMap;
 import org.graalvm.util.Equivalence;
 import org.graalvm.util.UnmodifiableEconomicMap;
@@ -223,11 +225,20 @@
             String help = desc.getHelp();
             if (desc.getOptionKey() instanceof EnumOptionKey) {
                 EnumOptionKey<?> eoption = (EnumOptionKey<?>) desc.getOptionKey();
-                String evalues = eoption.getAllValues().toString();
+                EnumSet<?> evalues = eoption.getAllValues();
+                String evaluesString = evalues.toString();
+                ValueHelp<?> valueHelp = eoption.getValueHelp();
                 if (help.length() > 0 && !help.endsWith(".")) {
                     help += ".";
                 }
-                help += " Valid values are: " + evalues.substring(1, evalues.length() - 1);
+                if (valueHelp == null) {
+                    help += " Valid values are: " + evaluesString.substring(1, evaluesString.length() - 1);
+                } else {
+                    for (Object o : evalues) {
+                        String vhelp = valueHelp.getHelp(o);
+                        help += "%n" + (vhelp == null ? o : vhelp);
+                    }
+                }
             }
             String name = namePrefix + e.getKey();
             String assign = containsKey(desc.optionKey) ? ":=" : "=";
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinterObserver.java	Mon Jul 17 16:31:51 2017 -0700
@@ -144,7 +144,7 @@
                 OutputStream out = new BufferedOutputStream(new FileOutputStream(cfgFile));
                 cfgPrinter = new CFGPrinter(out);
             } catch (IOException e) {
-                throw (GraalError) new GraalError("Could not open %s", cfgFile.getAbsolutePath()).initCause(e);
+                throw (GraalError) new GraalError("Could not open %s", cfgFile == null ? "[null]" : cfgFile.getAbsolutePath()).initCause(e);
             }
         }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraalDebugHandlersFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -28,6 +28,7 @@
 import static org.graalvm.compiler.debug.DebugOptions.PrintXmlGraphPort;
 import static org.graalvm.compiler.debug.DebugOptions.ShowDumpFiles;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InterruptedIOException;
 import java.net.InetSocketAddress;
@@ -53,7 +54,7 @@
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.debug.TTY;
-import org.graalvm.compiler.debug.UniquePathUtilities;
+import org.graalvm.compiler.debug.PathUtilities;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -117,7 +118,13 @@
         return new CanonicalStringGraphPrinter(snippetReflection);
     }
 
-    public static String sanitizedFileName(String name) {
+    public static String sanitizedFileName(String n) {
+        /*
+         * First ensure that the name does not contain the directory separator (which would be
+         * considered a valid path).
+         */
+        String name = n.replace(File.separatorChar, '_');
+
         try {
             Paths.get(name);
             return name;
@@ -194,7 +201,7 @@
             label = graph == null ? null : graph.name != null ? graph.name : graph.toString();
             id = "UnknownCompilation-" + unknownCompilationId.incrementAndGet();
         }
-        String ext = UniquePathUtilities.formatExtension(extension);
+        String ext = PathUtilities.formatExtension(extension);
         Path result = createUnique(DebugOptions.getDumpDirectory(options), id, label, ext, createDirectory);
         if (ShowDumpFiles.getValue(options)) {
             TTY.println("Dumping debug output to %s", result.toAbsolutePath().toString());
@@ -220,7 +227,7 @@
                 // This means `id` is very long
                 String suffix = timestamp + ext;
                 int idLengthLimit = Math.min(MAX_FILE_NAME_LENGTH - suffix.length(), id.length());
-                fileName = id.substring(0, idLengthLimit) + suffix;
+                fileName = sanitizedFileName(id.substring(0, idLengthLimit) + suffix);
             } else {
                 if (label == null) {
                     fileName = sanitizedFileName(id + timestamp + ext);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -30,7 +30,7 @@
 import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.word.Pointer;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordBase;
 import org.graalvm.word.WordFactory;
 import org.junit.Test;
@@ -118,7 +118,7 @@
     @Snippet
     public static long cast(long input) {
         WordBase base = WordFactory.signed(input);
-        Unsigned unsigned = (Unsigned) base;
+        UnsignedWord unsigned = (UnsignedWord) base;
         Pointer pointer = (Pointer) unsigned;
         Word word = (Word) pointer;
         return word.rawValue();
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java	Mon Jul 17 16:31:51 2017 -0700
@@ -151,6 +151,13 @@
                         String name = zipEntry.getName();
                         if (name.endsWith(".class") && !name.equals("module-info.class")) {
                             String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
+                            if (isInNativeImage(className)) {
+                                /*
+                                 * Native image requires non-graalsdk classes to be present in the
+                                 * classpath.
+                                 */
+                                continue;
+                            }
                             try {
                                 checkClass(metaAccess, getSnippetReflection(), className);
                             } catch (ClassNotFoundException e) {
@@ -165,6 +172,10 @@
         }
     }
 
+    private static boolean isInNativeImage(String className) {
+        return className.startsWith("org.graalvm.nativeimage");
+    }
+
     protected void checkClass(MetaAccessProvider metaAccess, SnippetReflectionProvider snippetReflection, String className) throws ClassNotFoundException {
         Class<?> c = Class.forName(className, true, getClass().getClassLoader());
         ClassfileBytecodeProvider cbp = new ClassfileBytecodeProvider(metaAccess, snippetReflection);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Mon Jul 17 16:31:51 2017 -0700
@@ -32,6 +32,7 @@
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
+import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node.ValueNumberable;
 import org.graalvm.compiler.java.FrameStateBuilder;
@@ -206,7 +207,7 @@
                 method = providers.getMetaAccess().lookupJavaMethod(m);
             }
         }
-        assert method != null : "did not find method in " + declaringClass + " named " + name;
+        GraalError.guarantee(method != null, "Could not find %s.%s (%s)", declaringClass, name, isStatic ? "static" : "non-static");
         return method;
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java	Mon Jul 17 16:31:51 2017 -0700
@@ -26,8 +26,8 @@
 import org.graalvm.compiler.word.Word.Operation;
 import org.graalvm.word.LocationIdentity;
 import org.graalvm.word.Pointer;
-import org.graalvm.word.Signed;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.SignedWord;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordBase;
 
 /**
@@ -41,8 +41,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -56,8 +56,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -71,8 +71,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -86,8 +86,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -101,8 +101,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -116,8 +116,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -131,8 +131,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -146,8 +146,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -161,8 +161,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -275,8 +275,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -290,8 +290,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -305,8 +305,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -320,8 +320,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -335,8 +335,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -350,8 +350,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -365,8 +365,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -380,8 +380,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -395,8 +395,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -509,8 +509,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -523,8 +523,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -537,8 +537,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -551,8 +551,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -565,8 +565,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -579,8 +579,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -593,8 +593,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -607,8 +607,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -621,8 +621,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -725,8 +725,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -739,8 +739,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -753,8 +753,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -767,8 +767,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -781,8 +781,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -795,8 +795,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -809,8 +809,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -823,8 +823,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -837,8 +837,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java	Mon Jul 17 16:31:51 2017 -0700
@@ -26,8 +26,8 @@
 import org.graalvm.compiler.word.Word.Operation;
 import org.graalvm.word.LocationIdentity;
 import org.graalvm.word.Pointer;
-import org.graalvm.word.Signed;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.SignedWord;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordBase;
 
 /**
@@ -41,8 +41,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -56,8 +56,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -71,8 +71,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -86,8 +86,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -101,8 +101,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -116,8 +116,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -131,8 +131,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -146,8 +146,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -161,8 +161,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -275,8 +275,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -290,8 +290,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -305,8 +305,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -320,8 +320,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -335,8 +335,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -350,8 +350,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -365,8 +365,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -380,8 +380,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -395,8 +395,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -509,8 +509,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -523,8 +523,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -537,8 +537,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -551,8 +551,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -565,8 +565,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -579,8 +579,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -593,8 +593,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -607,8 +607,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -621,8 +621,8 @@
     /**
      * Reads the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -725,8 +725,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -739,8 +739,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -753,8 +753,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -767,8 +767,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -781,8 +781,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -795,8 +795,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -809,8 +809,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -823,8 +823,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
@@ -837,8 +837,8 @@
     /**
      * Writes the memory at address {@code (object + offset)}. The offset is in bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param object the base object for the memory access
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java	Mon Jul 17 16:31:51 2017 -0700
@@ -51,12 +51,21 @@
 import org.graalvm.word.ComparableWord;
 import org.graalvm.word.LocationIdentity;
 import org.graalvm.word.Pointer;
-import org.graalvm.word.Signed;
-import org.graalvm.word.Unsigned;
+import org.graalvm.word.SignedWord;
+import org.graalvm.word.UnsignedWord;
 import org.graalvm.word.WordBase;
 import org.graalvm.word.WordFactory;
 
-public abstract class Word extends WordFactory implements Signed, Unsigned, Pointer {
+public abstract class Word extends WordFactory implements SignedWord, UnsignedWord, Pointer {
+
+    static {
+        assert WordFactory.boxFactory == null : "BoxFactory must be initialized only once.";
+        WordFactory.boxFactory = new BoxFactoryImpl();
+    }
+
+    public static void ensureInitialized() {
+        /* Calling this method ensures that the static initializer has been executed. */
+    }
 
     /**
      * Links a method to a canonical operation represented by an {@link Opcode} val.
@@ -166,13 +175,13 @@
 
     @Override
     @Operation(node = AddNode.class)
-    public Word add(Signed val) {
+    public Word add(SignedWord val) {
         return add((Word) val);
     }
 
     @Override
     @Operation(node = AddNode.class)
-    public Word add(Unsigned val) {
+    public Word add(UnsignedWord val) {
         return add((Word) val);
     }
 
@@ -189,13 +198,13 @@
 
     @Override
     @Operation(node = SubNode.class)
-    public Word subtract(Signed val) {
+    public Word subtract(SignedWord val) {
         return subtract((Word) val);
     }
 
     @Override
     @Operation(node = SubNode.class)
-    public Word subtract(Unsigned val) {
+    public Word subtract(UnsignedWord val) {
         return subtract((Word) val);
     }
 
@@ -212,13 +221,13 @@
 
     @Override
     @Operation(node = MulNode.class)
-    public Word multiply(Signed val) {
+    public Word multiply(SignedWord val) {
         return multiply((Word) val);
     }
 
     @Override
     @Operation(node = MulNode.class)
-    public Word multiply(Unsigned val) {
+    public Word multiply(UnsignedWord val) {
         return multiply((Word) val);
     }
 
@@ -235,7 +244,7 @@
 
     @Override
     @Operation(node = SignedDivNode.class)
-    public Word signedDivide(Signed val) {
+    public Word signedDivide(SignedWord val) {
         return signedDivide((Word) val);
     }
 
@@ -252,7 +261,7 @@
 
     @Override
     @Operation(node = UnsignedDivNode.class)
-    public Word unsignedDivide(Unsigned val) {
+    public Word unsignedDivide(UnsignedWord val) {
         return unsignedDivide((Word) val);
     }
 
@@ -269,7 +278,7 @@
 
     @Override
     @Operation(node = SignedRemNode.class)
-    public Word signedRemainder(Signed val) {
+    public Word signedRemainder(SignedWord val) {
         return signedRemainder((Word) val);
     }
 
@@ -286,7 +295,7 @@
 
     @Override
     @Operation(node = UnsignedRemNode.class)
-    public Word unsignedRemainder(Unsigned val) {
+    public Word unsignedRemainder(UnsignedWord val) {
         return unsignedRemainder((Word) val);
     }
 
@@ -303,7 +312,7 @@
 
     @Override
     @Operation(node = LeftShiftNode.class, rightOperandIsInt = true)
-    public Word shiftLeft(Unsigned val) {
+    public Word shiftLeft(UnsignedWord val) {
         return shiftLeft((Word) val);
     }
 
@@ -320,7 +329,7 @@
 
     @Override
     @Operation(node = RightShiftNode.class, rightOperandIsInt = true)
-    public Word signedShiftRight(Unsigned val) {
+    public Word signedShiftRight(UnsignedWord val) {
         return signedShiftRight((Word) val);
     }
 
@@ -337,7 +346,7 @@
 
     @Override
     @Operation(node = UnsignedRightShiftNode.class, rightOperandIsInt = true)
-    public Word unsignedShiftRight(Unsigned val) {
+    public Word unsignedShiftRight(UnsignedWord val) {
         return unsignedShiftRight((Word) val);
     }
 
@@ -354,13 +363,13 @@
 
     @Override
     @Operation(node = AndNode.class)
-    public Word and(Signed val) {
+    public Word and(SignedWord val) {
         return and((Word) val);
     }
 
     @Override
     @Operation(node = AndNode.class)
-    public Word and(Unsigned val) {
+    public Word and(UnsignedWord val) {
         return and((Word) val);
     }
 
@@ -377,13 +386,13 @@
 
     @Override
     @Operation(node = OrNode.class)
-    public Word or(Signed val) {
+    public Word or(SignedWord val) {
         return or((Word) val);
     }
 
     @Override
     @Operation(node = OrNode.class)
-    public Word or(Unsigned val) {
+    public Word or(UnsignedWord val) {
         return or((Word) val);
     }
 
@@ -400,13 +409,13 @@
 
     @Override
     @Operation(node = XorNode.class)
-    public Word xor(Signed val) {
+    public Word xor(SignedWord val) {
         return xor((Word) val);
     }
 
     @Override
     @Operation(node = XorNode.class)
-    public Word xor(Unsigned val) {
+    public Word xor(UnsignedWord val) {
         return xor((Word) val);
     }
 
@@ -447,13 +456,13 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
-    public boolean equal(Signed val) {
+    public boolean equal(SignedWord val) {
         return equal((Word) val);
     }
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.EQ)
-    public boolean equal(Unsigned val) {
+    public boolean equal(UnsignedWord val) {
         return equal((Word) val);
     }
 
@@ -476,13 +485,13 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
-    public boolean notEqual(Signed val) {
+    public boolean notEqual(SignedWord val) {
         return notEqual((Word) val);
     }
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.NE)
-    public boolean notEqual(Unsigned val) {
+    public boolean notEqual(UnsignedWord val) {
         return notEqual((Word) val);
     }
 
@@ -499,7 +508,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.LT)
-    public boolean lessThan(Signed val) {
+    public boolean lessThan(SignedWord val) {
         return lessThan((Word) val);
     }
 
@@ -516,7 +525,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.LE)
-    public boolean lessOrEqual(Signed val) {
+    public boolean lessOrEqual(SignedWord val) {
         return lessOrEqual((Word) val);
     }
 
@@ -533,7 +542,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.GT)
-    public boolean greaterThan(Signed val) {
+    public boolean greaterThan(SignedWord val) {
         return greaterThan((Word) val);
     }
 
@@ -550,7 +559,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.GE)
-    public boolean greaterOrEqual(Signed val) {
+    public boolean greaterOrEqual(SignedWord val) {
         return greaterOrEqual((Word) val);
     }
 
@@ -567,7 +576,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.BT)
-    public boolean belowThan(Unsigned val) {
+    public boolean belowThan(UnsignedWord val) {
         return belowThan((Word) val);
     }
 
@@ -584,7 +593,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.BE)
-    public boolean belowOrEqual(Unsigned val) {
+    public boolean belowOrEqual(UnsignedWord val) {
         return belowOrEqual((Word) val);
     }
 
@@ -601,7 +610,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.AT)
-    public boolean aboveThan(Unsigned val) {
+    public boolean aboveThan(UnsignedWord val) {
         return aboveThan((Word) val);
     }
 
@@ -618,7 +627,7 @@
 
     @Override
     @Operation(opcode = Opcode.COMPARISON, condition = Condition.AE)
-    public boolean aboveOrEqual(Unsigned val) {
+    public boolean aboveOrEqual(UnsignedWord val) {
         return aboveOrEqual((Word) val);
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.java	Mon Jul 17 16:31:51 2017 -0700
@@ -76,6 +76,7 @@
         this.objectAccessType = metaAccess.lookupJavaType(ObjectAccess.class);
         this.barrieredAccessType = metaAccess.lookupJavaType(BarrieredAccess.class);
 
+        Word.ensureInitialized();
         this.wordImplType.initialize();
     }
 
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionCategory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -25,7 +25,7 @@
 package org.graalvm.options;
 
 /**
- * Classifies options in several categories depending on who this option is relevant for.
+ * Categorizes options according to user relevance.
  *
  * @since 1.0
  */
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptor.java	Mon Jul 17 16:31:51 2017 -0700
@@ -27,7 +27,7 @@
 import java.util.Objects;
 
 /**
- * Represents meta-data for a single option.
+ * Represents metadata for a single option.
  *
  * @since 1.0
  */
@@ -48,7 +48,7 @@
     }
 
     /**
-     * Returns the option name of the option represented by this descriptor.
+     * Returns the name of the option that this descriptor represents.
      *
      * @since 1.0
      */
@@ -185,7 +185,7 @@
         }
 
         /**
-         * Defines whether this option is deprecated. The default value for deprecated is
+         * Defines if 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
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionDescriptors.java	Mon Jul 17 16:31:51 2017 -0700
@@ -57,14 +57,14 @@
 
     /**
      * Gets the {@link OptionDescriptor} matching a given option name or {@code null} if this option
-     * descriptor set doesn't contain a matching option name.
+     * descriptor set does not contain a matching option name.
      *
      * @since 1.0
      */
     OptionDescriptor get(String optionName);
 
     /**
-     * Create a union options descriptor out of multiple given descriptors. The operation
+     * Creates 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.
      *
@@ -89,7 +89,7 @@
     Iterator<OptionDescriptor> iterator();
 
     /**
-     * Create an {@link OptionDescriptors} instance from a list. The option descriptors
+     * Creates an {@link OptionDescriptors} instance from a list. The option descriptors
      * implementation is backed by a {@link LinkedHashMap} that preserves ordering.
      *
      * @since 1.0
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionKey.java	Mon Jul 17 16:31:51 2017 -0700
@@ -27,7 +27,7 @@
 import java.util.Objects;
 
 /**
- * Represents the option key for a option specification.
+ * Represents the option key for an option specification.
  *
  * @since 1.0
  */
@@ -48,12 +48,12 @@
         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.");
+            throw new IllegalArgumentException("No default type specified for type " + defaultValue.getClass().getName() + ". Specify the option type explicitly to resolve this.");
         }
     }
 
     /**
-     * Contructs a new option key givena default value and option key. The default value and the
+     * Constructs a new option key given a default value and option key. The default value and the
      * type must not be <code>null</code>.
      *
      * @since 1.0
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionType.java	Mon Jul 17 16:31:51 2017 -0700
@@ -31,7 +31,7 @@
 import java.util.function.Function;
 
 /**
- * Represents a type of an option that allows to convert string values to a java value.
+ * Represents a type of an option that allows to convert string values to Java values.
  *
  * @since 1.0
  */
@@ -43,13 +43,13 @@
     private final T defaultValue;
 
     /**
-     * Constructs a new option type with name, defaultValue and function that allows to convert a
+     * 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 name the name of the type.
+     * @param defaultValue the default value to use if no value is given.
+     * @param stringConverter a function that converts a string value to the 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.
      *
@@ -67,13 +67,13 @@
     }
 
     /**
-     * Constructs a new option type with name, defaultValue and function that allows to convert a
+     * 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 name the name of the type.
+     * @param defaultValue the default value to use if no value is given.
+     * @param stringConverter a function that converts a string value to the option value. Can throw
+     *            {@link IllegalArgumentException} to indicate an invalid string.
      *
      * @since 1.0
      */
@@ -85,7 +85,7 @@
     }
 
     /**
-     * Returns the default value of this type, to be used if no value is available.
+     * Returns the default value of this type. Used if no value is available.
      *
      * @since 1.0
      */
@@ -103,7 +103,7 @@
     }
 
     /**
-     * Converts a string value, validates it and converts it to an object of this type.
+     * 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
@@ -115,7 +115,8 @@
     }
 
     /**
-     * Validates an option value and throws an {@link IllegalArgumentException} if it is invalid.
+     * Validates an option value and throws an {@link IllegalArgumentException} if the value is
+     * invalid.
      *
      * @throws IllegalArgumentException if the value is invalid or cannot be converted.
      * @since 1.0
@@ -199,7 +200,7 @@
 
     /**
      * Returns the default option type for a given value. Returns <code>null</code> if no default
-     * option type is available for this java type.
+     * option type is available for this Java type.
      *
      * @since 1.0
      */
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.options/src/org/graalvm/options/OptionValues.java	Mon Jul 17 16:31:51 2017 -0700
@@ -42,8 +42,8 @@
      * Sets the value of {@code optionKey} to {@code value}.
      *
      * @throws IllegalArgumentException if the given value is not {@link OptionType#validate(Object)
-     *             validated} by the {@link OptionKey#getType() option type} of the key. Please note
-     *             that the operation does not fail if the option key is not described by any of the
+     *             validated} by the {@link OptionKey#getType() option type} of the key. Note that
+     *             the operation succeeds if the option key is not described by any of the
      *             associated {@link #getDescriptors() descriptors}.
      *
      * @since 1.0
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/AtomicUnsigned.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  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.word;
-
-/**
- * A {@link Unsigned} value that may be updated atomically. See the
- * {@link java.util.concurrent.atomic} package specification for description of the properties of
- * atomic variables.
- */
-public class AtomicUnsigned extends AtomicWord<Unsigned> {
-
-    /**
-     * Atomically adds the given value to the current value.
-     *
-     * @param delta the value to add
-     * @return the previous value
-     */
-    public final Unsigned getAndAdd(Unsigned delta) {
-        return WordFactory.unsigned(value.getAndAdd(delta.rawValue()));
-    }
-
-    /**
-     * Atomically adds the given value to the current value.
-     *
-     * @param delta the value to add
-     * @return the updated value
-     */
-    public final Unsigned addAndGet(Unsigned delta) {
-        return WordFactory.unsigned(value.addAndGet(delta.rawValue()));
-    }
-
-    /**
-     * Atomically subtracts the given value from the current value.
-     *
-     * @param delta the value to add
-     * @return the previous value
-     */
-    public final Unsigned getAndSubtract(Unsigned delta) {
-        return WordFactory.unsigned(value.getAndAdd(-delta.rawValue()));
-    }
-
-    /**
-     * Atomically subtracts the given value from the current value.
-     *
-     * @param delta the value to add
-     * @return the updated value
-     */
-    public final Unsigned subtractAndGet(Unsigned delta) {
-        return WordFactory.unsigned(value.addAndGet(-delta.rawValue()));
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/AtomicWord.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  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.word;
-
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * A {@link WordBase word} value that may be updated atomically. See the
- * {@link java.util.concurrent.atomic} package specification for description of the properties of
- * atomic variables.
- *
- * Similar to {@link AtomicReference}, but for {@link WordBase word} types. A dedicated
- * implementation is necessary because Object and word types cannot be mixed.
- */
-public class AtomicWord<T extends WordBase> {
-
-    /**
-     * For simplicity, we convert the word value to a long and delegate to existing atomic
-     * operations.
-     */
-    protected final AtomicLong value;
-
-    /**
-     * Creates a new AtomicWord with initial value {@link WordFactory#zero}.
-     */
-    public AtomicWord() {
-        value = new AtomicLong();
-    }
-
-    /**
-     * Gets the current value.
-     *
-     * @return the current value
-     */
-    public final T get() {
-        return WordFactory.unsigned(value.get());
-    }
-
-    /**
-     * Sets to the given value.
-     *
-     * @param newValue the new value
-     */
-    public final void set(T newValue) {
-        value.set(newValue.rawValue());
-    }
-
-    /**
-     * Atomically sets to the given value and returns the old value.
-     *
-     * @param newValue the new value
-     * @return the previous value
-     */
-    public final T getAndSet(T newValue) {
-        return WordFactory.unsigned(value.getAndSet(newValue.rawValue()));
-    }
-
-    /**
-     * Atomically sets the value to the given updated value if the current value {@code ==} the
-     * expected value.
-     *
-     * @param expect the expected value
-     * @param update the new value
-     * @return {@code true} if successful. False return indicates that the actual value was not
-     *         equal to the expected value.
-     */
-    public final boolean compareAndSet(T expect, T update) {
-        return value.compareAndSet(expect.rawValue(), update.rawValue());
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Pointer.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Pointer.java	Mon Jul 17 16:31:51 2017 -0700
@@ -31,7 +31,7 @@
  * null checks, read- or write barriers. Even when the VM uses compressed pointers, then readObject
  * and writeObject methods access uncompressed pointers.
  */
-public interface Pointer extends Unsigned, PointerBase {
+public interface Pointer extends UnsignedWord, PointerBase {
 
     /**
      * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
@@ -55,8 +55,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -69,8 +69,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -83,8 +83,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -97,8 +97,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -111,8 +111,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -125,8 +125,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -139,8 +139,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -153,8 +153,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -167,8 +167,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -271,8 +271,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -285,8 +285,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -299,8 +299,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -313,8 +313,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -327,8 +327,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -341,8 +341,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -355,8 +355,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -369,8 +369,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -383,8 +383,8 @@
      * Initializes the memory at address {@code (this + offset)}. Both the base address and offset
      * are in bytes. The memory must be uninitialized or zero prior to this operation.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -397,8 +397,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -511,8 +511,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -524,8 +524,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -537,8 +537,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -550,8 +550,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -563,8 +563,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -576,8 +576,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -589,8 +589,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -602,8 +602,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -615,8 +615,8 @@
      * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -709,8 +709,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -722,8 +722,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -735,8 +735,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -748,8 +748,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -761,8 +761,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -774,8 +774,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -787,8 +787,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -800,8 +800,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -813,8 +813,8 @@
      * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
      * bytes.
      * <p>
-     * The offset is always treated as a {@link Signed} value. However, the static type is
-     * {@link WordBase} to avoid the frequent casts to of {@link Unsigned} values (where the caller
+     * The offset is always treated as a {@link SignedWord} value. However, the static type is
+     * {@link WordBase} to avoid the frequent casts of {@link UnsignedWord} values (where the caller
      * knows that the highest-order bit of the unsigned value is never used).
      *
      * @param offset the signed offset for the memory access
@@ -940,25 +940,25 @@
     // It is therefore safe that they return a static type of Pointer instead of Unsigned.
 
     @Override
-    Pointer add(Unsigned val);
+    Pointer add(UnsignedWord val);
 
     @Override
     Pointer add(int val);
 
     @Override
-    Pointer subtract(Unsigned val);
+    Pointer subtract(UnsignedWord val);
 
     @Override
     Pointer subtract(int val);
 
     @Override
-    Pointer and(Unsigned val);
+    Pointer and(UnsignedWord val);
 
     @Override
     Pointer and(int val);
 
     @Override
-    Pointer or(Unsigned val);
+    Pointer or(UnsignedWord val);
 
     @Override
     Pointer or(int val);
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerUtils.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,139 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  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.word;
-
-/**
- * Utility methods on Pointers.
- */
-public final class PointerUtils {
-
-    private PointerUtils() {
-        // This is a class of static methods, so no need for any instances.
-    }
-
-    /**
-     * The value of a null Pointer.
-     *
-     * @return A null Pointer value.
-     */
-    public static <T extends PointerBase> T nullPointer() {
-        /* This method will be deleted soon. */
-        return WordFactory.nullPointer();
-    }
-
-    /**
-     * Predicate to check for the null Pointer value.
-     *
-     * @return Whether that Pointer is the null Pointer.
-     */
-    public static boolean isNull(ComparableWord that) {
-        /* This method will be deleted soon. */
-        return ((PointerBase) that).isNull();
-    }
-
-    /**
-     * Predicate to check for a non-null Pointer value.
-     *
-     * @return Whether that Pointer is not the null Pointer.
-     */
-    public static boolean isNonNull(ComparableWord that) {
-        /* This method will be deleted soon. */
-        return ((PointerBase) that).isNonNull();
-    }
-
-    /**
-     * Round a Pointer down to the nearest smaller multiple.
-     *
-     * @param that The Pointer to be rounded up.
-     * @param multiple The multiple to which that Pointer should be decreased.
-     * @return That Pointer, but rounded down.
-     */
-    public static Pointer roundDown(PointerBase that, Unsigned multiple) {
-        return (Pointer) UnsignedUtils.roundDown((Unsigned) that, multiple);
-    }
-
-    /**
-     * Round a Pointer up to the nearest larger multiple.
-     *
-     * @param that The Pointer to be rounded up.
-     * @param multiple The multiple to which that Pointer should be increased.
-     * @return That Pointer, but rounded up.
-     */
-    public static Pointer roundUp(PointerBase that, Unsigned multiple) {
-        return (Pointer) UnsignedUtils.roundUp((Unsigned) that, multiple);
-    }
-
-    /**
-     * Check that a Pointer is an even multiple.
-     *
-     * @param that The Pointer to be verified as a multiple.
-     * @param multiple The multiple against which the Pointer should be verified.
-     * @return true if that Pointer is a multiple, false otherwise.
-     */
-    public static boolean isAMultiple(PointerBase that, Unsigned multiple) {
-        return that.equal(PointerUtils.roundDown(that, multiple));
-    }
-
-    /**
-     * Return the distance between two Pointers.
-     *
-     * @param pointer1 A first Pointer.
-     * @param pointer2 A second Pointer.
-     * @return The distance in bytes between the two Pointers.
-     */
-    public static Unsigned absoluteDifference(PointerBase pointer1, PointerBase pointer2) {
-        Pointer p1 = (Pointer) pointer1;
-        Pointer p2 = (Pointer) pointer2;
-        final Unsigned result;
-        if (p1.aboveOrEqual(p2)) {
-            result = p1.subtract(p2);
-        } else {
-            result = p2.subtract(p1);
-        }
-        return result;
-    }
-
-    /**
-     * The minimum of two Pointers.
-     *
-     * @param x A Pointer.
-     * @param y Another Pointer.
-     * @return The whichever Pointer is smaller.
-     */
-    public static <T extends PointerBase> T min(T x, T y) {
-        return (((Pointer) x).belowOrEqual((Pointer) y)) ? x : y;
-    }
-
-    /**
-     * The maximum of two Pointers.
-     *
-     * @param x A Pointer.
-     * @param y Another Pointer.
-     * @return The whichever Pointer is larger.
-     */
-    public static <T extends PointerBase> T max(T x, T y) {
-        return (((Pointer) x).aboveOrEqual((Pointer) y)) ? x : y;
-    }
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Signed.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,298 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, 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.word;
-
-public interface Signed extends ComparableWord {
-
-    /**
-     * Returns a Signed whose value is {@code (this + val)}.
-     *
-     * @param val value to be added to this Signed.
-     * @return {@code this + val}
-     */
-    Signed add(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this - val)}.
-     *
-     * @param val value to be subtracted from this Signed.
-     * @return {@code this - val}
-     */
-    Signed subtract(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this * val)}.
-     *
-     * @param val value to be multiplied by this Signed.
-     * @return {@code this * val}
-     */
-    Signed multiply(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this / val)}.
-     *
-     * @param val value by which this Signed is to be divided.
-     * @return {@code this / val}
-     */
-    Signed signedDivide(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this % val)}.
-     *
-     * @param val value by which this Signed is to be divided, and the remainder computed.
-     * @return {@code this % val}
-     */
-    Signed signedRemainder(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this << n)}.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this << n}
-     */
-    Signed shiftLeft(Unsigned n);
-
-    /**
-     * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this >> n}
-     */
-    Signed signedShiftRight(Unsigned n);
-
-    /**
-     * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
-     * if and only if this and val are both negative.)
-     *
-     * @param val value to be AND'ed with this Signed.
-     * @return {@code this & val}
-     */
-    Signed and(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
-     * if and only if either this or val is negative.)
-     *
-     * @param val value to be OR'ed with this Signed.
-     * @return {@code this | val}
-     */
-    Signed or(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
-     * if and only if exactly one of this and val are negative.)
-     *
-     * @param val value to be XOR'ed with this Signed.
-     * @return {@code this ^ val}
-     */
-    Signed xor(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and
-     * only if this Signed is non-negative.)
-     *
-     * @return {@code ~this}
-     */
-    Signed not();
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this == val}
-     */
-    boolean equal(Signed val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this != val}
-     */
-    boolean notEqual(Signed val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this < val}
-     */
-    boolean lessThan(Signed val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this <= val}
-     */
-    boolean lessOrEqual(Signed val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this > val}
-     */
-    boolean greaterThan(Signed val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this >= val}
-     */
-    boolean greaterOrEqual(Signed val);
-
-    /**
-     * Returns a Signed whose value is {@code (this + val)}.
-     *
-     * @param val value to be added to this Signed.
-     * @return {@code this + val}
-     */
-    Signed add(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this - val)}.
-     *
-     * @param val value to be subtracted from this Signed.
-     * @return {@code this - val}
-     */
-    Signed subtract(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this * val)}.
-     *
-     * @param val value to be multiplied by this Signed.
-     * @return {@code this * val}
-     */
-    Signed multiply(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this / val)}.
-     *
-     * @param val value by which this Signed is to be divided.
-     * @return {@code this / val}
-     */
-    Signed signedDivide(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this % val)}.
-     *
-     * @param val value by which this Signed is to be divided, and the remainder computed.
-     * @return {@code this % val}
-     */
-    Signed signedRemainder(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this << n)}.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this << n}
-     */
-    Signed shiftLeft(int n);
-
-    /**
-     * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this >> n}
-     */
-    Signed signedShiftRight(int n);
-
-    /**
-     * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
-     * if and only if this and val are both negative.)
-     *
-     * @param val value to be AND'ed with this Signed.
-     * @return {@code this & val}
-     */
-    Signed and(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
-     * if and only if either this or val is negative.)
-     *
-     * @param val value to be OR'ed with this Signed.
-     * @return {@code this | val}
-     */
-    Signed or(int val);
-
-    /**
-     * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
-     * if and only if exactly one of this and val are negative.)
-     *
-     * @param val value to be XOR'ed with this Signed.
-     * @return {@code this ^ val}
-     */
-    Signed xor(int val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this == val}
-     */
-    boolean equal(int val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this != val}
-     */
-    boolean notEqual(int val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this < val}
-     */
-    boolean lessThan(int val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this <= val}
-     */
-    boolean lessOrEqual(int val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this > val}
-     */
-    boolean greaterThan(int val);
-
-    /**
-     * Compares this Signed with the specified value.
-     *
-     * @param val value to which this Signed is to be compared.
-     * @return {@code this >= val}
-     */
-    boolean greaterOrEqual(int val);
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/SignedWord.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 2012, 2012, 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.word;
+
+public interface SignedWord extends ComparableWord {
+
+    /**
+     * Returns a Signed whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Signed.
+     * @return {@code this + val}
+     */
+    SignedWord add(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Signed.
+     * @return {@code this - val}
+     */
+    SignedWord subtract(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this * val)}.
+     *
+     * @param val value to be multiplied by this Signed.
+     * @return {@code this * val}
+     */
+    SignedWord multiply(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this / val)}.
+     *
+     * @param val value by which this Signed is to be divided.
+     * @return {@code this / val}
+     */
+    SignedWord signedDivide(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this % val)}.
+     *
+     * @param val value by which this Signed is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    SignedWord signedRemainder(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    SignedWord shiftLeft(UnsignedWord n);
+
+    /**
+     * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    SignedWord signedShiftRight(UnsignedWord n);
+
+    /**
+     * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
+     * if and only if this and val are both negative.)
+     *
+     * @param val value to be AND'ed with this Signed.
+     * @return {@code this & val}
+     */
+    SignedWord and(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
+     * if and only if either this or val is negative.)
+     *
+     * @param val value to be OR'ed with this Signed.
+     * @return {@code this | val}
+     */
+    SignedWord or(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
+     * if and only if exactly one of this and val are negative.)
+     *
+     * @param val value to be XOR'ed with this Signed.
+     * @return {@code this ^ val}
+     */
+    SignedWord xor(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (~this)}. (This method returns a negative value if and
+     * only if this Signed is non-negative.)
+     *
+     * @return {@code ~this}
+     */
+    SignedWord not();
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(SignedWord val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(SignedWord val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this < val}
+     */
+    boolean lessThan(SignedWord val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean lessOrEqual(SignedWord val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this > val}
+     */
+    boolean greaterThan(SignedWord val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean greaterOrEqual(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Signed.
+     * @return {@code this + val}
+     */
+    SignedWord add(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Signed.
+     * @return {@code this - val}
+     */
+    SignedWord subtract(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this * val)}.
+     *
+     * @param val value to be multiplied by this Signed.
+     * @return {@code this * val}
+     */
+    SignedWord multiply(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this / val)}.
+     *
+     * @param val value by which this Signed is to be divided.
+     * @return {@code this / val}
+     */
+    SignedWord signedDivide(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this % val)}.
+     *
+     * @param val value by which this Signed is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    SignedWord signedRemainder(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    SignedWord shiftLeft(int n);
+
+    /**
+     * Returns a Signed whose value is {@code (this >> n)}. Sign extension is performed.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    SignedWord signedShiftRight(int n);
+
+    /**
+     * Returns a Signed whose value is {@code (this & val)}. (This method returns a negative Signed
+     * if and only if this and val are both negative.)
+     *
+     * @param val value to be AND'ed with this Signed.
+     * @return {@code this & val}
+     */
+    SignedWord and(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this | val)}. (This method returns a negative Signed
+     * if and only if either this or val is negative.)
+     *
+     * @param val value to be OR'ed with this Signed.
+     * @return {@code this | val}
+     */
+    SignedWord or(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this ^ val)}. (This method returns a negative Signed
+     * if and only if exactly one of this and val are negative.)
+     *
+     * @param val value to be XOR'ed with this Signed.
+     * @return {@code this ^ val}
+     */
+    SignedWord xor(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this < val}
+     */
+    boolean lessThan(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean lessOrEqual(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this > val}
+     */
+    boolean greaterThan(int val);
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean greaterOrEqual(int val);
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Unsigned.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,339 +0,0 @@
-/*
- * Copyright (c) 2012, 2012, 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.word;
-
-public interface Unsigned extends ComparableWord {
-
-    /**
-     * Returns a Unsigned whose value is {@code (this + val)}.
-     *
-     * @param val value to be added to this Unsigned.
-     * @return {@code this + val}
-     */
-    Unsigned add(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this - val)}.
-     *
-     * @param val value to be subtracted from this Unsigned.
-     * @return {@code this - val}
-     */
-    Unsigned subtract(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this * val)}.
-     *
-     * @param val value to be multiplied by this Unsigned.
-     * @return {@code this * val}
-     */
-    Unsigned multiply(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this / val)}.
-     *
-     * @param val value by which this Unsigned is to be divided.
-     * @return {@code this / val}
-     */
-    Unsigned unsignedDivide(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this % val)}.
-     *
-     * @param val value by which this Unsigned is to be divided, and the remainder computed.
-     * @return {@code this % val}
-     */
-    Unsigned unsignedRemainder(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this << n)}.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this << n}
-     */
-    Unsigned shiftLeft(Unsigned n);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this >> n}
-     */
-    Unsigned unsignedShiftRight(Unsigned n);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this & val)}.
-     *
-     * @param val value to be AND'ed with this Unsigned.
-     * @return {@code this & val}
-     */
-    Unsigned and(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this | val)}.
-     *
-     * @param val value to be OR'ed with this Unsigned.
-     * @return {@code this | val}
-     */
-    Unsigned or(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this ^ val)}.
-     *
-     * @param val value to be XOR'ed with this Unsigned.
-     * @return {@code this ^ val}
-     */
-    Unsigned xor(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (~this)}.
-     *
-     * @return {@code ~this}
-     */
-    Unsigned not();
-
-    /**
-     * Compares this Unsigned with the specified value.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this == val}
-     */
-    boolean equal(Unsigned val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this != val}
-     */
-    boolean notEqual(Unsigned val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this < val}
-     */
-    boolean belowThan(Unsigned val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this <= val}
-     */
-    boolean belowOrEqual(Unsigned val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this > val}
-     */
-    boolean aboveThan(Unsigned val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this >= val}
-     */
-    boolean aboveOrEqual(Unsigned val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this + val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to be added to this Unsigned.
-     * @return {@code this + val}
-     */
-    Unsigned add(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this - val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to be subtracted from this Unsigned.
-     * @return {@code this - val}
-     */
-    Unsigned subtract(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this * val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to be multiplied by this Unsigned.
-     * @return {@code this * val}
-     */
-    Unsigned multiply(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this / val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value by which this Unsigned is to be divided.
-     * @return {@code this / val}
-     */
-    Unsigned unsignedDivide(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this % val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value by which this Unsigned is to be divided, and the remainder computed.
-     * @return {@code this % val}
-     */
-    Unsigned unsignedRemainder(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this << n)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this << n}
-     */
-    Unsigned shiftLeft(int n);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param n shift distance, in bits.
-     * @return {@code this >> n}
-     */
-    Unsigned unsignedShiftRight(int n);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this & val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to be AND'ed with this Unsigned.
-     * @return {@code this & val}
-     */
-    Unsigned and(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this | val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to be OR'ed with this Unsigned.
-     * @return {@code this | val}
-     */
-    Unsigned or(int val);
-
-    /**
-     * Returns a Unsigned whose value is {@code (this ^ val)}.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to be XOR'ed with this Unsigned.
-     * @return {@code this ^ val}
-     */
-    Unsigned xor(int val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this == val}
-     */
-    boolean equal(int val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this != val}
-     */
-    boolean notEqual(int val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this < val}
-     */
-    boolean belowThan(int val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this <= val}
-     */
-    boolean belowOrEqual(int val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this > val}
-     */
-    boolean aboveThan(int val);
-
-    /**
-     * Compares this Unsigned with the specified value.
-     * <p>
-     * Note that the right operand is a signed value, while the operation is performed unsigned.
-     * Therefore, the result is only well-defined for positive right operands.
-     *
-     * @param val value to which this Unsigned is to be compared.
-     * @return {@code this >= val}
-     */
-    boolean aboveOrEqual(int val);
-}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedUtils.java	Mon Jul 17 09:21:48 2017 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2015, 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.  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.word;
-
-/**
- * Utility methods on Unsigned values.
- */
-public final class UnsignedUtils {
-
-    private UnsignedUtils() {
-        // This is a class of static methods, so no need for any instances.
-    }
-
-    /**
-     * Round an Unsigned down to the nearest smaller multiple.
-     *
-     * @param that The Unsigned to be rounded down.
-     * @param multiple The multiple to which that Unsigned should be decreased.
-     * @return That Unsigned, but rounded down.
-     */
-    public static Unsigned roundDown(Unsigned that, Unsigned multiple) {
-        return that.unsignedDivide(multiple).multiply(multiple);
-    }
-
-    /**
-     * Round an Unsigned up to the nearest larger multiple.
-     *
-     * @param that The Unsigned to be rounded up.
-     * @param multiple The multiple to which that Unsigned should be increased.
-     * @return That Unsigned, but rounded up.
-     */
-    public static Unsigned roundUp(Unsigned that, Unsigned multiple) {
-        return UnsignedUtils.roundDown(that.add(multiple.subtract(1)), multiple);
-    }
-
-    /**
-     * Check that an Unsigned is an even multiple.
-     *
-     * @param that The Unsigned to be verified as a multiple.
-     * @param multiple The multiple against which the Unsigned should be verified.
-     * @return true if that Unsigned is a multiple, false otherwise.
-     */
-    public static boolean isAMultiple(Unsigned that, Unsigned multiple) {
-        return that.equal(UnsignedUtils.roundDown(that, multiple));
-    }
-
-    /**
-     * The minimum of two Unsigneds.
-     *
-     * @param x An Unsigned.
-     * @param y Another Unsigned.
-     * @return The whichever Unsigned is smaller.
-     */
-    public static Unsigned min(Unsigned x, Unsigned y) {
-        return (x.belowOrEqual(y)) ? x : y;
-    }
-
-    /**
-     * The maximum of two Unsigneds.
-     *
-     * @param x An Unsigned.
-     * @param y Another Unsigned.
-     * @return The whichever Unsigned is larger.
-     */
-    public static Unsigned max(Unsigned x, Unsigned y) {
-        return (x.aboveOrEqual(y)) ? x : y;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedWord.java	Mon Jul 17 16:31:51 2017 -0700
@@ -0,0 +1,339 @@
+/*
+ * Copyright (c) 2012, 2012, 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.word;
+
+public interface UnsignedWord extends ComparableWord {
+
+    /**
+     * Returns a Unsigned whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Unsigned.
+     * @return {@code this + val}
+     */
+    UnsignedWord add(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Unsigned.
+     * @return {@code this - val}
+     */
+    UnsignedWord subtract(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this * val)}.
+     *
+     * @param val value to be multiplied by this Unsigned.
+     * @return {@code this * val}
+     */
+    UnsignedWord multiply(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this / val)}.
+     *
+     * @param val value by which this Unsigned is to be divided.
+     * @return {@code this / val}
+     */
+    UnsignedWord unsignedDivide(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this % val)}.
+     *
+     * @param val value by which this Unsigned is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    UnsignedWord unsignedRemainder(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    UnsignedWord shiftLeft(UnsignedWord n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    UnsignedWord unsignedShiftRight(UnsignedWord n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this & val)}.
+     *
+     * @param val value to be AND'ed with this Unsigned.
+     * @return {@code this & val}
+     */
+    UnsignedWord and(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this | val)}.
+     *
+     * @param val value to be OR'ed with this Unsigned.
+     * @return {@code this | val}
+     */
+    UnsignedWord or(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this ^ val)}.
+     *
+     * @param val value to be XOR'ed with this Unsigned.
+     * @return {@code this ^ val}
+     */
+    UnsignedWord xor(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (~this)}.
+     *
+     * @return {@code ~this}
+     */
+    UnsignedWord not();
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(UnsignedWord val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(UnsignedWord val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this < val}
+     */
+    boolean belowThan(UnsignedWord val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean belowOrEqual(UnsignedWord val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this > val}
+     */
+    boolean aboveThan(UnsignedWord val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean aboveOrEqual(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this + val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to be added to this Unsigned.
+     * @return {@code this + val}
+     */
+    UnsignedWord add(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this - val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to be subtracted from this Unsigned.
+     * @return {@code this - val}
+     */
+    UnsignedWord subtract(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this * val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to be multiplied by this Unsigned.
+     * @return {@code this * val}
+     */
+    UnsignedWord multiply(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this / val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value by which this Unsigned is to be divided.
+     * @return {@code this / val}
+     */
+    UnsignedWord unsignedDivide(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this % val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value by which this Unsigned is to be divided, and the remainder computed.
+     * @return {@code this % val}
+     */
+    UnsignedWord unsignedRemainder(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this << n)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     */
+    UnsignedWord shiftLeft(int n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this >>> n)}. No sign extension is performed.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this >> n}
+     */
+    UnsignedWord unsignedShiftRight(int n);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this & val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to be AND'ed with this Unsigned.
+     * @return {@code this & val}
+     */
+    UnsignedWord and(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this | val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to be OR'ed with this Unsigned.
+     * @return {@code this | val}
+     */
+    UnsignedWord or(int val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this ^ val)}.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to be XOR'ed with this Unsigned.
+     * @return {@code this ^ val}
+     */
+    UnsignedWord xor(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this == val}
+     */
+    boolean equal(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this != val}
+     */
+    boolean notEqual(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this < val}
+     */
+    boolean belowThan(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this <= val}
+     */
+    boolean belowOrEqual(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this > val}
+     */
+    boolean aboveThan(int val);
+
+    /**
+     * Compares this Unsigned with the specified value.
+     * <p>
+     * Note that the right operand is a signed value, while the operation is performed unsigned.
+     * Therefore, the result is only well-defined for positive right operands.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this >= val}
+     */
+    boolean aboveOrEqual(int val);
+}
--- a/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java	Mon Jul 17 09:21:48 2017 -0700
+++ b/hotspot/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java	Mon Jul 17 16:31:51 2017 -0700
@@ -28,7 +28,6 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
-import java.lang.reflect.InvocationTargetException;
 
 public abstract class WordFactory {
 
@@ -54,19 +53,7 @@
         <T extends WordBase> T box(long val);
     }
 
-    protected static final BoxFactory boxFactory;
-
-    static {
-        try {
-            /*
-             * We know the implementation class, but cannot reference it statically because we need
-             * to break the dependency between the interface and the implementation.
-             */
-            boxFactory = (BoxFactory) Class.forName("org.graalvm.compiler.word.Word$BoxFactoryImpl").getConstructor().newInstance();
-        } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
-            throw new ExceptionInInitializerError("Could not find and initialize the word type factory. The Graal compiler needs to be on the class path to use the word type.");
-        }
-    }
+    protected static BoxFactory boxFactory;
 
     /**
      * We allow subclassing, because only subclasses can access the protected inner classes that we
@@ -105,7 +92,7 @@
      * @return the value cast to Word
      */
     @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
-    public static <T extends Unsigned> T unsigned(long val) {
+    public static <T extends UnsignedWord> T unsigned(long val) {
         return boxFactory.box(val);
     }
 
@@ -129,7 +116,7 @@
      * @return the value cast to Word
      */
     @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
-    public static <T extends Unsigned> T unsigned(int val) {
+    public static <T extends UnsignedWord> T unsigned(int val) {
         return boxFactory.box(val & 0xffffffffL);
     }
 
@@ -141,7 +128,7 @@
      * @return the value cast to Word
      */
     @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
-    public static <T extends Signed> T signed(long val) {
+    public static <T extends SignedWord> T signed(long val) {
         return boxFactory.box(val);
     }
 
@@ -153,7 +140,7 @@
      * @return the value cast to Word
      */
     @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
-    public static <T extends Signed> T signed(int val) {
+    public static <T extends SignedWord> T signed(int val) {
         return boxFactory.box(val);
     }
 }