Merge epsilon-gc-branch
authorshade
Thu, 26 Apr 2018 17:59:02 +0200
branchepsilon-gc-branch
changeset 56489 016b77c3734a
parent 56473 63a5ea2cdd0d (current diff)
parent 49900 770679787db5 (diff)
child 56490 0d0e6b083a3f
Merge
src/hotspot/share/c1/c1_LIRGenerator.cpp
src/hotspot/share/gc/shared/collectedHeap.hpp
src/hotspot/share/gc/shared/commandLineFlagConstraintsGC.cpp
src/hotspot/share/gc/shared/commandLineFlagConstraintsGC.hpp
src/hotspot/share/memory/universe.cpp
src/hotspot/share/precompiled/precompiled.hpp
src/hotspot/share/runtime/arguments.cpp
src/hotspot/share/runtime/arguments.hpp
src/hotspot/share/runtime/commandLineFlagConstraintList.cpp
src/hotspot/share/runtime/commandLineFlagConstraintList.hpp
src/hotspot/share/runtime/commandLineFlagConstraintsCompiler.cpp
src/hotspot/share/runtime/commandLineFlagConstraintsCompiler.hpp
src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.cpp
src/hotspot/share/runtime/commandLineFlagConstraintsRuntime.hpp
src/hotspot/share/runtime/commandLineFlagRangeList.cpp
src/hotspot/share/runtime/commandLineFlagRangeList.hpp
src/hotspot/share/runtime/commandLineFlagWriteableList.cpp
src/hotspot/share/runtime/commandLineFlagWriteableList.hpp
src/hotspot/share/runtime/globals.cpp
src/hotspot/share/runtime/globals.hpp
src/hotspot/share/runtime/globals_extension.hpp
src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java
src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c
src/java.base/windows/native/libnet/portconfig.c
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CoreCompilerConfigurationFactory.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValuesAccess.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadReplacementPhase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JDK9Method.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual.bench/.checkstyle.exclude
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/ComparableWord.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/LocationIdentity.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Pointer.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerBase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/SignedWord.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedWord.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordBase.java
src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ImplementedMethods.java
src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java
test/hotspot/jtreg/TEST.groups
test/hotspot/jtreg/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm
test/hotspot/jtreg/runtime/appcds/javaldr/CheckAnonymousClass.java
test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main2.jasm
test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/javax/activation/UnsupportedDataTypeException2.jasm
test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/javax/activation/UnsupportedDataTypeException.java
test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/module-info.java
test/hotspot/jtreg/runtime/appcds/test-classes/javax/activation/MimeType.jasm
--- a/make/CompileJavaModules.gmk	Mon Apr 23 12:53:43 2018 +0200
+++ b/make/CompileJavaModules.gmk	Thu Apr 26 17:59:02 2018 +0200
@@ -439,7 +439,7 @@
     #
 
 jdk.internal.vm.compiler_EXCLUDES += \
-    org.graalvm.collections.test \
+    jdk.internal.vm.compiler.collections.test \
     org.graalvm.compiler.core.match.processor \
     org.graalvm.compiler.nodeinfo.processor \
     org.graalvm.compiler.options.processor \
--- a/make/CompileToolsHotspot.gmk	Mon Apr 23 12:53:43 2018 +0200
+++ b/make/CompileToolsHotspot.gmk	Thu Apr 26 17:59:02 2018 +0200
@@ -47,8 +47,8 @@
   $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_MATCH_PROCESSOR, \
       SETUP := GENERATE_OLDBYTECODE, \
       SRC := \
-          $(SRC_DIR)/org.graalvm.word/src \
-          $(SRC_DIR)/org.graalvm.collections/src \
+          $(SRC_DIR)/jdk.internal.vm.compiler.word/src \
+          $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \
           $(SRC_DIR)/org.graalvm.compiler.core/src \
           $(SRC_DIR)/org.graalvm.compiler.core.common/src \
           $(SRC_DIR)/org.graalvm.compiler.core.match.processor/src \
@@ -102,7 +102,7 @@
   $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_OPTIONS_PROCESSOR, \
       SETUP := GENERATE_OLDBYTECODE, \
       SRC := \
-          $(SRC_DIR)/org.graalvm.collections/src \
+          $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \
           $(SRC_DIR)/org.graalvm.compiler.options/src \
           $(SRC_DIR)/org.graalvm.compiler.options.processor/src \
           $(SRC_DIR)/org.graalvm.util/src \
@@ -118,8 +118,8 @@
   $(eval $(call SetupJavaCompilation, BUILD_VM_COMPILER_REPLACEMENTS_VERIFIER, \
       SETUP := GENERATE_OLDBYTECODE, \
       SRC := \
-          $(SRC_DIR)/org.graalvm.word/src \
-          $(SRC_DIR)/org.graalvm.collections/src \
+          $(SRC_DIR)/jdk.internal.vm.compiler.word/src \
+          $(SRC_DIR)/jdk.internal.vm.compiler.collections/src \
           $(SRC_DIR)/org.graalvm.compiler.bytecode/src \
           $(SRC_DIR)/org.graalvm.compiler.replacements.verifier/src \
           $(SRC_DIR)/org.graalvm.compiler.api.replacements/src \
--- a/make/Images.gmk	Mon Apr 23 12:53:43 2018 +0200
+++ b/make/Images.gmk	Thu Apr 26 17:59:02 2018 +0200
@@ -117,7 +117,7 @@
 
 JLINK_TOOL := $(JLINK) -J-Djlink.debug=true \
     --module-path $(IMAGES_OUTPUTDIR)/jmods \
-    --endian $(OPENJDK_BUILD_CPU_ENDIAN) \
+    --endian $(OPENJDK_TARGET_CPU_ENDIAN) \
     --release-info $(BASE_RELEASE_FILE) \
     --order-resources=$(call CommaList, $(JLINK_ORDER_RESOURCES)) \
     --dedup-legal-notices=error-if-not-same-content \
--- a/make/launcher/Launcher-jdk.pack.gmk	Mon Apr 23 12:53:43 2018 +0200
+++ b/make/launcher/Launcher-jdk.pack.gmk	Thu Apr 26 17:59:02 2018 +0200
@@ -88,7 +88,6 @@
     CFLAGS_solaris := -KPIC, \
     CFLAGS_macosx := -fPIC, \
     DISABLED_WARNINGS_gcc := unused-result implicit-fallthrough, \
-    DISABLED_WARNINGS_microsoft := 4005, \
     LDFLAGS := $(UNPACKEXE_ZIPOBJS) \
         $(LDFLAGS_JDKEXE) $(LDFLAGS_CXX_JDK) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
--- a/make/lib/Lib-jdk.pack.gmk	Mon Apr 23 12:53:43 2018 +0200
+++ b/make/lib/Lib-jdk.pack.gmk	Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,6 @@
         $(LIBJAVA_HEADER_FLAGS), \
     CFLAGS_release := -DPRODUCT, \
     DISABLED_WARNINGS_gcc := implicit-fallthrough, \
-    DISABLED_WARNINGS_microsoft := 4005, \
     LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LDFLAGS_windows := -map:$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/unpack.map -debug, \
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
+#include "runtime/jniHandles.hpp"
 
 #define __ masm->
 
@@ -64,3 +65,10 @@
   default: Unimplemented();
   }
 }
+
+void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath) {
+  // If mask changes we need to ensure that the inverse is still encodable as an immediate
+  STATIC_ASSERT(JNIHandles::weak_tag_mask == 1);
+  __ andr(robj, robj, ~JNIHandles::weak_tag_mask);
+  __ ldr(robj, Address(robj, 0));             // *obj
+}
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -40,6 +40,8 @@
   virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                         Address dst, Register val, Register tmp1, Register tmp2);
 
+  virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath);
+
   virtual void barrier_stubs_init() {}
 };
 
--- a/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/jniFastGetField_aarch64.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -25,6 +25,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "memory/resourceArea.hpp"
 #include "prims/jniFastGetField.hpp"
 #include "prims/jvm_misc.hpp"
@@ -82,11 +84,9 @@
                                               // robj ^ rcounter ^ rcounter == robj
                                               // robj is address dependent on rcounter.
 
-  // If mask changes we need to ensure that the inverse is still encodable as an immediate
-  STATIC_ASSERT(JNIHandles::weak_tag_mask == 1);
-  __ andr(robj, robj, ~JNIHandles::weak_tag_mask);
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->try_resolve_jobject_in_native(masm, robj, rscratch1, slow);
 
-  __ ldr(robj, Address(robj, 0));             // *obj
   __ lsr(roffset, c_rarg2, 2);                // offset
 
   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
@@ -177,4 +177,3 @@
 address JNI_FastGetField::generate_fast_get_double_field() {
   return generate_fast_get_int_field0(T_DOUBLE);
 }
-
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -368,7 +368,7 @@
   CodeBuffer cb(code_pos, instruction_size);
   MacroAssembler a(&cb);
 
-  a.mov(rscratch1, entry);
+  a.movptr(rscratch1, (uintptr_t)entry);
   a.br(rscratch1);
 
   ICache::invalidate_range(code_pos, instruction_size);
--- a/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interp_masm.hpp"
+#include "runtime/jniHandles.hpp"
 
 #define __ masm->
 
@@ -98,3 +99,8 @@
   default: Unimplemented();
   }
 }
+
+void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath) {
+  __ andn (robj, JNIHandles::weak_tag_mask, robj);
+  __ ld_ptr(robj, 0, robj);
+}
--- a/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -44,6 +44,9 @@
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        Address src, Register dst, Register tmp);
 
+  // Support for jniFastGetField to try resolving a jobject/jweak in native
+  virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath);
+
   virtual void barrier_stubs_init() {}
 };
 
--- a/src/hotspot/cpu/sparc/jniFastGetField_sparc.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/sparc/jniFastGetField_sparc.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "memory/resourceArea.hpp"
 #include "prims/jniFastGetField.hpp"
 #include "prims/jvm_misc.hpp"
@@ -68,17 +70,18 @@
   __ andcc (G4, 1, G0);
   __ br (Assembler::notZero, false, Assembler::pn, label1);
   __ delayed()->srl (O2, 2, O4);
-  __ andn (O1, JNIHandles::weak_tag_mask, O1);
-  __ ld_ptr (O1, 0, O5);
+
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->try_resolve_jobject_in_native(masm, O1, G3_scratch, label1);
 
   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   speculative_load_pclist[count] = __ pc();
   switch (type) {
-    case T_BOOLEAN: __ ldub (O5, O4, G3);  break;
-    case T_BYTE:    __ ldsb (O5, O4, G3);  break;
-    case T_CHAR:    __ lduh (O5, O4, G3);  break;
-    case T_SHORT:   __ ldsh (O5, O4, G3);  break;
-    case T_INT:     __ ld (O5, O4, G3);    break;
+    case T_BOOLEAN: __ ldub (O1, O4, G3);  break;
+    case T_BYTE:    __ ldsb (O1, O4, G3);  break;
+    case T_CHAR:    __ lduh (O1, O4, G3);  break;
+    case T_SHORT:   __ ldsh (O1, O4, G3);  break;
+    case T_INT:     __ ld (O1, O4, G3);    break;
     default:        ShouldNotReachHere();
   }
 
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interp_masm.hpp"
+#include "runtime/jniHandles.hpp"
 
 #define __ masm->
 
@@ -108,3 +109,8 @@
   default: Unimplemented();
   }
 }
+
+void BarrierSetAssembler::try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath) {
+  __ clear_jweak_tag(robj);
+  __ movptr(robj, Address(robj, 0));
+}
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -44,6 +44,9 @@
   virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                         Address dst, Register val, Register tmp1, Register tmp2);
 
+  // Support for jniFastGetField to try resolving a jobject/jweak in native
+  virtual void try_resolve_jobject_in_native(MacroAssembler* masm, Register robj, Register tmp, Label& slowpath);
+
   virtual void barrier_stubs_init() {}
 };
 
--- a/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/cpu/x86/jniFastGetField_x86_64.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "memory/resourceArea.hpp"
 #include "prims/jniFastGetField.hpp"
 #include "prims/jvm_misc.hpp"
@@ -81,12 +83,12 @@
                                                 // robj is data dependent on rcounter.
   }
 
-  __ clear_jweak_tag(robj);
-
-  __ movptr(robj, Address(robj, 0));             // *obj
   __ mov   (roffset, c_rarg2);
   __ shrptr(roffset, 2);                         // offset
 
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->try_resolve_jobject_in_native(masm, robj, rscratch1, slow);
+
   assert(count < LIST_CAPACITY, "LIST_CAPACITY too small");
   speculative_load_pclist[count] = __ pc();
   switch (type) {
--- a/src/hotspot/share/adlc/formssel.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/adlc/formssel.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1171,6 +1171,9 @@
   else if (is_ideal_nop()) {
     return "MachNopNode";
   }
+  else if (is_ideal_jump()) {
+    return "MachJumpNode";
+  }
   else if (is_mach_constant()) {
     return "MachConstantNode";
   }
--- a/src/hotspot/share/adlc/output_c.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/adlc/output_c.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -3936,6 +3936,9 @@
     fprintf(fp_cpp, "%s node->_prob = _leaf->as_If()->_prob;\n", indent);
     fprintf(fp_cpp, "%s node->_fcnt = _leaf->as_If()->_fcnt;\n", indent);
   }
+  if (inst->is_ideal_jump()) {
+    fprintf(fp_cpp, "%s node->_probs = _leaf->as_Jump()->_probs;\n", indent);
+  }
   if( inst->is_ideal_fastlock() ) {
     fprintf(fp_cpp, "%s node->_counters = _leaf->as_FastLock()->counters();\n", indent);
     fprintf(fp_cpp, "%s node->_rtm_counters = _leaf->as_FastLock()->rtm_counters();\n", indent);
--- a/src/hotspot/share/aot/aotCompiledMethod.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/aot/aotCompiledMethod.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -285,7 +285,7 @@
 
 protected:
   virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred);
-  virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) { return false; }
+  virtual bool do_unloading_jvmci(bool unloading_occurred) { return false; }
 
 };
 
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1324,7 +1324,7 @@
 void GraphBuilder::table_switch() {
   Bytecode_tableswitch sw(stream());
   const int l = sw.length();
-  if (CanonicalizeNodes && l == 1) {
+  if (CanonicalizeNodes && l == 1 && compilation()->env()->comp_level() != CompLevel_full_profile) {
     // total of 2 successors => use If instead of switch
     // Note: This code should go into the canonicalizer as soon as it can
     //       can handle canonicalized forms that contain more than one node.
@@ -1368,7 +1368,7 @@
 void GraphBuilder::lookup_switch() {
   Bytecode_lookupswitch sw(stream());
   const int l = sw.number_of_pairs();
-  if (CanonicalizeNodes && l == 1) {
+  if (CanonicalizeNodes && l == 1 && compilation()->env()->comp_level() != CompLevel_full_profile) {
     // total of 2 successors => use If instead of switch
     // Note: This code should go into the canonicalizer as soon as it can
     //       can handle canonicalized forms that contain more than one node.
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -2558,6 +2558,36 @@
   int hi_key = x->hi_key();
   int len = x->length();
   LIR_Opr value = tag.result();
+
+  if (compilation()->env()->comp_level() == CompLevel_full_profile && UseSwitchProfiling) {
+    ciMethod* method = x->state()->scope()->method();
+    ciMethodData* md = method->method_data_or_null();
+    ciProfileData* data = md->bci_to_data(x->state()->bci());
+    assert(data->is_MultiBranchData(), "bad profile data?");
+    int default_count_offset = md->byte_offset_of_slot(data, MultiBranchData::default_count_offset());
+    LIR_Opr md_reg = new_register(T_METADATA);
+    __ metadata2reg(md->constant_encoding(), md_reg);
+    LIR_Opr data_offset_reg = new_pointer_register();
+    LIR_Opr tmp_reg = new_pointer_register();
+
+    __ move(LIR_OprFact::intptrConst(default_count_offset), data_offset_reg);
+    for (int i = 0; i < len; i++) {
+      int count_offset = md->byte_offset_of_slot(data, MultiBranchData::case_count_offset(i));
+      __ cmp(lir_cond_equal, value, i + lo_key);
+      __ move(data_offset_reg, tmp_reg);
+      __ cmove(lir_cond_equal,
+               LIR_OprFact::intptrConst(count_offset),
+               tmp_reg,
+               data_offset_reg, T_INT);
+    }
+
+    LIR_Opr data_reg = new_pointer_register();
+    LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type());
+    __ move(data_addr, data_reg);
+    __ add(data_reg, LIR_OprFact::intptrConst(1), data_reg);
+    __ move(data_reg, data_addr);
+  }
+
   if (UseTableRanges) {
     do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux());
   } else {
@@ -2583,6 +2613,37 @@
   move_to_phi(x->state());
 
   LIR_Opr value = tag.result();
+  int len = x->length();
+
+  if (compilation()->env()->comp_level() == CompLevel_full_profile && UseSwitchProfiling) {
+    ciMethod* method = x->state()->scope()->method();
+    ciMethodData* md = method->method_data_or_null();
+    ciProfileData* data = md->bci_to_data(x->state()->bci());
+    assert(data->is_MultiBranchData(), "bad profile data?");
+    int default_count_offset = md->byte_offset_of_slot(data, MultiBranchData::default_count_offset());
+    LIR_Opr md_reg = new_register(T_METADATA);
+    __ metadata2reg(md->constant_encoding(), md_reg);
+    LIR_Opr data_offset_reg = new_pointer_register();
+    LIR_Opr tmp_reg = new_pointer_register();
+
+    __ move(LIR_OprFact::intptrConst(default_count_offset), data_offset_reg);
+    for (int i = 0; i < len; i++) {
+      int count_offset = md->byte_offset_of_slot(data, MultiBranchData::case_count_offset(i));
+      __ cmp(lir_cond_equal, value, x->key_at(i));
+      __ move(data_offset_reg, tmp_reg);
+      __ cmove(lir_cond_equal,
+               LIR_OprFact::intptrConst(count_offset),
+               tmp_reg,
+               data_offset_reg, T_INT);
+    }
+
+    LIR_Opr data_reg = new_pointer_register();
+    LIR_Address* data_addr = new LIR_Address(md_reg, data_offset_reg, data_reg->type());
+    __ move(data_addr, data_reg);
+    __ add(data_reg, LIR_OprFact::intptrConst(1), data_reg);
+    __ move(data_reg, data_addr);
+  }
+
   if (UseTableRanges) {
     do_SwitchRanges(create_lookup_ranges(x), value, x->default_sux());
   } else {
--- a/src/hotspot/share/code/codeHeapState.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/codeHeapState.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -2050,16 +2050,10 @@
 }
 
 
-#define JDK8200450_REMEDY
-#define JDK8200450_TRACE
 void CodeHeapState::print_names(outputStream* out, CodeHeap* heap) {
   if (!initialization_complete) {
     return;
   }
-#ifdef JDK8200450_TRACE
-  out->print_cr("print_names() entered for heap @ " INTPTR_FORMAT, p2i(heap));
-  out->flush();
-#endif
 
   const char* heapName   = get_heapName(heap);
   get_HeapStatGlobals(out, heapName);
@@ -2105,41 +2099,18 @@
     // Only check granule if it contains at least one blob.
     unsigned int nBlobs  = StatArray[ix].t1_count   + StatArray[ix].t2_count + StatArray[ix].tx_count +
                            StatArray[ix].stub_count + StatArray[ix].dead_count;
-#ifdef JDK8200450_REMEDY
-    if (nBlobs > 0 )
-#endif
-    {
+    if (nBlobs > 0 ) {
     for (unsigned int is = 0; is < granule_size; is+=(unsigned int)seg_size) {
       // heap->find_start() is safe. Only working with _segmap. Returns NULL or void*. Returned CodeBlob may be uninitialized.
       CodeBlob* this_blob = (CodeBlob *)(heap->find_start(low_bound+ix*granule_size+is));
-#ifndef JDK8200450_REMEDY
-      bool blob_initialized = (this_blob != NULL)
-#else
-#ifndef JDK8200450_TRACE
       bool blob_initialized = (this_blob != NULL) && (this_blob->header_size() >= 0) && (this_blob->relocation_size() >= 0) &&
                               ((address)this_blob + this_blob->header_size() == (address)(this_blob->relocation_begin())) &&
-                              ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin()) &&
-                              is_readable_pointer((address)(this_blob->relocation_begin()) &&
+                              ((address)this_blob + CodeBlob::align_code_offset(this_blob->header_size() + this_blob->relocation_size()) == (address)(this_blob->content_begin())) &&
+                              is_readable_pointer((address)(this_blob->relocation_begin())) &&
                               is_readable_pointer(this_blob->content_begin());
-#else
-      int   hdr_size      = 0;
-      int   reloc_size    = 0;
-      address reloc_begin = NULL;
-      address cntnt_begin = NULL;
-      if (this_blob != NULL) {
-        hdr_size    = this_blob->header_size();
-        reloc_size  = this_blob->relocation_size();
-        reloc_begin = (address)(this_blob->relocation_begin());
-        cntnt_begin = this_blob->content_begin();
-      }
-      bool blob_initialized = (this_blob != NULL) && (hdr_size >= 0) && (reloc_size >= 0) &&
-                              ((address)this_blob + hdr_size == reloc_begin) &&
-                              ((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin) &&
-                              is_readable_pointer(reloc_begin) &&
-                              is_readable_pointer(cntnt_begin);
-#endif
-#endif
-      if (blob_initialized && (this_blob != last_blob)) {
+      // blob could have been flushed, freed, and merged.
+      // this_blob < last_blob is an indicator for that.
+      if (blob_initialized && (this_blob > last_blob)) {
         last_blob          = this_blob;
 
         //---<  get type and name  >---
@@ -2147,15 +2118,13 @@
         if (segment_granules) {
           cbType = (blobType)StatArray[ix].type;
         } else {
-          cbType = get_cbType(this_blob);  // Is this here safe?
+          cbType = get_cbType(this_blob);
         }
-        // this_blob->name() could return NULL if no name is given to CTOR. Inlined, maybe invisible on stack
+        // this_blob->name() could return NULL if no name was given to CTOR. Inlined, maybe invisible on stack
         const char* blob_name = this_blob->name();
-#ifdef JDK8200450_REMEDY
-        if (blob_name == NULL) {
+        if ((blob_name == NULL) || !is_readable_pointer(blob_name)) {
           blob_name = "<unavailable>";
         }
-#endif
 
         //---<  print table header for new print range  >---
         if (!name_in_addr_range) {
@@ -2174,24 +2143,16 @@
         ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
         ast->fill_to(33);
 
-#ifdef JDK8200450_TRACE
-        STRINGSTREAM_FLUSH_LOCKED("")   // Remove before push!!!
-#endif
-
         // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
         nmethod*    nm     = this_blob->as_nmethod_or_null();
         Method*     method = (nm == NULL) ? NULL : nm->method();  // may be uninitialized, i.e. != NULL, but invalid
-#ifdef JDK8200450_REMEDY
-        if ((nm != NULL) && (method != NULL) && is_readable_pointer(method) && is_readable_pointer(method->constants())) {
-#else
-        if ((nm != NULL) && (method != NULL)) {
-#endif
+        if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) &&
+            is_readable_pointer(method) && is_readable_pointer(method->constants())) {
           ResourceMark rm;
           //---<  collect all data to locals as quickly as possible  >---
           unsigned int total_size = nm->total_size();
           int          hotness    = nm->hotness_counter();
-          bool         nm_zombie  = nm->is_zombie();
-          bool         get_name   = nm->is_in_use() || nm->is_not_entrant();
+          bool         get_name   = (cbType == nMethod_inuse) || (cbType == nMethod_notused);
           //---<  nMethod size in hex  >---
           ast->print(PTR32_FORMAT, total_size);
           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
@@ -2205,16 +2166,11 @@
           ast->fill_to(62+6);
           ast->print("%s", blobTypeName[cbType]);
           ast->fill_to(82+6);
-          if (nm_zombie) {
+          if (cbType == nMethod_dead) {
             ast->print("%14s", " zombie method");
           }
 
-#ifdef JDK8200450_TRACE
-        STRINGSTREAM_FLUSH_LOCKED("")   // Remove before push!!!
-#endif
-
           if (get_name) {
-#ifdef JDK8200450_REMEDY
             Symbol* methName  = method->name();
             const char*   methNameS = (methName == NULL) ? NULL : methName->as_C_string();
             methNameS = (methNameS == NULL) ? "<method name unavailable>" : methNameS;
@@ -2223,10 +2179,6 @@
             methSigS  = (methSigS  == NULL) ? "<method signature unavailable>" : methSigS;
             ast->print("%s", methNameS);
             ast->print("%s", methSigS);
-#else
-            blob_name = method->name_and_sig_as_C_string();
-            ast->print("%s", blob_name);
-#endif
           } else {
             ast->print("%s", blob_name);
           }
@@ -2237,45 +2189,9 @@
           ast->print("%s", blob_name);
         }
         STRINGSTREAM_FLUSH_LOCKED("\n")
-#ifdef JDK8200450_TRACE
-        if ((nm != NULL) && (method != NULL) && !(is_readable_pointer(method) && is_readable_pointer(method->constants()))) {
-          ast->print("Potential CodeHeap State Analytics issue found.\n");
-          if (is_readable_pointer(method)) {
-            ast->print("  Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method->constants())) check.\n", p2i(method->constants()));
-          } else {
-            ast->print("  Issue would have been detected by is_readable_pointer(" INTPTR_FORMAT "(method)) check.\n", p2i(method));
-          }
-          STRINGSTREAM_FLUSH_LOCKED("\n")
-        }
-#endif
       } else if (!blob_initialized && (this_blob != last_blob) && (this_blob != NULL)) {
         last_blob          = this_blob;
-#ifdef JDK8200450_TRACE
-        ast->print("Potential CodeHeap State Analytics issue found.\n");
-        if (nBlobs == 0) {
-          ast->print("  Issue would have been detected by (nBlobs > 0) check.\n");
-        } else {
-          if (!((address)this_blob + hdr_size == reloc_begin)) {
-            ast->print("  Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) == relocation_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, p2i(reloc_begin));
-          }
-          if (!((address)this_blob + CodeBlob::align_code_offset(hdr_size + reloc_size) == cntnt_begin)) {
-            ast->print("  Issue would have been detected by (this(" INTPTR_FORMAT ") + header(%d) + relocation(%d) == content_begin(" INTPTR_FORMAT ")) check.\n", p2i(this_blob), hdr_size, reloc_size, p2i(cntnt_begin));
-          }
-          if (hdr_size    != this_blob->header_size()) {
-            ast->print("  header_size      meanwhile changed from %d to %d\n", hdr_size, this_blob->header_size());
-          }
-          if (reloc_size  != this_blob->relocation_size()) {
-            ast->print("  relocation_size  meanwhile changed from %d to %d\n", reloc_size, this_blob->relocation_size());
-          }
-          if (reloc_begin != (address)(this_blob->relocation_begin())) {
-            ast->print("  relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(reloc_begin), p2i(this_blob->relocation_begin()));
-          }
-          if (cntnt_begin != this_blob->content_begin()) {
-            ast->print("  relocation_begin meanwhile changed from " INTPTR_FORMAT " to " INTPTR_FORMAT "\n", p2i(cntnt_begin), p2i(this_blob->content_begin()));
-          }
-        }
         STRINGSTREAM_FLUSH_LOCKED("\n")
-#endif
       }
     }
     } // nBlobs > 0
@@ -2430,7 +2346,7 @@
 }
 
 CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
-  if (cb != NULL ) {
+  if ((cb != NULL) && is_readable_pointer(cb)) {
     if (cb->is_runtime_stub())                return runtimeStub;
     if (cb->is_deoptimization_stub())         return deoptimizationStub;
     if (cb->is_uncommon_trap_stub())          return uncommonTrapStub;
@@ -2440,13 +2356,13 @@
     if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
     if (cb->is_buffer_blob())                 return bufferBlob;
 
-    if (cb->is_nmethod() ) {
-      if (((nmethod*)cb)->is_in_use())        return nMethod_inuse;
-      if (((nmethod*)cb)->is_alive() && !(((nmethod*)cb)->is_not_entrant()))   return nMethod_notused;
-      if (((nmethod*)cb)->is_alive())         return nMethod_alive;
-      if (((nmethod*)cb)->is_unloaded())      return nMethod_unloaded;
-      if (((nmethod*)cb)->is_zombie())        return nMethod_dead;
-      tty->print_cr("unhandled nmethod state");
+    nmethod*  nm = cb->as_nmethod_or_null();
+    if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.
+      if (nm->is_zombie())        return nMethod_dead;
+      if (nm->is_unloaded())      return nMethod_unloaded;
+      if (nm->is_alive() && !(nm->is_not_entrant()))   return nMethod_notused;
+      if (nm->is_alive())         return nMethod_alive;
+      if (nm->is_in_use())        return nMethod_inuse;
       return nMethod_dead;
     }
   }
--- a/src/hotspot/share/code/compiledMethod.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/compiledMethod.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -525,7 +525,7 @@
   }
 
 #if INCLUDE_JVMCI
-  if (do_unloading_jvmci(is_alive, unloading_occurred)) {
+  if (do_unloading_jvmci(unloading_occurred)) {
     return;
   }
 #endif
@@ -535,7 +535,7 @@
 }
 
 template <class CompiledICorStaticCall>
-static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, BoolObjectClosure *is_alive, CompiledMethod* from) {
+static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, CompiledMethod* from) {
   // Ok, to lookup references to zombies here
   CodeBlob *cb = CodeCache::find_blob_unsafe(addr);
   CompiledMethod* nm = (cb != NULL) ? cb->as_compiled_method_or_null() : NULL;
@@ -555,12 +555,12 @@
   return false;
 }
 
-static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, BoolObjectClosure *is_alive, CompiledMethod* from) {
-  return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), is_alive, from);
+static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, CompiledMethod* from) {
+  return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), from);
 }
 
-static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, BoolObjectClosure *is_alive, CompiledMethod* from) {
-  return clean_if_nmethod_is_unloaded(csc, csc->destination(), is_alive, from);
+static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, CompiledMethod* from) {
+  return clean_if_nmethod_is_unloaded(csc, csc->destination(), from);
 }
 
 bool CompiledMethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) {
@@ -608,15 +608,15 @@
         clean_ic_if_metadata_is_dead(CompiledIC_at(&iter));
       }
 
-      postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
       break;
 
     case relocInfo::opt_virtual_call_type:
-      postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
       break;
 
     case relocInfo::static_call_type:
-      postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
+      postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this);
       break;
 
     case relocInfo::oop_type:
@@ -636,7 +636,7 @@
   }
 
 #if INCLUDE_JVMCI
-  if (do_unloading_jvmci(is_alive, unloading_occurred)) {
+  if (do_unloading_jvmci(unloading_occurred)) {
     return postponed;
   }
 #endif
@@ -647,7 +647,7 @@
   return postponed;
 }
 
-void CompiledMethod::do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred) {
+void CompiledMethod::do_unloading_parallel_postponed() {
   ResourceMark rm;
 
   // Make sure the oop's ready to receive visitors
@@ -671,15 +671,15 @@
     switch (iter.type()) {
 
     case relocInfo::virtual_call_type:
-      clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
       break;
 
     case relocInfo::opt_virtual_call_type:
-      clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), this);
       break;
 
     case relocInfo::static_call_type:
-      clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
+      clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), this);
       break;
 
     default:
--- a/src/hotspot/share/code/compiledMethod.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/compiledMethod.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -372,7 +372,7 @@
   virtual void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
   //  The parallel versions are used by G1.
   virtual bool do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred);
-  virtual void do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred);
+  virtual void do_unloading_parallel_postponed();
 
   static unsigned char global_unloading_clock()   { return _global_unloading_clock; }
   static void increase_unloading_clock();
@@ -383,7 +383,7 @@
 protected:
   virtual bool do_unloading_oops(address low_boundary, BoolObjectClosure* is_alive, bool unloading_occurred) = 0;
 #if INCLUDE_JVMCI
-  virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) = 0;
+  virtual bool do_unloading_jvmci(bool unloading_occurred) = 0;
 #endif
 
 private:
--- a/src/hotspot/share/code/nmethod.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/nmethod.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1028,17 +1028,16 @@
   mdo->inc_decompile_count();
 }
 
-void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
+void nmethod::make_unloaded(oop cause) {
 
   post_compiled_method_unload();
 
-  // Since this nmethod is being unloaded, make sure that dependencies
-  // recorded in instanceKlasses get flushed and pass non-NULL closure to
-  // indicate that this work is being done during a GC.
+  // This nmethod is being unloaded, make sure that dependencies
+  // recorded in instanceKlasses get flushed.
+  // Since this work is being done during a GC, defer deleting dependencies from the
+  // InstanceKlass.
   assert(Universe::heap()->is_gc_active(), "should only be called during gc");
-  assert(is_alive != NULL, "Should be non-NULL");
-  // A non-NULL is_alive closure indicates that this is being called during GC.
-  flush_dependencies(is_alive);
+  flush_dependencies(/*delete_immediately*/false);
 
   // Break cycle between nmethod & method
   LogTarget(Trace, class, unload) lt;
@@ -1261,7 +1260,7 @@
       if (nmethod_needs_unregister) {
         Universe::heap()->unregister_nmethod(this);
       }
-      flush_dependencies(NULL);
+      flush_dependencies(/*delete_immediately*/true);
     }
 
     // zombie only - if a JVMTI agent has enabled the CompiledMethodUnload
@@ -1344,13 +1343,13 @@
 // of dependencies must happen during phase 1 since after GC any
 // dependencies in the unloaded nmethod won't be updated, so
 // traversing the dependency information in unsafe.  In that case this
-// function is called with a non-NULL argument and this function only
+// function is called with a boolean argument and this function only
 // notifies instanceKlasses that are reachable
 
-void nmethod::flush_dependencies(BoolObjectClosure* is_alive) {
+void nmethod::flush_dependencies(bool delete_immediately) {
   assert_locked_or_safepoint(CodeCache_lock);
-  assert(Universe::heap()->is_gc_active() == (is_alive != NULL),
-  "is_alive is non-NULL if and only if we are called during GC");
+  assert(Universe::heap()->is_gc_active() != delete_immediately,
+  "delete_immediately is false if and only if we are called during GC");
   if (!has_flushed_dependencies()) {
     set_has_flushed_dependencies();
     for (Dependencies::DepStream deps(this); deps.next(); ) {
@@ -1363,13 +1362,12 @@
         if (klass == NULL) {
           continue;  // ignore things like evol_method
         }
-        // During GC the is_alive closure is non-NULL, and is used to
-        // determine liveness of dependees that need to be updated.
-        if (is_alive == NULL || klass->is_loader_alive()) {
+        // During GC delete_immediately is false, and liveness
+        // of dependee determines class that needs to be updated.
+        if (delete_immediately || klass->is_loader_alive()) {
           // The GC defers deletion of this entry, since there might be multiple threads
           // iterating over the _dependencies graph. Other call paths are single-threaded
           // and may delete it immediately.
-          bool delete_immediately = is_alive == NULL;
           InstanceKlass::cast(klass)->remove_dependent_nmethod(this, delete_immediately);
         }
       }
@@ -1390,7 +1388,7 @@
   // simply because one of its constant oops has gone dead.
   // No actual classes need to be unloaded in order for this to occur.
   assert(unloading_occurred || ScavengeRootsInCode, "Inconsistency in unloading");
-  make_unloaded(is_alive, obj);
+  make_unloaded(obj);
   return true;
 }
 
@@ -1516,12 +1514,12 @@
 }
 
 #if INCLUDE_JVMCI
-bool nmethod::do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred) {
+bool nmethod::do_unloading_jvmci(bool unloading_occurred) {
   if (_jvmci_installed_code != NULL) {
     if (JNIHandles::is_global_weak_cleared(_jvmci_installed_code)) {
       if (_jvmci_installed_code_triggers_unloading) {
         // jweak reference processing has already cleared the referent
-        make_unloaded(is_alive, NULL);
+        make_unloaded(NULL);
         return true;
       } else {
         clear_jvmci_installed_code();
--- a/src/hotspot/share/code/nmethod.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/code/nmethod.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -349,10 +349,10 @@
     return _state;
   }
 
-  void  make_unloaded(BoolObjectClosure* is_alive, oop cause);
+  void  make_unloaded(oop cause);
 
   bool has_dependencies()                         { return dependencies_size() != 0; }
-  void flush_dependencies(BoolObjectClosure* is_alive);
+  void flush_dependencies(bool delete_immediately);
   bool has_flushed_dependencies()                 { return _has_flushed_dependencies; }
   void set_has_flushed_dependencies()             {
     assert(!has_flushed_dependencies(), "should only happen once");
@@ -488,7 +488,7 @@
 #if INCLUDE_JVMCI
   // See comment for _jvmci_installed_code_triggers_unloading field.
   // Returns whether this nmethod was unloaded.
-  virtual bool do_unloading_jvmci(BoolObjectClosure* is_alive, bool unloading_occurred);
+  virtual bool do_unloading_jvmci(bool unloading_occurred);
 #endif
 
  private:
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -3353,7 +3353,7 @@
   }
 
   void clean_nmethod_postponed(CompiledMethod* nm) {
-    nm->do_unloading_parallel_postponed(_is_alive, _unloading_occurred);
+    nm->do_unloading_parallel_postponed();
   }
 
   static const int MaxClaimNmethods = 16;
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1695,14 +1695,6 @@
     assert(!rp->discovery_enabled(), "Post condition");
   }
 
-  assert(has_overflown() || _global_mark_stack.is_empty(),
-         "Mark stack should be empty (unless it has overflown)");
-
-  {
-    GCTraceTime(Debug, gc, phases) debug("Weak Processing", _gc_timer_cm);
-    WeakProcessor::weak_oops_do(&g1_is_alive, &do_nothing_cl);
-  }
-
   if (has_overflown()) {
     // We can not trust g1_is_alive if the marking stack overflowed
     return;
@@ -1710,6 +1702,11 @@
 
   assert(_global_mark_stack.is_empty(), "Marking should have completed");
 
+  {
+    GCTraceTime(Debug, gc, phases) debug("Weak Processing", _gc_timer_cm);
+    WeakProcessor::weak_oops_do(&g1_is_alive, &do_nothing_cl);
+  }
+
   // Unload Klasses, String, Symbols, Code Cache, etc.
   if (ClassUnloadingWithConcurrentMark) {
     GCTraceTime(Debug, gc, phases) debug("Class Unloading", _gc_timer_cm);
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -172,6 +172,22 @@
   return false;
 }
 
+bool CollectedHeap::is_oop(oop object) const {
+  if (!check_obj_alignment(object)) {
+    return false;
+  }
+
+  if (!is_in_reserved(object)) {
+    return false;
+  }
+
+  if (is_in_reserved(object->klass_or_null())) {
+    return false;
+  }
+
+  return true;
+}
+
 // Memory state functions.
 
 
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -592,6 +592,8 @@
   virtual oop pin_object(JavaThread* thread, oop obj);
   virtual void unpin_object(JavaThread* thread, oop obj);
 
+  virtual bool is_oop(oop object) const;
+
   // Non product verification and debugging.
 #ifndef PRODUCT
   // Support for PromotionFailureALot.  Return true if it's time to cause a
--- a/src/hotspot/share/memory/filemap.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/memory/filemap.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -75,6 +75,7 @@
 class FileMapInfo : public CHeapObj<mtInternal> {
 private:
   friend class ManifestStream;
+  friend class VMStructs;
   enum {
     _invalid_version = -1,
     _current_version = 3
--- a/src/hotspot/share/memory/metaspace.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/memory/metaspace.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -3378,6 +3378,7 @@
 }
 
 MetaWord* SpaceManager::grow_and_allocate(size_t word_size) {
+  assert_lock_strong(_lock);
   assert(vs_list()->current_virtual_space() != NULL,
          "Should have been set");
   assert(current_chunk() == NULL ||
@@ -3406,7 +3407,16 @@
   // and do an allocation from it.
   if (next != NULL) {
     // Add to this manager's list of chunks in use.
-    add_chunk(next, false);
+    // If the new chunk is humongous, it was created to serve a single large allocation. In that
+    // case it usually makes no sense to make it the current chunk, since the next allocation would
+    // need to allocate a new chunk anyway, while we would now prematurely retire a perfectly
+    // good chunk which could be used for more normal allocations.
+    bool make_current = true;
+    if (next->get_chunk_type() == HumongousIndex &&
+        current_chunk() != NULL) {
+      make_current = false;
+    }
+    add_chunk(next, make_current);
     mem = next->allocate(word_size);
   }
 
@@ -3553,6 +3563,7 @@
 // Adds a chunk to the list of chunks in use.
 void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) {
 
+  assert_lock_strong(_lock);
   assert(new_chunk != NULL, "Should not be NULL");
   assert(new_chunk->next() == NULL, "Should not be on a list");
 
@@ -3562,28 +3573,16 @@
   // chunk for that list.
   ChunkIndex index = chunk_manager()->list_index(new_chunk->word_size());
 
-  if (index != HumongousIndex) {
+  if (make_current) {
+    // If we are to make the chunk current, retire the old current chunk and replace
+    // it with the new chunk.
     retire_current_chunk();
     set_current_chunk(new_chunk);
-    new_chunk->set_next(chunks_in_use(index));
-    set_chunks_in_use(index, new_chunk);
-  } else {
-    // For null class loader data and DumpSharedSpaces, the first chunk isn't
-    // small, so small will be null.  Link this first chunk as the current
-    // chunk.
-    if (make_current) {
-      // Set as the current chunk but otherwise treat as a humongous chunk.
-      set_current_chunk(new_chunk);
-    }
-    // Link at head.  The _current_chunk only points to a humongous chunk for
-    // the null class loader metaspace (class and data virtual space managers)
-    // any humongous chunks so will not point to the tail
-    // of the humongous chunks list.
-    new_chunk->set_next(chunks_in_use(HumongousIndex));
-    set_chunks_in_use(HumongousIndex, new_chunk);
-
-    assert(new_chunk->word_size() > medium_chunk_size(), "List inconsistency");
-  }
+  }
+
+  // Add the new chunk at the head of its respective chunk list.
+  new_chunk->set_next(chunks_in_use(index));
+  set_chunks_in_use(index, new_chunk);
 
   // Add to the running sum of capacity
   inc_size_metrics(new_chunk->word_size());
@@ -4800,7 +4799,7 @@
 void ClassLoaderMetaspace::initialize_first_chunk(Metaspace::MetaspaceType type, Metaspace::MetadataType mdtype) {
   Metachunk* chunk = get_initialization_chunk(type, mdtype);
   if (chunk != NULL) {
-    // Add to this manager's list of chunks in use and current_chunk().
+    // Add to this manager's list of chunks in use and make it the current_chunk().
     get_space_manager(mdtype)->add_chunk(chunk, true);
   }
 }
--- a/src/hotspot/share/oops/oop.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/oops/oop.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -122,10 +122,9 @@
 
 // used only for asserts and guarantees
 bool oopDesc::is_oop(oop obj, bool ignore_mark_word) {
-  if (!check_obj_alignment(obj)) return false;
-  if (!Universe::heap()->is_in_reserved(obj)) return false;
-  // obj is aligned and accessible in heap
-  if (Universe::heap()->is_in_reserved(obj->klass_or_null())) return false;
+  if (!Universe::heap()->is_oop(obj)) {
+    return false;
+  }
 
   // Header verification: the mark is typically non-NULL. If we're
   // at a safepoint, it must not be null.
--- a/src/hotspot/share/opto/cfgnode.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/cfgnode.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -298,6 +298,7 @@
   void reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn);
   ProjNode* uncommon_trap_proj(CallStaticJavaNode*& call) const;
   bool fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn);
+  static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc);
 
 protected:
   ProjNode* range_check_trap_proj(int& flip, Node*& l, Node*& r);
@@ -484,8 +485,13 @@
 // Indirect branch.  Uses PCTable above to implement a switch statement.
 // It emits as a table load and local branch.
 class JumpNode : public PCTableNode {
+  virtual uint size_of() const { return sizeof(*this); }
 public:
-  JumpNode( Node* control, Node* switch_val, uint size) : PCTableNode(control, switch_val, size) {
+  float* _probs; // probability of each projection
+  float _fcnt;   // total number of times this Jump was executed
+  JumpNode( Node* control, Node* switch_val, uint size, float* probs, float cnt)
+    : PCTableNode(control, switch_val, size),
+      _probs(probs), _fcnt(cnt) {
     init_class_id(Class_Jump);
   }
   virtual int   Opcode() const;
--- a/src/hotspot/share/opto/gcm.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/gcm.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1867,8 +1867,7 @@
   }
 
   case Op_Jump:
-    // Divide the frequency between all successors evenly
-    return 1.0f/_num_succs;
+    return n->as_MachJump()->_probs[get_node(i + eidx + 1)->as_JumpProj()->_con];
 
   case Op_Catch: {
     const CatchProjNode *ci = get_node(i + eidx + 1)->as_CatchProj();
--- a/src/hotspot/share/opto/ifnode.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/ifnode.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -775,6 +775,38 @@
   return success != NULL && fail != NULL;
 }
 
+bool IfNode::is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc) {
+  // Different methods and methods containing jsrs are not supported.
+  ciMethod* method = unc->jvms()->method();
+  ciMethod* dom_method = dom_unc->jvms()->method();
+  if (method != dom_method || method->has_jsrs()) {
+    return false;
+  }
+  // Check that both traps are in the same activation of the method (instead
+  // of two activations being inlined through different call sites) by verifying
+  // that the call stacks are equal for both JVMStates.
+  JVMState* dom_caller = dom_unc->jvms()->caller();
+  JVMState* caller = unc->jvms()->caller();
+  if ((dom_caller == NULL) != (caller == NULL)) {
+    // The current method must either be inlined into both dom_caller and
+    // caller or must not be inlined at all (top method). Bail out otherwise.
+    return false;
+  } else if (dom_caller != NULL && !dom_caller->same_calls_as(caller)) {
+    return false;
+  }
+  // Check that the bci of the dominating uncommon trap dominates the bci
+  // of the dominated uncommon trap. Otherwise we may not re-execute
+  // the dominated check after deoptimization from the merged uncommon trap.
+  ciTypeFlow* flow = dom_method->get_flow_analysis();
+  int bci = unc->jvms()->bci();
+  int dom_bci = dom_unc->jvms()->bci();
+  if (!flow->is_dominated_by(bci, dom_bci)) {
+    return false;
+  }
+
+  return true;
+}
+
 // Return projection that leads to an uncommon trap if any
 ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call) const {
   for (int i = 0; i < 2; i++) {
@@ -811,31 +843,7 @@
         return false;
       }
 
-      // Different methods and methods containing jsrs are not supported.
-      ciMethod* method = unc->jvms()->method();
-      ciMethod* dom_method = dom_unc->jvms()->method();
-      if (method != dom_method || method->has_jsrs()) {
-        return false;
-      }
-      // Check that both traps are in the same activation of the method (instead
-      // of two activations being inlined through different call sites) by verifying
-      // that the call stacks are equal for both JVMStates.
-      JVMState* dom_caller = dom_unc->jvms()->caller();
-      JVMState* caller = unc->jvms()->caller();
-      if ((dom_caller == NULL) != (caller == NULL)) {
-        // The current method must either be inlined into both dom_caller and
-        // caller or must not be inlined at all (top method). Bail out otherwise.
-        return false;
-      } else if (dom_caller != NULL && !dom_caller->same_calls_as(caller)) {
-        return false;
-      }
-      // Check that the bci of the dominating uncommon trap dominates the bci
-      // of the dominated uncommon trap. Otherwise we may not re-execute
-      // the dominated check after deoptimization from the merged uncommon trap.
-      ciTypeFlow* flow = dom_method->get_flow_analysis();
-      int bci = unc->jvms()->bci();
-      int dom_bci = dom_unc->jvms()->bci();
-      if (!flow->is_dominated_by(bci, dom_bci)) {
+      if (!is_dominator_unc(dom_unc, unc)) {
         return false;
       }
 
@@ -843,6 +851,8 @@
       // will be changed and the state of the dominating If will be
       // used. Checked that we didn't apply this transformation in a
       // previous compilation and it didn't cause too many traps
+      ciMethod* dom_method = dom_unc->jvms()->method();
+      int dom_bci = dom_unc->jvms()->bci();
       if (!igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_unstable_fused_if) &&
           !igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_range_check)) {
         success = unc_proj;
@@ -1220,6 +1230,10 @@
         return false;
       }
 
+      if (!is_dominator_unc(dom_unc, unc)) {
+        return false;
+      }
+
       return true;
     }
   }
--- a/src/hotspot/share/opto/machnode.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/machnode.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -750,6 +750,16 @@
 #endif
 };
 
+//------------------------------MachJumpNode-----------------------------------
+// Machine-specific versions of JumpNodes
+class MachJumpNode : public MachConstantNode {
+public:
+  float* _probs;
+  MachJumpNode() : MachConstantNode() {
+    init_class_id(Class_MachJump);
+  }
+};
+
 //------------------------------MachGotoNode-----------------------------------
 // Machine-specific versions of GotoNodes
 class MachGotoNode : public MachBranchNode {
--- a/src/hotspot/share/opto/node.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/node.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -94,6 +94,7 @@
 class MachConstantNode;
 class MachGotoNode;
 class MachIfNode;
+class MachJumpNode;
 class MachNode;
 class MachNullCheckNode;
 class MachProjNode;
@@ -651,6 +652,7 @@
       DEFINE_CLASS_ID(MachTemp,         Mach, 3)
       DEFINE_CLASS_ID(MachConstantBase, Mach, 4)
       DEFINE_CLASS_ID(MachConstant,     Mach, 5)
+        DEFINE_CLASS_ID(MachJump,       MachConstant, 0)
       DEFINE_CLASS_ID(MachMerge,        Mach, 6)
 
     DEFINE_CLASS_ID(Type,  Node, 2)
@@ -831,6 +833,7 @@
   DEFINE_CLASS_QUERY(MachConstant)
   DEFINE_CLASS_QUERY(MachGoto)
   DEFINE_CLASS_QUERY(MachIf)
+  DEFINE_CLASS_QUERY(MachJump)
   DEFINE_CLASS_QUERY(MachNullCheck)
   DEFINE_CLASS_QUERY(MachProj)
   DEFINE_CLASS_QUERY(MachReturn)
--- a/src/hotspot/share/opto/parse.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/parse.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -552,17 +552,18 @@
   void    sharpen_type_after_if(BoolTest::mask btest,
                                 Node* con, const Type* tcon,
                                 Node* val, const Type* tval);
-  IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask);
+  IfNode* jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float prob, float cnt);
   Node*   jump_if_join(Node* iffalse, Node* iftrue);
-  void    jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, int prof_table_index);
-  void    jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, int prof_table_index);
-  void    jump_if_always_fork(int dest_bci_if_true, int prof_table_index);
+  void    jump_if_true_fork(IfNode *ifNode, int dest_bci_if_true, int prof_table_index, bool unc);
+  void    jump_if_false_fork(IfNode *ifNode, int dest_bci_if_false, int prof_table_index, bool unc);
+  void    jump_if_always_fork(int dest_bci_if_true, int prof_table_index, bool unc);
 
   friend class SwitchRange;
   void    do_tableswitch();
   void    do_lookupswitch();
   void    jump_switch_ranges(Node* a, SwitchRange* lo, SwitchRange* hi, int depth = 0);
   bool    create_jump_tables(Node* a, SwitchRange* lo, SwitchRange* hi);
+  void    linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchRange*& hi);
 
   void decrement_age();
   // helper functions for methodData style profiling
--- a/src/hotspot/share/opto/parse2.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/parse2.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -186,10 +186,10 @@
 
 
 // returns IfNode
-IfNode* Parse::jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask) {
-  Node   *cmp = _gvn.transform( new CmpINode( a, b)); // two cases: shiftcount > 32 and shiftcount <= 32
-  Node   *tst = _gvn.transform( new BoolNode( cmp, mask));
-  IfNode *iff = create_and_map_if( control(), tst, ((mask == BoolTest::eq) ? PROB_STATIC_INFREQUENT : PROB_FAIR), COUNT_UNKNOWN );
+IfNode* Parse::jump_if_fork_int(Node* a, Node* b, BoolTest::mask mask, float prob, float cnt) {
+  Node   *cmp = _gvn.transform(new CmpINode(a, b)); // two cases: shiftcount > 32 and shiftcount <= 32
+  Node   *tst = _gvn.transform(new BoolNode(cmp, mask));
+  IfNode *iff = create_and_map_if(control(), tst, prob, cnt);
   return iff;
 }
 
@@ -205,15 +205,27 @@
   return region;
 }
 
+// sentinel value for the target bci to mark never taken branches
+// (according to profiling)
+static const int never_reached = INT_MAX;
 
 //------------------------------helper for tableswitch-------------------------
-void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index) {
+void Parse::jump_if_true_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index, bool unc) {
   // True branch, use existing map info
   { PreserveJVMState pjvms(this);
     Node *iftrue  = _gvn.transform( new IfTrueNode (iff) );
     set_control( iftrue );
-    profile_switch_case(prof_table_index);
-    merge_new_path(dest_bci_if_true);
+    if (unc) {
+      repush_if_args();
+      uncommon_trap(Deoptimization::Reason_unstable_if,
+                    Deoptimization::Action_reinterpret,
+                    NULL,
+                    "taken always");
+    } else {
+      assert(dest_bci_if_true != never_reached, "inconsistent dest");
+      profile_switch_case(prof_table_index);
+      merge_new_path(dest_bci_if_true);
+    }
   }
 
   // False branch
@@ -221,13 +233,22 @@
   set_control( iffalse );
 }
 
-void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index) {
+void Parse::jump_if_false_fork(IfNode *iff, int dest_bci_if_true, int prof_table_index, bool unc) {
   // True branch, use existing map info
   { PreserveJVMState pjvms(this);
     Node *iffalse  = _gvn.transform( new IfFalseNode (iff) );
     set_control( iffalse );
-    profile_switch_case(prof_table_index);
-    merge_new_path(dest_bci_if_true);
+    if (unc) {
+      repush_if_args();
+      uncommon_trap(Deoptimization::Reason_unstable_if,
+                    Deoptimization::Action_reinterpret,
+                    NULL,
+                    "taken never");
+    } else {
+      assert(dest_bci_if_true != never_reached, "inconsistent dest");
+      profile_switch_case(prof_table_index);
+      merge_new_path(dest_bci_if_true);
+    }
   }
 
   // False branch
@@ -235,10 +256,19 @@
   set_control( iftrue );
 }
 
-void Parse::jump_if_always_fork(int dest_bci, int prof_table_index) {
+void Parse::jump_if_always_fork(int dest_bci, int prof_table_index, bool unc) {
   // False branch, use existing map and control()
-  profile_switch_case(prof_table_index);
-  merge_new_path(dest_bci);
+  if (unc) {
+    repush_if_args();
+    uncommon_trap(Deoptimization::Reason_unstable_if,
+                  Deoptimization::Action_reinterpret,
+                  NULL,
+                  "taken never");
+  } else {
+    assert(dest_bci != never_reached, "inconsistent dest");
+    profile_switch_case(prof_table_index);
+    merge_new_path(dest_bci);
+  }
 }
 
 
@@ -261,6 +291,7 @@
   jint _hi;                     // inclusive upper limit
   int _dest;
   int _table_index;             // index into method data table
+  float _cnt;                   // how many times this range was hit according to profiling
 
 public:
   jint lo() const              { return _lo;   }
@@ -268,44 +299,111 @@
   int  dest() const            { return _dest; }
   int  table_index() const     { return _table_index; }
   bool is_singleton() const    { return _lo == _hi; }
+  float cnt() const            { return _cnt; }
 
-  void setRange(jint lo, jint hi, int dest, int table_index) {
+  void setRange(jint lo, jint hi, int dest, int table_index, float cnt) {
     assert(lo <= hi, "must be a non-empty range");
-    _lo = lo, _hi = hi; _dest = dest; _table_index = table_index;
+    _lo = lo, _hi = hi; _dest = dest; _table_index = table_index; _cnt = cnt;
+    assert(_cnt >= 0, "");
   }
-  bool adjoinRange(jint lo, jint hi, int dest, int table_index) {
+  bool adjoinRange(jint lo, jint hi, int dest, int table_index, float cnt, bool trim_ranges) {
     assert(lo <= hi, "must be a non-empty range");
-    if (lo == _hi+1 && dest == _dest && table_index == _table_index) {
+    if (lo == _hi+1 && table_index == _table_index) {
+      // see merge_ranges() comment below
+      if (trim_ranges) {
+        if (cnt == 0) {
+          if (_cnt != 0) {
+            return false;
+          }
+          if (dest != _dest) {
+            _dest = never_reached;
+          }
+        } else {
+          if (_cnt == 0) {
+            return false;
+          }
+          if (dest != _dest) {
+            return false;
+          }
+        }
+      } else {
+        if (dest != _dest) {
+          return false;
+        }
+      }
       _hi = hi;
+      _cnt += cnt;
       return true;
     }
     return false;
   }
 
-  void set (jint value, int dest, int table_index) {
-    setRange(value, value, dest, table_index);
+  void set (jint value, int dest, int table_index, float cnt) {
+    setRange(value, value, dest, table_index, cnt);
   }
-  bool adjoin(jint value, int dest, int table_index) {
-    return adjoinRange(value, value, dest, table_index);
+  bool adjoin(jint value, int dest, int table_index, float cnt, bool trim_ranges) {
+    return adjoinRange(value, value, dest, table_index, cnt, trim_ranges);
+  }
+  bool adjoin(SwitchRange& other) {
+    return adjoinRange(other._lo, other._hi, other._dest, other._table_index, other._cnt, false);
   }
 
   void print() {
     if (is_singleton())
-      tty->print(" {%d}=>%d", lo(), dest());
+      tty->print(" {%d}=>%d (cnt=%f)", lo(), dest(), cnt());
     else if (lo() == min_jint)
-      tty->print(" {..%d}=>%d", hi(), dest());
+      tty->print(" {..%d}=>%d (cnt=%f)", hi(), dest(), cnt());
     else if (hi() == max_jint)
-      tty->print(" {%d..}=>%d", lo(), dest());
+      tty->print(" {%d..}=>%d (cnt=%f)", lo(), dest(), cnt());
     else
-      tty->print(" {%d..%d}=>%d", lo(), hi(), dest());
+      tty->print(" {%d..%d}=>%d (cnt=%f)", lo(), hi(), dest(), cnt());
   }
 };
 
+// We try to minimize the number of ranges and the size of the taken
+// ones using profiling data. When ranges are created,
+// SwitchRange::adjoinRange() only allows 2 adjoining ranges to merge
+// if both were never hit or both were hit to build longer unreached
+// ranges. Here, we now merge adjoining ranges with the same
+// destination and finally set destination of unreached ranges to the
+// special value never_reached because it can help minimize the number
+// of tests that are necessary.
+//
+// For instance:
+// [0, 1] to target1 sometimes taken
+// [1, 2] to target1 never taken
+// [2, 3] to target2 never taken
+// would lead to:
+// [0, 1] to target1 sometimes taken
+// [1, 3] never taken
+//
+// (first 2 ranges to target1 are not merged)
+static void merge_ranges(SwitchRange* ranges, int& rp) {
+  if (rp == 0) {
+    return;
+  }
+  int shift = 0;
+  for (int j = 0; j < rp; j++) {
+    SwitchRange& r1 = ranges[j-shift];
+    SwitchRange& r2 = ranges[j+1];
+    if (r1.adjoin(r2)) {
+      shift++;
+    } else if (shift > 0) {
+      ranges[j+1-shift] = r2;
+    }
+  }
+  rp -= shift;
+  for (int j = 0; j <= rp; j++) {
+    SwitchRange& r = ranges[j];
+    if (r.cnt() == 0 && r.dest() != never_reached) {
+      r.setRange(r.lo(), r.hi(), never_reached, r.table_index(), r.cnt());
+    }
+  }
+}
 
 //-------------------------------do_tableswitch--------------------------------
 void Parse::do_tableswitch() {
   Node* lookup = pop();
-
   // Get information about tableswitch
   int default_dest = iter().get_dest_table(0);
   int lo_index     = iter().get_int_table(1);
@@ -319,31 +417,58 @@
     return;
   }
 
+  ciMethodData* methodData = method()->method_data();
+  ciMultiBranchData* profile = NULL;
+  if (methodData->is_mature() && UseSwitchProfiling) {
+    ciProfileData* data = methodData->bci_to_data(bci());
+    if (data != NULL && data->is_MultiBranchData()) {
+      profile = (ciMultiBranchData*)data;
+    }
+  }
+  bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
+
   // generate decision tree, using trichotomy when possible
   int rnum = len+2;
   bool makes_backward_branch = false;
   SwitchRange* ranges = NEW_RESOURCE_ARRAY(SwitchRange, rnum);
   int rp = -1;
   if (lo_index != min_jint) {
-    ranges[++rp].setRange(min_jint, lo_index-1, default_dest, NullTableIndex);
+    uint cnt = 1;
+    if (profile != NULL) {
+      cnt = profile->default_count() / (hi_index != max_jint ? 2 : 1);
+    }
+    ranges[++rp].setRange(min_jint, lo_index-1, default_dest, NullTableIndex, cnt);
   }
   for (int j = 0; j < len; j++) {
     jint match_int = lo_index+j;
     int  dest      = iter().get_dest_table(j+3);
     makes_backward_branch |= (dest <= bci());
     int  table_index = method_data_update() ? j : NullTableIndex;
-    if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index)) {
-      ranges[++rp].set(match_int, dest, table_index);
+    uint cnt = 1;
+    if (profile != NULL) {
+      cnt = profile->count_at(j);
+    }
+    if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index, cnt, trim_ranges)) {
+      ranges[++rp].set(match_int, dest, table_index, cnt);
     }
   }
   jint highest = lo_index+(len-1);
   assert(ranges[rp].hi() == highest, "");
-  if (highest != max_jint
-      && !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex)) {
-    ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex);
+  if (highest != max_jint) {
+    uint cnt = 1;
+    if (profile != NULL) {
+      cnt = profile->default_count() / (lo_index != min_jint ? 2 : 1);
+    }
+    if (!ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex, cnt, trim_ranges)) {
+      ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex, cnt);
+    }
   }
   assert(rp < len+2, "not too many ranges");
 
+  if (trim_ranges) {
+    merge_ranges(ranges, rp);
+  }
+
   // Safepoint in case if backward branch observed
   if( makes_backward_branch && UseLoopSafepoints )
     add_safepoint();
@@ -365,48 +490,263 @@
     return;
   }
 
+  ciMethodData* methodData = method()->method_data();
+  ciMultiBranchData* profile = NULL;
+  if (methodData->is_mature() && UseSwitchProfiling) {
+    ciProfileData* data = methodData->bci_to_data(bci());
+    if (data != NULL && data->is_MultiBranchData()) {
+      profile = (ciMultiBranchData*)data;
+    }
+  }
+  bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
+
   // generate decision tree, using trichotomy when possible
-  jint* table = NEW_RESOURCE_ARRAY(jint, len*2);
+  jint* table = NEW_RESOURCE_ARRAY(jint, len*3);
   {
-    for( int j = 0; j < len; j++ ) {
-      table[j+j+0] = iter().get_int_table(2+j+j);
-      table[j+j+1] = iter().get_dest_table(2+j+j+1);
+    for (int j = 0; j < len; j++) {
+      table[3*j+0] = iter().get_int_table(2+2*j);
+      table[3*j+1] = iter().get_dest_table(2+2*j+1);
+      table[3*j+2] = profile == NULL ? 1 : profile->count_at(j);
     }
-    qsort( table, len, 2*sizeof(table[0]), jint_cmp );
+    qsort(table, len, 3*sizeof(table[0]), jint_cmp);
+  }
+
+  float defaults = 0;
+  jint prev = min_jint;
+  for (int j = 0; j < len; j++) {
+    jint match_int = table[3*j+0];
+    if (match_int != prev) {
+      defaults += (float)match_int - prev;
+    }
+    prev = match_int+1;
+  }
+  if (prev-1 != max_jint) {
+    defaults += (float)max_jint - prev + 1;
+  }
+  float default_cnt = 1;
+  if (profile != NULL) {
+    default_cnt = profile->default_count()/defaults;
   }
 
   int rnum = len*2+1;
   bool makes_backward_branch = false;
   SwitchRange* ranges = NEW_RESOURCE_ARRAY(SwitchRange, rnum);
   int rp = -1;
-  for( int j = 0; j < len; j++ ) {
-    jint match_int   = table[j+j+0];
-    int  dest        = table[j+j+1];
+  for (int j = 0; j < len; j++) {
+    jint match_int   = table[3*j+0];
+    int  dest        = table[3*j+1];
+    int  cnt         = table[3*j+2];
     int  next_lo     = rp < 0 ? min_jint : ranges[rp].hi()+1;
     int  table_index = method_data_update() ? j : NullTableIndex;
     makes_backward_branch |= (dest <= bci());
-    if( match_int != next_lo ) {
-      ranges[++rp].setRange(next_lo, match_int-1, default_dest, NullTableIndex);
+    float c = default_cnt * ((float)match_int - next_lo);
+    if (match_int != next_lo && (rp < 0 || !ranges[rp].adjoinRange(next_lo, match_int-1, default_dest, NullTableIndex, c, trim_ranges))) {
+      assert(default_dest != never_reached, "sentinel value for dead destinations");
+      ranges[++rp].setRange(next_lo, match_int-1, default_dest, NullTableIndex, c);
     }
-    if( rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index) ) {
-      ranges[++rp].set(match_int, dest, table_index);
+    if (rp < 0 || !ranges[rp].adjoin(match_int, dest, table_index, cnt, trim_ranges)) {
+      assert(dest != never_reached, "sentinel value for dead destinations");
+      ranges[++rp].set(match_int, dest, table_index, cnt);
     }
   }
-  jint highest = table[2*(len-1)];
+  jint highest = table[3*(len-1)];
   assert(ranges[rp].hi() == highest, "");
-  if( highest != max_jint
-      && !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex) ) {
-    ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex);
+  if (highest != max_jint &&
+      !ranges[rp].adjoinRange(highest+1, max_jint, default_dest, NullTableIndex, default_cnt * ((float)max_jint - highest), trim_ranges)) {
+    ranges[++rp].setRange(highest+1, max_jint, default_dest, NullTableIndex, default_cnt * ((float)max_jint - highest));
   }
   assert(rp < rnum, "not too many ranges");
 
+  if (trim_ranges) {
+    merge_ranges(ranges, rp);
+  }
+
   // Safepoint in case backward branch observed
-  if( makes_backward_branch && UseLoopSafepoints )
+  if (makes_backward_branch && UseLoopSafepoints)
     add_safepoint();
 
   jump_switch_ranges(lookup, &ranges[0], &ranges[rp]);
 }
 
+static float if_prob(float taken_cnt, float total_cnt) {
+  assert(taken_cnt <= total_cnt, "");
+  if (total_cnt == 0) {
+    return PROB_FAIR;
+  }
+  float p = taken_cnt / total_cnt;
+  return MIN2(MAX2(p, PROB_MIN), PROB_MAX);
+}
+
+static float if_cnt(float cnt) {
+  if (cnt == 0) {
+    return COUNT_UNKNOWN;
+  }
+  return cnt;
+}
+
+static float sum_of_cnts(SwitchRange *lo, SwitchRange *hi) {
+  float total_cnt = 0;
+  for (SwitchRange* sr = lo; sr <= hi; sr++) {
+    total_cnt += sr->cnt();
+  }
+  return total_cnt;
+}
+
+class SwitchRanges : public ResourceObj {
+public:
+  SwitchRange* _lo;
+  SwitchRange* _hi;
+  SwitchRange* _mid;
+  float _cost;
+
+  enum {
+    Start,
+    LeftDone,
+    RightDone,
+    Done
+  } _state;
+
+  SwitchRanges(SwitchRange *lo, SwitchRange *hi)
+    : _lo(lo), _hi(hi), _mid(NULL),
+      _cost(0), _state(Start) {
+  }
+
+  SwitchRanges()
+    : _lo(NULL), _hi(NULL), _mid(NULL),
+      _cost(0), _state(Start) {}
+};
+
+// Estimate cost of performing a binary search on lo..hi
+static float compute_tree_cost(SwitchRange *lo, SwitchRange *hi, float total_cnt) {
+  GrowableArray<SwitchRanges> tree;
+  SwitchRanges root(lo, hi);
+  tree.push(root);
+
+  float cost = 0;
+  do {
+    SwitchRanges& r = *tree.adr_at(tree.length()-1);
+    if (r._hi != r._lo) {
+      if (r._mid == NULL) {
+        float r_cnt = sum_of_cnts(r._lo, r._hi);
+
+        if (r_cnt == 0) {
+          tree.pop();
+          cost = 0;
+          continue;
+        }
+
+        SwitchRange* mid = NULL;
+        mid = r._lo;
+        for (float cnt = 0; ; ) {
+          assert(mid <= r._hi, "out of bounds");
+          cnt += mid->cnt();
+          if (cnt > r_cnt / 2) {
+            break;
+          }
+          mid++;
+        }
+        assert(mid <= r._hi, "out of bounds");
+        r._mid = mid;
+        r._cost = r_cnt / total_cnt;
+      }
+      r._cost += cost;
+      if (r._state < SwitchRanges::LeftDone && r._mid > r._lo) {
+        cost = 0;
+        r._state = SwitchRanges::LeftDone;
+        tree.push(SwitchRanges(r._lo, r._mid-1));
+      } else if (r._state < SwitchRanges::RightDone) {
+        cost = 0;
+        r._state = SwitchRanges::RightDone;
+        tree.push(SwitchRanges(r._mid == r._lo ? r._mid+1 : r._mid, r._hi));
+      } else {
+        tree.pop();
+        cost = r._cost;
+      }
+    } else {
+      tree.pop();
+      cost = r._cost;
+    }
+  } while (tree.length() > 0);
+
+
+  return cost;
+}
+
+// It sometimes pays off to test most common ranges before the binary search
+void Parse::linear_search_switch_ranges(Node* key_val, SwitchRange*& lo, SwitchRange*& hi) {
+  uint nr = hi - lo + 1;
+  float total_cnt = sum_of_cnts(lo, hi);
+
+  float min = compute_tree_cost(lo, hi, total_cnt);
+  float extra = 1;
+  float sub = 0;
+
+  SwitchRange* array1 = lo;
+  SwitchRange* array2 = NEW_RESOURCE_ARRAY(SwitchRange, nr);
+
+  SwitchRange* ranges = NULL;
+
+  while (nr >= 2) {
+    assert(lo == array1 || lo == array2, "one the 2 already allocated arrays");
+    ranges = (lo == array1) ? array2 : array1;
+
+    // Find highest frequency range
+    SwitchRange* candidate = lo;
+    for (SwitchRange* sr = lo+1; sr <= hi; sr++) {
+      if (sr->cnt() > candidate->cnt()) {
+        candidate = sr;
+      }
+    }
+    SwitchRange most_freq = *candidate;
+    if (most_freq.cnt() == 0) {
+      break;
+    }
+
+    // Copy remaining ranges into another array
+    int shift = 0;
+    for (uint i = 0; i < nr; i++) {
+      SwitchRange* sr = &lo[i];
+      if (sr != candidate) {
+        ranges[i-shift] = *sr;
+      } else {
+        shift++;
+        if (i > 0 && i < nr-1) {
+          SwitchRange prev = lo[i-1];
+          prev.setRange(prev.lo(), sr->hi(), prev.dest(), prev.table_index(), prev.cnt());
+          if (prev.adjoin(lo[i+1])) {
+            shift++;
+            i++;
+          }
+          ranges[i-shift] = prev;
+        }
+      }
+    }
+    nr -= shift;
+
+    // Evaluate cost of testing the most common range and performing a
+    // binary search on the other ranges
+    float cost = extra + compute_tree_cost(&ranges[0], &ranges[nr-1], total_cnt);
+    if (cost >= min) {
+      break;
+    }
+    // swap arrays
+    lo = &ranges[0];
+    hi = &ranges[nr-1];
+
+    // It pays off: emit the test for the most common range
+    assert(most_freq.cnt() > 0, "must be taken");
+    Node* val = _gvn.transform(new SubINode(key_val, _gvn.intcon(most_freq.lo())));
+    Node* cmp = _gvn.transform(new CmpUNode(val, _gvn.intcon(most_freq.hi() - most_freq.lo())));
+    Node* tst = _gvn.transform(new BoolNode(cmp, BoolTest::le));
+    IfNode* iff = create_and_map_if(control(), tst, if_prob(most_freq.cnt(), total_cnt), if_cnt(most_freq.cnt()));
+    jump_if_true_fork(iff, most_freq.dest(), most_freq.table_index(), false);
+
+    sub += most_freq.cnt() / total_cnt;
+    extra += 1 - sub;
+    min = cost;
+  }
+}
+
 //----------------------------create_jump_tables-------------------------------
 bool Parse::create_jump_tables(Node* key_val, SwitchRange* lo, SwitchRange* hi) {
   // Are jumptables enabled
@@ -418,6 +758,8 @@
   // Don't make jump table if profiling
   if (method_data_update())  return false;
 
+  bool trim_ranges = !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
+
   // Decide if a guard is needed to lop off big ranges at either (or
   // both) end(s) of the input set. We'll call this the default target
   // even though we can't be sure that it is the true "default".
@@ -439,12 +781,22 @@
     default_dest = hi->dest();
   }
 
+  float total = sum_of_cnts(lo, hi);
+  float cost = compute_tree_cost(lo, hi, total);
+
   // If a guard test will eliminate very sparse end ranges, then
   // it is worth the cost of an extra jump.
+  float trimmed_cnt = 0;
   if (total_outlier_size > (MaxJumpTableSparseness * 4)) {
     needs_guard = true;
-    if (default_dest == lo->dest()) lo++;
-    if (default_dest == hi->dest()) hi--;
+    if (default_dest == lo->dest()) {
+      trimmed_cnt += lo->cnt();
+      lo++;
+    }
+    if (default_dest == hi->dest()) {
+      trimmed_cnt += hi->cnt();
+      hi--;
+    }
   }
 
   // Find the total number of cases and ranges
@@ -452,8 +804,23 @@
   int num_range = hi - lo + 1;
 
   // Don't create table if: too large, too small, or too sparse.
-  if (num_cases < MinJumpTableSize || num_cases > MaxJumpTableSize)
+  if (num_cases > MaxJumpTableSize)
     return false;
+  if (UseSwitchProfiling) {
+    // MinJumpTableSize is set so with a well balanced binary tree,
+    // when the number of ranges is MinJumpTableSize, it's cheaper to
+    // go through a JumpNode that a tree of IfNodes. Average cost of a
+    // tree of IfNodes with MinJumpTableSize is
+    // log2f(MinJumpTableSize) comparisons. So if the cost computed
+    // from profile data is less than log2f(MinJumpTableSize) then
+    // going with the binary search is cheaper.
+    if (cost < log2f(MinJumpTableSize)) {
+      return false;
+    }
+  } else {
+    if (num_cases < MinJumpTableSize)
+      return false;
+  }
   if (num_cases > (MaxJumpTableSparseness * num_range))
     return false;
 
@@ -465,10 +832,12 @@
   // in the switch domain.
   if (needs_guard) {
     Node*   size = _gvn.intcon(num_cases);
-    Node*   cmp = _gvn.transform( new CmpUNode(key_val, size) );
-    Node*   tst = _gvn.transform( new BoolNode(cmp, BoolTest::ge) );
-    IfNode* iff = create_and_map_if( control(), tst, PROB_FAIR, COUNT_UNKNOWN);
-    jump_if_true_fork(iff, default_dest, NullTableIndex);
+    Node*   cmp = _gvn.transform(new CmpUNode(key_val, size));
+    Node*   tst = _gvn.transform(new BoolNode(cmp, BoolTest::ge));
+    IfNode* iff = create_and_map_if(control(), tst, if_prob(trimmed_cnt, total), if_cnt(trimmed_cnt));
+    jump_if_true_fork(iff, default_dest, NullTableIndex, trim_ranges && trimmed_cnt == 0);
+
+    total -= trimmed_cnt;
   }
 
   // Create an ideal node JumpTable that has projections
@@ -489,17 +858,44 @@
   key_val = _gvn.transform( new MulXNode( key_val, shiftWord));
 
   // Create the JumpNode
-  Node* jtn = _gvn.transform( new JumpNode(control(), key_val, num_cases) );
+  Arena* arena = C->comp_arena();
+  float* probs = (float*)arena->Amalloc(sizeof(float)*num_cases);
+  int i = 0;
+  if (total == 0) {
+    for (SwitchRange* r = lo; r <= hi; r++) {
+      for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
+        probs[i] = 1.0F / num_cases;
+      }
+    }
+  } else {
+    for (SwitchRange* r = lo; r <= hi; r++) {
+      float prob = r->cnt()/total;
+      for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
+        probs[i] = prob / (r->hi() - r->lo() + 1);
+      }
+    }
+  }
+
+  ciMethodData* methodData = method()->method_data();
+  ciMultiBranchData* profile = NULL;
+  if (methodData->is_mature()) {
+    ciProfileData* data = methodData->bci_to_data(bci());
+    if (data != NULL && data->is_MultiBranchData()) {
+      profile = (ciMultiBranchData*)data;
+    }
+  }
+
+  Node* jtn = _gvn.transform(new JumpNode(control(), key_val, num_cases, probs, profile == NULL ? COUNT_UNKNOWN : total));
 
   // These are the switch destinations hanging off the jumpnode
-  int i = 0;
+  i = 0;
   for (SwitchRange* r = lo; r <= hi; r++) {
     for (int64_t j = r->lo(); j <= r->hi(); j++, i++) {
       Node* input = _gvn.transform(new JumpProjNode(jtn, i, r->dest(), (int)(j - lowval)));
       {
         PreserveJVMState pjvms(this);
         set_control(input);
-        jump_if_always_fork(r->dest(), r->table_index());
+        jump_if_always_fork(r->dest(), r->table_index(), trim_ranges && r->cnt() == 0);
       }
     }
   }
@@ -511,6 +907,7 @@
 //----------------------------jump_switch_ranges-------------------------------
 void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, int switch_depth) {
   Block* switch_block = block();
+  bool trim_ranges = !method_data_update() && !C->too_many_traps(method(), bci(), Deoptimization::Reason_unstable_if);
 
   if (switch_depth == 0) {
     // Do special processing for the top-level call.
@@ -519,21 +916,23 @@
 
     // Decrement pred-numbers for the unique set of nodes.
 #ifdef ASSERT
-    // Ensure that the block's successors are a (duplicate-free) set.
-    int successors_counted = 0;  // block occurrences in [hi..lo]
-    int unique_successors = switch_block->num_successors();
-    for (int i = 0; i < unique_successors; i++) {
-      Block* target = switch_block->successor_at(i);
+    if (!trim_ranges) {
+      // Ensure that the block's successors are a (duplicate-free) set.
+      int successors_counted = 0;  // block occurrences in [hi..lo]
+      int unique_successors = switch_block->num_successors();
+      for (int i = 0; i < unique_successors; i++) {
+        Block* target = switch_block->successor_at(i);
 
-      // Check that the set of successors is the same in both places.
-      int successors_found = 0;
-      for (SwitchRange* p = lo; p <= hi; p++) {
-        if (p->dest() == target->start())  successors_found++;
+        // Check that the set of successors is the same in both places.
+        int successors_found = 0;
+        for (SwitchRange* p = lo; p <= hi; p++) {
+          if (p->dest() == target->start())  successors_found++;
+        }
+        assert(successors_found > 0, "successor must be known");
+        successors_counted += successors_found;
       }
-      assert(successors_found > 0, "successor must be known");
-      successors_counted += successors_found;
+      assert(successors_counted == (hi-lo)+1, "no unexpected successors");
     }
-    assert(successors_counted == (hi-lo)+1, "no unexpected successors");
 #endif
 
     // Maybe prune the inputs, based on the type of key_val.
@@ -545,10 +944,20 @@
       max_val = ti->_hi;
       assert(min_val <= max_val, "invalid int type");
     }
-    while (lo->hi() < min_val)  lo++;
-    if (lo->lo() < min_val)  lo->setRange(min_val, lo->hi(), lo->dest(), lo->table_index());
-    while (hi->lo() > max_val)  hi--;
-    if (hi->hi() > max_val)  hi->setRange(hi->lo(), max_val, hi->dest(), hi->table_index());
+    while (lo->hi() < min_val) {
+      lo++;
+    }
+    if (lo->lo() < min_val)  {
+      lo->setRange(min_val, lo->hi(), lo->dest(), lo->table_index(), lo->cnt());
+    }
+    while (hi->lo() > max_val) {
+      hi--;
+    }
+    if (hi->hi() > max_val) {
+      hi->setRange(hi->lo(), max_val, hi->dest(), hi->table_index(), hi->cnt());
+    }
+
+    linear_search_switch_ranges(key_val, lo, hi);
   }
 
 #ifndef PRODUCT
@@ -560,42 +969,57 @@
 
   assert(lo <= hi, "must be a non-empty set of ranges");
   if (lo == hi) {
-    jump_if_always_fork(lo->dest(), lo->table_index());
+    jump_if_always_fork(lo->dest(), lo->table_index(), trim_ranges && lo->cnt() == 0);
   } else {
     assert(lo->hi() == (lo+1)->lo()-1, "contiguous ranges");
     assert(hi->lo() == (hi-1)->hi()+1, "contiguous ranges");
 
     if (create_jump_tables(key_val, lo, hi)) return;
 
-    int nr = hi - lo + 1;
-
-    SwitchRange* mid = lo + nr/2;
-    // if there is an easy choice, pivot at a singleton:
-    if (nr > 3 && !mid->is_singleton() && (mid-1)->is_singleton())  mid--;
+    SwitchRange* mid = NULL;
+    float total_cnt = sum_of_cnts(lo, hi);
 
-    assert(lo < mid && mid <= hi, "good pivot choice");
-    assert(nr != 2 || mid == hi,   "should pick higher of 2");
-    assert(nr != 3 || mid == hi-1, "should pick middle of 3");
+    int nr = hi - lo + 1;
+    if (UseSwitchProfiling) {
+      // Don't keep the binary search tree balanced: pick up mid point
+      // that split frequencies in half.
+      float cnt = 0;
+      for (SwitchRange* sr = lo; sr <= hi; sr++) {
+        cnt += sr->cnt();
+        if (cnt >= total_cnt / 2) {
+          mid = sr;
+          break;
+        }
+      }
+    } else {
+      mid = lo + nr/2;
 
-    Node *test_val = _gvn.intcon(mid->lo());
+      // if there is an easy choice, pivot at a singleton:
+      if (nr > 3 && !mid->is_singleton() && (mid-1)->is_singleton())  mid--;
+
+      assert(lo < mid && mid <= hi, "good pivot choice");
+      assert(nr != 2 || mid == hi,   "should pick higher of 2");
+      assert(nr != 3 || mid == hi-1, "should pick middle of 3");
+    }
+
+
+    Node *test_val = _gvn.intcon(mid == lo ? mid->hi() : mid->lo());
 
     if (mid->is_singleton()) {
-      IfNode *iff_ne = jump_if_fork_int(key_val, test_val, BoolTest::ne);
-      jump_if_false_fork(iff_ne, mid->dest(), mid->table_index());
+      IfNode *iff_ne = jump_if_fork_int(key_val, test_val, BoolTest::ne, 1-if_prob(mid->cnt(), total_cnt), if_cnt(mid->cnt()));
+      jump_if_false_fork(iff_ne, mid->dest(), mid->table_index(), trim_ranges && mid->cnt() == 0);
 
       // Special Case:  If there are exactly three ranges, and the high
       // and low range each go to the same place, omit the "gt" test,
       // since it will not discriminate anything.
-      bool eq_test_only = (hi == lo+2 && hi->dest() == lo->dest());
-      if (eq_test_only) {
-        assert(mid == hi-1, "");
-      }
+      bool eq_test_only = (hi == lo+2 && hi->dest() == lo->dest() && mid == hi-1) || mid == lo;
 
       // if there is a higher range, test for it and process it:
       if (mid < hi && !eq_test_only) {
         // two comparisons of same values--should enable 1 test for 2 branches
         // Use BoolTest::le instead of BoolTest::gt
-        IfNode *iff_le  = jump_if_fork_int(key_val, test_val, BoolTest::le);
+        float cnt = sum_of_cnts(lo, mid-1);
+        IfNode *iff_le  = jump_if_fork_int(key_val, test_val, BoolTest::le, if_prob(cnt, total_cnt), if_cnt(cnt));
         Node   *iftrue  = _gvn.transform( new IfTrueNode(iff_le) );
         Node   *iffalse = _gvn.transform( new IfFalseNode(iff_le) );
         { PreserveJVMState pjvms(this);
@@ -607,24 +1031,33 @@
 
     } else {
       // mid is a range, not a singleton, so treat mid..hi as a unit
-      IfNode *iff_ge = jump_if_fork_int(key_val, test_val, BoolTest::ge);
+      float cnt = sum_of_cnts(mid == lo ? mid+1 : mid, hi);
+      IfNode *iff_ge = jump_if_fork_int(key_val, test_val, mid == lo ? BoolTest::gt : BoolTest::ge, if_prob(cnt, total_cnt), if_cnt(cnt));
 
       // if there is a higher range, test for it and process it:
       if (mid == hi) {
-        jump_if_true_fork(iff_ge, mid->dest(), mid->table_index());
+        jump_if_true_fork(iff_ge, mid->dest(), mid->table_index(), trim_ranges && cnt == 0);
       } else {
         Node *iftrue  = _gvn.transform( new IfTrueNode(iff_ge) );
         Node *iffalse = _gvn.transform( new IfFalseNode(iff_ge) );
         { PreserveJVMState pjvms(this);
           set_control(iftrue);
-          jump_switch_ranges(key_val, mid, hi, switch_depth+1);
+          jump_switch_ranges(key_val, mid == lo ? mid+1 : mid, hi, switch_depth+1);
         }
         set_control(iffalse);
       }
     }
 
     // in any case, process the lower range
-    jump_switch_ranges(key_val, lo, mid-1, switch_depth+1);
+    if (mid == lo) {
+      if (mid->is_singleton()) {
+        jump_switch_ranges(key_val, lo+1, hi, switch_depth+1);
+      } else {
+        jump_if_always_fork(lo->dest(), lo->table_index(), trim_ranges && lo->cnt() == 0);
+      }
+    } else {
+      jump_switch_ranges(key_val, lo, mid-1, switch_depth+1);
+    }
   }
 
   // Decrease pred_count for each successor after all is done.
@@ -724,7 +1157,7 @@
         Node *mask = _gvn.intcon((divisor - 1));
         // Sigh, must handle negative dividends
         Node *zero = _gvn.intcon(0);
-        IfNode *ifff = jump_if_fork_int(a, zero, BoolTest::lt);
+        IfNode *ifff = jump_if_fork_int(a, zero, BoolTest::lt, PROB_FAIR, COUNT_UNKNOWN);
         Node *iff = _gvn.transform( new IfFalseNode(ifff) );
         Node *ift = _gvn.transform( new IfTrueNode (ifff) );
         Node *reg = jump_if_join(ift, iff);
--- a/src/hotspot/share/opto/superword.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/opto/superword.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1943,9 +1943,14 @@
         for (uint k = 0; k < use->req(); k++) {
           Node* n = use->in(k);
           if (def == n) {
-            // reductions can be loop carried dependences
-            if (def->is_reduction() && use->is_Phi())
+            // reductions should only have a Phi use at the the loop
+            // head and out of loop uses
+            if (def->is_reduction() &&
+                ((use->is_Phi() && use->in(0) == _lpt->_head) ||
+                 !_lpt->is_member(_phase->get_loop(_phase->ctrl_or_self(use))))) {
+              assert(i == p->size()-1, "must be last element of the pack");
               continue;
+            }
             if (!is_vector_use(use, k)) {
               return false;
             }
--- a/src/hotspot/share/prims/whitebox.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/prims/whitebox.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1359,7 +1359,9 @@
   {
     MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
     blob = (BufferBlob*) CodeCache::allocate(full_size, blob_type);
-    ::new (blob) BufferBlob("WB::DummyBlob", full_size);
+    if (blob != NULL) {
+      ::new (blob) BufferBlob("WB::DummyBlob", full_size);
+    }
   }
   // Track memory usage statistic after releasing CodeCache_lock
   MemoryService::track_code_cache_memory_usage();
--- a/src/hotspot/share/runtime/arguments.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/runtime/arguments.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1821,18 +1821,6 @@
 
   GCConfig::initialize();
 
-#if COMPILER2_OR_JVMCI
-  // Shared spaces work fine with other GCs but causes bytecode rewriting
-  // to be disabled, which hurts interpreter performance and decreases
-  // server performance.  When -server is specified, keep the default off
-  // unless it is asked for.  Future work: either add bytecode rewriting
-  // at link time, or rewrite bytecodes in non-shared methods.
-  if (is_server_compilation_mode_vm() && !DumpSharedSpaces && !RequireSharedSpaces &&
-      (FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) {
-    no_shared_spaces("COMPILER2 default: -Xshare:auto | off, have to manually setup to on.");
-  }
-#endif
-
 #if defined(IA32)
   // Only server compiler can optimize safepoints well enough.
   if (!is_server_compilation_mode_vm()) {
--- a/src/hotspot/share/runtime/globals.hpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/runtime/globals.hpp	Thu Apr 26 17:59:02 2018 +0200
@@ -2997,6 +2997,8 @@
   diagnostic(bool, ShowRegistersOnAssert, false,                            \
           "On internal errors, include registers in error report.")         \
                                                                             \
+  experimental(bool, UseSwitchProfiling, true,                              \
+          "leverage profiling for table/lookup switch")                     \
 
 #define VM_FLAGS(develop,                                                   \
                  develop_pd,                                                \
--- a/src/hotspot/share/runtime/vmStructs.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -56,6 +56,7 @@
 #include "memory/referenceType.hpp"
 #include "memory/universe.hpp"
 #include "memory/virtualspace.hpp"
+#include "memory/filemap.hpp"
 #include "oops/array.hpp"
 #include "oops/arrayKlass.hpp"
 #include "oops/arrayOop.hpp"
@@ -1000,6 +1001,8 @@
   c2_nonstatic_field(MachIfNode,               _prob,                                         jfloat)                                \
   c2_nonstatic_field(MachIfNode,               _fcnt,                                         jfloat)                                \
                                                                                                                                      \
+  c2_nonstatic_field(MachJumpNode,             _probs,                                        jfloat*)                               \
+                                                                                                                                     \
   c2_nonstatic_field(CallNode,                 _entry_point,                                  address)                               \
                                                                                                                                      \
   c2_nonstatic_field(CallJavaNode,             _method,                                       ciMethod*)                             \
@@ -1118,6 +1121,16 @@
      static_field(java_lang_Class,             _oop_size_offset,                              int)                                   \
      static_field(java_lang_Class,             _static_oop_field_count_offset,                int)                                   \
                                                                                                                                      \
+  /********************************************/                                                                                     \
+  /* FileMapInfo fields (CDS archive related) */                                                                                     \
+  /********************************************/                                                                                     \
+                                                                                                                                     \
+  nonstatic_field(FileMapInfo,                 _header,                                       FileMapInfo::FileMapHeader*)           \
+     static_field(FileMapInfo,                 _current_info,                                 FileMapInfo*)                          \
+  nonstatic_field(FileMapInfo::FileMapHeader,  _space[0],                                     FileMapInfo::FileMapHeader::space_info)\
+  nonstatic_field(FileMapInfo::FileMapHeader::space_info, _addr._base,                        char*)                                 \
+  nonstatic_field(FileMapInfo::FileMapHeader::space_info, _used,                              size_t)                                \
+                                                                                                                                     \
   /******************/                                                                                                               \
   /* VMError fields */                                                                                                               \
   /******************/                                                                                                               \
@@ -1442,7 +1455,7 @@
   declare_type(SafepointBlob,            SingletonBlob)                   \
   declare_type(DeoptimizationBlob,       SingletonBlob)                   \
   declare_c2_type(ExceptionBlob,         SingletonBlob)                   \
-  declare_c2_type(UncommonTrapBlob,      RuntimeBlob)                        \
+  declare_c2_type(UncommonTrapBlob,      RuntimeBlob)                     \
                                                                           \
   /***************************************/                               \
   /* PcDesc and other compiled code info */                               \
@@ -1663,6 +1676,7 @@
   declare_c2_type(MachNullCheckNode, MachIdealNode)                       \
   declare_c2_type(MachProjNode, ProjNode)                                 \
   declare_c2_type(MachIfNode, MachNode)                                   \
+  declare_c2_type(MachJumpNode, MachNode)                                 \
   declare_c2_type(MachFastLockNode, MachNode)                             \
   declare_c2_type(MachReturnNode, MachNode)                               \
   declare_c2_type(MachSafePointNode, MachReturnNode)                      \
@@ -1997,6 +2011,10 @@
   declare_toplevel_type(vframeArrayElement)                               \
   declare_toplevel_type(Annotations*)                                     \
   declare_type(OopMapValue, StackObj)                                     \
+  declare_type(FileMapInfo, CHeapObj<mtInternal>)                         \
+  declare_type(FileMapInfo::FileMapHeaderBase, CHeapObj<mtClass>)         \
+  declare_type(FileMapInfo::FileMapHeader, FileMapInfo::FileMapHeaderBase)\
+  declare_toplevel_type(FileMapInfo::FileMapHeader::space_info)           \
                                                                           \
   /************/                                                          \
   /* GC types */                                                          \
--- a/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m	Thu Apr 26 17:59:02 2018 +0200
@@ -438,12 +438,11 @@
             if (passwordChars == NULL) {
                 goto errOut;
             }
-            passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
 
-            // clear the password and release
-            memset(passwordChars, 0, passwordLen);
-            (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
-                JNI_ABORT);
+            passwordStrRef = CFStringCreateWithCharactersNoCopy(NULL, passwordChars, passwordLen, kCFAllocatorNull);
+            if (passwordStrRef == NULL) {
+                goto errOut;
+            }
         }
     }
 
@@ -471,7 +470,12 @@
 errOut:
     if (exportedData) CFRelease(exportedData);
     if (passwordStrRef) CFRelease(passwordStrRef);
-
+    if (passwordChars) {
+        // clear the password and release
+        memset(passwordChars, 0, passwordLen);
+        (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
+            JNI_ABORT);
+    }
     return returnValue;
 }
 
@@ -538,12 +542,11 @@
             if (passwordChars == NULL) {
                 goto errOut;
             }
-            passwordStrRef = CFStringCreateWithCharacters(kCFAllocatorDefault, passwordChars, passwordLen);
 
-            // clear the password and release
-            memset(passwordChars, 0, passwordLen);
-            (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
-                JNI_ABORT);
+            passwordStrRef = CFStringCreateWithCharactersNoCopy(NULL, passwordChars, passwordLen, kCFAllocatorNull);
+            if (passwordStrRef == NULL) {
+                goto errOut;
+            }
         }
     }
 
@@ -581,7 +584,14 @@
         CFRelease(createdItems);
     }
 
-errOut: ;
+errOut:
+    if (passwordStrRef) CFRelease(passwordStrRef);
+    if (passwordChars) {
+        // clear the password and release
+        memset(passwordChars, 0, passwordLen);
+        (*env)->ReleaseCharArrayElements(env, passwordObj, passwordChars,
+            JNI_ABORT);
+    }
 
 JNF_COCOA_EXIT(env);
 
--- a/src/java.base/share/classes/java/io/FileInputStream.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/io/FileInputStream.java	Thu Apr 26 17:59:02 2018 +0200
@@ -79,7 +79,7 @@
 
     private volatile boolean closed;
 
-    private final AltFinalizer altFinalizer;
+    private final Object altFinalizer;
 
     /**
      * Creates a <code>FileInputStream</code> by
@@ -155,7 +155,7 @@
         fd.attach(this);
         path = name;
         open(name);
-        altFinalizer = AltFinalizer.get(this);
+        altFinalizer = getFinalizer(this);
         if (altFinalizer == null) {
             FileCleanable.register(fd);       // open set the fd, register the cleanup
         }
@@ -471,6 +471,23 @@
     protected void finalize() throws IOException {
     }
 
+    /*
+     * Returns a finalizer object if the FIS needs a finalizer; otherwise null.
+     * If the FIS has a close method; it needs an AltFinalizer.
+     */
+    private static Object getFinalizer(FileInputStream fis) {
+        Class<?> clazz = fis.getClass();
+        while (clazz != FileInputStream.class) {
+            try {
+                clazz.getDeclaredMethod("close");
+                return new AltFinalizer(fis);
+            } catch (NoSuchMethodException nsme) {
+                // ignore
+            }
+            clazz = clazz.getSuperclass();
+        }
+        return null;
+    }
     /**
      * Class to call {@code FileInputStream.close} when finalized.
      * If finalization of the stream is needed, an instance is created
@@ -481,25 +498,7 @@
     static class AltFinalizer {
         private final FileInputStream fis;
 
-        /*
-         * Returns a finalizer object if the FIS needs a finalizer; otherwise null.
-         * If the FIS has a close method; it needs an AltFinalizer.
-         */
-        static AltFinalizer get(FileInputStream fis) {
-            Class<?> clazz = fis.getClass();
-            while (clazz != FileInputStream.class) {
-                try {
-                    clazz.getDeclaredMethod("close");
-                    return new AltFinalizer(fis);
-                } catch (NoSuchMethodException nsme) {
-                    // ignore
-                }
-                clazz = clazz.getSuperclass();
-            }
-            return null;
-        }
-
-        private AltFinalizer(FileInputStream fis) {
+        AltFinalizer(FileInputStream fis) {
             this.fis = fis;
         }
 
--- a/src/java.base/share/classes/java/io/FileOutputStream.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/io/FileOutputStream.java	Thu Apr 26 17:59:02 2018 +0200
@@ -95,7 +95,7 @@
 
     private volatile boolean closed;
 
-    private final AltFinalizer altFinalizer;
+    private final Object altFinalizer;
 
     /**
      * Creates a file output stream to write to the file with the
@@ -235,7 +235,7 @@
         this.path = name;
 
         open(name, append);
-        altFinalizer = AltFinalizer.get(this);
+        altFinalizer = getFinalizer(this);
         if (altFinalizer == null) {
             FileCleanable.register(fd);   // open sets the fd, register the cleanup
         }
@@ -496,6 +496,24 @@
         initIDs();
     }
 
+    /*
+     * Returns a finalizer object if the FOS needs a finalizer; otherwise null.
+     * If the FOS has a close method; it needs an AltFinalizer.
+     */
+    private static Object getFinalizer(FileOutputStream fos) {
+        Class<?> clazz = fos.getClass();
+        while (clazz != FileOutputStream.class) {
+            try {
+                clazz.getDeclaredMethod("close");
+                return new AltFinalizer(fos);
+            } catch (NoSuchMethodException nsme) {
+                // ignore
+            }
+            clazz = clazz.getSuperclass();
+        }
+        return null;
+    }
+
     /**
      * Class to call {@code FileOutputStream.close} when finalized.
      * If finalization of the stream is needed, an instance is created
@@ -506,25 +524,7 @@
     static class AltFinalizer {
         private final FileOutputStream fos;
 
-        /*
-         * Returns a finalizer object if the FOS needs a finalizer; otherwise null.
-         * If the FOS has a close method; it needs an AltFinalizer.
-         */
-        static AltFinalizer get(FileOutputStream fos) {
-            Class<?> clazz = fos.getClass();
-            while (clazz != FileOutputStream.class) {
-                try {
-                    clazz.getDeclaredMethod("close");
-                    return new AltFinalizer(fos);
-                } catch (NoSuchMethodException nsme) {
-                    // ignore
-                }
-                clazz = clazz.getSuperclass();
-            }
-            return null;
-        }
-
-        private AltFinalizer(FileOutputStream fos) {
+        AltFinalizer(FileOutputStream fos) {
             this.fos = fos;
         }
 
--- a/src/java.base/share/classes/java/lang/Long.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/lang/Long.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1164,10 +1164,8 @@
      * significantly better space and time performance by caching
      * frequently requested values.
      *
-     * Note that unlike the {@linkplain Integer#valueOf(int)
-     * corresponding method} in the {@code Integer} class, this method
-     * is <em>not</em> required to cache values within a particular
-     * range.
+     * This method will always cache values in the range -128 to 127,
+     * inclusive, and may cache other values outside of this range.
      *
      * @param  l a long value.
      * @return a {@code Long} instance representing {@code l}.
--- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,13 +32,17 @@
 import jdk.internal.vm.annotation.Stable;
 import sun.invoke.util.BytecodeName;
 
-import java.lang.reflect.*;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
 import java.util.function.Function;
 
 import static java.lang.invoke.LambdaForm.*;
@@ -64,7 +68,7 @@
     private final List<MemberName> transformMethods;
     private final MethodType baseConstructorType;
     private final S topSpecies;
-    private final ConcurrentMap<K, S> cache = new ConcurrentHashMap<>();
+    private final ConcurrentHashMap<K, S> cache = new ConcurrentHashMap<>();
     private final Factory factory;
     private @Stable boolean topClassIsSuper;
 
@@ -113,8 +117,7 @@
         this.keyType = keyType;
         this.metaType = metaType;
         this.sdAccessor = sdAccessor;
-        // FIXME: use List.copyOf once 8177290 is in
-        this.transformMethods = List.of(transformMethods.toArray(new MemberName[transformMethods.size()]));
+        this.transformMethods = List.copyOf(transformMethods);
         this.sdFieldName = sdFieldName;
         this.baseConstructorType = baseConstructorType.changeReturnType(void.class);
         this.factory = makeFactory();
@@ -149,12 +152,6 @@
     }
 
     public final S findSpecies(K key) {
-        S speciesData = cache.computeIfAbsent(key, new Function<>() {
-            @Override
-            public S apply(K key1) {
-                return factory.loadSpecies(newSpeciesData(key1));
-            }
-        });
         // Note:  Species instantiation may throw VirtualMachineError because of
         // code cache overflow.  If this happens the species bytecode may be
         // loaded but not linked to its species metadata (with MH's etc).
@@ -176,7 +173,33 @@
         // successfully on a concrete class if ever.
         // The concrete class is published via SpeciesData instance
         // returned here only after the class and species data are linked together.
-        assert(speciesData != null);
+        S speciesData = cache.computeIfAbsent(key, new Function<>() {
+            @Override
+            public S apply(K key1) {
+                return newSpeciesData(key1);
+            }
+        });
+        // Separating the creation of a placeholder SpeciesData instance above
+        // from the loading and linking a real one below ensures we can never
+        // accidentally call computeIfAbsent recursively.  Replacing rather than
+        // updating the placeholder is done to ensure safe publication.
+        if (!speciesData.isResolved()) {
+            synchronized (speciesData) {
+                S existingSpeciesData = cache.get(key);
+                if (existingSpeciesData == speciesData) { // won the race
+                    // create a new SpeciesData...
+                    speciesData = newSpeciesData(key);
+                    // load and link it...
+                    speciesData = factory.loadSpecies(speciesData);
+                    if (!cache.replace(key, existingSpeciesData, speciesData)) {
+                        throw newInternalError("Concurrent loadSpecies");
+                    }
+                } else { // lost the race; the retrieved existingSpeciesData is the final
+                    speciesData = existingSpeciesData;
+                }
+            }
+        }
+        assert(speciesData != null && speciesData.isResolved());
         return speciesData;
     }
 
@@ -208,9 +231,7 @@
         protected SpeciesData(K key) {
             this.key = keyType.cast(Objects.requireNonNull(key));
             List<Class<?>> types = deriveFieldTypes(key);
-            // TODO: List.copyOf
-            int arity = types.size();
-            this.fieldTypes = List.of(types.toArray(new Class<?>[arity]));
+            this.fieldTypes = List.copyOf(types);
         }
 
         public final K key() {
@@ -458,8 +479,8 @@
             final Class<? extends T> speciesCode;
             if (salvage != null) {
                 speciesCode = salvage.asSubclass(topClass());
-                factory.linkSpeciesDataToCode(speciesData, speciesCode);
-                factory.linkCodeToSpeciesData(speciesCode, speciesData, true);
+                linkSpeciesDataToCode(speciesData, speciesCode);
+                linkCodeToSpeciesData(speciesCode, speciesData, true);
             } else {
                 // Not pregenerated, generate the class
                 try {
@@ -486,7 +507,7 @@
             if (!speciesData.isResolved()) {
                 throw newInternalError("bad species class linkage for " + className + ": " + speciesData);
             }
-            assert(speciesData == factory.loadSpeciesDataFromCode(speciesCode));
+            assert(speciesData == loadSpeciesDataFromCode(speciesCode));
             return speciesData;
         }
 
--- a/src/java.base/share/classes/java/util/jar/Attributes.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/java/util/jar/Attributes.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,10 +28,10 @@
 import java.io.DataOutputStream;
 import java.io.IOException;
 import java.util.Collection;
-import java.util.Comparator;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.Locale;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 
 import sun.util.logging.PlatformLogger;
@@ -116,7 +116,7 @@
      * @throws IllegalArgumentException if the attribute name is invalid
      */
     public String getValue(String name) {
-        return (String)get(new Attributes.Name(name));
+        return (String)get(Name.of(name));
     }
 
     /**
@@ -168,7 +168,7 @@
      * @exception IllegalArgumentException if the attribute name is invalid
      */
     public String putValue(String name, String value) {
-        return (String)put(new Name(name), value);
+        return (String)put(Name.of(name), value);
     }
 
     /**
@@ -371,7 +371,7 @@
      */
     @SuppressWarnings("deprecation")
     void read(Manifest.FastInputStream is, byte[] lbuf) throws IOException {
-        String name = null, value = null;
+        String name = null, value;
         byte[] lastline = null;
 
         int len;
@@ -447,8 +447,21 @@
      * for more information about valid attribute names and values.
      */
     public static class Name {
-        private String name;
-        private int hashCode = -1;
+        private final String name;
+        private final int hashCode;
+
+        /**
+         * Avoid allocation for common Names
+         */
+        private static final Map<String, Name> KNOWN_NAMES;
+
+        static final Name of(String name) {
+            Name n = KNOWN_NAMES.get(name);
+            if (n != null) {
+                return n;
+            }
+            return new Name(name);
+        }
 
         /**
          * Constructs a new attribute name using the given string name.
@@ -459,38 +472,33 @@
          * @exception NullPointerException if the attribute name was null
          */
         public Name(String name) {
-            if (name == null) {
-                throw new NullPointerException("name");
-            }
-            if (!isValid(name)) {
-                throw new IllegalArgumentException(name);
-            }
+            this.hashCode = hash(name);
             this.name = name.intern();
         }
 
-        private static boolean isValid(String name) {
+        // Checks the string is valid
+        private final int hash(String name) {
+            Objects.requireNonNull(name, "name");
             int len = name.length();
             if (len > 70 || len == 0) {
-                return false;
+                throw new IllegalArgumentException(name);
             }
+            // Calculate hash code case insensitively
+            int h = 0;
             for (int i = 0; i < len; i++) {
-                if (!isValid(name.charAt(i))) {
-                    return false;
+                char c = name.charAt(i);
+                if (c >= 'a' && c <= 'z') {
+                    // hashcode must be identical for upper and lower case
+                    h = h * 31 + (c - 0x20);
+                } else if ((c >= 'A' && c <= 'Z' ||
+                        c >= '0' && c <= '9' ||
+                        c == '_' || c == '-')) {
+                    h = h * 31 + c;
+                } else {
+                    throw new IllegalArgumentException(name);
                 }
             }
-            return true;
-        }
-
-        private static boolean isValid(char c) {
-            return isAlpha(c) || isDigit(c) || c == '_' || c == '-';
-        }
-
-        private static boolean isAlpha(char c) {
-            return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
-        }
-
-        private static boolean isDigit(char c) {
-            return c >= '0' && c <= '9';
+            return h;
         }
 
         /**
@@ -500,9 +508,12 @@
          *         specified attribute object
          */
         public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
             if (o instanceof Name) {
-                Comparator<String> c = String.CASE_INSENSITIVE_ORDER;
-                return c.compare(name, ((Name)o).name) == 0;
+                Name other = (Name)o;
+                return other.name.equalsIgnoreCase(name);
             } else {
                 return false;
             }
@@ -512,9 +523,6 @@
          * Computes the hash value for this attribute name.
          */
         public int hashCode() {
-            if (hashCode == -1) {
-                hashCode = name.toLowerCase(Locale.ROOT).hashCode();
-            }
             return hashCode;
         }
 
@@ -573,7 +581,7 @@
          */
         public static final Name SEALED = new Name("Sealed");
 
-       /**
+        /**
          * {@code Name} object for {@code Extension-List} manifest attribute
          * used for the extension mechanism that is no longer supported.
          */
@@ -620,7 +628,7 @@
         @Deprecated
         public static final Name IMPLEMENTATION_VENDOR_ID = new Name("Implementation-Vendor-Id");
 
-       /**
+        /**
          * {@code Name} object for {@code Implementation-URL}
          * manifest attribute.
          *
@@ -654,5 +662,55 @@
          * @since   9
          */
         public static final Name MULTI_RELEASE = new Name("Multi-Release");
+
+        private static void addName(Map<String, Name> names, Name name) {
+            names.put(name.name, name);
+        }
+
+        static {
+            var names = new HashMap<String, Name>(64);
+            addName(names, MANIFEST_VERSION);
+            addName(names, SIGNATURE_VERSION);
+            addName(names, CONTENT_TYPE);
+            addName(names, CLASS_PATH);
+            addName(names, MAIN_CLASS);
+            addName(names, SEALED);
+            addName(names, EXTENSION_LIST);
+            addName(names, EXTENSION_NAME);
+            addName(names, IMPLEMENTATION_TITLE);
+            addName(names, IMPLEMENTATION_VERSION);
+            addName(names, IMPLEMENTATION_VENDOR);
+            addName(names, SPECIFICATION_TITLE);
+            addName(names, SPECIFICATION_VERSION);
+            addName(names, SPECIFICATION_VENDOR);
+            addName(names, MULTI_RELEASE);
+
+            // Common attributes used in MANIFEST.MF et.al; adding these has a
+            // small footprint cost, but is likely to be quickly paid for by
+            // reducing allocation when reading and parsing typical manifests
+            addName(names, new Name("Add-Exports"));
+            addName(names, new Name("Add-Opens"));
+            addName(names, new Name("Ant-Version"));
+            addName(names, new Name("Archiver-Version"));
+            addName(names, new Name("Build-Jdk"));
+            addName(names, new Name("Built-By"));
+            addName(names, new Name("Bnd-LastModified"));
+            addName(names, new Name("Bundle-Description"));
+            addName(names, new Name("Bundle-DocURL"));
+            addName(names, new Name("Bundle-License"));
+            addName(names, new Name("Bundle-ManifestVersion"));
+            addName(names, new Name("Bundle-Name"));
+            addName(names, new Name("Bundle-Vendor"));
+            addName(names, new Name("Bundle-Version"));
+            addName(names, new Name("Bundle-SymbolicName"));
+            addName(names, new Name("Created-By"));
+            addName(names, new Name("Export-Package"));
+            addName(names, new Name("Import-Package"));
+            addName(names, new Name("Name"));
+            addName(names, new Name("SHA1-Digest"));
+            addName(names, new Name("X-Compile-Source-JDK"));
+            addName(names, new Name("X-Compile-Target-JDK"));
+            KNOWN_NAMES = names;
+        }
     }
 }
--- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -334,7 +334,7 @@
                 boolean append = fdAccess.getAppend(fd);
                 do {
                     // in append-mode then position is advanced to end before writing
-                    p = (append) ? nd.size(fd) : position0(fd, -1);
+                    p = (append) ? nd.size(fd) : nd.seek(fd, -1);
                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
                 return IOStatus.normalize(p);
             } finally {
@@ -358,7 +358,7 @@
                 if (!isOpen())
                     return null;
                 do {
-                    p = position0(fd, newPosition);
+                    p = nd.seek(fd, newPosition);
                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
                 return this;
             } finally {
@@ -418,7 +418,7 @@
 
                 // get current position
                 do {
-                    p = position0(fd, -1);
+                    p = nd.seek(fd, -1);
                 } while ((p == IOStatus.INTERRUPTED) && isOpen());
                 if (!isOpen())
                     return null;
@@ -437,7 +437,7 @@
                 if (p > newSize)
                     p = newSize;
                 do {
-                    rp = position0(fd, p);
+                    rp = nd.seek(fd, p);
                 } while ((rp == IOStatus.INTERRUPTED) && isOpen());
                 return this;
             } finally {
@@ -985,7 +985,7 @@
                     }
                     int rv;
                     do {
-                        rv = nd.allocate(fd, position + size);
+                        rv = nd.truncate(fd, position + size);
                     } while ((rv == IOStatus.INTERRUPTED) && isOpen());
                     if (!isOpen())
                         return null;
@@ -1212,11 +1212,6 @@
     private native long transferTo0(FileDescriptor src, long position,
                                     long count, FileDescriptor dst);
 
-    // Sets or reports this file's position
-    // If offset is -1, the current position is returned
-    // otherwise the position is set to offset
-    private native long position0(FileDescriptor fd, long offset);
-
     // Caches fieldIDs
     private static native long initIDs();
 
--- a/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/sun/nio/ch/FileDispatcher.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -36,12 +36,17 @@
     public static final int RET_EX_LOCK = 1;    // Obtained exclusive lock
     public static final int INTERRUPTED = 2;    // Request interrupted
 
+    /**
+     * Sets or reports this file's position
+     * If offset is -1, the current position is returned
+     * otherwise the position is set to offset.
+     */
+    abstract long seek(FileDescriptor fd, long offset) throws IOException;
+
     abstract int force(FileDescriptor fd, boolean metaData) throws IOException;
 
     abstract int truncate(FileDescriptor fd, long size) throws IOException;
 
-    abstract int allocate(FileDescriptor fd, long size) throws IOException;
-
     abstract long size(FileDescriptor fd) throws IOException;
 
     abstract int lock(FileDescriptor fd, boolean blocking, long pos, long size,
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,7 @@
 import java.io.FilePermission;
 import java.net.SocketPermission;
 import java.net.NetPermission;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.ConcurrentHashMap;
 import jdk.internal.misc.JavaSecurityAccess;
 import static jdk.internal.misc.JavaSecurityAccess.ProtectionDomainCache;
 import jdk.internal.misc.SharedSecrets;
@@ -248,7 +248,8 @@
     private static final int DEFAULT_CACHE_SIZE = 1;
 
     // contains the policy grant entries, PD cache, and alias mapping
-    private AtomicReference<PolicyInfo> policyInfo = new AtomicReference<>();
+    // can be updated if refresh() is called
+    private volatile PolicyInfo policyInfo;
 
     private boolean expandProperties = true;
     private boolean allowSystemProperties = true;
@@ -268,8 +269,8 @@
      * previously parsed and have syntax errors, so that they can be
      * subsequently ignored.
      */
-    private static AtomicReference<Set<URL>> badPolicyURLs =
-        new AtomicReference<>(new HashSet<>());
+    private static Set<URL> badPolicyURLs =
+        Collections.newSetFromMap(new ConcurrentHashMap<URL,Boolean>());
 
     // The default.policy file
     private static final URL DEFAULT_POLICY_URL =
@@ -341,7 +342,7 @@
         // System.out.println("number caches=" + numCaches);
         PolicyInfo newInfo = new PolicyInfo(numCaches);
         initPolicyFile(newInfo, url);
-        policyInfo.set(newInfo);
+        policyInfo = newInfo;
     }
 
     private void initPolicyFile(final PolicyInfo newInfo, final URL url) {
@@ -498,7 +499,7 @@
 
         // skip parsing policy file if it has been previously parsed and
         // has syntax errors
-        if (badPolicyURLs.get().contains(policy)) {
+        if (badPolicyURLs.contains(policy)) {
             if (debug != null) {
                 debug.println("skipping bad policy file: " + policy);
             }
@@ -539,10 +540,7 @@
                 throw new InternalError("Failed to load default.policy", pe);
             }
             // record bad policy file to avoid later reparsing it
-            badPolicyURLs.updateAndGet(k -> {
-                k.add(policy);
-                return k;
-            });
+            badPolicyURLs.add(policy);
             Object[] source = {policy, pe.getNonlocalizedMessage()};
             System.err.println(LocalizedMessage.getNonlocalized
                 (POLICY + ".error.parsing.policy.message", source));
@@ -991,9 +989,7 @@
      */
     @Override
     public boolean implies(ProtectionDomain pd, Permission p) {
-        PolicyInfo pi = policyInfo.get();
-        ProtectionDomainCache pdMap = pi.getPdMapping();
-
+        ProtectionDomainCache pdMap = policyInfo.getPdMapping();
         PermissionCollection pc = pdMap.get(pd);
 
         if (pc != null) {
@@ -1139,9 +1135,7 @@
     private Permissions getPermissions(Permissions perms,
                                        final CodeSource cs,
                                        Principal[] principals) {
-        PolicyInfo pi = policyInfo.get();
-
-        for (PolicyEntry entry : pi.policyEntries) {
+        for (PolicyEntry entry : policyInfo.policyEntries) {
             addPermissions(perms, cs, principals, entry);
         }
 
--- a/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/classes/sun/nio/ch/FileDispatcherImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -74,6 +74,10 @@
         return writev0(fd, address, len);
     }
 
+    long seek(FileDescriptor fd, long offset) throws IOException {
+        return seek0(fd, offset);
+    }
+
     int force(FileDescriptor fd, boolean metaData) throws IOException {
         return force0(fd, metaData);
     }
@@ -82,10 +86,6 @@
         return truncate0(fd, size);
     }
 
-    int allocate(FileDescriptor fd, long size) throws IOException {
-        return allocate0(fd, size);
-    }
-
     long size(FileDescriptor fd) throws IOException {
         return size0(fd);
     }
@@ -156,10 +156,10 @@
     static native int force0(FileDescriptor fd, boolean metaData)
         throws IOException;
 
-    static native int truncate0(FileDescriptor fd, long size)
+    static native long seek0(FileDescriptor fd, long offset)
         throws IOException;
 
-    static native int allocate0(FileDescriptor fd, long size)
+    static native int truncate0(FileDescriptor fd, long size)
         throws IOException;
 
     static native long size0(FileDescriptor fd) throws IOException;
--- a/src/java.base/unix/native/libjava/io_util_md.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/native/libjava/io_util_md.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -232,25 +232,6 @@
 handleSetLength(FD fd, jlong length)
 {
     int result;
-#if defined(__linux__)
-    /*
-     * On Linux, if the file size is being increased, then ftruncate64()
-     * will modify the metadata value of the size without actually allocating
-     * any blocks which can cause a SIGBUS error if the file is subsequently
-     * memory-mapped.
-     */
-    struct stat64 sb;
-
-    if (fstat64(fd, &sb) == 0 && length > sb.st_blocks*512) {
-        RESTARTABLE(fallocate64(fd, 0, 0, length), result);
-        // Return on success or if errno is neither EOPNOTSUPP nor ENOSYS
-        if (result == 0) {
-            return 0;
-        } else if (errno != EOPNOTSUPP && errno != ENOSYS) {
-            return result;
-        }
-    }
-#endif
     RESTARTABLE(ftruncate64(fd, length), result);
     return result;
 }
--- a/src/java.base/unix/native/libnio/ch/FileChannelImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/native/libnio/ch/FileChannelImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -23,33 +23,31 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jvm_md.h"
-#include "jlong.h"
 #include <sys/mman.h>
 #include <sys/stat.h>
 #include <fcntl.h>
-#include "sun_nio_ch_FileChannelImpl.h"
-#include "java_lang_Integer.h"
-#include "nio.h"
-#include "nio_util.h"
-#include <dlfcn.h>
+#include <sys/types.h>
+#include <unistd.h>
 
 #if defined(__linux__) || defined(__solaris__)
 #include <sys/sendfile.h>
 #elif defined(_AIX)
 #include <sys/socket.h>
 #elif defined(_ALLBSD_SOURCE)
-#include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/uio.h>
-
 #define lseek64 lseek
 #define mmap64 mmap
 #endif
 
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "sun_nio_ch_FileChannelImpl.h"
+#include "java_lang_Integer.h"
+
 static jfieldID chan_fd;        /* jobject 'fd' in sun.nio.ch.FileChannelImpl */
 
 JNIEXPORT jlong JNICALL
@@ -123,23 +121,6 @@
                   "Unmap failed");
 }
 
-
-JNIEXPORT jlong JNICALL
-Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
-                                          jobject fdo, jlong offset)
-{
-    jint fd = fdval(env, fdo);
-    jlong result = 0;
-
-    if (offset < 0) {
-        result = lseek64(fd, 0, SEEK_CUR);
-    } else {
-        result = lseek64(fd, offset, SEEK_SET);
-    }
-    return handle(env, result, "Position failed");
-}
-
-
 JNIEXPORT jlong JNICALL
 Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
                                             jobject srcFDO,
--- a/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/unix/native/libnio/ch/FileDispatcherImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -23,40 +23,42 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "sun_nio_ch_FileDispatcherImpl.h"
-#include "java_lang_Long.h"
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <fcntl.h>
 #include <sys/uio.h>
 #include <unistd.h>
+#include <sys/stat.h>
 #include <sys/statvfs.h>
+
 #if defined(__linux__)
 #include <linux/fs.h>
 #include <sys/ioctl.h>
 #endif
-#include "nio.h"
-#include "nio_util.h"
 
-#ifdef _ALLBSD_SOURCE
+#if defined(_ALLBSD_SOURCE)
+#define lseek64 lseek
 #define stat64 stat
 #define flock64 flock
 #define off64_t off_t
 #define F_SETLKW64 F_SETLKW
 #define F_SETLK64 F_SETLK
-
 #define pread64 pread
 #define pwrite64 pwrite
 #define ftruncate64 ftruncate
 #define fstat64 fstat
-
 #define fdatasync fsync
 #endif
 
+#include "jni.h"
+#include "jni_util.h"
+#include "jvm.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+#include "sun_nio_ch_FileDispatcherImpl.h"
+#include "java_lang_Long.h"
+
 static int preCloseFD = -1;     /* File descriptor to which we dup other fd's
                                    before closing them for real */
 
@@ -142,6 +144,20 @@
     return IOS_THROWN;
 }
 
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv *env, jclass clazz,
+                                         jobject fdo, jlong offset)
+{
+    jint fd = fdval(env, fdo);
+    off64_t result;
+    if (offset < 0) {
+        result = lseek64(fd, 0, SEEK_CUR);
+    } else {
+        result = lseek64(fd, offset, SEEK_SET);
+    }
+    return handle(env, (jlong)result, "lseek64 failed");
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
                                           jobject fdo, jboolean md)
@@ -187,30 +203,6 @@
                   "Truncation failed");
 }
 
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_FileDispatcherImpl_allocate0(JNIEnv *env, jobject this,
-                                             jobject fdo, jlong size)
-{
-#if defined(__linux__)
-    /*
-     * On Linux, if the file size is being increased, then ftruncate64()
-     * will modify the metadata value of the size without actually allocating
-     * any blocks which can cause a SIGBUS error if the file is subsequently
-     * memory-mapped.
-     */
-    // Return on success or if errno is neither EOPNOTSUPP nor ENOSYS
-    int result = fallocate64(fdval(env, fdo), 0, 0, size);
-    if (result == 0) {
-        return 0;
-    } else if (errno != EOPNOTSUPP && errno != ENOSYS) {
-        return handle(env, result, "Allocation failed");
-    }
-#endif
-    return handle(env,
-                  ftruncate64(fdval(env, fdo), size),
-                  "Truncation failed");
-}
-
 JNIEXPORT jlong JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo)
 {
--- a/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -69,7 +69,7 @@
         if (fd == null)
             throw new SocketException("Socket closed");
 
-        int newfd = socketCreate(false /* v6Only */);
+        int newfd = socketCreate();
 
         fdAccess.set(fd, newfd);
     }
@@ -274,7 +274,7 @@
 
     private static native void initIDs();
 
-    private static native int socketCreate(boolean v6Only);
+    private static native int socketCreate();
 
     private static native void socketBind(int fd, InetAddress localAddress,
             int localport, boolean exclBind) throws SocketException;
--- a/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,356 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, 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 java.net;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetPropertyAction;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.misc.JavaIOFileDescriptorAccess;
-
-/**
- * This class defines the plain SocketImpl.
- * When java.net.preferIPv4Stack system property is set to true, it uses
- * IPv4-only socket.
- * When java.net.preferIPv4Stack is set to false, it handles both IPv4
- * and IPv6 through a single file descriptor.
- *
- * @author Chris Hegarty
- */
-
-class DualStackPlainSocketImpl extends AbstractPlainSocketImpl {
-
-    private static final JavaIOFileDescriptorAccess fdAccess =
-        SharedSecrets.getJavaIOFileDescriptorAccess();
-
-    private static final boolean preferIPv4Stack =
-            Boolean.parseBoolean(AccessController.doPrivileged(
-                new GetPropertyAction("java.net.preferIPv4Stack", "false")));
-
-    /**
-     * Empty value of sun.net.useExclusiveBind is treated as 'true'.
-     */
-    private static final boolean useExclusiveBind;
-
-    static {
-        String exclBindProp = AccessController.doPrivileged(
-                new GetPropertyAction("sun.net.useExclusiveBind", ""));
-        useExclusiveBind = exclBindProp.isEmpty()
-                || Boolean.parseBoolean(exclBindProp);
-    }
-
-    // emulates SO_REUSEADDR when useExclusiveBind is true
-    private boolean isReuseAddress;
-
-    public DualStackPlainSocketImpl() {
-    }
-
-    public DualStackPlainSocketImpl(FileDescriptor fd) {
-        this.fd = fd;
-    }
-
-    @Override
-    void socketCreate(boolean stream) throws IOException {
-        if (fd == null)
-            throw new SocketException("Socket closed");
-
-        int newfd = socket0(stream);
-
-        fdAccess.set(fd, newfd);
-    }
-
-    @Override
-    void socketConnect(InetAddress address, int port, int timeout)
-        throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (address == null)
-            throw new NullPointerException("inet address argument is null.");
-
-        if (preferIPv4Stack && !(address instanceof Inet4Address))
-            throw new SocketException("Protocol family not supported");
-
-        int connectResult;
-        if (timeout <= 0) {
-            connectResult = connect0(nativefd, address, port);
-        } else {
-            configureBlocking(nativefd, false);
-            try {
-                connectResult = connect0(nativefd, address, port);
-                if (connectResult == WOULDBLOCK) {
-                    waitForConnect(nativefd, timeout);
-                }
-            } finally {
-                configureBlocking(nativefd, true);
-            }
-        }
-        /*
-         * We need to set the local port field. If bind was called
-         * previous to the connect (by the client) then localport field
-         * will already be set.
-         */
-        if (localport == 0)
-            localport = localPort0(nativefd);
-    }
-
-    @Override
-    void socketBind(InetAddress address, int port) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (address == null)
-            throw new NullPointerException("inet address argument is null.");
-
-        if (preferIPv4Stack && !(address instanceof Inet4Address))
-            throw new SocketException("Protocol family not supported");
-
-        bind0(nativefd, address, port, useExclusiveBind);
-        if (port == 0) {
-            localport = localPort0(nativefd);
-        } else {
-            localport = port;
-        }
-
-        this.address = address;
-    }
-
-    @Override
-    void socketListen(int backlog) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        listen0(nativefd, backlog);
-    }
-
-    @Override
-    void socketAccept(SocketImpl s) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (s == null)
-            throw new NullPointerException("socket is null");
-
-        int newfd = -1;
-        InetSocketAddress[] isaa = new InetSocketAddress[1];
-        if (timeout <= 0) {
-            newfd = accept0(nativefd, isaa);
-        } else {
-            configureBlocking(nativefd, false);
-            try {
-                waitForNewConnection(nativefd, timeout);
-                newfd = accept0(nativefd, isaa);
-                if (newfd != -1) {
-                    configureBlocking(newfd, true);
-                }
-            } finally {
-                configureBlocking(nativefd, true);
-            }
-        }
-        /* Update (SocketImpl)s' fd */
-        fdAccess.set(s.fd, newfd);
-        /* Update socketImpls remote port, address and localport */
-        InetSocketAddress isa = isaa[0];
-        s.port = isa.getPort();
-        s.address = isa.getAddress();
-        s.localport = localport;
-        if (preferIPv4Stack && !(s.address instanceof Inet4Address))
-            throw new SocketException("Protocol family not supported");
-    }
-
-    @Override
-    int socketAvailable() throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-        return available0(nativefd);
-    }
-
-    @Override
-    void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
-        if (fd == null)
-            throw new SocketException("Socket closed");
-
-        if (!fd.valid())
-            return;
-
-        final int nativefd = fdAccess.get(fd);
-        fdAccess.set(fd, -1);
-        close0(nativefd);
-    }
-
-    @Override
-    void socketShutdown(int howto) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-        shutdown0(nativefd, howto);
-    }
-
-    // Intentional fallthrough after SO_REUSEADDR
-    @SuppressWarnings("fallthrough")
-    @Override
-    void socketSetOption(int opt, boolean on, Object value)
-        throws SocketException {
-
-        // SO_REUSEPORT is not supported on Windows.
-        if (opt == SO_REUSEPORT) {
-            throw new UnsupportedOperationException("unsupported option");
-        }
-
-        int nativefd = checkAndReturnNativeFD();
-
-        if (opt == SO_TIMEOUT) {
-            if (preferIPv4Stack) {
-                // Don't enable the socket option on ServerSocket as it's
-                // meaningless (we don't receive on a ServerSocket).
-                if (serverSocket == null) {
-                    setSoTimeout0(nativefd, ((Integer)value).intValue());
-                }
-            } // else timeout is implemented through select.
-            return;
-        }
-
-        int optionValue = 0;
-
-        switch(opt) {
-            case SO_REUSEADDR:
-                if (useExclusiveBind) {
-                    // SO_REUSEADDR emulated when using exclusive bind
-                    isReuseAddress = on;
-                    return;
-                }
-                // intentional fallthrough
-            case TCP_NODELAY:
-            case SO_OOBINLINE:
-            case SO_KEEPALIVE:
-                optionValue = on ? 1 : 0;
-                break;
-            case SO_SNDBUF:
-            case SO_RCVBUF:
-            case IP_TOS:
-                optionValue = ((Integer)value).intValue();
-                break;
-            case SO_LINGER:
-                if (on) {
-                    optionValue = ((Integer)value).intValue();
-                } else {
-                    optionValue = -1;
-                }
-                break;
-            default :/* shouldn't get here */
-                throw new SocketException("Option not supported");
-        }
-
-        setIntOption(nativefd, opt, optionValue);
-    }
-
-    @Override
-    int socketGetOption(int opt, Object iaContainerObj)
-        throws SocketException {
-
-        // SO_REUSEPORT is not supported on Windows.
-        if (opt == SO_REUSEPORT) {
-            throw new UnsupportedOperationException("unsupported option");
-        }
-
-        int nativefd = checkAndReturnNativeFD();
-
-        // SO_BINDADDR is not a socket option.
-        if (opt == SO_BINDADDR) {
-            localAddress(nativefd, (InetAddressContainer)iaContainerObj);
-            return 0;  // return value doesn't matter.
-        }
-
-        // SO_REUSEADDR emulated when using exclusive bind
-        if (opt == SO_REUSEADDR && useExclusiveBind)
-            return isReuseAddress ? 1 : -1;
-
-        int value = getIntOption(nativefd, opt);
-
-        switch (opt) {
-            case TCP_NODELAY:
-            case SO_OOBINLINE:
-            case SO_KEEPALIVE:
-            case SO_REUSEADDR:
-                return (value == 0) ? -1 : 1;
-        }
-        return value;
-    }
-
-    @Override
-    void socketSendUrgentData(int data) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-        sendOOB(nativefd, data);
-    }
-
-    private int checkAndReturnNativeFD() throws SocketException {
-        if (fd == null || !fd.valid())
-            throw new SocketException("Socket closed");
-
-        return fdAccess.get(fd);
-    }
-
-    static final int WOULDBLOCK = -2;       // Nothing available (non-blocking)
-
-    static {
-        initIDs();
-    }
-
-    /* Native methods */
-
-    static native void initIDs();
-
-    static native int socket0(boolean stream) throws IOException;
-
-    static native void bind0(int fd, InetAddress localAddress, int localport,
-                             boolean exclBind)
-        throws IOException;
-
-    static native int connect0(int fd, InetAddress remote, int remotePort)
-        throws IOException;
-
-    static native void waitForConnect(int fd, int timeout) throws IOException;
-
-    static native int localPort0(int fd) throws IOException;
-
-    static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
-
-    static native void listen0(int fd, int backlog) throws IOException;
-
-    static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
-
-    static native void waitForNewConnection(int fd, int timeout) throws IOException;
-
-    static native int available0(int fd) throws IOException;
-
-    static native void close0(int fd) throws IOException;
-
-    static native void shutdown0(int fd, int howto) throws IOException;
-
-    static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
-
-    static native void setSoTimeout0(int fd, int timeout) throws SocketException;
-
-    static native int getIntOption(int fd, int cmd) throws SocketException;
-
-    static native void sendOOB(int fd, int data) throws IOException;
-
-    static native void configureBlocking(int fd, boolean blocking) throws IOException;
-}
--- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,261 +24,335 @@
  */
 package java.net;
 
-import java.io.*;
+import java.io.IOException;
+import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
+import jdk.internal.misc.SharedSecrets;
+import jdk.internal.misc.JavaIOFileDescriptorAccess;
 
-/*
- * This class PlainSocketImpl simply delegates to the appropriate real
- * SocketImpl. We do this because PlainSocketImpl is already extended
- * by SocksSocketImpl.
- * <p>
- * There is one possibility for the real SocketImpl: DualStackPlainSocketImpl.
+/**
+ * On Windows system we simply delegate to native methods.
  *
  * @author Chris Hegarty
  */
 
 class PlainSocketImpl extends AbstractPlainSocketImpl {
-    private AbstractPlainSocketImpl impl;
+
+    private static final JavaIOFileDescriptorAccess fdAccess =
+        SharedSecrets.getJavaIOFileDescriptorAccess();
+
+    private static final boolean preferIPv4Stack =
+            Boolean.parseBoolean(AccessController.doPrivileged(
+                new GetPropertyAction("java.net.preferIPv4Stack", "false")));
+
+    /**
+     * Empty value of sun.net.useExclusiveBind is treated as 'true'.
+     */
+    private static final boolean useExclusiveBind;
+
+    static {
+        String exclBindProp = AccessController.doPrivileged(
+                new GetPropertyAction("sun.net.useExclusiveBind", ""));
+        useExclusiveBind = exclBindProp.isEmpty()
+                || Boolean.parseBoolean(exclBindProp);
+    }
+
+    // emulates SO_REUSEADDR when useExclusiveBind is true
+    private boolean isReuseAddress;
 
     /**
      * Constructs an empty instance.
      */
-    PlainSocketImpl() {
-        impl = new DualStackPlainSocketImpl();
+    public PlainSocketImpl() {
     }
 
     /**
      * Constructs an instance with the given file descriptor.
      */
-    PlainSocketImpl(FileDescriptor fd) {
-        impl = new DualStackPlainSocketImpl(fd);
-    }
-
-    // Override methods in SocketImpl that access impl's fields.
-
-    protected FileDescriptor getFileDescriptor() {
-        return impl.getFileDescriptor();
+    public PlainSocketImpl(FileDescriptor fd) {
+        this.fd = fd;
     }
 
-    protected InetAddress getInetAddress() {
-        return impl.getInetAddress();
-    }
+    @Override
+    void socketCreate(boolean stream) throws IOException {
+        if (fd == null)
+            throw new SocketException("Socket closed");
 
-    protected int getPort() {
-        return impl.getPort();
-    }
+        int newfd = socket0(stream);
 
-    protected int getLocalPort() {
-        return impl.getLocalPort();
-    }
-
-    void setSocket(Socket soc) {
-        impl.setSocket(soc);
+        fdAccess.set(fd, newfd);
     }
 
-    Socket getSocket() {
-        return impl.getSocket();
-    }
+    @Override
+    void socketConnect(InetAddress address, int port, int timeout)
+        throws IOException {
+        int nativefd = checkAndReturnNativeFD();
 
-    void setServerSocket(ServerSocket soc) {
-        impl.setServerSocket(soc);
-    }
+        if (address == null)
+            throw new NullPointerException("inet address argument is null.");
 
-    ServerSocket getServerSocket() {
-        return impl.getServerSocket();
-    }
+        if (preferIPv4Stack && !(address instanceof Inet4Address))
+            throw new SocketException("Protocol family not supported");
 
-    public String toString() {
-        return impl.toString();
-    }
-
-    // Override methods in AbstractPlainSocketImpl that access impl's fields.
-
-    protected synchronized void create(boolean stream) throws IOException {
-        impl.create(stream);
-
-        // set fd to delegate's fd to be compatible with older releases
-        this.fd = impl.fd;
-    }
-
-    protected void connect(String host, int port)
-        throws UnknownHostException, IOException
-    {
-        impl.connect(host, port);
+        int connectResult;
+        if (timeout <= 0) {
+            connectResult = connect0(nativefd, address, port);
+        } else {
+            configureBlocking(nativefd, false);
+            try {
+                connectResult = connect0(nativefd, address, port);
+                if (connectResult == WOULDBLOCK) {
+                    waitForConnect(nativefd, timeout);
+                }
+            } finally {
+                configureBlocking(nativefd, true);
+            }
+        }
+        /*
+         * We need to set the local port field. If bind was called
+         * previous to the connect (by the client) then localport field
+         * will already be set.
+         */
+        if (localport == 0)
+            localport = localPort0(nativefd);
     }
 
-    protected void connect(InetAddress address, int port) throws IOException {
-        impl.connect(address, port);
-    }
+    @Override
+    void socketBind(InetAddress address, int port) throws IOException {
+        int nativefd = checkAndReturnNativeFD();
+
+        if (address == null)
+            throw new NullPointerException("inet address argument is null.");
 
-    protected void connect(SocketAddress address, int timeout) throws IOException {
-        impl.connect(address, timeout);
-    }
+        if (preferIPv4Stack && !(address instanceof Inet4Address))
+            throw new SocketException("Protocol family not supported");
 
-    public void setOption(int opt, Object val) throws SocketException {
-        impl.setOption(opt, val);
+        bind0(nativefd, address, port, useExclusiveBind);
+        if (port == 0) {
+            localport = localPort0(nativefd);
+        } else {
+            localport = port;
+        }
+
+        this.address = address;
     }
 
-    public Object getOption(int opt) throws SocketException {
-        return impl.getOption(opt);
-    }
+    @Override
+    void socketListen(int backlog) throws IOException {
+        int nativefd = checkAndReturnNativeFD();
 
-    synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
-        impl.doConnect(address, port, timeout);
-    }
-
-    protected synchronized void bind(InetAddress address, int lport)
-        throws IOException
-    {
-        impl.bind(address, lport);
+        listen0(nativefd, backlog);
     }
 
-    protected synchronized void accept(SocketImpl s) throws IOException {
-        if (s instanceof PlainSocketImpl) {
-            // pass in the real impl not the wrapper.
-            SocketImpl delegate = ((PlainSocketImpl)s).impl;
-            delegate.address = new InetAddress();
-            delegate.fd = new FileDescriptor();
-            impl.accept(delegate);
-            // set fd to delegate's fd to be compatible with older releases
-            s.fd = delegate.fd;
+    @Override
+    void socketAccept(SocketImpl s) throws IOException {
+        int nativefd = checkAndReturnNativeFD();
+
+        if (s == null)
+            throw new NullPointerException("socket is null");
+
+        int newfd = -1;
+        InetSocketAddress[] isaa = new InetSocketAddress[1];
+        if (timeout <= 0) {
+            newfd = accept0(nativefd, isaa);
         } else {
-            impl.accept(s);
+            configureBlocking(nativefd, false);
+            try {
+                waitForNewConnection(nativefd, timeout);
+                newfd = accept0(nativefd, isaa);
+                if (newfd != -1) {
+                    configureBlocking(newfd, true);
+                }
+            } finally {
+                configureBlocking(nativefd, true);
+            }
         }
+        /* Update (SocketImpl)s' fd */
+        fdAccess.set(s.fd, newfd);
+        /* Update socketImpls remote port, address and localport */
+        InetSocketAddress isa = isaa[0];
+        s.port = isa.getPort();
+        s.address = isa.getAddress();
+        s.localport = localport;
+        if (preferIPv4Stack && !(s.address instanceof Inet4Address))
+            throw new SocketException("Protocol family not supported");
     }
 
-    void setFileDescriptor(FileDescriptor fd) {
-        impl.setFileDescriptor(fd);
-    }
-
-    void setAddress(InetAddress address) {
-        impl.setAddress(address);
+    @Override
+    int socketAvailable() throws IOException {
+        int nativefd = checkAndReturnNativeFD();
+        return available0(nativefd);
     }
 
-    void setPort(int port) {
-        impl.setPort(port);
+    @Override
+    void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
+        if (fd == null)
+            throw new SocketException("Socket closed");
+
+        if (!fd.valid())
+            return;
+
+        final int nativefd = fdAccess.get(fd);
+        fdAccess.set(fd, -1);
+        close0(nativefd);
     }
 
-    void setLocalPort(int localPort) {
-        impl.setLocalPort(localPort);
-    }
-
-    protected synchronized InputStream getInputStream() throws IOException {
-        return impl.getInputStream();
+    @Override
+    void socketShutdown(int howto) throws IOException {
+        int nativefd = checkAndReturnNativeFD();
+        shutdown0(nativefd, howto);
     }
 
-    void setInputStream(SocketInputStream in) {
-        impl.setInputStream(in);
-    }
+    // Intentional fallthrough after SO_REUSEADDR
+    @SuppressWarnings("fallthrough")
+    @Override
+    void socketSetOption(int opt, boolean on, Object value)
+        throws SocketException {
 
-    protected synchronized OutputStream getOutputStream() throws IOException {
-        return impl.getOutputStream();
-    }
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+
+        int nativefd = checkAndReturnNativeFD();
 
-    protected void close() throws IOException {
-        try {
-            impl.close();
-        } finally {
-            // set fd to delegate's fd to be compatible with older releases
-            this.fd = null;
+        if (opt == SO_TIMEOUT) {
+            if (preferIPv4Stack) {
+                // Don't enable the socket option on ServerSocket as it's
+                // meaningless (we don't receive on a ServerSocket).
+                if (serverSocket == null) {
+                    setSoTimeout0(nativefd, ((Integer)value).intValue());
+                }
+            } // else timeout is implemented through select.
+            return;
         }
-    }
 
-    void reset() throws IOException {
-        try {
-            impl.reset();
-        } finally {
-            // set fd to delegate's fd to be compatible with older releases
-            this.fd = null;
-        }
-    }
+        int optionValue = 0;
 
-    protected void shutdownInput() throws IOException {
-        impl.shutdownInput();
-    }
-
-    protected void shutdownOutput() throws IOException {
-        impl.shutdownOutput();
-    }
-
-    protected void sendUrgentData(int data) throws IOException {
-        impl.sendUrgentData(data);
-    }
+        switch(opt) {
+            case SO_REUSEADDR:
+                if (useExclusiveBind) {
+                    // SO_REUSEADDR emulated when using exclusive bind
+                    isReuseAddress = on;
+                    return;
+                }
+                // intentional fallthrough
+            case TCP_NODELAY:
+            case SO_OOBINLINE:
+            case SO_KEEPALIVE:
+                optionValue = on ? 1 : 0;
+                break;
+            case SO_SNDBUF:
+            case SO_RCVBUF:
+            case IP_TOS:
+                optionValue = ((Integer)value).intValue();
+                break;
+            case SO_LINGER:
+                if (on) {
+                    optionValue = ((Integer)value).intValue();
+                } else {
+                    optionValue = -1;
+                }
+                break;
+            default :/* shouldn't get here */
+                throw new SocketException("Option not supported");
+        }
 
-    FileDescriptor acquireFD() {
-        return impl.acquireFD();
-    }
-
-    void releaseFD() {
-        impl.releaseFD();
-    }
-
-    boolean isConnectionReset() {
-        return impl.isConnectionReset();
-    }
-
-    void setConnectionReset() {
-        impl.setConnectionReset();
-    }
-
-    public boolean isClosedOrPending() {
-        return impl.isClosedOrPending();
+        setIntOption(nativefd, opt, optionValue);
     }
 
-    public int getTimeout() {
-        return impl.getTimeout();
-    }
+    @Override
+    int socketGetOption(int opt, Object iaContainerObj)
+        throws SocketException {
+
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+
+        int nativefd = checkAndReturnNativeFD();
 
-    // Override methods in AbstractPlainSocketImpl that need to be implemented.
+        // SO_BINDADDR is not a socket option.
+        if (opt == SO_BINDADDR) {
+            localAddress(nativefd, (InetAddressContainer)iaContainerObj);
+            return 0;  // return value doesn't matter.
+        }
+
+        // SO_REUSEADDR emulated when using exclusive bind
+        if (opt == SO_REUSEADDR && useExclusiveBind)
+            return isReuseAddress ? 1 : -1;
 
-    void socketCreate(boolean stream) throws IOException {
-        impl.socketCreate(stream);
+        int value = getIntOption(nativefd, opt);
+
+        switch (opt) {
+            case TCP_NODELAY:
+            case SO_OOBINLINE:
+            case SO_KEEPALIVE:
+            case SO_REUSEADDR:
+                return (value == 0) ? -1 : 1;
+        }
+        return value;
     }
 
-    void socketConnect(InetAddress address, int port, int timeout)
-        throws IOException {
-        impl.socketConnect(address, port, timeout);
+    @Override
+    void socketSendUrgentData(int data) throws IOException {
+        int nativefd = checkAndReturnNativeFD();
+        sendOOB(nativefd, data);
     }
 
-    void socketBind(InetAddress address, int port)
-        throws IOException {
-        impl.socketBind(address, port);
-    }
+    private int checkAndReturnNativeFD() throws SocketException {
+        if (fd == null || !fd.valid())
+            throw new SocketException("Socket closed");
 
-    void socketListen(int count) throws IOException {
-        impl.socketListen(count);
-    }
-
-    void socketAccept(SocketImpl s) throws IOException {
-        impl.socketAccept(s);
+        return fdAccess.get(fd);
     }
 
-    int socketAvailable() throws IOException {
-        return impl.socketAvailable();
-    }
+    static final int WOULDBLOCK = -2;       // Nothing available (non-blocking)
 
-    void socketClose0(boolean useDeferredClose) throws IOException {
-        impl.socketClose0(useDeferredClose);
-    }
-
-    void socketShutdown(int howto) throws IOException {
-        impl.socketShutdown(howto);
+    static {
+        initIDs();
     }
 
-    void socketSetOption(int cmd, boolean on, Object value)
-        throws SocketException {
-        impl.socketSetOption(cmd, on, value);
-    }
+    /* Native methods */
+
+    static native void initIDs();
+
+    static native int socket0(boolean stream) throws IOException;
+
+    static native void bind0(int fd, InetAddress localAddress, int localport,
+                             boolean exclBind)
+        throws IOException;
 
-    int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
-        return impl.socketGetOption(opt, iaContainerObj);
-    }
+    static native int connect0(int fd, InetAddress remote, int remotePort)
+        throws IOException;
+
+    static native void waitForConnect(int fd, int timeout) throws IOException;
+
+    static native int localPort0(int fd) throws IOException;
+
+    static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
+
+    static native void listen0(int fd, int backlog) throws IOException;
 
-    void socketSendUrgentData(int data) throws IOException {
-        impl.socketSendUrgentData(data);
-    }
+    static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
+
+    static native void waitForNewConnection(int fd, int timeout) throws IOException;
+
+    static native int available0(int fd) throws IOException;
+
+    static native void close0(int fd) throws IOException;
+
+    static native void shutdown0(int fd, int howto) throws IOException;
 
-    static boolean isReusePortAvailable() {
-        // SO_REUSEPORT is not supported on Windows.
-        return false;
-    }
+    static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
+
+    static native void setSoTimeout0(int fd, int timeout) throws SocketException;
+
+    static native int getIntOption(int fd, int cmd) throws SocketException;
+
+    static native void sendOOB(int fd, int data) throws IOException;
+
+    static native void configureBlocking(int fd, boolean blocking) throws IOException;
 }
--- a/src/java.base/windows/classes/sun/net/PortConfig.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/sun/net/PortConfig.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,49 +25,21 @@
 
 package sun.net;
 
-import java.security.AccessController;
-
 /**
  * Determines the ephemeral port range in use on this system.
- * If this cannot be determined, then the default settings
- * of the OS are returned.
+ * On Windows we always use the default range.
  */
 
 public final class PortConfig {
 
-    private static int defaultUpper, defaultLower;
-    private static final int upper, lower;
-
-    static {
-        AccessController.doPrivileged(
-            new java.security.PrivilegedAction<Void>() {
-                public Void run() {
-                    System.loadLibrary("net");
-                    return null;
-                }
-            });
-
-        int v = getLower0();
-        if (v == -1) {
-            v = defaultLower;
-        }
-        lower = v;
-
-        v = getUpper0();
-        if (v == -1) {
-            v = defaultUpper;
-        }
-        upper = v;
-    }
-
-    static native int getLower0();
-    static native int getUpper0();
+    private static final int defaultLower = 49152;
+    private static final int defaultUpper = 65535;
 
     public static int getLower() {
-        return lower;
+        return defaultLower;
     }
 
     public static int getUpper() {
-        return upper;
+        return defaultUpper;
     }
 }
--- a/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/classes/sun/nio/ch/FileDispatcherImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -78,6 +78,10 @@
         return writev0(fd, address, len, fdAccess.getAppend(fd));
     }
 
+    long seek(FileDescriptor fd, long offset) throws IOException {
+        return seek0(fd, offset);
+    }
+
     int force(FileDescriptor fd, boolean metaData) throws IOException {
         return force0(fd, metaData);
     }
@@ -86,11 +90,6 @@
         return truncate0(fd, size);
     }
 
-    int allocate(FileDescriptor fd, long size) throws IOException {
-        // truncate0() works for extending and truncating file size
-        return truncate0(fd, size);
-    }
-
     long size(FileDescriptor fd) throws IOException {
         return size0(fd);
     }
@@ -126,8 +125,7 @@
         return true;
     }
 
-    int setDirectIO(FileDescriptor fd, String path)
-    {
+    int setDirectIO(FileDescriptor fd, String path) {
         int result = -1;
         String filePath = path.substring(0, path.lastIndexOf(File.separator));
         CharBuffer buffer = CharBuffer.allocate(filePath.length());
@@ -178,6 +176,8 @@
     static native long writev0(FileDescriptor fd, long address, int len, boolean append)
         throws IOException;
 
+    static native long seek0(FileDescriptor fd, long offset) throws IOException;
+
     static native int force0(FileDescriptor fd, boolean metaData)
         throws IOException;
 
--- a/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/DualStackPlainDatagramSocketImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -92,10 +92,10 @@
 /*
  * Class:     java_net_DualStackPlainDatagramSocketImpl
  * Method:    socketCreate
- * Signature: (Z)I
+ * Signature: ()I
  */
 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketCreate
-  (JNIEnv *env, jclass clazz, jboolean v6Only /*unused*/) {
+  (JNIEnv *env, jclass clazz) {
     int fd, rv, opt=0, t=TRUE;
     DWORD x1, x2; /* ignored result codes */
 
@@ -121,7 +121,7 @@
      * when the socket is connected.
      */
     t = FALSE;
-    WSAIoctl(fd ,SIO_UDP_CONNRESET ,&t ,sizeof(t) ,&x1 ,sizeof(x1) ,&x2 ,0 ,0);
+    WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
 
     return fd;
 }
@@ -158,7 +158,7 @@
 JNIEXPORT void JNICALL Java_java_net_DualStackPlainDatagramSocketImpl_socketConnect
   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
     SOCKETADDRESS sa;
-    int rv, sa_len = 0, t = TRUE;
+    int rv, sa_len = 0, t;
     DWORD x1, x2; /* ignored result codes */
 
     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
@@ -173,6 +173,7 @@
     }
 
     /* see comment in socketCreate */
+    t = TRUE;
     WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
 }
 
--- a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,534 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, 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.
- */
-#include "net_util.h"
-
-#include "java_net_DualStackPlainSocketImpl.h"
-#include "java_net_SocketOptions.h"
-
-#define SET_BLOCKING     0
-#define SET_NONBLOCKING  1
-
-static jclass isa_class;        /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
-  (JNIEnv *env, jclass clazz) {
-
-    jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
-    CHECK_NULL(cls);
-    isa_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(isa_class);
-    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
-                                     "(Ljava/net/InetAddress;I)V");
-    CHECK_NULL(isa_ctorID);
-    initInetAddressIDs(env);
-
-    // implement read timeout with select.
-    isRcvTimeoutSupported = JNI_FALSE;
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    socket0
- * Signature: (ZZ)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
-  (JNIEnv *env, jclass clazz, jboolean stream) {
-    int fd, rv, opt=0;
-    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
-    int domain = ipv6_available() ? AF_INET6 : AF_INET;
-
-    fd = NET_Socket(domain, type, 0);
-
-    if (fd == INVALID_SOCKET) {
-        NET_ThrowNew(env, WSAGetLastError(), "create");
-        return -1;
-    }
-
-    if (domain == AF_INET6) {
-        rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
-                        sizeof(opt));
-        if (rv == SOCKET_ERROR) {
-            NET_ThrowNew(env, WSAGetLastError(), "create");
-            closesocket(fd);
-            return -1;
-        }
-    }
-
-    return fd;
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    bind0
- * Signature: (ILjava/net/InetAddress;I)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_bind0
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
-   jboolean exclBind)
-{
-    SOCKETADDRESS sa;
-    int rv, sa_len = 0;
-    jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
-
-    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
-                                  &sa_len, v4MappedAddress) != 0) {
-        return;
-    }
-
-    rv = NET_WinBind(fd, &sa, sa_len, exclBind);
-
-    if (rv == SOCKET_ERROR)
-        NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    connect0
- * Signature: (ILjava/net/InetAddress;I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_connect0
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
-    SOCKETADDRESS sa;
-    int rv, sa_len = 0;
-    jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
-
-    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
-                                  &sa_len, v4MappedAddress) != 0) {
-        return -1;
-    }
-
-    rv = connect(fd, &sa.sa, sa_len);
-    if (rv == SOCKET_ERROR) {
-        int err = WSAGetLastError();
-        if (err == WSAEWOULDBLOCK) {
-            return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
-        } else if (err == WSAEADDRNOTAVAIL) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
-                "connect: Address is invalid on local machine,"
-                " or port is not valid on remote machine");
-        } else {
-            NET_ThrowNew(env, err, "connect");
-        }
-        return -1;  // return value not important.
-    }
-    return rv;
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    waitForConnect
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForConnect
-  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
-    int rv, retry;
-    int optlen = sizeof(rv);
-    fd_set wr, ex;
-    struct timeval t;
-
-    FD_ZERO(&wr);
-    FD_ZERO(&ex);
-    FD_SET(fd, &wr);
-    FD_SET(fd, &ex);
-    t.tv_sec = timeout / 1000;
-    t.tv_usec = (timeout % 1000) * 1000;
-
-    /*
-     * Wait for timeout, connection established or
-     * connection failed.
-     */
-    rv = select(fd+1, 0, &wr, &ex, &t);
-
-    /*
-     * Timeout before connection is established/failed so
-     * we throw exception and shutdown input/output to prevent
-     * socket from being used.
-     * The socket should be closed immediately by the caller.
-     */
-    if (rv == 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
-                        "connect timed out");
-        shutdown( fd, SD_BOTH );
-        return;
-    }
-
-    /*
-     * Socket is writable or error occurred. On some Windows editions
-     * the socket will appear writable when the connect fails so we
-     * check for error rather than writable.
-     */
-    if (!FD_ISSET(fd, &ex)) {
-        return;         /* connection established */
-    }
-
-    /*
-     * Connection failed. The logic here is designed to work around
-     * bug on Windows NT whereby using getsockopt to obtain the
-     * last error (SO_ERROR) indicates there is no error. The workaround
-     * on NT is to allow winsock to be scheduled and this is done by
-     * yielding and retrying. As yielding is problematic in heavy
-     * load conditions we attempt up to 3 times to get the error reason.
-     */
-    for (retry=0; retry<3; retry++) {
-        NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
-                       (char*)&rv, &optlen);
-        if (rv) {
-            break;
-        }
-        Sleep(0);
-    }
-
-    if (rv == 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "Unable to establish connection");
-    } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
-                        "connect: Address is invalid on local machine,"
-                        " or port is not valid on remote machine");
-    } else {
-        NET_ThrowNew(env, rv, "connect");
-    }
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    localPort0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_localPort0
-  (JNIEnv *env, jclass clazz, jint fd) {
-    SOCKETADDRESS sa;
-    int len = sizeof(sa);
-
-    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
-        if (WSAGetLastError() == WSAENOTSOCK) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                    "Socket closed");
-        } else {
-            NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
-        }
-        return -1;
-    }
-    return (int) ntohs((u_short)GET_PORT(&sa));
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    localAddress
- * Signature: (ILjava/net/InetAddressContainer;)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_localAddress
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
-    int port;
-    SOCKETADDRESS sa;
-    int len = sizeof(sa);
-    jobject iaObj;
-    jclass iaContainerClass;
-    jfieldID iaFieldID;
-
-    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
-        return;
-    }
-    iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
-    CHECK_NULL(iaObj);
-
-    iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
-    iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
-    CHECK_NULL(iaFieldID);
-    (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
-}
-
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    listen0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_listen0
-  (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
-    if (listen(fd, backlog) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "listen failed");
-    }
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    accept0
- * Signature: (I[Ljava/net/InetSocketAddress;)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
-  (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
-    int newfd, port=0;
-    jobject isa;
-    jobject ia;
-    SOCKETADDRESS sa;
-    int len = sizeof(sa);
-
-    memset((char *)&sa, 0, len);
-    newfd = accept(fd, &sa.sa, &len);
-
-    if (newfd == INVALID_SOCKET) {
-        NET_ThrowNew(env, WSAGetLastError(), "accept failed");
-        return -1;
-    }
-
-    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
-
-    ia = NET_SockaddrToInetAddress(env, &sa, &port);
-    isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
-    if (isa == NULL) {
-        closesocket(newfd);
-        return -1;
-    }
-    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
-
-    return newfd;
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    waitForNewConnection
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_waitForNewConnection
-  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
-    int rv;
-
-    rv = NET_Timeout(fd, timeout);
-    if (rv == 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
-                        "Accept timed out");
-    } else if (rv == -1) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
-    } else if (rv == -2) {
-        JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
-                        "operation interrupted");
-    }
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    available0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_available0
-  (JNIEnv *env, jclass clazz, jint fd) {
-    jint available = -1;
-
-    if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "socket available");
-    }
-
-    return available;
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    close0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_close0
-  (JNIEnv *env, jclass clazz, jint fd) {
-     NET_SocketClose(fd);
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    shutdown0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_shutdown0
-  (JNIEnv *env, jclass clazz, jint fd, jint howto) {
-    shutdown(fd, howto);
-}
-
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    setIntOption
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_DualStackPlainSocketImpl_setIntOption
-  (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
-{
-    int level = 0, opt = 0;
-    struct linger linger = {0, 0};
-    char *parg;
-    int arglen;
-
-    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
-        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
-        return;
-    }
-
-    if (opt == java_net_SocketOptions_SO_LINGER) {
-        parg = (char *)&linger;
-        arglen = sizeof(linger);
-        if (value >= 0) {
-            linger.l_onoff = 1;
-            linger.l_linger = (unsigned short)value;
-        } else {
-            linger.l_onoff = 0;
-            linger.l_linger = 0;
-        }
-    } else {
-        parg = (char *)&value;
-        arglen = sizeof(value);
-    }
-
-    if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
-        NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
-    }
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    setSoTimeout0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_DualStackPlainSocketImpl_setSoTimeout0
-  (JNIEnv *env, jclass clazz, jint fd, jint timeout)
-{
-    /*
-     * SO_TIMEOUT is the socket option used to specify the timeout
-     * for ServerSocket.accept and Socket.getInputStream().read.
-     * It does not typically map to a native level socket option.
-     * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
-     * socket option to specify a receive timeout on the socket. This
-     * receive timeout is applicable to Socket only and the socket
-     * option should not be set on ServerSocket.
-     */
-
-    /*
-     * SO_RCVTIMEO is only supported on Microsoft's implementation
-     * of Windows Sockets so if WSAENOPROTOOPT returned then
-     * reset flag and timeout will be implemented using
-     * select() -- see SocketInputStream.socketRead.
-     */
-    if (isRcvTimeoutSupported) {
-        /*
-         * Disable SO_RCVTIMEO if timeout is <= 5 second.
-         */
-        if (timeout <= 5000) {
-            timeout = 0;
-        }
-
-        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
-            sizeof(timeout)) < 0) {
-            int err = WSAGetLastError();
-            if (err == WSAENOPROTOOPT) {
-                isRcvTimeoutSupported = JNI_FALSE;
-            } else {
-                NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
-            }
-        }
-    }
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    getIntOption
- * Signature: (II)I
- */
-JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_getIntOption
-  (JNIEnv *env, jclass clazz, jint fd, jint cmd)
-{
-    int level = 0, opt = 0;
-    int result=0;
-    struct linger linger = {0, 0};
-    char *arg;
-    int arglen;
-
-    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
-        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
-        return -1;
-    }
-
-    if (opt == java_net_SocketOptions_SO_LINGER) {
-        arg = (char *)&linger;
-        arglen = sizeof(linger);
-    } else {
-        arg = (char *)&result;
-        arglen = sizeof(result);
-    }
-
-    if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
-        NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
-        return -1;
-    }
-
-    if (opt == java_net_SocketOptions_SO_LINGER)
-        return linger.l_onoff ? linger.l_linger : -1;
-    else
-        return result;
-}
-
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    sendOOB
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_sendOOB
-  (JNIEnv *env, jclass clazz, jint fd, jint data) {
-    jint n;
-    unsigned char d = (unsigned char) data & 0xff;
-
-    n = send(fd, (char *)&data, 1, MSG_OOB);
-    if (n == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "send");
-    }
-}
-
-/*
- * Class:     java_net_DualStackPlainSocketImpl
- * Method:    configureBlocking
- * Signature: (IZ)V
- */
-JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_configureBlocking
-  (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
-    u_long arg;
-    int result;
-
-    if (blocking == JNI_TRUE) {
-        arg = SET_BLOCKING;      // 0
-    } else {
-        arg = SET_NONBLOCKING;   // 1
-    }
-
-    result = ioctlsocket(fd, FIONBIO, &arg);
-    if (result == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/windows/native/libnet/PlainSocketImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,531 @@
+/*
+ * Copyright (c) 2007, 2018, 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.
+ */
+#include "net_util.h"
+
+#include "java_net_PlainSocketImpl.h"
+#include "java_net_SocketOptions.h"
+
+#define SET_BLOCKING     0
+#define SET_NONBLOCKING  1
+
+static jclass isa_class;        /* java.net.InetSocketAddress */
+static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    initIDs
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_initIDs
+  (JNIEnv *env, jclass clazz) {
+
+    jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
+    CHECK_NULL(cls);
+    isa_class = (*env)->NewGlobalRef(env, cls);
+    CHECK_NULL(isa_class);
+    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
+                                     "(Ljava/net/InetAddress;I)V");
+    CHECK_NULL(isa_ctorID);
+    initInetAddressIDs(env);
+
+    // implement read timeout with select.
+    isRcvTimeoutSupported = JNI_FALSE;
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    socket0
+ * Signature: (ZZ)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_socket0
+  (JNIEnv *env, jclass clazz, jboolean stream) {
+    int fd, rv, opt = 0;
+    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
+
+    fd = NET_Socket(domain, type, 0);
+
+    if (fd == INVALID_SOCKET) {
+        NET_ThrowNew(env, WSAGetLastError(), "create");
+        return -1;
+    }
+
+    if (domain == AF_INET6) {
+        rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
+                        sizeof(opt));
+        if (rv == SOCKET_ERROR) {
+            NET_ThrowNew(env, WSAGetLastError(), "create");
+            closesocket(fd);
+            return -1;
+        }
+    }
+
+    return fd;
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    bind0
+ * Signature: (ILjava/net/InetAddress;I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_bind0
+  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
+   jboolean exclBind)
+{
+    SOCKETADDRESS sa;
+    int rv, sa_len = 0;
+    jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
+
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+                                  &sa_len, v4MappedAddress) != 0) {
+        return;
+    }
+
+    rv = NET_WinBind(fd, &sa, sa_len, exclBind);
+
+    if (rv == SOCKET_ERROR)
+        NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    connect0
+ * Signature: (ILjava/net/InetAddress;I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_connect0
+  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
+    SOCKETADDRESS sa;
+    int rv, sa_len = 0;
+    jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
+
+    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
+                                  &sa_len, v4MappedAddress) != 0) {
+        return -1;
+    }
+
+    rv = connect(fd, &sa.sa, sa_len);
+    if (rv == SOCKET_ERROR) {
+        int err = WSAGetLastError();
+        if (err == WSAEWOULDBLOCK) {
+            return java_net_PlainSocketImpl_WOULDBLOCK;
+        } else if (err == WSAEADDRNOTAVAIL) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+                "connect: Address is invalid on local machine,"
+                " or port is not valid on remote machine");
+        } else {
+            NET_ThrowNew(env, err, "connect");
+        }
+        // return value not important.
+    }
+    return rv;
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    waitForConnect
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_waitForConnect
+  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
+    int rv, retry;
+    int optlen = sizeof(rv);
+    fd_set wr, ex;
+    struct timeval t;
+
+    FD_ZERO(&wr);
+    FD_ZERO(&ex);
+    FD_SET(fd, &wr);
+    FD_SET(fd, &ex);
+    t.tv_sec = timeout / 1000;
+    t.tv_usec = (timeout % 1000) * 1000;
+
+    /*
+     * Wait for timeout, connection established or
+     * connection failed.
+     */
+    rv = select(fd+1, 0, &wr, &ex, &t);
+
+    /*
+     * Timeout before connection is established/failed so
+     * we throw exception and shutdown input/output to prevent
+     * socket from being used.
+     * The socket should be closed immediately by the caller.
+     */
+    if (rv == 0) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+                        "connect timed out");
+        shutdown(fd, SD_BOTH);
+        return;
+    }
+
+    /*
+     * Socket is writable or error occurred. On some Windows editions
+     * the socket will appear writable when the connect fails so we
+     * check for error rather than writable.
+     */
+    if (!FD_ISSET(fd, &ex)) {
+        return;         /* connection established */
+    }
+
+    /*
+     * Connection failed. The logic here is designed to work around
+     * bug on Windows NT whereby using getsockopt to obtain the
+     * last error (SO_ERROR) indicates there is no error. The workaround
+     * on NT is to allow winsock to be scheduled and this is done by
+     * yielding and retrying. As yielding is problematic in heavy
+     * load conditions we attempt up to 3 times to get the error reason.
+     */
+    for (retry = 0; retry < 3; retry++) {
+        NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
+                       (char*)&rv, &optlen);
+        if (rv) {
+            break;
+        }
+        Sleep(0);
+    }
+
+    if (rv == 0) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                        "Unable to establish connection");
+    } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+                        "connect: Address is invalid on local machine,"
+                        " or port is not valid on remote machine");
+    } else {
+        NET_ThrowNew(env, rv, "connect");
+    }
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    localPort0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_localPort0
+  (JNIEnv *env, jclass clazz, jint fd) {
+    SOCKETADDRESS sa;
+    int len = sizeof(sa);
+
+    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
+        if (WSAGetLastError() == WSAENOTSOCK) {
+            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
+                    "Socket closed");
+        } else {
+            NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
+        }
+        return -1;
+    }
+    return (int) ntohs((u_short)GET_PORT(&sa));
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    localAddress
+ * Signature: (ILjava/net/InetAddressContainer;)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_localAddress
+  (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
+    int port;
+    SOCKETADDRESS sa;
+    int len = sizeof(sa);
+    jobject iaObj;
+    jclass iaContainerClass;
+    jfieldID iaFieldID;
+
+    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
+        NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
+        return;
+    }
+    iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
+    CHECK_NULL(iaObj);
+
+    iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
+    iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
+    CHECK_NULL(iaFieldID);
+    (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    listen0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_listen0
+  (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
+    if (listen(fd, backlog) == SOCKET_ERROR) {
+        NET_ThrowNew(env, WSAGetLastError(), "listen failed");
+    }
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    accept0
+ * Signature: (I[Ljava/net/InetSocketAddress;)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_accept0
+  (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
+    int newfd, port = 0;
+    jobject isa;
+    jobject ia;
+    SOCKETADDRESS sa;
+    int len = sizeof(sa);
+
+    memset((char *)&sa, 0, len);
+    newfd = accept(fd, &sa.sa, &len);
+
+    if (newfd == INVALID_SOCKET) {
+        NET_ThrowNew(env, WSAGetLastError(), "accept failed");
+        return -1;
+    }
+
+    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
+
+    ia = NET_SockaddrToInetAddress(env, &sa, &port);
+    isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
+    if (isa == NULL) {
+        closesocket(newfd);
+        return -1;
+    }
+    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
+
+    return newfd;
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    waitForNewConnection
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_waitForNewConnection
+  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
+    int rv;
+
+    rv = NET_Timeout(fd, timeout);
+    if (rv == 0) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+                        "Accept timed out");
+    } else if (rv == -1) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
+    } else if (rv == -2) {
+        JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
+                        "operation interrupted");
+    }
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    available0
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_available0
+  (JNIEnv *env, jclass clazz, jint fd) {
+    jint available = -1;
+
+    if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
+        NET_ThrowNew(env, WSAGetLastError(), "socket available");
+    }
+
+    return available;
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    close0
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_close0
+  (JNIEnv *env, jclass clazz, jint fd) {
+     NET_SocketClose(fd);
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    shutdown0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_shutdown0
+  (JNIEnv *env, jclass clazz, jint fd, jint howto) {
+    shutdown(fd, howto);
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    setIntOption
+ * Signature: (III)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_setIntOption
+  (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
+{
+    int level = 0, opt = 0;
+    struct linger linger = {0, 0};
+    char *parg;
+    int arglen;
+
+    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
+        return;
+    }
+
+    if (opt == java_net_SocketOptions_SO_LINGER) {
+        parg = (char *)&linger;
+        arglen = sizeof(linger);
+        if (value >= 0) {
+            linger.l_onoff = 1;
+            linger.l_linger = (unsigned short)value;
+        } else {
+            linger.l_onoff = 0;
+            linger.l_linger = 0;
+        }
+    } else {
+        parg = (char *)&value;
+        arglen = sizeof(value);
+    }
+
+    if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
+        NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
+    }
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    setSoTimeout0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_PlainSocketImpl_setSoTimeout0
+  (JNIEnv *env, jclass clazz, jint fd, jint timeout)
+{
+    /*
+     * SO_TIMEOUT is the socket option used to specify the timeout
+     * for ServerSocket.accept and Socket.getInputStream().read.
+     * It does not typically map to a native level socket option.
+     * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
+     * socket option to specify a receive timeout on the socket. This
+     * receive timeout is applicable to Socket only and the socket
+     * option should not be set on ServerSocket.
+     */
+
+    /*
+     * SO_RCVTIMEO is only supported on Microsoft's implementation
+     * of Windows Sockets so if WSAENOPROTOOPT returned then
+     * reset flag and timeout will be implemented using
+     * select() -- see SocketInputStream.socketRead.
+     */
+    if (isRcvTimeoutSupported) {
+        /*
+         * Disable SO_RCVTIMEO if timeout is <= 5 second.
+         */
+        if (timeout <= 5000) {
+            timeout = 0;
+        }
+
+        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+            sizeof(timeout)) < 0) {
+            int err = WSAGetLastError();
+            if (err == WSAENOPROTOOPT) {
+                isRcvTimeoutSupported = JNI_FALSE;
+            } else {
+                NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
+            }
+        }
+    }
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    getIntOption
+ * Signature: (II)I
+ */
+JNIEXPORT jint JNICALL Java_java_net_PlainSocketImpl_getIntOption
+  (JNIEnv *env, jclass clazz, jint fd, jint cmd)
+{
+    int level = 0, opt = 0;
+    int result = 0;
+    struct linger linger = {0, 0};
+    char *arg;
+    int arglen;
+
+    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
+        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
+        return -1;
+    }
+
+    if (opt == java_net_SocketOptions_SO_LINGER) {
+        arg = (char *)&linger;
+        arglen = sizeof(linger);
+    } else {
+        arg = (char *)&result;
+        arglen = sizeof(result);
+    }
+
+    if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
+        NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
+        return -1;
+    }
+
+    if (opt == java_net_SocketOptions_SO_LINGER)
+        return linger.l_onoff ? linger.l_linger : -1;
+    else
+        return result;
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    sendOOB
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_sendOOB
+  (JNIEnv *env, jclass clazz, jint fd, jint data) {
+    jint n;
+    unsigned char d = (unsigned char) data & 0xff;
+
+    n = send(fd, (char *)&data, 1, MSG_OOB);
+    if (n == SOCKET_ERROR) {
+        NET_ThrowNew(env, WSAGetLastError(), "send");
+    }
+}
+
+/*
+ * Class:     java_net_PlainSocketImpl
+ * Method:    configureBlocking
+ * Signature: (IZ)V
+ */
+JNIEXPORT void JNICALL Java_java_net_PlainSocketImpl_configureBlocking
+  (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
+    u_long arg;
+    int result;
+
+    if (blocking == JNI_TRUE) {
+        arg = SET_BLOCKING;      // 0
+    } else {
+        arg = SET_NONBLOCKING;   // 1
+    }
+
+    result = ioctlsocket(fd, FIONBIO, &arg);
+    if (result == SOCKET_ERROR) {
+        NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
+    }
+}
--- a/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -63,13 +63,6 @@
 static jclass ia4_clazz;
 static jmethodID ia4_ctor;
 
-static CRITICAL_SECTION sizeCheckLock;
-
-/* Windows OS version is XP or better */
-static int xp_or_later = 0;
-/* Windows OS version is Windows 2000 or better */
-static int w2k_or_later = 0;
-
 /*
  * Notes about UDP/IPV6 on Windows (XP and 2003 server):
  *
@@ -137,182 +130,6 @@
 }
 
 /*
- * This function returns JNI_TRUE if the datagram size exceeds the underlying
- * provider's ability to send to the target address. The following OS
- * oddities have been observed :-
- *
- * 1. On Windows 95/98 if we try to send a datagram > 12k to an application
- *    on the same machine then the send will fail silently.
- *
- * 2. On Windows ME if we try to send a datagram > supported by underlying
- *    provider then send will not return an error.
- *
- * 3. On Windows NT/2000 if we exceeds the maximum size then send will fail
- *    with WSAEADDRNOTAVAIL.
- *
- * 4. On Windows 95/98 if we exceed the maximum size when sending to
- *    another machine then WSAEINVAL is returned.
- *
- */
-jboolean exceedSizeLimit(JNIEnv *env, jint fd, jint addr, jint size)
-{
-#define DEFAULT_MSG_SIZE        65527
-    static jboolean initDone;
-    static jboolean is95or98;
-    static int maxmsg;
-
-    typedef struct _netaddr  {          /* Windows 95/98 only */
-        unsigned long addr;
-        struct _netaddr *next;
-    } netaddr;
-    static netaddr *addrList;
-    netaddr *curr;
-
-    /*
-     * First time we are called we must determine which OS this is and also
-     * get the maximum size supported by the underlying provider.
-     *
-     * In addition on 95/98 we must enumerate our IP addresses.
-     */
-    if (!initDone) {
-        EnterCriticalSection(&sizeCheckLock);
-
-        if (initDone) {
-            /* another thread got there first */
-            LeaveCriticalSection(&sizeCheckLock);
-
-        } else {
-            OSVERSIONINFO ver;
-            int len;
-
-            /*
-             * Step 1: Determine which OS this is.
-             */
-            ver.dwOSVersionInfoSize = sizeof(ver);
-            GetVersionEx(&ver);
-
-            is95or98 = JNI_FALSE;
-            if (ver.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
-                ver.dwMajorVersion == 4 &&
-                (ver.dwMinorVersion == 0 || ver.dwMinorVersion == 10)) {
-
-                is95or98 = JNI_TRUE;
-            }
-
-            /*
-             * Step 2: Determine the maximum datagram supported by the
-             * underlying provider. On Windows 95 if winsock hasn't been
-             * upgraded (ie: unsupported configuration) then we assume
-             * the default 64k limit.
-             */
-            len = sizeof(maxmsg);
-            if (NET_GetSockOpt(fd, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&maxmsg, &len) < 0) {
-                maxmsg = DEFAULT_MSG_SIZE;
-            }
-
-            /*
-             * Step 3: On Windows 95/98 then enumerate the IP addresses on
-             * this machine. This is neccesary because we need to check if the
-             * datagram is being sent to an application on the same machine.
-             */
-            if (is95or98) {
-                char hostname[255];
-                struct hostent *hp;
-
-                if (gethostname(hostname, sizeof(hostname)) == -1) {
-                    LeaveCriticalSection(&sizeCheckLock);
-                    JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "Unable to obtain hostname");
-                    return JNI_TRUE;
-                }
-                hp = (struct hostent *)gethostbyname(hostname);
-                if (hp != NULL) {
-                    struct in_addr **addrp = (struct in_addr **) hp->h_addr_list;
-
-                    while (*addrp != (struct in_addr *) 0) {
-                        curr = (netaddr *)malloc(sizeof(netaddr));
-                        if (curr == NULL) {
-                            while (addrList != NULL) {
-                                curr = addrList->next;
-                                free(addrList);
-                                addrList = curr;
-                            }
-                            LeaveCriticalSection(&sizeCheckLock);
-                            JNU_ThrowOutOfMemoryError(env, "Native heap allocation failed");
-                            return JNI_TRUE;
-                        }
-                        curr->addr = htonl((*addrp)->S_un.S_addr);
-                        curr->next = addrList;
-                        addrList = curr;
-                        addrp++;
-                    }
-                }
-            }
-
-            /*
-             * Step 4: initialization is done so set flag and unlock cs
-             */
-            initDone = JNI_TRUE;
-            LeaveCriticalSection(&sizeCheckLock);
-        }
-    }
-
-    /*
-     * Now examine the size of the datagram :-
-     *
-     * (a) If exceeds size of service provider return 'false' to indicate that
-     *     we exceed the limit.
-     * (b) If not 95/98 then return 'true' to indicate that the size is okay.
-     * (c) On 95/98 if the size is <12k we are okay.
-     * (d) On 95/98 if size > 12k then check if the destination is the current
-     *     machine.
-     */
-    if (size > maxmsg) {        /* step (a) */
-        return JNI_TRUE;
-    }
-    if (!is95or98) {            /* step (b) */
-        return JNI_FALSE;
-    }
-    if (size <= 12280) {        /* step (c) */
-        return JNI_FALSE;
-    }
-
-    /* step (d) */
-
-    if ((addr & 0x7f000000) == 0x7f000000) {
-        return JNI_TRUE;
-    }
-    curr = addrList;
-    while (curr != NULL) {
-        if (curr->addr == addr) {
-            return JNI_TRUE;
-        }
-        curr = curr->next;
-    }
-    return JNI_FALSE;
-}
-
-/*
- * Return JNI_TRUE if this Windows edition supports ICMP Port Unreachable
- */
-__inline static jboolean supportPortUnreachable() {
-    static jboolean initDone;
-    static jboolean portUnreachableSupported;
-
-    if (!initDone) {
-        OSVERSIONINFO ver;
-        ver.dwOSVersionInfoSize = sizeof(ver);
-        GetVersionEx(&ver);
-        if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT && ver.dwMajorVersion >= 5) {
-            portUnreachableSupported = JNI_TRUE;
-        } else {
-            portUnreachableSupported = JNI_FALSE;
-        }
-        initDone = JNI_TRUE;
-    }
-    return portUnreachableSupported;
-}
-
-/*
  * This function "purges" all outstanding ICMP port unreachable packets
  * outstanding on a socket and returns JNI_TRUE if any ICMP messages
  * have been purged. The rational for purging is to emulate normal BSD
@@ -331,13 +148,6 @@
     memset((char *)&rmtaddr, 0, sizeof(rmtaddr));
 
     /*
-     * A no-op if this OS doesn't support it.
-     */
-    if (!supportPortUnreachable()) {
-        return JNI_FALSE;
-    }
-
-    /*
      * Peek at the queue to see if there is an ICMP port unreachable. If there
      * is then receive it.
      */
@@ -370,16 +180,6 @@
  */
 JNIEXPORT void JNICALL
 Java_java_net_TwoStacksPlainDatagramSocketImpl_init(JNIEnv *env, jclass cls) {
-
-    OSVERSIONINFO ver;
-    int version;
-    ver.dwOSVersionInfoSize = sizeof(ver);
-    GetVersionEx(&ver);
-
-    version = ver.dwMajorVersion * 10 + ver.dwMinorVersion;
-    xp_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 51);
-    w2k_or_later = (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) && (version >= 50);
-
     /* get fieldIDs */
     pdsi_fdID = (*env)->GetFieldID(env, cls, "fd", "Ljava/io/FileDescriptor;");
     CHECK_NULL(pdsi_fdID);
@@ -409,9 +209,6 @@
     CHECK_NULL(ia4_clazz);
     ia4_ctor = (*env)->GetMethodID(env, ia4_clazz, "<init>", "()V");
     CHECK_NULL(ia4_ctor);
-
-
-    InitializeCriticalSection(&sizeCheckLock);
 }
 
 JNIEXPORT void JNICALL
@@ -524,6 +321,8 @@
     jint fd = -1, fd1 = -1, fdc, family;
     SOCKETADDRESS rmtaddr;
     int rmtaddrlen = 0;
+    DWORD x1, x2; /* ignored result codes */
+    int res, t;
 
     if (IS_NULL(fdObj) && IS_NULL(fd1Obj)) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
@@ -553,16 +352,13 @@
 
     fdc = family == java_net_InetAddress_IPv4 ? fd : fd1;
 
-    if (xp_or_later) {
-        /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
-         * returns connection reset errors on connected UDP sockets (as well
-         * as connected sockets). The solution is to only enable this feature
-         * when the socket is connected
-         */
-        DWORD x1, x2; /* ignored result codes */
-        int res, t = TRUE;
-        res = WSAIoctl(fdc,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
-    }
+    /* SIO_UDP_CONNRESET fixes a bug introduced in Windows 2000, which
+     * returns connection reset errors on connected UDP sockets (as well
+     * as connected sockets). The solution is to only enable this feature
+     * when the socket is connected
+     */
+    t = TRUE;
+    res = WSAIoctl(fdc, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
 
     if (NET_InetAddressToSockaddr(env, address, port, &rmtaddr,
                                   &rmtaddrlen, JNI_FALSE) != 0) {
@@ -588,6 +384,8 @@
     /* The fdObj'fd */
     jint fd, len;
     SOCKETADDRESS addr;
+    DWORD x1 = 0, x2 = 0; /* ignored result codes */
+    int t;
 
     if (family == java_net_InetAddress_IPv4) {
         fdObj = (*env)->GetObjectField(env, this, pdsi_fdID);
@@ -610,11 +408,8 @@
      * use SIO_UDP_CONNRESET
      * to disable ICMP port unreachable handling here.
      */
-    if (xp_or_later) {
-        DWORD x1 = 0, x2 = 0; /* ignored result codes */
-        int t = FALSE;
-        WSAIoctl(fd,SIO_UDP_CONNRESET,&t,sizeof(t),&x1,sizeof(x1),&x2,0,0);
-    }
+    t = FALSE;
+    WSAIoctl(fd, SIO_UDP_CONNRESET, &t, sizeof(t), &x1, sizeof(x1), &x2, 0, 0);
 }
 
 /*
@@ -632,7 +427,6 @@
     jint fd;
 
     jobject iaObj;
-    jint address;
     jint family;
 
     jint packetBufferOffset, packetBufferLen, packetPort;
@@ -697,32 +491,6 @@
     }
 
     if (packetBufferLen > MAX_BUFFER_LEN) {
-
-        /*
-         * On 95/98 if we try to send a datagram >12k to an application
-         * on the same machine then this will fail silently. Thus we
-         * catch this situation here so that we can throw an exception
-         * when this arises.
-         * On ME if we try to send a datagram with a size greater than
-         * that supported by the service provider then no error is
-         * returned.
-         */
-        if (!w2k_or_later) { /* avoid this check on Win 2K or better. Does not work with IPv6.
-                      * Check is not necessary on these OSes */
-            if (connected) {
-                address = getInetAddress_addr(env, iaObj);
-            } else {
-                address = ntohl(rmtaddr.sa4.sin_addr.s_addr);
-            }
-
-            if (exceedSizeLimit(env, fd, address, packetBufferLen)) {
-                if (!((*env)->ExceptionOccurred(env))) {
-                    NET_ThrowNew(env, WSAEMSGSIZE, "Datagram send failed");
-                }
-                return;
-            }
-        }
-
         /* When JNI-ifying the JDK's IO routines, we turned
          * reads and writes of byte arrays of size greater
          * than 2048 bytes into several operations of size 2048.
@@ -1282,16 +1050,15 @@
 
 
     /*
-     * If this Windows edition supports ICMP port unreachable and if we
-     * are not connected then we need to know if a timeout has been specified
-     * and if so we need to pick up the current time. These are required in
-     * order to implement the semantics of timeout, viz :-
+     * If we are not connected then we need to know if a timeout has been
+     * specified and if so we need to pick up the current time. These are
+     * required in order to implement the semantics of timeout, viz :-
      * timeout set to t1 but ICMP port unreachable arrives in t2 where
      * t2 < t1. In this case we must discard the ICMP packets and then
      * wait for the next packet up to a maximum of t1 minus t2.
      */
     connected = (*env)->GetBooleanField(env, this, pdsi_connected);
-    if (supportPortUnreachable() && !connected && timeout &&!ipv6_supported) {
+    if (!connected && timeout && !ipv6_supported) {
         prevTime = JVM_CurrentTimeMillis(env, 0);
     }
 
--- a/src/java.base/windows/native/libnet/net_util_md.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/net_util_md.c	Thu Apr 26 17:59:02 2018 +0200
@@ -227,73 +227,9 @@
 
 jint reuseport_supported()
 {
-    /* SO_REUSEPORT is not supported onn Windows */
+    /* SO_REUSEPORT is not supported on Windows */
     return JNI_FALSE;
 }
-/*
- * Return the default TOS value
- */
-int NET_GetDefaultTOS() {
-    static int default_tos = -1;
-    OSVERSIONINFO ver;
-    HKEY hKey;
-    LONG ret;
-
-    /*
-     * If default ToS already determined then return it
-     */
-    if (default_tos >= 0) {
-        return default_tos;
-    }
-
-    /*
-     * Assume default is "normal service"
-     */
-    default_tos = 0;
-
-    /*
-     * Which OS is this?
-     */
-    ver.dwOSVersionInfoSize = sizeof(ver);
-    GetVersionEx(&ver);
-
-    /*
-     * If 2000 or greater then no default ToS in registry
-     */
-    if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-        if (ver.dwMajorVersion >= 5) {
-            return default_tos;
-        }
-    }
-
-    /*
-     * Query the registry to see if a Default ToS has been set.
-     * Different registry entry for NT vs 95/98/ME.
-     */
-    if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT) {
-        ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                           "SYSTEM\\CurrentControlSet\\Services\\Tcp\\Parameters",
-                           0, KEY_READ, (PHKEY)&hKey);
-    } else {
-        ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                           "SYSTEM\\CurrentControlSet\\Services\\VxD\\MSTCP\\Parameters",
-                           0, KEY_READ, (PHKEY)&hKey);
-    }
-    if (ret == ERROR_SUCCESS) {
-        DWORD dwLen;
-        DWORD dwDefaultTOS;
-        ULONG ulType;
-        dwLen = sizeof(dwDefaultTOS);
-
-        ret = RegQueryValueEx(hKey, "DefaultTOS",  NULL, &ulType,
-                             (LPBYTE)&dwDefaultTOS, &dwLen);
-        RegCloseKey(hKey);
-        if (ret == ERROR_SUCCESS) {
-            default_tos = (int)dwDefaultTOS;
-        }
-    }
-    return default_tos;
-}
 
 /* call NET_MapSocketOptionV6 for the IPv6 fd only
  * and NET_MapSocketOption for the IPv4 fd
@@ -454,10 +390,7 @@
         if (WSAGetLastError() == WSAENOPROTOOPT &&
             level == IPPROTO_IP && optname == IP_TOS) {
 
-            int *tos;
-            tos = (int *)optval;
-            *tos = NET_GetDefaultTOS();
-
+            *((int *)optval) = 0;
             rv = 0;
         }
     }
--- a/src/java.base/windows/native/libnet/net_util_md.h	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/net_util_md.h	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,11 +52,6 @@
 
 void NET_ThrowCurrent(JNIEnv *env, char *msg);
 
-/*
- * Return default Type Of Service
- */
-int NET_GetDefaultTOS(void);
-
 typedef union {
     struct sockaddr     sa;
     struct sockaddr_in  sa4;
--- a/src/java.base/windows/native/libnet/portconfig.c	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,107 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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.
- */
-
-#include <windows.h>
-#include "jni.h"
-#include "net_util.h"
-#include "sun_net_PortConfig.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct portrange {
-    int lower;
-    int higher;
-};
-
-static int getPortRange(struct portrange *range)
-{
-    OSVERSIONINFO ver;
-    ver.dwOSVersionInfoSize = sizeof(ver);
-    GetVersionEx(&ver);
-
-    /* Check for major version 5 or less = Windows XP/2003 or older */
-    if (ver.dwMajorVersion <= 5) {
-        LONG ret;
-        HKEY hKey;
-        range->lower = 1024;
-        range->higher = 4999;
-
-        /* check registry to see if upper limit was raised */
-        ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
-                   "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
-                   0, KEY_READ, (PHKEY)&hKey
-        );
-        if (ret == ERROR_SUCCESS) {
-            DWORD maxuserport;
-            ULONG ulType;
-            DWORD dwLen = sizeof(maxuserport);
-            ret = RegQueryValueEx(hKey, "MaxUserPort",  NULL, &ulType,
-                             (LPBYTE)&maxuserport, &dwLen);
-            RegCloseKey(hKey);
-            if (ret == ERROR_SUCCESS) {
-                range->higher = maxuserport;
-            }
-        }
-    } else {
-        /* There doesn't seem to be an API to access this. "MaxUserPort"
-          * is affected, but is not sufficient to determine.
-         * so we just use the defaults, which are less likely to change
-          */
-        range->lower = 49152;
-        range->higher = 65535;
-    }
-    return 0;
-}
-
-/*
- * Class:     sun_net_PortConfig
- * Method:    getLower0
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_sun_net_PortConfig_getLower0
-  (JNIEnv *env, jclass clazz)
-{
-    struct portrange range;
-    getPortRange(&range);
-    return range.lower;
-}
-
-/*
- * Class:     sun_net_PortConfig
- * Method:    getUpper0
- * Signature: ()I
- */
-JNIEXPORT jint JNICALL Java_sun_net_PortConfig_getUpper0
-  (JNIEnv *env, jclass clazz)
-{
-    struct portrange range;
-    getPortRange(&range);
-    return range.higher;
-}
-#ifdef __cplusplus
-}
-#endif
--- a/src/java.base/windows/native/libnio/ch/FileChannelImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnio/ch/FileChannelImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018 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
@@ -141,31 +141,6 @@
 }
 
 JNIEXPORT jlong JNICALL
-Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
-                                          jobject fdo, jlong offset)
-{
-    BOOL result = 0;
-    HANDLE h = (HANDLE)(handleval(env, fdo));
-    LARGE_INTEGER where;
-    DWORD whence;
-
-    if (offset < 0) {
-        where.QuadPart = 0;
-        whence = FILE_CURRENT;
-    } else {
-        where.QuadPart = offset;
-        whence = FILE_BEGIN;
-    }
-
-    result = SetFilePointerEx(h, where, &where, whence);
-    if (result == 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "Seek failed");
-        return IOS_THROWN;
-    }
-    return (jlong)where.QuadPart;
-}
-
-JNIEXPORT jlong JNICALL
 Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
                                             jobject srcFD,
                                             jlong position, jlong count,
@@ -173,14 +148,17 @@
 {
     const int PACKET_SIZE = 524288;
 
+    LARGE_INTEGER where;
     HANDLE src = (HANDLE)(handleval(env, srcFD));
     SOCKET dst = (SOCKET)(fdval(env, dstFD));
     DWORD chunkSize = (count > java_lang_Integer_MAX_VALUE) ?
         java_lang_Integer_MAX_VALUE : (DWORD)count;
-    BOOL result = 0;
+    BOOL result;
 
-    jlong pos = Java_sun_nio_ch_FileChannelImpl_position0(env, this, srcFD, position);
-    if (pos == IOS_THROWN) {
+    where.QuadPart = position;
+    result = SetFilePointerEx(src, where, &where, FILE_BEGIN);
+    if (result == 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed");
         return IOS_THROWN;
     }
 
--- a/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.base/windows/native/libnio/ch/FileDispatcherImpl.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -298,6 +298,31 @@
     return convertReturnVal(env, (jint)written, JNI_FALSE);
 }
 
+JNIEXPORT jlong JNICALL
+Java_sun_nio_ch_FileDispatcherImpl_seek0(JNIEnv *env, jclass clazz,
+                                         jobject fdo, jlong offset)
+{
+    BOOL result = 0;
+    HANDLE h = (HANDLE)(handleval(env, fdo));
+    LARGE_INTEGER where;
+    DWORD whence;
+
+    if (offset < 0) {
+        where.QuadPart = 0;
+        whence = FILE_CURRENT;
+    } else {
+        where.QuadPart = offset;
+        whence = FILE_BEGIN;
+    }
+
+    result = SetFilePointerEx(h, where, &where, whence);
+    if (result == 0) {
+        JNU_ThrowIOExceptionWithLastError(env, "SetFilePointerEx failed");
+        return IOS_THROWN;
+    }
+    return (jlong)where.QuadPart;
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this,
                                           jobject fdo, jboolean md)
--- a/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -47,6 +47,7 @@
 
 import java.lang.reflect.UndeclaredThrowableException;
 import java.security.PrivilegedAction;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -162,6 +163,16 @@
         return LoggingMXBeanAccess.isAvailable();
     }
 
+    /**
+     * Returns an array of the name of all memory pools.  The order of the memory pools is
+     * significant and maintained in the VM.
+     */
+    public static String[] getAllMemoryPoolNames() {
+        return Arrays.stream(MemoryImpl.getMemoryPools())
+                .map(MemoryPoolMXBean::getName)
+                .toArray(String[]::new);
+    }
+
     // The LoggingMXBeanAccess class uses reflection to determine
     // whether java.util.logging is present, and load the actual LoggingMXBean
     // implementation.
--- a/src/java.scripting/share/classes/javax/script/AbstractScriptEngine.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.scripting/share/classes/javax/script/AbstractScriptEngine.java	Thu Apr 26 17:59:02 2018 +0200
@@ -287,7 +287,7 @@
      */
     protected ScriptContext getScriptContext(Bindings nn) {
 
-        SimpleScriptContext ctxt = new SimpleScriptContext();
+        SimpleScriptContext ctxt = new SimpleScriptContext(context.getReader(), context.getWriter(), context.getErrorWriter());
         Bindings gs = getBindings(ScriptContext.GLOBAL_SCOPE);
 
         if (gs != null) {
@@ -301,10 +301,6 @@
             throw new NullPointerException("Engine scope Bindings may not be null.");
         }
 
-        ctxt.setReader(context.getReader());
-        ctxt.setWriter(context.getWriter());
-        ctxt.setErrorWriter(context.getErrorWriter());
-
         return ctxt;
 
     }
--- a/src/java.scripting/share/classes/javax/script/CompiledScript.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.scripting/share/classes/javax/script/CompiledScript.java	Thu Apr 26 17:59:02 2018 +0200
@@ -79,13 +79,10 @@
         ScriptContext ctxt = getEngine().getContext();
 
         if (bindings != null) {
-            SimpleScriptContext tempctxt = new SimpleScriptContext();
+            SimpleScriptContext tempctxt = new SimpleScriptContext(ctxt.getReader(), ctxt.getWriter(), ctxt.getErrorWriter());
             tempctxt.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
             tempctxt.setBindings(ctxt.getBindings(ScriptContext.GLOBAL_SCOPE),
                     ScriptContext.GLOBAL_SCOPE);
-            tempctxt.setWriter(ctxt.getWriter());
-            tempctxt.setReader(ctxt.getReader());
-            tempctxt.setErrorWriter(ctxt.getErrorWriter());
             ctxt = tempctxt;
         }
 
--- a/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java	Thu Apr 26 17:59:02 2018 +0200
@@ -86,11 +86,25 @@
      * Create a {@code SimpleScriptContext}.
      */
     public SimpleScriptContext() {
+        this(new InputStreamReader(System.in),
+             new PrintWriter(System.out , true),
+             new PrintWriter(System.err, true));
         engineScope = new SimpleBindings();
         globalScope = null;
-        reader = new InputStreamReader(System.in);
-        writer = new PrintWriter(System.out , true);
-        errorWriter = new PrintWriter(System.err, true);
+    }
+
+    /**
+     * Package-private constructor to avoid needless creation of reader and writers.
+     * It is the caller's responsability to initialize the engine scope.
+     *
+     * @param reader the reader
+     * @param writer the writer
+     * @param errorWriter the error writer
+     */
+    SimpleScriptContext(Reader reader, Writer writer, Writer errorWriter) {
+        this.reader = reader;
+        this.writer = writer;
+        this.errorWriter = errorWriter;
     }
 
     /**
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/SchemaContentHandler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/SchemaContentHandler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,7 @@
 import com.sun.org.apache.xerces.internal.util.SAXLocatorWrapper;
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
+import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
 import com.sun.org.apache.xerces.internal.xni.QName;
@@ -78,6 +79,7 @@
     private final QName fAttributeQName = new QName();
     private final XMLAttributesImpl fAttributes = new XMLAttributesImpl();
     private final XMLString fTempString = new XMLString();
+    private final XMLStringBuffer fStringBuffer = new XMLStringBuffer();
 
     /**
      * <p>Constructs an SchemaContentHandler.</p>
@@ -103,6 +105,7 @@
      */
     public void startDocument() throws SAXException {
         fNeedPushNSContext = true;
+        fNamespaceContext.reset();
         try {
             fSchemaDOMParser.startDocument(fSAXLocatorWrapper, null, fNamespaceContext, null);
         }
@@ -326,7 +329,11 @@
             if (nsPrefix.length() > 0) {
                 prefix = XMLSymbols.PREFIX_XMLNS;
                 localpart = nsPrefix;
-                rawname = fSymbolTable.addSymbol(prefix + ":" + localpart);
+                fStringBuffer.clear();
+                fStringBuffer.append(prefix);
+                fStringBuffer.append(':');
+                fStringBuffer.append(localpart);
+                rawname = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
             }
             else {
                 prefix = XMLSymbols.EMPTY_STRING;
@@ -334,7 +341,8 @@
                 rawname = XMLSymbols.PREFIX_XMLNS;
             }
             fAttributeQName.setValues(prefix, localpart, rawname, NamespaceContext.XMLNS_URI);
-            fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, nsURI);
+            fAttributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol,
+                    (nsURI != null) ? nsURI : XMLSymbols.EMPTY_STRING);
         }
     }
 
--- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -2266,6 +2266,8 @@
                             fSecurityManager.isSecureProcessing());
 
                     try {
+                        parser.setFeature(NAMESPACE_PREFIXES, true);
+                        namespacePrefixes = true;
                         // If this is a Xerces SAX parser set the security manager if there is one
                         if (parser instanceof SAXParser) {
                             if (fSecurityManager != null) {
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/AOTCompilationTask.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,11 +30,11 @@
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.core.GraalCompilerOptions;
 import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.Management;
 import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.debug.DebugContext.Activation;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -52,8 +52,6 @@
 
     private static final AtomicInteger ids = new AtomicInteger();
 
-    private static final com.sun.management.ThreadMXBean threadMXBean = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
-
     private final Main main;
 
     private OptionValues graalOptions;
@@ -99,7 +97,7 @@
 
         final long threadId = Thread.currentThread().getId();
 
-        final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed();
+        final boolean printCompilation = GraalCompilerOptions.PrintCompilation.getValue(graalOptions) && !TTY.isSuppressed() && GraalServices.isThreadAllocatedMemorySupported();
         if (printCompilation) {
             TTY.println(getMethodDescription() + "...");
         }
@@ -108,7 +106,7 @@
         final long allocatedBytesBefore;
         if (printCompilation) {
             start = System.currentTimeMillis();
-            allocatedBytesBefore = printCompilation ? threadMXBean.getThreadAllocatedBytes(threadId) : 0L;
+            allocatedBytesBefore = GraalServices.getThreadAllocatedBytes(threadId);
         } else {
             start = 0L;
             allocatedBytesBefore = 0L;
@@ -125,7 +123,7 @@
         if (printCompilation) {
             final long stop = System.currentTimeMillis();
             final int targetCodeSize = compResult != null ? compResult.getTargetCodeSize() : -1;
-            final long allocatedBytesAfter = threadMXBean.getThreadAllocatedBytes(threadId);
+            final long allocatedBytesAfter = GraalServices.getThreadAllocatedBytes(threadId);
             final long allocatedBytes = (allocatedBytesAfter - allocatedBytesBefore) / 1024;
 
             TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dkB", stop - start, targetCodeSize, allocatedBytes));
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/GraalFilters.java	Thu Apr 26 17:59:02 2018 +0200
@@ -45,7 +45,7 @@
 import org.graalvm.compiler.hotspot.replacements.HotSpotClassSubstitutions;
 import org.graalvm.compiler.hotspot.word.MetaspacePointer;
 import org.graalvm.compiler.replacements.Snippets;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.WordBase;
 
 final class GraalFilters {
     private List<ResolvedJavaType> specialClasses;
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc/src/jdk/tools/jaotc/Main.java	Thu Apr 26 17:59:02 2018 +0200
@@ -141,7 +141,7 @@
                 graalOptions = new OptionValues(graalOptions, TieredAOT, options.tiered);
             }
             graalOptions = new OptionValues(graalOptions, GeneratePIC, true, ImmutableCode, true);
-            GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler(JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
+            GraalJVMCICompiler graalCompiler = HotSpotGraalCompilerFactory.createCompiler("JAOTC", JVMCI.getRuntime(), graalOptions, CompilerConfigurationFactory.selectFactory(null, graalOptions));
             HotSpotGraalRuntimeProvider runtime = (HotSpotGraalRuntimeProvider) graalCompiler.getGraalRuntime();
             HotSpotHostBackend backend = (HotSpotHostBackend) runtime.getCapability(RuntimeProvider.class).getHostBackend();
             MetaAccessProvider metaAccess = backend.getProviders().getMetaAccess();
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -51,6 +51,7 @@
 import com.sun.tools.javac.code.Type.JCVoidType;
 import com.sun.tools.javac.code.Type.MethodType;
 import com.sun.tools.javac.code.Type.UnknownType;
+import com.sun.tools.javac.code.Types.UniqueType;
 import com.sun.tools.javac.comp.Modules;
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
@@ -247,6 +248,26 @@
      */
     private final Map<Name, ModuleSymbol> modules = new LinkedHashMap<>();
 
+    private final Map<Types.UniqueType, VarSymbol> classFields = new HashMap<>();
+
+    public VarSymbol getClassField(Type type, Types types) {
+        return classFields.computeIfAbsent(
+            new UniqueType(type, types), k -> {
+                Type arg = null;
+                if (type.getTag() == ARRAY || type.getTag() == CLASS)
+                    arg = types.erasure(type);
+                else if (type.isPrimitiveOrVoid())
+                    arg = types.boxedClass(type).type;
+                else
+                    throw new AssertionError(type);
+
+                Type t = new ClassType(
+                    classType.getEnclosingType(), List.of(arg), classType.tsym);
+                return new VarSymbol(
+                    STATIC | PUBLIC | FINAL, names._class, t, type.tsym);
+            });
+    }
+
     public void initType(Type type, ClassSymbol c) {
         type.tsym = c;
         typeOfTag[type.getTag().ordinal()] = type;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java	Thu Apr 26 17:59:02 2018 +0200
@@ -3731,11 +3731,7 @@
                 } else if (name == names._class) {
                     // In this case, we have already made sure in
                     // visitSelect that qualifier expression is a type.
-                    Type t = syms.classType;
-                    List<Type> typeargs = List.of(types.erasure(site));
-                    t = new ClassType(t.getEnclosingType(), typeargs, t.tsym);
-                    return new VarSymbol(
-                        STATIC | PUBLIC | FINAL, names._class, t, site.tsym);
+                    return syms.getClassField(site, types);
                 } else {
                     // We are seeing a plain identifier as selector.
                     Symbol sym = rs.findIdentInType(env, site, name, resultInfo.pkind);
@@ -3773,11 +3769,7 @@
                 if (name == names._class) {
                     // In this case, we have already made sure in Select that
                     // qualifier expression is a type.
-                    Type t = syms.classType;
-                    Type arg = types.boxedClass(site).type;
-                    t = new ClassType(t.getEnclosingType(), List.of(arg), t.tsym);
-                    return new VarSymbol(
-                        STATIC | PUBLIC | FINAL, names._class, t, site.tsym);
+                    return syms.getClassField(site, types);
                 } else {
                     log.error(pos, Errors.CantDeref(site));
                     return syms.errSymbol;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -37,6 +37,7 @@
 import com.sun.tools.javac.util.*;
 import com.sun.tools.javac.util.GraphUtils.DottableNode;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.JCDiagnostic.Fragment;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.code.*;
 import com.sun.tools.javac.code.Type.*;
@@ -115,7 +116,6 @@
         types = Types.instance(context);
         diags = JCDiagnostic.Factory.instance(context);
         log = Log.instance(context);
-        inferenceException = new InferenceException(diags);
         Options options = Options.instance(context);
         Source source = Source.instance(context);
         allowGraphInference = Feature.GRAPH_INFERENCE.allowedInSource(source)
@@ -138,33 +138,23 @@
 
         List<JCDiagnostic> messages = List.nil();
 
-        InferenceException(JCDiagnostic.Factory diags) {
-            super(diags);
-        }
-
-        @Override
-        InapplicableMethodException setMessage() {
-            //no message to set
-            return this;
-        }
-
-        @Override
-        InapplicableMethodException setMessage(JCDiagnostic diag) {
-            messages = messages.append(diag);
-            return this;
+        InferenceException() {
+            super(null);
         }
 
         @Override
         public JCDiagnostic getDiagnostic() {
             return messages.head;
         }
-
-        void clear() {
-            messages = List.nil();
-        }
     }
 
-    protected final InferenceException inferenceException;
+    InferenceException error(JCDiagnostic diag) {
+        InferenceException result = new InferenceException();
+        if (diag != null) {
+            result.messages = result.messages.append(diag);
+        }
+        return result;
+    }
 
     // <editor-fold defaultstate="collapsed" desc="Inference routines">
     /**
@@ -183,7 +173,6 @@
                             Warner warn) throws InferenceException {
         //-System.err.println("instantiateMethod(" + tvars + ", " + mt + ", " + argtypes + ")"); //DEBUG
         final InferenceContext inferenceContext = new InferenceContext(this, tvars);  //B0
-        inferenceException.clear();
         try {
             DeferredAttr.DeferredAttrContext deferredAttrContext =
                         resolveContext.deferredAttrContext(msym, inferenceContext, resultInfo, warn);
@@ -315,7 +304,6 @@
          */
         Type check(Attr.ResultInfo resultInfo) {
             Warner noWarnings = new Warner(null);
-            inferenceException.clear();
             List<Type> saved_undet = null;
             try {
                 /** we need to save the inference context before generating target type constraints.
@@ -430,9 +418,7 @@
         if (!resultInfo.checkContext.compatible(qtype, rsInfoInfContext.asUndetVar(to), retWarn) ||
                 //unchecked conversion is not allowed in source 7 mode
                 (!allowGraphInference && retWarn.hasLint(Lint.LintCategory.UNCHECKED))) {
-            throw inferenceException
-                    .setMessage("infer.no.conforming.instance.exists",
-                    inferenceContext.restvars(), mt.getReturnType(), to);
+            throw error(diags.fragment(Fragments.InferNoConformingInstanceExists(inferenceContext.restvars(), mt.getReturnType(), to)));
         }
         return from;
     }
@@ -1269,41 +1255,49 @@
      * Incorporation error: mismatch between inferred type and given bound.
      */
     void reportInstError(UndetVar uv, InferenceBound ib) {
-        reportInferenceError(
-                String.format("inferred.do.not.conform.to.%s.bounds", StringUtils.toLowerCase(ib.name())),
-                uv.getInst(),
-                uv.getBounds(ib));
+        switch (ib) {
+            case EQ:
+                throw error(diags.fragment(Fragments.InferredDoNotConformToEqBounds(uv.getInst(), uv.getBounds(ib))));
+            case LOWER:
+                throw error(diags.fragment(Fragments.InferredDoNotConformToLowerBounds(uv.getInst(), uv.getBounds(ib))));
+            case UPPER:
+                throw error(diags.fragment(Fragments.InferredDoNotConformToUpperBounds(uv.getInst(), uv.getBounds(ib))));
+        }
     }
 
     /**
      * Incorporation error: mismatch between two (or more) bounds of same kind.
      */
     void reportBoundError(UndetVar uv, InferenceBound ib) {
-        reportInferenceError(
-                String.format("incompatible.%s.bounds", StringUtils.toLowerCase(ib.name())),
-                uv.qtype,
-                uv.getBounds(ib));
+        switch (ib) {
+            case EQ:
+                throw error(diags.fragment(Fragments.IncompatibleEqBounds(uv.qtype, uv.getBounds(ib))));
+            case UPPER:
+                throw error(diags.fragment(Fragments.IncompatibleUpperBounds(uv.qtype, uv.getBounds(ib))));
+            case LOWER:
+                throw new AssertionError("this case shouldn't happen");
+        }
     }
 
     /**
      * Incorporation error: mismatch between two (or more) bounds of different kinds.
      */
     void reportBoundError(UndetVar uv, InferenceBound ib1, InferenceBound ib2) {
-        reportInferenceError(
-                String.format("incompatible.%s.%s.bounds",
-                        StringUtils.toLowerCase(ib1.name()),
-                        StringUtils.toLowerCase(ib2.name())),
+        throw error(diags.fragment(Fragments.IncompatibleBounds(
                 uv.qtype,
-                uv.getBounds(ib1),
-                uv.getBounds(ib2));
+                getBoundFragment(ib1, uv.getBounds(ib1)),
+                getBoundFragment(ib2, uv.getBounds(ib2)))));
     }
 
-    /**
-     * Helper method: reports an inference error.
-     */
-    void reportInferenceError(String key, Object... args) {
-        throw inferenceException.setMessage(key, args);
+    Fragment getBoundFragment(InferenceBound ib, List<Type> types) {
+        switch (ib) {
+            case EQ: return Fragments.EqBounds(types);
+            case LOWER: return Fragments.LowerBounds(types);
+            case UPPER: return Fragments.UpperBounds(types);
+        }
+        throw new AssertionError("can't get to this place");
     }
+
     // </editor-fold>
 
     // <editor-fold defaultstate="collapsed" desc="Inference engine">
@@ -1456,9 +1450,7 @@
                 //note: lobounds should have at least one element
                 Type owntype = lobounds.tail.tail == null  ? lobounds.head : infer.types.lub(lobounds);
                 if (owntype.isPrimitive() || owntype.hasTag(ERROR)) {
-                    throw infer.inferenceException
-                        .setMessage("no.unique.minimal.instance.exists",
-                                    uv.qtype, lobounds);
+                    throw infer.error(infer.diags.fragment(Fragments.NoUniqueMinimalInstanceExists(uv.qtype, lobounds)));
                 } else {
                     return owntype;
                 }
@@ -1499,9 +1491,7 @@
                 //note: hibounds should have at least one element
                 Type owntype = hibounds.tail.tail == null  ? hibounds.head : infer.types.glb(hibounds);
                 if (owntype.isPrimitive() || owntype.hasTag(ERROR)) {
-                    throw infer.inferenceException
-                        .setMessage("no.unique.maximal.instance.exists",
-                                    uv.qtype, hibounds);
+                    throw infer.error(infer.diags.fragment(Fragments.NoUniqueMaximalInstanceExists(uv.qtype, hibounds)));
                 } else {
                     return owntype;
                 }
@@ -1677,7 +1667,7 @@
                             }
                         }
                         //no progress
-                        throw inferenceException.setMessage();
+                        throw error(null);
                     }
                 }
                 catch (InferenceException ex) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2018, 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
@@ -36,7 +36,6 @@
 import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
 import com.sun.tools.javac.comp.DeferredAttr.DeferredType;
-import com.sun.tools.javac.comp.Infer.FreeTypeListener;
 import com.sun.tools.javac.comp.Resolve.MethodResolutionContext.Candidate;
 import com.sun.tools.javac.comp.Resolve.MethodResolutionDiagHelper.Template;
 import com.sun.tools.javac.comp.Resolve.ReferenceLookupResult.StaticKind;
@@ -60,7 +59,6 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
-import java.util.LinkedList;
 import java.util.Map;
 import java.util.Set;
 import java.util.function.BiFunction;
@@ -71,6 +69,8 @@
 
 import javax.lang.model.element.ElementVisitor;
 
+import com.sun.tools.javac.comp.Infer.InferenceException;
+
 import static com.sun.tools.javac.code.Flags.*;
 import static com.sun.tools.javac.code.Flags.BLOCK;
 import static com.sun.tools.javac.code.Flags.STATIC;
@@ -143,9 +143,6 @@
         checkVarargsAccessAfterResolution =
                 Feature.POST_APPLICABILITY_VARARGS_ACCESS_CHECK.allowedInSource(source);
         polymorphicSignatureScope = WriteableScope.create(syms.noSymbol);
-
-        inapplicableMethodException = new InapplicableMethodException(diags);
-
         allowModules = Feature.MODULES.allowedInSource(source);
     }
 
@@ -575,7 +572,7 @@
             ForAll pmt = (ForAll) mt;
             if (typeargtypes.length() != pmt.tvars.length())
                  // not enough args
-                throw inapplicableMethodException.setMessage("wrong.number.type.args", Integer.toString(pmt.tvars.length()));
+                throw new InapplicableMethodException(diags.fragment(Fragments.WrongNumberTypeArgs(Integer.toString(pmt.tvars.length()))));
             // Check type arguments are within bounds
             List<Type> formals = pmt.tvars;
             List<Type> actuals = typeargtypes;
@@ -583,8 +580,9 @@
                 List<Type> bounds = types.subst(types.getBounds((TypeVar)formals.head),
                                                 pmt.tvars, typeargtypes);
                 for (; bounds.nonEmpty(); bounds = bounds.tail) {
-                    if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn))
-                        throw inapplicableMethodException.setMessage("explicit.param.do.not.conform.to.bounds",actuals.head, bounds);
+                    if (!types.isSubtypeUnchecked(actuals.head, bounds.head, warn)) {
+                        throw new InapplicableMethodException(diags.fragment(Fragments.ExplicitParamDoNotConformToBounds(actuals.head, bounds)));
+                    }
                 }
                 formals = formals.tail;
                 actuals = actuals.tail;
@@ -811,8 +809,6 @@
 
         protected void reportMC(DiagnosticPosition pos, MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
             boolean inferDiag = inferenceContext != infer.emptyContext;
-            InapplicableMethodException ex = inferDiag ?
-                    infer.inferenceException : inapplicableMethodException;
             if (inferDiag && (!diag.inferKey.equals(diag.basicKey))) {
                 Object[] args2 = new Object[args.length + 1];
                 System.arraycopy(args, 0, args2, 1, args.length);
@@ -820,7 +816,9 @@
                 args = args2;
             }
             String key = inferDiag ? diag.inferKey : diag.basicKey;
-            throw ex.setMessage(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
+            throw inferDiag ?
+                infer.error(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args)) :
+                new InapplicableMethodException(diags.create(DiagnosticType.FRAGMENT, log.currentSource(), pos, key, args));
         }
 
         public MethodCheck mostSpecificCheck(List<Type> actuals) {
@@ -1006,7 +1004,7 @@
         }
 
         public void report(DiagnosticPosition pos, JCDiagnostic details) {
-            throw inapplicableMethodException.setMessage(details);
+            throw new InapplicableMethodException(details);
         }
 
         public Warner checkWarner(DiagnosticPosition pos, Type found, Type req) {
@@ -1367,31 +1365,15 @@
         private static final long serialVersionUID = 0;
 
         JCDiagnostic diagnostic;
-        JCDiagnostic.Factory diags;
-
-        InapplicableMethodException(JCDiagnostic.Factory diags) {
-            this.diagnostic = null;
-            this.diags = diags;
-        }
-        InapplicableMethodException setMessage() {
-            return setMessage((JCDiagnostic)null);
-        }
-        InapplicableMethodException setMessage(String key) {
-            return setMessage(key != null ? diags.fragment(key) : null);
-        }
-        InapplicableMethodException setMessage(String key, Object... args) {
-            return setMessage(key != null ? diags.fragment(key, args) : null);
-        }
-        InapplicableMethodException setMessage(JCDiagnostic diag) {
+
+        InapplicableMethodException(JCDiagnostic diag) {
             this.diagnostic = diag;
-            return this;
         }
 
         public JCDiagnostic getDiagnostic() {
             return diagnostic;
         }
     }
-    private final InapplicableMethodException inapplicableMethodException;
 
 /* ***************************************************************************
  *  Symbol lookup
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties	Thu Apr 26 17:59:02 2018 +0200
@@ -2302,6 +2302,7 @@
 compiler.misc.no.unique.maximal.instance.exists=\
     no unique maximal instance exists for type variable {0} with upper bounds {1}
 
+# 0: type, 1: list of type
 compiler.misc.no.unique.minimal.instance.exists=\
     no unique minimal instance exists for type variable {0} with lower bounds {1}
 
@@ -2313,23 +2314,23 @@
 compiler.misc.incompatible.eq.bounds=\
     inference variable {0} has incompatible equality constraints {1}
 
-# 0: type, 1: list of type, 2: list of type
-compiler.misc.incompatible.eq.upper.bounds=\
-    inference variable {0} has incompatible bounds\n\
-    equality constraints: {1}\n\
-    upper bounds: {2}
-
-# 0: type, 1: list of type, 2: list of type
-compiler.misc.incompatible.upper.lower.bounds=\
+# 0: type, 1: fragment, 2: fragment
+compiler.misc.incompatible.bounds=\
     inference variable {0} has incompatible bounds\n\
-    upper bounds: {1}\n\
-    lower bounds: {2}
-
-# 0: type, 1: list of type, 2: list of type
-compiler.misc.incompatible.eq.lower.bounds=\
-    inference variable {0} has incompatible bounds\n\
-    equality constraints: {1}\n\
-    lower bounds: {2}
+    {1}\n\
+    {2}
+
+# 0: list of type
+compiler.misc.lower.bounds=\
+        lower bounds: {0}
+
+# 0: list of type
+compiler.misc.eq.bounds=\
+        equality constraints: {0}
+
+# 0: list of type
+compiler.misc.upper.bounds=\
+        lower bounds: {0}
 
 # 0: list of type, 1: type, 2: type
 compiler.misc.infer.no.conforming.instance.exists=\
--- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c	Thu Apr 26 17:59:02 2018 +0200
@@ -212,29 +212,51 @@
 // mapped.  This structure gets written to a file.  It is not a class,
 // so that the compilers don't add any compiler-private data to it.
 
-#define NUM_SHARED_MAPS 4
+#define NUM_SHARED_MAPS 9
 
 // Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 1
+#define CURRENT_ARCHIVE_VERSION 3
+
+typedef unsigned char* address;
+typedef uintptr_t      uintx;
+typedef intptr_t       intx;
 
 struct FileMapHeader {
-  int   _magic;              // identify file type.
-  int   _version;            // (from enum, above.)
-  size_t _alignment;         // how shared archive should be aligned
+  int     _magic;                   // identify file type.
+  int     _crc;                     // header crc checksum.
+  int     _version;                 // (from enum, above.)
+  size_t  _alignment;               // how shared archive should be aligned
+  int     _obj_alignment;           // value of ObjectAlignmentInBytes
+  address _narrow_oop_base;         // compressed oop encoding base
+  int     _narrow_oop_shift;        // compressed oop encoding shift
+  bool    _compact_strings;         // value of CompactStrings
+  uintx   _max_heap_size;           // java max heap size during dumping
+  int     _narrow_oop_mode;         // compressed oop encoding mode
+  int     _narrow_klass_shift;      // save narrow klass base and shift
+  address _narrow_klass_base;
+  char*   _misc_data_patching_start;
+  char*   _read_only_tables_start;
+  address _cds_i2i_entry_code_buffers;
+  size_t  _cds_i2i_entry_code_buffers_size;
+  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
+                                    // (mc, md, ro, rw and od).
+
 
   struct space_info {
-    int    _file_offset;     // sizeof(this) rounded to vm page size
-    char*  _base;            // copy-on-write base address
-    size_t _capacity;        // for validity checking
-    size_t _used;            // for setting space top on read
-
+    int     _crc;          // crc checksum of the current space
+    size_t  _file_offset;  // sizeof(this) rounded to vm page size
+    union {
+      char*  _base;        // copy-on-write base address
+      intx   _offset;      // offset from the compressed oop encoding base, only used
+                           // by archive heap space
+    } _addr;
+    size_t _used;          // for setting space top on read
     // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
     // the C type matching the C++ bool type on any given platform.
     // We assume the corresponding C type is char but licensees
     // may need to adjust the type of these fields.
-    char   _read_only;       // read only space?
-    char   _allow_exec;      // executable code in space?
-
+    char   _read_only;     // read only space?
+    char   _allow_exec;    // executable code in space?
   } _space[NUM_SHARED_MAPS];
 
   // Ignore the rest of the FileMapHeader. We don't need those fields here.
@@ -381,7 +403,7 @@
       // add read-only maps from classes.jsa to the list of maps
       for (m = 0; m < NUM_SHARED_MAPS; m++) {
         if (header._space[m]._read_only) {
-          base = (uintptr_t) header._space[m]._base;
+          base = (uintptr_t) header._space[m]._addr._base;
           // no need to worry about the fractional pages at-the-end.
           // possible fractional pages are handled by core_read_data.
           add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
--- a/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/macosx/native/libsaproc/ps_core.c	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -213,29 +213,52 @@
 // mapped.  This structure gets written to a file.  It is not a class,
 // so that the compilers don't add any compiler-private data to it.
 
-#define NUM_SHARED_MAPS 4
+#define NUM_SHARED_MAPS 9
 
 // Refer to FileMapInfo::_current_version in filemap.hpp
-#define CURRENT_ARCHIVE_VERSION 1
+#define CURRENT_ARCHIVE_VERSION 3
+
+typedef unsigned char* address;
+typedef uintptr_t      uintx;
+typedef intptr_t       intx;
+
 
 struct FileMapHeader {
-  int   _magic;              // identify file type.
-  int   _version;            // (from enum, above.)
-  size_t _alignment;         // how shared archive should be aligned
+  int     _magic;                   // identify file type.
+  int     _crc;                     // header crc checksum.
+  int     _version;                 // (from enum, above.)
+  size_t  _alignment;               // how shared archive should be aligned
+  int     _obj_alignment;           // value of ObjectAlignmentInBytes
+  address _narrow_oop_base;         // compressed oop encoding base
+  int     _narrow_oop_shift;        // compressed oop encoding shift
+  bool    _compact_strings;         // value of CompactStrings
+  uintx   _max_heap_size;           // java max heap size during dumping
+  int     _narrow_oop_mode;         // compressed oop encoding mode
+  int     _narrow_klass_shift;      // save narrow klass base and shift
+  address _narrow_klass_base;
+  char*   _misc_data_patching_start;
+  char*   _read_only_tables_start;
+  address _cds_i2i_entry_code_buffers;
+  size_t  _cds_i2i_entry_code_buffers_size;
+  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
+                                    // (mc, md, ro, rw and od).
+
 
   struct space_info {
-    int    _file_offset;     // sizeof(this) rounded to vm page size
-    char*  _base;            // copy-on-write base address
-    size_t _capacity;        // for validity checking
-    size_t _used;            // for setting space top on read
-
+    int     _crc;          // crc checksum of the current space
+    size_t  _file_offset;  // sizeof(this) rounded to vm page size
+    union {
+      char*  _base;        // copy-on-write base address
+      intx   _offset;      // offset from the compressed oop encoding base, only used
+                           // by archive heap space
+    } _addr;
+    size_t _used;          // for setting space top on read
     // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
     // the C type matching the C++ bool type on any given platform.
     // We assume the corresponding C type is char but licensees
     // may need to adjust the type of these fields.
-    char   _read_only;       // read only space?
-    char   _allow_exec;      // executable code in space?
-
+    char   _read_only;     // read only space?
+    char   _allow_exec;    // executable code in space?
   } _space[NUM_SHARED_MAPS];
 
   // Ignore the rest of the FileMapHeader. We don't need those fields here.
@@ -282,15 +305,14 @@
   return true;
 }
 
+// mangled name of Arguments::SharedArchivePath
+#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
+
 #ifdef __APPLE__
 #define USE_SHARED_SPACES_SYM "_UseSharedSpaces"
-// mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "_ZN9Arguments17SharedArchivePathE"
 #define LIBJVM_NAME "/libjvm.dylib"
 #else
 #define USE_SHARED_SPACES_SYM "UseSharedSpaces"
-// mangled name of Arguments::SharedArchivePath
-#define SHARED_ARCHIVE_PATH_SYM "__ZN9Arguments17SharedArchivePathE"
 #define LIBJVM_NAME "/libjvm.so"
 #endif // __APPLE_
 
@@ -387,7 +409,7 @@
       // add read-only maps from classes.jsa to the list of maps
       for (m = 0; m < NUM_SHARED_MAPS; m++) {
         if (header._space[m]._read_only) {
-          base = (uintptr_t) header._space[m]._base;
+          base = (uintptr_t) header._space[m]._addr._base;
           // no need to worry about the fractional pages at-the-end.
           // possible fractional pages are handled by core_read_data.
           add_class_share_map_info(ph, (off_t) header._space[m]._file_offset,
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/memory/FileMapInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2018, 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 sun.jvm.hotspot.memory;
+
+import java.util.*;
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObject;
+import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.*;
+
+public class FileMapInfo {
+  private static FileMapHeader header;
+  private static Address headerValue;
+
+  // Fields for class FileMapHeader
+  private static Address mdSpaceValue;
+  private static Address mdRegionBaseAddress;
+  private static Address mdRegionEndAddress;
+
+  // HashMap created by mapping the vTable addresses in the md region with
+  // the corresponding metadata type.
+  private static Map<Address, Type> vTableTypeMap;
+
+  private static Type metadataTypeArray[];
+
+  static {
+    VM.registerVMInitializedObserver(new Observer() {
+        public void update(Observable o, Object data) {
+          initialize(VM.getVM().getTypeDataBase());
+        }
+      });
+  }
+
+  private static void initialize(TypeDataBase db) {
+    // FileMapInfo
+    Type type = db.lookupType("FileMapInfo");
+    AddressField currentInfoField = type.getAddressField("_current_info");
+    long headerFieldOffset = type.getField("_header").getOffset();
+    Address headerAddress = currentInfoField.getValue().addOffsetTo(headerFieldOffset);
+    headerValue = headerAddress.getAddressAt(0);
+
+    // FileMapHeader
+    type = db.lookupType("FileMapInfo::FileMapHeader");
+    AddressField spaceField = type.getAddressField("_space[0]");
+    Address spaceValue = headerValue.addOffsetTo(type.getField("_space[0]").getOffset());
+    mdSpaceValue = spaceValue.addOffsetTo(3 * spaceField.getSize());
+
+    // SpaceInfo
+    type = db.lookupType("FileMapInfo::FileMapHeader::space_info");
+    long mdRegionBaseAddressOffset = type.getField("_addr._base").getOffset();
+    mdRegionBaseAddress = (mdSpaceValue.addOffsetTo(mdRegionBaseAddressOffset)).getAddressAt(0);
+    long mdRegionSizeOffset = type.getField("_used").getOffset();
+    long mdRegionSize = (mdSpaceValue.addOffsetTo(mdRegionSizeOffset)).getAddressAt(0).asLongValue();
+    mdRegionEndAddress = mdRegionBaseAddress.addOffsetTo(mdRegionSize);
+
+    populateMetadataTypeArray(db);
+  }
+
+  private static void populateMetadataTypeArray(TypeDataBase db) {
+    metadataTypeArray = new Type[8];
+
+    metadataTypeArray[0] = db.lookupType("ConstantPool");
+    metadataTypeArray[1] = db.lookupType("InstanceKlass");
+    metadataTypeArray[2] = db.lookupType("InstanceClassLoaderKlass");
+    metadataTypeArray[3] = db.lookupType("InstanceMirrorKlass");
+    metadataTypeArray[4] = db.lookupType("InstanceRefKlass");
+    metadataTypeArray[5] = db.lookupType("Method");
+    metadataTypeArray[6] = db.lookupType("ObjArrayKlass");
+    metadataTypeArray[7] = db.lookupType("TypeArrayKlass");
+  }
+
+  public FileMapHeader getHeader() {
+    if (header == null) {
+      header = (FileMapHeader) VMObjectFactory.newObject(FileMapInfo.FileMapHeader.class, headerValue);
+    }
+    return header;
+  }
+
+  public boolean inCopiedVtableSpace(Address vptrAddress) {
+    FileMapHeader fmHeader = getHeader();
+    return fmHeader.inCopiedVtableSpace(vptrAddress);
+  }
+
+  public Type getTypeForVptrAddress(Address vptrAddress) {
+    if (vTableTypeMap == null) {
+      getHeader().createVtableTypeMapping();
+    }
+    return vTableTypeMap.get(vptrAddress);
+  }
+
+
+  //------------------------------------------------------------------------------------------
+
+  public static class FileMapHeader extends VMObject {
+
+    public FileMapHeader(Address addr) {
+      super(addr);
+    }
+
+    public boolean inCopiedVtableSpace(Address vptrAddress) {
+      if (vptrAddress.greaterThan(mdRegionBaseAddress) &&
+          vptrAddress.lessThanOrEqual(mdRegionEndAddress)) {
+        return true;
+      }
+      return false;
+    }
+
+    public void createVtableTypeMapping() {
+      vTableTypeMap = new HashMap<Address, Type>();
+      long metadataVTableSize = 0;
+      long addressSize = VM.getVM().getAddressSize();
+
+      Address copiedVtableAddress = mdRegionBaseAddress;
+      for (int i=0; i < metadataTypeArray.length; i++) {
+        // The first entry denotes the vtable size.
+        metadataVTableSize = copiedVtableAddress.getAddressAt(0).asLongValue();
+        vTableTypeMap.put(copiedVtableAddress.addOffsetTo(addressSize), metadataTypeArray[i]);
+
+        // The '+ 1' below is to skip the entry containing the size of this metadata's vtable.
+        copiedVtableAddress =
+          copiedVtableAddress.addOffsetTo((metadataVTableSize + 1) * addressSize);
+      }
+    }
+  }
+}
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/VM.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -87,6 +87,7 @@
   private JNIHandles   handles;
   private Interpreter  interpreter;
   private StubRoutines stubRoutines;
+  private FileMapInfo  fileMapInfo;
   private Bytes        bytes;
 
   /** Flag indicating if JVMTI support is included in the build */
@@ -717,6 +718,16 @@
     return vmregImpl;
   }
 
+  public FileMapInfo getFileMapInfo() {
+    if (!isSharingEnabled()) {
+      return null;
+    }
+    if (fileMapInfo == null) {
+      fileMapInfo = new FileMapInfo();
+    }
+    return fileMapInfo;
+  }
+
   public Bytes getBytes() {
     if (bytes == null) {
       bytes = new Bytes(debugger.getMachineDescription());
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, 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
@@ -33,6 +33,7 @@
 import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.types.Type;
 import sun.jvm.hotspot.types.TypeDataBase;
+import sun.jvm.hotspot.memory.FileMapInfo;
 
 /** <P> This is a basic implementation of the TypeDataBase interface.
     It allows an external type database builder to add types to be
@@ -294,6 +295,15 @@
     // the locations searched.
 
     Address loc1 = addr.getAddressAt(0);
+
+    if (VM.getVM().isSharingEnabled()) {
+      // Check if the value falls in the _md_region
+      FileMapInfo cdsFileMapInfo = VM.getVM().getFileMapInfo();
+      if (cdsFileMapInfo.inCopiedVtableSpace(loc1)) {
+         return cdsFileMapInfo.getTypeForVptrAddress(loc1);
+      }
+    }
+
     Address loc2 = null;
     Address loc3 = null;
     long offset2 = baseType.getSize();
--- a/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.hotspot.agent/solaris/native/libsaproc/saproc.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, 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
@@ -496,29 +496,54 @@
 // mapped.  This structure gets written to a file.  It is not a class, so
 // that the compilers don't add any compiler-private data to it.
 
-const int NUM_SHARED_MAPS = 4;
+const int NUM_SHARED_MAPS = 9;
 
 // Refer to FileMapInfo::_current_version in filemap.hpp
-const int CURRENT_ARCHIVE_VERSION = 1;
+const int CURRENT_ARCHIVE_VERSION = 3;
+
+typedef unsigned char* address;
+typedef uintptr_t      uintx;
+typedef intptr_t       intx;
 
 struct FileMapHeader {
- int   _magic;              // identify file type.
- int   _version;            // (from enum, above.)
- size_t _alignment;         // how shared archive should be aligned
+  int     _magic;                   // identify file type.
+  int     _crc;                     // header crc checksum.
+  int     _version;                 // (from enum, above.)
+  size_t  _alignment;               // how shared archive should be aligned
+  int     _obj_alignment;           // value of ObjectAlignmentInBytes
+  address _narrow_oop_base;         // compressed oop encoding base
+  int     _narrow_oop_shift;        // compressed oop encoding shift
+  bool    _compact_strings;         // value of CompactStrings
+  uintx   _max_heap_size;           // java max heap size during dumping
+  int     _narrow_oop_mode;         // compressed oop encoding mode
+  int     _narrow_klass_shift;      // save narrow klass base and shift
+  address _narrow_klass_base;
+  char*   _misc_data_patching_start;
+  char*   _read_only_tables_start;
+  address _cds_i2i_entry_code_buffers;
+  size_t  _cds_i2i_entry_code_buffers_size;
+  size_t  _core_spaces_size;        // number of bytes allocated by the core spaces
+                                    // (mc, md, ro, rw and od).
 
 
- struct space_info {
-   int    _file_offset;     // sizeof(this) rounded to vm page size
-   char*  _base;            // copy-on-write base address
-   size_t _capacity;        // for validity checking
-   size_t _used;            // for setting space top on read
+  struct space_info {
+    int     _crc;          // crc checksum of the current space
+    size_t  _file_offset;  // sizeof(this) rounded to vm page size
+    union {
+      char*  _base;        // copy-on-write base address
+      intx   _offset;      // offset from the compressed oop encoding base, only used
+                           // by archive heap space
+    } _addr;
+    size_t _used;          // for setting space top on read
+    // 4991491 NOTICE These are C++ bool's in filemap.hpp and must match up with
+    // the C type matching the C++ bool type on any given platform.
+    // We assume the corresponding C type is char but licensees
+    // may need to adjust the type of these fields.
+    char   _read_only;     // read only space?
+    char   _allow_exec;    // executable code in space?
+  } _space[NUM_SHARED_MAPS];
 
-   bool   _read_only;       // read only space?
-   bool   _allow_exec;      // executable code in space?
-
- } _space[NUM_SHARED_MAPS];
-
- // Ignore the rest of the FileMapHeader. We don't need those fields here.
+// Ignore the rest of the FileMapHeader. We don't need those fields here.
 };
 
 static bool
@@ -677,7 +702,7 @@
   if (_libsaproc_debug) {
     for (int m = 0; m < NUM_SHARED_MAPS; m++) {
        print_debug("shared file offset %d mapped at 0x%lx, size = %ld, read only? = %d\n",
-          pheader->_space[m]._file_offset, pheader->_space[m]._base,
+          pheader->_space[m]._file_offset, pheader->_space[m]._addr._base,
           pheader->_space[m]._used, pheader->_space[m]._read_only);
     }
   }
@@ -1058,7 +1083,7 @@
       print_debug("read failed at 0x%lx, attempting shared heap area\n", (long) address);
 
       struct FileMapHeader* pheader = (struct FileMapHeader*) env->GetLongField(this_obj, p_file_map_header_ID);
-      // walk through the shared mappings -- we just have 4 of them.
+      // walk through the shared mappings -- we just have 9 of them.
       // so, linear walking is okay.
       for (int m = 0; m < NUM_SHARED_MAPS; m++) {
 
@@ -1066,7 +1091,7 @@
         // and hence will be read by libproc. Besides, the file copy may be
         // stale because the process might have modified those pages.
         if (pheader->_space[m]._read_only) {
-          jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._base;
+          jlong baseAddress = (jlong) (uintptr_t) pheader->_space[m]._addr._base;
           size_t usedSize = pheader->_space[m]._used;
           if (address >= baseAddress && address < (baseAddress + usedSize)) {
             // the given address falls in this shared heap area
--- a/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalManagement.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,154 @@
  */
 package org.graalvm.compiler.hotspot.management;
 
+import java.lang.management.ManagementFactory;
+import java.util.ArrayList;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.MBeanRegistrationException;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.MalformedObjectNameException;
+import javax.management.NotCompliantMBeanException;
+import javax.management.ObjectName;
+
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
+import org.graalvm.compiler.serviceprovider.ServiceProvider;
+
 /**
- * Placeholder until next Graal update.
+ * Dynamically registers an MBean with the {@link ManagementFactory#getPlatformMBeanServer()}.
+ *
+ * Polling for an active platform MBean server is done by calling
+ * {@link MBeanServerFactory#findMBeanServer(String)} with an argument value of {@code null}. Once
+ * this returns an non-empty list, {@link ManagementFactory#getPlatformMBeanServer()} can be called
+ * to obtain a reference to the platform MBean server instance.
  */
-public final class HotSpotGraalManagement  {
+@ServiceProvider(HotSpotGraalManagementRegistration.class)
+public final class HotSpotGraalManagement implements HotSpotGraalManagementRegistration {
+
+    private HotSpotGraalRuntimeMBean bean;
+    private volatile boolean needsRegistration = true;
+    HotSpotGraalManagement nextDeferred;
+
+    @Override
+    public void initialize(HotSpotGraalRuntime runtime) {
+        if (bean == null) {
+            if (runtime.getManagement() != this) {
+                throw new IllegalArgumentException("Cannot initialize a second management object for runtime " + runtime.getName());
+            }
+            try {
+                String name = runtime.getName().replace(':', '_');
+                ObjectName objectName = new ObjectName("org.graalvm.compiler.hotspot:type=" + name);
+                bean = new HotSpotGraalRuntimeMBean(objectName, runtime);
+                registration.add(this);
+            } catch (MalformedObjectNameException err) {
+                err.printStackTrace(TTY.out);
+            }
+        } else if (bean.getRuntime() != runtime) {
+            throw new IllegalArgumentException("Cannot change the runtime a management interface is associated with");
+        }
+    }
+
+    static final class RegistrationThread extends Thread {
+
+        private MBeanServer platformMBeanServer;
+        private HotSpotGraalManagement deferred;
+
+        RegistrationThread() {
+            super("HotSpotGraalManagement Bean Registration");
+            this.setPriority(Thread.MIN_PRIORITY);
+            this.setDaemon(true);
+            this.start();
+        }
+
+        /**
+         * Poll for active MBean server every 2 seconds.
+         */
+        private static final int POLL_INTERVAL_MS = 2000;
+
+        /**
+         * Adds a {@link HotSpotGraalManagement} to register with an active MBean server when one
+         * becomes available.
+         */
+        synchronized void add(HotSpotGraalManagement e) {
+            if (deferred != null) {
+                e.nextDeferred = deferred;
+            }
+            deferred = e;
+
+            // Notify the registration thread that there is now
+            // a deferred registration to process
+            notify();
+        }
+
+        /**
+         * Processes and clears any deferred registrations.
+         */
+        private void process() {
+            for (HotSpotGraalManagement m = deferred; m != null; m = m.nextDeferred) {
+                HotSpotGraalRuntimeMBean bean = m.bean;
+                if (m.needsRegistration && bean != null) {
+                    try {
+                        platformMBeanServer.registerMBean(bean, bean.getObjectName());
+                    } catch (InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException e) {
+                        e.printStackTrace(TTY.out);
+                        // Registration failed - don't try again
+                        m.bean = null;
+                    }
+                    m.needsRegistration = false;
+                }
+            }
+            deferred = null;
+        }
+
+        @Override
+        public void run() {
+            while (true) {
+                try {
+                    synchronized (this) {
+                        // Wait until there are deferred registrations to process
+                        while (deferred == null) {
+                            wait();
+                        }
+                    }
+                    poll();
+                    Thread.sleep(POLL_INTERVAL_MS);
+                } catch (InterruptedException e) {
+                    // Be verbose about unexpected interruption and then continue
+                    e.printStackTrace(TTY.out);
+                }
+            }
+        }
+
+        /**
+         * Checks for active MBean server and if available, processes deferred registrations.
+         */
+        synchronized void poll() {
+            if (platformMBeanServer == null) {
+                ArrayList<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
+                if (!servers.isEmpty()) {
+                    platformMBeanServer = ManagementFactory.getPlatformMBeanServer();
+                    process();
+                }
+            } else {
+                process();
+            }
+        }
+    }
+
+    private static final RegistrationThread registration = new RegistrationThread();
+
+    @Override
+    public ObjectName poll(boolean sync) {
+        if (sync) {
+            registration.poll();
+        }
+        if (bean == null || needsRegistration) {
+            // initialize() has not been called, it failed or registration failed
+            return null;
+        }
+        return bean.getObjectName();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/HotSpotGraalRuntimeMBean.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2018, 2018, 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.management;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.DynamicMBean;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
+import org.graalvm.compiler.debug.TTY;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
+import org.graalvm.compiler.options.OptionDescriptor;
+import org.graalvm.compiler.options.OptionDescriptors;
+import org.graalvm.compiler.options.OptionsParser;
+
+/**
+ * MBean used to access properties and operations of a {@link HotSpotGraalRuntime} instance.
+ */
+final class HotSpotGraalRuntimeMBean implements DynamicMBean {
+
+    /**
+     * The runtime instance to which this bean provides a management connection.
+     */
+    private final HotSpotGraalRuntime runtime;
+
+    /**
+     * The object name under which the bean is registered.
+     */
+    private final ObjectName objectName;
+
+    HotSpotGraalRuntimeMBean(ObjectName objectName, HotSpotGraalRuntime runtime) {
+        this.objectName = objectName;
+        this.runtime = runtime;
+    }
+
+    ObjectName getObjectName() {
+        return objectName;
+    }
+
+    HotSpotGraalRuntime getRuntime() {
+        return runtime;
+    }
+
+    private static final boolean DEBUG = Boolean.getBoolean(HotSpotGraalRuntimeMBean.class.getSimpleName() + ".debug");
+
+    @Override
+    public Object getAttribute(String name) throws AttributeNotFoundException {
+        String[] result = runtime.getOptionValues(name);
+        String value = result[0];
+        if (value == null) {
+            throw new AttributeNotFoundException(name);
+        }
+        if (DEBUG) {
+            System.out.printf("getAttribute: %s = %s (type: %s)%n", name, value, value == null ? "null" : value.getClass().getName());
+        }
+        return result[0];
+    }
+
+    @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality on the receiver is what we want")
+    @Override
+    public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException {
+        String name = attribute.getName();
+        Object value = attribute.getValue();
+        String svalue = String.valueOf(value);
+        if (DEBUG) {
+            System.out.printf("setAttribute: %s = %s (type: %s)%n", name, svalue, value == null ? "null" : value.getClass().getName());
+        }
+        String[] result = runtime.setOptionValues(new String[]{name}, new String[]{svalue});
+        if (result[0] != name) {
+            if (result[0] == null) {
+                throw new AttributeNotFoundException(name);
+            }
+            throw new InvalidAttributeValueException(result[0]);
+        }
+    }
+
+    @Override
+    public AttributeList getAttributes(String[] names) {
+        String[] values = runtime.getOptionValues(names);
+        AttributeList list = new AttributeList();
+        for (int i = 0; i < names.length; i++) {
+            String value = values[i];
+            String name = names[i];
+            if (value == null) {
+                TTY.printf("No such option named %s%n", name);
+            } else {
+                if (DEBUG) {
+                    System.out.printf("getAttributes: %s = %s (type: %s)%n", name, value, value == null ? "null" : value.getClass().getName());
+                }
+                list.add(new Attribute(name, value));
+            }
+        }
+        return list;
+    }
+
+    @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "reference equality on the receiver is what we want")
+    @Override
+    public AttributeList setAttributes(AttributeList attributes) {
+        String[] names = new String[attributes.size()];
+        String[] values = new String[attributes.size()];
+
+        int i = 0;
+        for (Attribute attr : attributes.asList()) {
+            String name = attr.getName();
+            names[i] = name;
+            Object value = attr.getValue();
+            String svalue = String.valueOf(value);
+            values[i] = svalue;
+            if (DEBUG) {
+                System.out.printf("setAttributes: %s = %s (type: %s)%n", name, svalue, value == null ? "null" : value.getClass().getName());
+            }
+            i++;
+        }
+        String[] result = runtime.setOptionValues(names, values);
+        AttributeList setOk = new AttributeList();
+        i = 0;
+        for (Attribute attr : attributes.asList()) {
+            if (names[i] == result[i]) {
+                setOk.add(attr);
+            } else if (result[i] == null) {
+                TTY.printf("Error setting %s to %s: unknown option%n", attr.getName(), attr.getValue());
+            } else {
+                TTY.printf("Error setting %s to %s: %s%n", attr.getName(), attr.getValue(), result[i]);
+            }
+            i++;
+        }
+        return setOk;
+    }
+
+    @Override
+    public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
+        try {
+            if (DEBUG) {
+                System.out.printf("invoke: %s%s%n", actionName, Arrays.asList(params));
+            }
+            Object retvalue = runtime.invokeManagementAction(actionName, params);
+            if (DEBUG) {
+                System.out.printf("invoke: %s%s = %s%n", actionName, Arrays.asList(params), retvalue);
+            }
+            return retvalue;
+        } catch (Exception ex) {
+            throw new ReflectionException(ex);
+        }
+    }
+
+    @Override
+    public MBeanInfo getMBeanInfo() {
+        List<MBeanAttributeInfo> attrs = new ArrayList<>();
+        for (OptionDescriptor option : getOptionDescriptors().getValues()) {
+            Class<?> optionValueType = option.getOptionValueType();
+            if (Enum.class.isAssignableFrom(optionValueType)) {
+                // Enum values are passed through
+                // the management interface as Strings.
+                optionValueType = String.class;
+            }
+            attrs.add(new MBeanAttributeInfo(option.getName(), optionValueType.getName(), option.getHelp(), true, true, false));
+        }
+        attrs.sort(new Comparator<MBeanAttributeInfo>() {
+            @Override
+            public int compare(MBeanAttributeInfo o1, MBeanAttributeInfo o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        MBeanOperationInfo[] ops = {
+                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                        }, "void", MBeanOperationInfo.ACTION),
+                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                        }, "void", MBeanOperationInfo.ACTION),
+                        new MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new MBeanParameterInfo[]{
+                                        new MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
+                                        new MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
+                                        new MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
+                                        new MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
+                                        new MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
+                        }, "void", MBeanOperationInfo.ACTION)
+        };
+
+        return new MBeanInfo(
+                        HotSpotGraalRuntimeMBean.class.getName(),
+                        "Graal",
+                        attrs.toArray(new MBeanAttributeInfo[attrs.size()]),
+                        null, ops, null);
+    }
+
+    private static EconomicMap<String, OptionDescriptor> getOptionDescriptors() {
+        EconomicMap<String, OptionDescriptor> result = EconomicMap.create();
+        for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
+            for (OptionDescriptor option : set) {
+                result.put(option.getName(), option);
+            }
+        }
+        return result;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/JMXServiceProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018, 2018, 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.management;
+
+import static java.lang.Thread.currentThread;
+
+import java.lang.management.ManagementFactory;
+import java.util.List;
+
+import org.graalvm.compiler.serviceprovider.ServiceProvider;
+import org.graalvm.compiler.serviceprovider.GraalServices.JMXService;
+
+import com.sun.management.ThreadMXBean;
+
+/**
+ * Implementation of {@link JMXService} for JDK 11 and later.
+ */
+@ServiceProvider(JMXService.class)
+public class JMXServiceProvider extends JMXService {
+    private final ThreadMXBean threadMXBean = (ThreadMXBean) ManagementFactory.getThreadMXBean();
+
+    @Override
+    protected long getThreadAllocatedBytes(long id) {
+        return threadMXBean.getThreadAllocatedBytes(id);
+    }
+
+    @Override
+    protected long getCurrentThreadCpuTime() {
+        long[] times = threadMXBean.getThreadCpuTime(new long[]{currentThread().getId()});
+        return times[0];
+    }
+
+    @Override
+    protected boolean isThreadAllocatedMemorySupported() {
+        return threadMXBean.isThreadAllocatedMemorySupported();
+    }
+
+    @Override
+    protected boolean isCurrentThreadCpuTimeSupported() {
+        return threadMXBean.isThreadCpuTimeSupported();
+    }
+
+    @Override
+    protected List<String> getInputArguments() {
+        return ManagementFactory.getRuntimeMXBean().getInputArguments();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler.management/share/classes/org.graalvm.compiler.hotspot.management/src/org/graalvm/compiler/hotspot/management/package-info.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2018, 2018, 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.
+ */
+
+/**
+ * JDK 11 and later versioned overlay for the {@code jdk.internal.vm.compiler.management} module.
+ * This cannot be used in JDK 10 where {@code jdk.internal.vm.compiler.management} is a
+ * non-upgradeable module.
+ */
+package org.graalvm.compiler.hotspot.management;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapImplTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.Arrays;
+import java.util.Iterator;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicSet;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicMapImplTest {
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testRemoveNull() {
+        EconomicMap<Integer, Integer> map = EconomicMap.create(10);
+        map.removeKey(null);
+    }
+
+    @Test
+    public void testInitFromHashSet() {
+        UnmodifiableEconomicSet<Integer> set = new UnmodifiableEconomicSet<Integer>() {
+
+            @Override
+            public boolean contains(Integer element) {
+                return element == 0;
+            }
+
+            @Override
+            public int size() {
+                return 1;
+            }
+
+            @Override
+            public boolean isEmpty() {
+                return false;
+            }
+
+            @Override
+            public Iterator<Integer> iterator() {
+                return new Iterator<Integer>() {
+
+                    private boolean visited = false;
+
+                    @Override
+                    public boolean hasNext() {
+                        return !visited;
+                    }
+
+                    @Override
+                    public Integer next() {
+                        if (visited) {
+                            return null;
+                        } else {
+                            visited = true;
+                            return 1;
+                        }
+                    }
+                };
+            }
+        };
+
+        EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.DEFAULT, set);
+        Assert.assertEquals(newSet.size(), 1);
+    }
+
+    @Test
+    public void testCopyHash() {
+        EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
+        set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+        EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.IDENTITY, set);
+        Assert.assertEquals(newSet.size(), 10);
+        newSet.remove(8);
+        newSet.remove(9);
+        Assert.assertEquals(newSet.size(), 8);
+    }
+
+    @Test
+    public void testNewEquivalence() {
+        EconomicSet<Integer> set = EconomicSet.create(new Equivalence() {
+            @Override
+            public boolean equals(Object a, Object b) {
+                return false;
+            }
+
+            @Override
+            public int hashCode(Object o) {
+                return 0;
+            }
+        });
+        set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+        Assert.assertTrue(set.add(new Integer(0)));
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testMapPutNull() {
+        EconomicMap<Integer, Integer> map = EconomicMap.create();
+        map.put(null, null);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapLargeTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Objects;
+import java.util.Random;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class EconomicMapLargeTest {
+
+    @Parameter(value = 0) public EconomicMap<Object, Object> testMap;
+    @Parameter(value = 1) public EconomicMap<Object, Object> referenceMap;
+    @Parameter(value = 2) public String name;
+
+    @Parameters(name = "{2}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.create(Equivalence.DEFAULT), "EconomicMap"},
+                        new Object[]{EconomicMap.create(Equivalence.IDENTITY), EconomicMap.create(Equivalence.IDENTITY), "EconomicMap(IDENTITY)"},
+                        new Object[]{EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE),
+                                        "EconomicMap(IDENTITY_WITH_SYSTEM_HASHCODE)"},
+                        new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.wrapMap(new LinkedHashMap<>()), "EconomicMap<->wrapMap"},
+                        new Object[]{EconomicMap.wrapMap(new LinkedHashMap<>()), EconomicMap.wrapMap(new LinkedHashMap<>()), "wrapMap"});
+    }
+
+    private static int[] createRandomRange(Random random, int count) {
+        int[] result = new int[count];
+        for (int i = 0; i < count; ++i) {
+            int range = random.nextInt(14);
+            if (range == 0 || range > 10) {
+                range = Integer.MAX_VALUE;
+            } else if (range == 10) {
+                range = 100;
+            }
+            result[i] = range;
+        }
+        return result;
+    }
+
+    private static final class BadHashClass {
+        private int value;
+
+        BadHashClass(int randomInt) {
+            this.value = randomInt;
+        }
+
+        @Override
+        public int hashCode() {
+            return 0;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            if (other instanceof BadHashClass) {
+                BadHashClass badHashClass = (BadHashClass) other;
+                return badHashClass.value == value;
+            }
+            return false;
+        }
+    }
+
+    interface MapAction {
+        Object perform(EconomicMap<Object, Object> map, int randomInt);
+    }
+
+    static final Object EXISTING_VALUE = new Object();
+
+    static final MapAction[] INCREASE_ACTIONS = new MapAction[]{
+                    (map, randomInt) -> map.put(randomInt, "value"),
+                    (map, randomInt) -> map.get(randomInt)
+    };
+
+    static final MapAction[] ACTIONS = new MapAction[]{
+                    (map, randomInt) -> map.removeKey(randomInt),
+                    (map, randomInt) -> map.put(randomInt, "value"),
+                    (map, randomInt) -> map.put(randomInt, null),
+                    (map, randomInt) -> map.put(EXISTING_VALUE, randomInt),
+                    (map, randomInt) -> {
+                        if (randomInt == 0) {
+                            map.clear();
+                        }
+                        return map.isEmpty();
+                    },
+                    (map, randomInt) -> map.containsKey(randomInt),
+                    (map, randomInt) -> map.get(randomInt),
+                    (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"),
+                    (map, randomInt) -> {
+                        if (randomInt == 0) {
+                            map.replaceAll((key, value) -> Objects.toString(value) + "!");
+                        }
+                        return map.isEmpty();
+                    }
+
+    };
+
+    @Test
+    public void testVeryLarge() {
+        testMap.clear();
+        referenceMap.clear();
+
+        Random random = new Random(0);
+        for (int i = 0; i < 200000; ++i) {
+            for (int j = 0; j < INCREASE_ACTIONS.length; ++j) {
+                int nextInt = random.nextInt(10000000);
+                MapAction action = INCREASE_ACTIONS[j];
+                Object result = action.perform(testMap, nextInt);
+                Object referenceResult = action.perform(referenceMap, nextInt);
+                Assert.assertEquals(result, referenceResult);
+            }
+        }
+    }
+
+    /**
+     * Tests a sequence of random operations on the map.
+     */
+    @Test
+    public void testAddRemove() {
+        testMap.clear();
+        referenceMap.clear();
+
+        for (int seed = 0; seed < 10; ++seed) {
+            Random random = new Random(seed);
+            int[] ranges = createRandomRange(random, ACTIONS.length);
+            int value = random.nextInt(10000);
+            for (int i = 0; i < value; ++i) {
+                for (int j = 0; j < ACTIONS.length; ++j) {
+                    if (random.nextInt(ranges[j]) == 0) {
+                        int nextInt = random.nextInt(100);
+                        MapAction action = ACTIONS[j];
+                        Object result = action.perform(testMap, nextInt);
+                        Object referenceResult = action.perform(referenceMap, nextInt);
+                        Assert.assertEquals(result, referenceResult);
+                        if (j % 100 == 0) {
+                            checkEquality(testMap, referenceMap);
+                        }
+                    }
+                }
+
+                if (random.nextInt(20) == 0) {
+                    removeElement(random.nextInt(100), testMap, referenceMap);
+                }
+            }
+        }
+    }
+
+    private static void removeElement(int index, EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
+        Assert.assertEquals(referenceMap.size(), map.size());
+        MapCursor<?, ?> cursor = map.getEntries();
+        MapCursor<?, ?> referenceCursor = referenceMap.getEntries();
+        int z = 0;
+        while (cursor.advance()) {
+            Assert.assertTrue(referenceCursor.advance());
+            Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
+            Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
+            if (index == z) {
+                cursor.remove();
+                referenceCursor.remove();
+            }
+            ++z;
+        }
+
+        Assert.assertFalse(referenceCursor.advance());
+    }
+
+    private static void checkEquality(EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
+        Assert.assertEquals(referenceMap.size(), map.size());
+
+        // Check entries.
+        UnmodifiableMapCursor<?, ?> cursor = map.getEntries();
+        UnmodifiableMapCursor<?, ?> referenceCursor = referenceMap.getEntries();
+        while (cursor.advance()) {
+            Assert.assertTrue(referenceCursor.advance());
+            Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
+            Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
+        }
+
+        // Check keys.
+        Iterator<?> iterator = map.getKeys().iterator();
+        Iterator<?> referenceIterator = referenceMap.getKeys().iterator();
+        while (iterator.hasNext()) {
+            Assert.assertTrue(referenceIterator.hasNext());
+            Assert.assertEquals(iterator.next(), referenceIterator.next());
+        }
+
+        // Check values.
+        iterator = map.getValues().iterator();
+        referenceIterator = referenceMap.getValues().iterator();
+        while (iterator.hasNext()) {
+            Assert.assertTrue(referenceIterator.hasNext());
+            Assert.assertEquals(iterator.next(), referenceIterator.next());
+        }
+        Assert.assertFalse(referenceIterator.hasNext());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicMapTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.LinkedHashMap;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicMapTest {
+
+    @Test
+    public void testMapGetDefault() {
+        EconomicMap<Integer, Integer> map = EconomicMap.create();
+        map.put(0, 1);
+        Assert.assertEquals(map.get(0, 2), Integer.valueOf(1));
+        Assert.assertEquals(map.get(1, 2), Integer.valueOf(2));
+    }
+
+    @Test
+    public void testMapPutAll() {
+        EconomicMap<Integer, Integer> map = EconomicMap.create();
+        EconomicMap<Integer, Integer> newMap = EconomicMap.wrapMap(new LinkedHashMap<>());
+        newMap.put(1, 1);
+        newMap.put(2, 4);
+        map.putAll(newMap);
+        Assert.assertEquals(map.size(), 2);
+
+        UnmodifiableEconomicMap<Integer, Integer> unmodifiableEconomicMap = EconomicMap.create(newMap);
+
+        map.removeKey(1);
+        map.put(2, 2);
+        map.put(3, 9);
+
+        map.putAll(unmodifiableEconomicMap);
+        Assert.assertEquals(map.size(), 3);
+        Assert.assertEquals(map.get(2), Integer.valueOf(4));
+    }
+
+    @Test
+    public void testToString() {
+        EconomicMap<Integer, Integer> map = EconomicMap.create();
+        map.put(0, 0);
+        map.put(1, 1);
+        Assert.assertEquals(map.toString(), "map(size=2, {(0,0),(1,1)})");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EconomicSetTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,148 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EconomicSetTest {
+
+    @Test
+    public void testUtilities() {
+        EconomicSet<Integer> set = EconomicSet.create(0);
+        set.add(0);
+        Assert.assertTrue(set.add(1));
+        Assert.assertEquals(set.size(), 2);
+        Assert.assertFalse(set.add(1));
+        Assert.assertEquals(set.size(), 2);
+        set.remove(1);
+        Assert.assertEquals(set.size(), 1);
+        set.remove(2);
+        Assert.assertEquals(set.size(), 1);
+        Assert.assertTrue(set.add(1));
+        set.clear();
+        Assert.assertEquals(set.size(), 0);
+    }
+
+    @Test
+    public void testAddAll() {
+        EconomicSet<Integer> set = EconomicSet.create();
+        set.addAll(Arrays.asList(0, 1, 0));
+        Assert.assertEquals(set.size(), 2);
+
+        EconomicSet<Integer> newSet = EconomicSet.create();
+        newSet.addAll(Arrays.asList(1, 2));
+        Assert.assertEquals(newSet.size(), 2);
+        newSet.addAll(set);
+        Assert.assertEquals(newSet.size(), 3);
+    }
+
+    @Test
+    public void testRemoveAll() {
+        EconomicSet<Integer> set = EconomicSet.create();
+        set.addAll(Arrays.asList(0, 1));
+
+        set.removeAll(Arrays.asList(1, 2));
+        Assert.assertEquals(set.size(), 1);
+
+        set.removeAll(EconomicSet.create(set));
+        Assert.assertEquals(set.size(), 0);
+    }
+
+    @Test
+    public void testRetainAll() {
+        EconomicSet<Integer> set = EconomicSet.create();
+        set.addAll(Arrays.asList(0, 1, 2));
+
+        EconomicSet<Integer> newSet = EconomicSet.create();
+        newSet.addAll(Arrays.asList(2, 3));
+
+        set.retainAll(newSet);
+        Assert.assertEquals(set.size(), 1);
+    }
+
+    @Test
+    public void testToArray() {
+        EconomicSet<Integer> set = EconomicSet.create();
+        set.addAll(Arrays.asList(0, 1));
+        Assert.assertArrayEquals(set.toArray(new Integer[2]), new Integer[]{0, 1});
+    }
+
+    @Test
+    public void testToString() {
+        EconomicSet<Integer> set = EconomicSet.create();
+        set.addAll(Arrays.asList(0, 1));
+        Assert.assertEquals(set.toString(), "set(size=2, {0,1})");
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testToUnalignedArray() {
+        Assert.assertArrayEquals(EconomicSet.create().toArray(new Integer[2]), new Integer[0]);
+    }
+
+    @Test
+    public void testSetRemoval() {
+        ArrayList<Integer> initialList = new ArrayList<>();
+        ArrayList<Integer> removalList = new ArrayList<>();
+        ArrayList<Integer> finalList = new ArrayList<>();
+        EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
+        set.add(1);
+        set.add(2);
+        set.add(3);
+        set.add(4);
+        set.add(5);
+        set.add(6);
+        set.add(7);
+        set.add(8);
+        set.add(9);
+        Iterator<Integer> i1 = set.iterator();
+        while (i1.hasNext()) {
+            initialList.add(i1.next());
+        }
+        int size = 0;
+        Iterator<Integer> i2 = set.iterator();
+        while (i2.hasNext()) {
+            Integer elem = i2.next();
+            if (size++ < 8) {
+                i2.remove();
+            }
+            removalList.add(elem);
+        }
+        Iterator<Integer> i3 = set.iterator();
+        while (i3.hasNext()) {
+            finalList.add(i3.next());
+        }
+        Assert.assertEquals(initialList, removalList);
+        Assert.assertEquals(1, finalList.size());
+        Assert.assertEquals(new Integer(9), finalList.get(0));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/EquivalenceTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import jdk.internal.vm.compiler.collections.Equivalence;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class EquivalenceTest {
+
+    private static final String TEST_STRING = "Graal";
+    private static final String TEST_STRING2 = "Graal2";
+
+    @Test
+    public void testDEFAULT() {
+        Assert.assertTrue(Equivalence.DEFAULT.equals(TEST_STRING, new String(TEST_STRING)));
+        Assert.assertEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(new String(TEST_STRING)));
+        Assert.assertFalse(Equivalence.DEFAULT.equals(TEST_STRING, TEST_STRING2));
+        Assert.assertNotEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(TEST_STRING2));
+    }
+
+    @Test
+    public void testIDENTITY() {
+        Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, new String(TEST_STRING)));
+        Assert.assertEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(new String(TEST_STRING)));
+        Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, TEST_STRING2));
+        Assert.assertNotEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(TEST_STRING2));
+    }
+
+    @Test
+    public void testIDENTITYWITHSYSTEMHASHCODE() {
+        Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, new String(TEST_STRING)));
+        Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(new String(TEST_STRING)));
+        Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, TEST_STRING2));
+        Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING2));
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections.test/src/jdk/internal/vm/compiler/collections/test/PairTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections.test;
+
+import jdk.internal.vm.compiler.collections.Pair;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class PairTest {
+
+    @Test
+    public void testCreate() {
+        Assert.assertEquals(Pair.create(null, null), Pair.empty());
+        Assert.assertNotEquals(Pair.create(null, null), null);
+        Assert.assertEquals(Pair.createLeft(null), Pair.empty());
+        Assert.assertEquals(Pair.createRight(null), Pair.empty());
+        Assert.assertEquals(Pair.create(1, null), Pair.createLeft(1));
+        Assert.assertEquals(Pair.create(null, 1), Pair.createRight(1));
+    }
+
+    @Test
+    public void testUtilities() {
+        Pair<Integer, Integer> pair = Pair.create(1, null);
+        Assert.assertEquals(pair.getLeft(), Integer.valueOf(1));
+        Assert.assertEquals(pair.getRight(), null);
+        Assert.assertEquals(pair.toString(), "(1, null)");
+        Assert.assertEquals(pair.hashCode(), Pair.createLeft(1).hashCode());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMap.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.function.BiFunction;
+
+/**
+ * Memory efficient map data structure.
+ *
+ * @since 1.0
+ */
+public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
+
+    /**
+     * Associates {@code value} with {@code key} in this map. If the map previously contained a
+     * mapping for {@code key}, the old value is replaced by {@code value}.
+     *
+     * @return the previous value associated with {@code key}, or {@code null} if there was no
+     *         mapping for {@code key}.
+     * @since 1.0
+     */
+    V put(K key, V value);
+
+    /**
+     * Copies all of the mappings from {@code other} to this map.
+     *
+     * @since 1.0
+     */
+    default void putAll(EconomicMap<K, V> other) {
+        MapCursor<K, V> e = other.getEntries();
+        while (e.advance()) {
+            put(e.getKey(), e.getValue());
+        }
+    }
+
+    /**
+     * Copies all of the mappings from {@code other} to this map.
+     *
+     * @since 1.0
+     */
+    default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
+        UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
+        while (entry.advance()) {
+            put(entry.getKey(), entry.getValue());
+        }
+    }
+
+    /**
+     * Removes all of the mappings from this map. The map will be empty after this call returns.
+     *
+     * @since 1.0
+     */
+    void clear();
+
+    /**
+     * Removes the mapping for {@code key} from this map if it is present. The map will not contain
+     * a mapping for {@code key} once the call returns.
+     *
+     * @return the previous value associated with {@code key}, or {@code null} if there was no
+     *         mapping for {@code key}.
+     * @since 1.0
+     */
+    V removeKey(K key);
+
+    /**
+     * Returns a {@link MapCursor} view of the mappings contained in this map.
+     *
+     * @since 1.0
+     */
+    @Override
+    MapCursor<K, V> getEntries();
+
+    /**
+     * Replaces each entry's value with the result of invoking {@code function} on that entry until
+     * all entries have been processed or the function throws an exception. Exceptions thrown by the
+     * function are relayed to the caller.
+     *
+     * @since 1.0
+     */
+    void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
+
+    /**
+     * Creates a new map that guarantees insertion order on the key set with the default
+     * {@link Equivalence#DEFAULT} comparison strategy for keys.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> create() {
+        return EconomicMap.create(Equivalence.DEFAULT);
+    }
+
+    /**
+     * Creates a new map that guarantees insertion order on the key set with the default
+     * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
+     * capacity.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> create(int initialCapacity) {
+        return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
+    }
+
+    /**
+     * Creates a new map that guarantees insertion order on the key set with the given comparison
+     * strategy for keys.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
+        return EconomicMapImpl.create(strategy, false);
+    }
+
+    /**
+     * Creates a new map that guarantees insertion order on the key set with the default
+     * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
+     * specified existing map.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
+        return EconomicMap.create(Equivalence.DEFAULT, m);
+    }
+
+    /**
+     * Creates a new map that guarantees insertion order on the key set and copies all elements from
+     * the specified existing map.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
+        return EconomicMapImpl.create(strategy, m, false);
+    }
+
+    /**
+     * Creates a new map that guarantees insertion order on the key set and initializes with a
+     * specified capacity.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
+        return EconomicMapImpl.create(strategy, initialCapacity, false);
+    }
+
+    /**
+     * Wraps an existing {@link Map} as an {@link EconomicMap}.
+     *
+     * @since 1.0
+     */
+    static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
+        return new EconomicMap<K, V>() {
+
+            @Override
+            public V get(K key) {
+                V result = map.get(key);
+                return result;
+            }
+
+            @Override
+            public V put(K key, V value) {
+                V result = map.put(key, value);
+                return result;
+            }
+
+            @Override
+            public int size() {
+                int result = map.size();
+                return result;
+            }
+
+            @Override
+            public boolean containsKey(K key) {
+                return map.containsKey(key);
+            }
+
+            @Override
+            public void clear() {
+                map.clear();
+            }
+
+            @Override
+            public V removeKey(K key) {
+                V result = map.remove(key);
+                return result;
+            }
+
+            @Override
+            public Iterable<V> getValues() {
+                return map.values();
+            }
+
+            @Override
+            public Iterable<K> getKeys() {
+                return map.keySet();
+            }
+
+            @Override
+            public boolean isEmpty() {
+                return map.isEmpty();
+            }
+
+            @Override
+            public MapCursor<K, V> getEntries() {
+                Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
+                return new MapCursor<K, V>() {
+
+                    private Map.Entry<K, V> current;
+
+                    @Override
+                    public boolean advance() {
+                        boolean result = iterator.hasNext();
+                        if (result) {
+                            current = iterator.next();
+                        }
+
+                        return result;
+                    }
+
+                    @Override
+                    public K getKey() {
+                        return current.getKey();
+                    }
+
+                    @Override
+                    public V getValue() {
+                        return current.getValue();
+                    }
+
+                    @Override
+                    public void remove() {
+                        iterator.remove();
+                    }
+                };
+            }
+
+            @Override
+            public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+                map.replaceAll(function);
+            }
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicMapImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,857 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.BiFunction;
+
+/**
+ * Implementation of a map with a memory-efficient structure that always preserves insertion order
+ * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal
+ * {@link #INITIAL_CAPACITY} or smaller 256.
+ *
+ * The key/value pairs are kept in an expanding flat object array with keys at even indices and
+ * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there
+ * is no additional hash data structure and comparisons are done via linear checking of the
+ * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an
+ * object identity comparison), this limit below which the map is without an actual hash table is
+ * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}.
+ *
+ * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash
+ * array where an entry of 0 means no hit and otherwise denotes the entry number in the
+ * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit
+ * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of
+ * integer values in other cases.
+ *
+ * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take
+ * the place of the values in the {@link #entries} array.
+ *
+ * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the
+ * map falls below a specific threshold, the map will be compressed via the
+ * {@link #maybeCompress(int)} method.
+ */
+final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
+
+    /**
+     * Initial number of key/value pair entries that is allocated in the first entries array.
+     */
+    private static final int INITIAL_CAPACITY = 4;
+
+    /**
+     * Maximum number of entries that are moved linearly forward if a key is removed.
+     */
+    private static final int COMPRESS_IMMEDIATE_CAPACITY = 8;
+
+    /**
+     * Minimum number of key/value pair entries added when the entries array is increased in size.
+     */
+    private static final int MIN_CAPACITY_INCREASE = 8;
+
+    /**
+     * Number of entries above which a hash table is created.
+     */
+    private static final int HASH_THRESHOLD = 4;
+
+    /**
+     * Number of entries above which a hash table is created when equality can be checked with
+     * object identity.
+     */
+    private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8;
+
+    /**
+     * Maximum number of entries allowed in the map.
+     */
+    private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1;
+
+    /**
+     * Number of entries above which more than 1 byte is necessary for the hash index.
+     */
+    private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1);
+
+    /**
+     * Number of entries above which more than 2 bytes are are necessary for the hash index.
+     */
+    private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE);
+
+    /**
+     * Total number of entries (actual entries plus deleted entries).
+     */
+    private int totalEntries;
+
+    /**
+     * Number of deleted entries.
+     */
+    private int deletedEntries;
+
+    /**
+     * Entries array with even indices storing keys and odd indices storing values.
+     */
+    private Object[] entries;
+
+    /**
+     * Hash array that is interpreted either as byte or short or int array depending on number of
+     * map entries.
+     */
+    private byte[] hashArray;
+
+    /**
+     * The strategy used for comparing keys or {@code null} for denoting special strategy
+     * {@link Equivalence#IDENTITY}.
+     */
+    private final Equivalence strategy;
+
+    /**
+     * Intercept method for debugging purposes.
+     */
+    private static <K, V> EconomicMapImpl<K, V> intercept(EconomicMapImpl<K, V> map) {
+        return map;
+    }
+
+    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, boolean isSet) {
+        return intercept(new EconomicMapImpl<>(strategy, isSet));
+    }
+
+    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, int initialCapacity, boolean isSet) {
+        return intercept(new EconomicMapImpl<>(strategy, initialCapacity, isSet));
+    }
+
+    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
+        return intercept(new EconomicMapImpl<>(strategy, other, isSet));
+    }
+
+    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
+        return intercept(new EconomicMapImpl<>(strategy, other, isSet));
+    }
+
+    private EconomicMapImpl(Equivalence strategy, boolean isSet) {
+        if (strategy == Equivalence.IDENTITY) {
+            this.strategy = null;
+        } else {
+            this.strategy = strategy;
+        }
+        this.isSet = isSet;
+    }
+
+    private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) {
+        this(strategy, isSet);
+        init(initialCapacity);
+    }
+
+    private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
+        this(strategy, isSet);
+        if (!initFrom(other)) {
+            init(other.size());
+            putAll(other);
+        }
+    }
+
+    private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
+        this(strategy, isSet);
+        if (!initFrom(other)) {
+            init(other.size());
+            addAll(other);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private boolean initFrom(Object o) {
+        if (o instanceof EconomicMapImpl) {
+            EconomicMapImpl<K, V> otherMap = (EconomicMapImpl<K, V>) o;
+            // We are only allowed to directly copy if the strategies of the two maps are the same.
+            if (strategy == otherMap.strategy) {
+                totalEntries = otherMap.totalEntries;
+                deletedEntries = otherMap.deletedEntries;
+                if (otherMap.entries != null) {
+                    entries = otherMap.entries.clone();
+                }
+                if (otherMap.hashArray != null) {
+                    hashArray = otherMap.hashArray.clone();
+                }
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void init(int size) {
+        if (size > INITIAL_CAPACITY) {
+            entries = new Object[size << 1];
+        }
+    }
+
+    /**
+     * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from
+     * other map on construction.
+     */
+    private static final class CollisionLink {
+
+        CollisionLink(Object value, int next) {
+            this.value = value;
+            this.next = next;
+        }
+
+        final Object value;
+
+        /**
+         * Index plus one of the next entry in the collision link chain.
+         */
+        final int next;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public V get(K key) {
+        Objects.requireNonNull(key);
+
+        int index = find(key);
+        if (index != -1) {
+            return (V) getValue(index);
+        }
+        return null;
+    }
+
+    private int find(K key) {
+        if (hasHashArray()) {
+            return findHash(key);
+        } else {
+            return findLinear(key);
+        }
+    }
+
+    private int findLinear(K key) {
+        for (int i = 0; i < totalEntries; i++) {
+            Object entryKey = entries[i << 1];
+            if (entryKey != null && compareKeys(key, entryKey)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private boolean compareKeys(Object key, Object entryKey) {
+        if (key == entryKey) {
+            return true;
+        }
+        if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+            if (strategy == Equivalence.DEFAULT) {
+                return key.equals(entryKey);
+            } else {
+                return strategy.equals(key, entryKey);
+            }
+        }
+        return false;
+    }
+
+    private int findHash(K key) {
+        int index = getHashArray(getHashIndex(key)) - 1;
+        if (index != -1) {
+            Object entryKey = getKey(index);
+            if (compareKeys(key, entryKey)) {
+                return index;
+            } else {
+                Object entryValue = getRawValue(index);
+                if (entryValue instanceof CollisionLink) {
+                    return findWithCollision(key, (CollisionLink) entryValue);
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    private int findWithCollision(K key, CollisionLink initialEntryValue) {
+        int index;
+        Object entryKey;
+        CollisionLink entryValue = initialEntryValue;
+        while (true) {
+            CollisionLink collisionLink = entryValue;
+            index = collisionLink.next;
+            entryKey = getKey(index);
+            if (compareKeys(key, entryKey)) {
+                return index;
+            } else {
+                Object value = getRawValue(index);
+                if (value instanceof CollisionLink) {
+                    entryValue = (CollisionLink) getRawValue(index);
+                } else {
+                    return -1;
+                }
+            }
+        }
+    }
+
+    private int getHashArray(int index) {
+        if (entries.length < LARGE_HASH_THRESHOLD) {
+            return (hashArray[index] & 0xFF);
+        } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+            int adjustedIndex = index << 1;
+            return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8);
+        } else {
+            int adjustedIndex = index << 2;
+            return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24);
+        }
+    }
+
+    private void setHashArray(int index, int value) {
+        if (entries.length < LARGE_HASH_THRESHOLD) {
+            hashArray[index] = (byte) value;
+        } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+            int adjustedIndex = index << 1;
+            hashArray[adjustedIndex] = (byte) value;
+            hashArray[adjustedIndex + 1] = (byte) (value >> 8);
+        } else {
+            int adjustedIndex = index << 2;
+            hashArray[adjustedIndex] = (byte) value;
+            hashArray[adjustedIndex + 1] = (byte) (value >> 8);
+            hashArray[adjustedIndex + 2] = (byte) (value >> 16);
+            hashArray[adjustedIndex + 3] = (byte) (value >> 24);
+        }
+    }
+
+    private int findAndRemoveHash(Object key) {
+        int hashIndex = getHashIndex(key);
+        int index = getHashArray(hashIndex) - 1;
+        if (index != -1) {
+            Object entryKey = getKey(index);
+            if (compareKeys(key, entryKey)) {
+                Object value = getRawValue(index);
+                int nextIndex = -1;
+                if (value instanceof CollisionLink) {
+                    CollisionLink collisionLink = (CollisionLink) value;
+                    nextIndex = collisionLink.next;
+                }
+                setHashArray(hashIndex, nextIndex + 1);
+                return index;
+            } else {
+                Object entryValue = getRawValue(index);
+                if (entryValue instanceof CollisionLink) {
+                    return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index);
+                }
+            }
+        }
+
+        return -1;
+    }
+
+    private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) {
+        int index;
+        Object entryKey;
+        CollisionLink entryValue = initialEntryValue;
+        int lastIndex = initialIndexValue;
+        while (true) {
+            CollisionLink collisionLink = entryValue;
+            index = collisionLink.next;
+            entryKey = getKey(index);
+            if (compareKeys(key, entryKey)) {
+                Object value = getRawValue(index);
+                if (value instanceof CollisionLink) {
+                    CollisionLink thisCollisionLink = (CollisionLink) value;
+                    setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next));
+                } else {
+                    setRawValue(lastIndex, collisionLink.value);
+                }
+                return index;
+            } else {
+                Object value = getRawValue(index);
+                if (value instanceof CollisionLink) {
+                    entryValue = (CollisionLink) getRawValue(index);
+                    lastIndex = index;
+                } else {
+                    return -1;
+                }
+            }
+        }
+    }
+
+    private int getHashIndex(Object key) {
+        int hash;
+        if (strategy != null && strategy != Equivalence.DEFAULT) {
+            if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+                hash = System.identityHashCode(key);
+            } else {
+                hash = strategy.hashCode(key);
+            }
+        } else {
+            hash = key.hashCode();
+        }
+        hash = hash ^ (hash >>> 16);
+        return hash & (getHashTableSize() - 1);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public V put(K key, V value) {
+        if (key == null) {
+            throw new UnsupportedOperationException("null not supported as key!");
+        }
+        int index = find(key);
+        if (index != -1) {
+            Object oldValue = getValue(index);
+            setValue(index, value);
+            return (V) oldValue;
+        }
+
+        int nextEntryIndex = totalEntries;
+        if (entries == null) {
+            entries = new Object[INITIAL_CAPACITY << 1];
+        } else if (entries.length == nextEntryIndex << 1) {
+            grow();
+
+            assert entries.length > totalEntries << 1;
+            // Can change if grow is actually compressing.
+            nextEntryIndex = totalEntries;
+        }
+
+        setKey(nextEntryIndex, key);
+        setValue(nextEntryIndex, value);
+        totalEntries++;
+
+        if (hasHashArray()) {
+            // Rehash on collision if hash table is more than three quarters full.
+            boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1)));
+            putHashEntry(key, nextEntryIndex, rehashOnCollision);
+        } else if (totalEntries > getHashThreshold()) {
+            createHash();
+        }
+
+        return null;
+    }
+
+    /**
+     * Number of entries above which a hash table should be constructed.
+     */
+    private int getHashThreshold() {
+        if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
+            return HASH_THRESHOLD_IDENTITY_COMPARE;
+        } else {
+            return HASH_THRESHOLD;
+        }
+    }
+
+    private void grow() {
+        int entriesLength = entries.length;
+        int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2);
+        if (newSize > MAX_ELEMENT_COUNT) {
+            throw new UnsupportedOperationException("map grown too large!");
+        }
+        Object[] newEntries = new Object[newSize << 1];
+        System.arraycopy(entries, 0, newEntries, 0, entriesLength);
+        entries = newEntries;
+        if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) ||
+                        (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) {
+            // Rehash in order to change number of bits reserved for hash indices.
+            createHash();
+        }
+    }
+
+    /**
+     * Compresses the graph if there is a large number of deleted entries and returns the translated
+     * new next index.
+     */
+    private int maybeCompress(int nextIndex) {
+        if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) {
+            return compressLarge(nextIndex);
+        }
+        return nextIndex;
+    }
+
+    /**
+     * Compresses the graph and returns the translated new next index.
+     */
+    private int compressLarge(int nextIndex) {
+        int size = INITIAL_CAPACITY;
+        int remaining = totalEntries - deletedEntries;
+
+        while (size <= remaining) {
+            size += Math.max(MIN_CAPACITY_INCREASE, size >> 1);
+        }
+
+        Object[] newEntries = new Object[size << 1];
+        int z = 0;
+        int newNextIndex = remaining;
+        for (int i = 0; i < totalEntries; ++i) {
+            Object key = getKey(i);
+            if (i == nextIndex) {
+                newNextIndex = z;
+            }
+            if (key != null) {
+                newEntries[z << 1] = key;
+                newEntries[(z << 1) + 1] = getValue(i);
+                z++;
+            }
+        }
+
+        this.entries = newEntries;
+        totalEntries = z;
+        deletedEntries = 0;
+        if (z <= getHashThreshold()) {
+            this.hashArray = null;
+        } else {
+            createHash();
+        }
+        return newNextIndex;
+    }
+
+    private int getHashTableSize() {
+        if (entries.length < LARGE_HASH_THRESHOLD) {
+            return hashArray.length;
+        } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
+            return hashArray.length >> 1;
+        } else {
+            return hashArray.length >> 2;
+        }
+    }
+
+    private void createHash() {
+        int entryCount = size();
+
+        // Calculate smallest 2^n that is greater number of entries.
+        int size = getHashThreshold();
+        while (size <= entryCount) {
+            size <<= 1;
+        }
+
+        // Give extra size to avoid collisions.
+        size <<= 1;
+
+        if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) {
+            // Every entry has 4 bytes.
+            size <<= 2;
+        } else if (this.entries.length >= LARGE_HASH_THRESHOLD) {
+            // Every entry has 2 bytes.
+            size <<= 1;
+        } else {
+            // Entries are very small => give extra size to further reduce collisions.
+            size <<= 1;
+        }
+
+        hashArray = new byte[size];
+        for (int i = 0; i < totalEntries; i++) {
+            Object entryKey = getKey(i);
+            if (entryKey != null) {
+                putHashEntry(entryKey, i, false);
+            }
+        }
+    }
+
+    private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) {
+        int hashIndex = getHashIndex(key);
+        int oldIndex = getHashArray(hashIndex) - 1;
+        if (oldIndex != -1 && rehashOnCollision) {
+            this.createHash();
+            return;
+        }
+        setHashArray(hashIndex, entryIndex + 1);
+        Object value = getRawValue(entryIndex);
+        if (oldIndex != -1) {
+            assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle";
+            if (value instanceof CollisionLink) {
+                CollisionLink collisionLink = (CollisionLink) value;
+                setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex));
+            } else {
+                setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex));
+            }
+        } else {
+            if (value instanceof CollisionLink) {
+                CollisionLink collisionLink = (CollisionLink) value;
+                setRawValue(entryIndex, collisionLink.value);
+            }
+        }
+    }
+
+    @Override
+    public int size() {
+        return totalEntries - deletedEntries;
+    }
+
+    @Override
+    public boolean containsKey(K key) {
+        return find(key) != -1;
+    }
+
+    @Override
+    public void clear() {
+        entries = null;
+        hashArray = null;
+        totalEntries = deletedEntries = 0;
+    }
+
+    private boolean hasHashArray() {
+        return hashArray != null;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public V removeKey(K key) {
+        if (key == null) {
+            throw new UnsupportedOperationException("null not supported as key!");
+        }
+        int index;
+        if (hasHashArray()) {
+            index = this.findAndRemoveHash(key);
+        } else {
+            index = this.findLinear(key);
+        }
+
+        if (index != -1) {
+            Object value = getValue(index);
+            remove(index);
+            return (V) value;
+        }
+        return null;
+    }
+
+    /**
+     * Removes the element at the specific index and returns the index of the next element. This can
+     * be a different value if graph compression was triggered.
+     */
+    private int remove(int indexToRemove) {
+        int index = indexToRemove;
+        int entriesAfterIndex = totalEntries - index - 1;
+        int result = index + 1;
+
+        // Without hash array, compress immediately.
+        if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) {
+            while (index < totalEntries - 1) {
+                setKey(index, getKey(index + 1));
+                setRawValue(index, getRawValue(index + 1));
+                index++;
+            }
+            result--;
+        }
+
+        setKey(index, null);
+        setRawValue(index, null);
+        if (index == totalEntries - 1) {
+            // Make sure last element is always non-null.
+            totalEntries--;
+            while (index > 0 && getKey(index - 1) == null) {
+                totalEntries--;
+                deletedEntries--;
+                index--;
+            }
+        } else {
+            deletedEntries++;
+            result = maybeCompress(result);
+        }
+
+        return result;
+    }
+
+    private abstract class SparseMapIterator<E> implements Iterator<E> {
+
+        protected int current;
+
+        @Override
+        public boolean hasNext() {
+            return current < totalEntries;
+        }
+
+        @Override
+        public void remove() {
+            if (hasHashArray()) {
+                EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1));
+            }
+            current = EconomicMapImpl.this.remove(current - 1);
+        }
+    }
+
+    @Override
+    public Iterable<V> getValues() {
+        return new Iterable<V>() {
+            @Override
+            public Iterator<V> iterator() {
+                return new SparseMapIterator<V>() {
+                    @SuppressWarnings("unchecked")
+                    @Override
+                    public V next() {
+                        Object result;
+                        while (true) {
+                            result = getValue(current);
+                            if (result == null && getKey(current) == null) {
+                                // values can be null, double-check if key is also null
+                                current++;
+                            } else {
+                                current++;
+                                break;
+                            }
+                        }
+                        return (V) result;
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public Iterable<K> getKeys() {
+        return this;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return this.size() == 0;
+    }
+
+    @Override
+    public MapCursor<K, V> getEntries() {
+        return new MapCursor<K, V>() {
+            int current = -1;
+
+            @Override
+            public boolean advance() {
+                current++;
+                if (current >= totalEntries) {
+                    return false;
+                } else {
+                    while (EconomicMapImpl.this.getKey(current) == null) {
+                        // Skip over null entries
+                        current++;
+                    }
+                    return true;
+                }
+            }
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public K getKey() {
+                return (K) EconomicMapImpl.this.getKey(current);
+            }
+
+            @SuppressWarnings("unchecked")
+            @Override
+            public V getValue() {
+                return (V) EconomicMapImpl.this.getValue(current);
+            }
+
+            @Override
+            public void remove() {
+                if (hasHashArray()) {
+                    EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current));
+                }
+                current = EconomicMapImpl.this.remove(current) - 1;
+            }
+        };
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+        for (int i = 0; i < totalEntries; i++) {
+            Object entryKey = getKey(i);
+            if (entryKey != null) {
+                Object newValue = function.apply((K) entryKey, (V) getValue(i));
+                setValue(i, newValue);
+            }
+        }
+    }
+
+    private Object getKey(int index) {
+        return entries[index << 1];
+    }
+
+    private void setKey(int index, Object newValue) {
+        entries[index << 1] = newValue;
+    }
+
+    private void setValue(int index, Object newValue) {
+        Object oldValue = getRawValue(index);
+        if (oldValue instanceof CollisionLink) {
+            CollisionLink collisionLink = (CollisionLink) oldValue;
+            setRawValue(index, new CollisionLink(newValue, collisionLink.next));
+        } else {
+            setRawValue(index, newValue);
+        }
+    }
+
+    private void setRawValue(int index, Object newValue) {
+        entries[(index << 1) + 1] = newValue;
+    }
+
+    private Object getRawValue(int index) {
+        return entries[(index << 1) + 1];
+    }
+
+    private Object getValue(int index) {
+        Object object = getRawValue(index);
+        if (object instanceof CollisionLink) {
+            return ((CollisionLink) object).value;
+        }
+        return object;
+    }
+
+    private final boolean isSet;
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {");
+        String sep = "";
+        MapCursor<K, V> cursor = getEntries();
+        while (cursor.advance()) {
+            builder.append(sep);
+            if (isSet) {
+                builder.append(cursor.getKey());
+            } else {
+                builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append(")");
+            }
+            sep = ",";
+        }
+        builder.append("})");
+        return builder.toString();
+    }
+
+    @Override
+    public Iterator<K> iterator() {
+        return new SparseMapIterator<K>() {
+            @SuppressWarnings("unchecked")
+            @Override
+            public K next() {
+                Object result;
+                while ((result = getKey(current++)) == null) {
+                    // skip null entries
+                }
+                return (K) result;
+            }
+        };
+    }
+
+    @Override
+    public boolean contains(K element) {
+        return containsKey(element);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean add(K element) {
+        return put(element, (V) element) == null;
+    }
+
+    @Override
+    public void remove(K element) {
+        removeKey(element);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/EconomicSet.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Iterator;
+
+/**
+ * Memory efficient set data structure.
+ *
+ * @since 1.0
+ */
+public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
+
+    /**
+     * Adds {@code element} to this set if it is not already present.
+     *
+     * @return {@code true} if this set did not already contain {@code element}.
+     * @since 1.0
+     */
+    boolean add(E element);
+
+    /**
+     * Removes {@code element} from this set if it is present. This set will not contain
+     * {@code element} once the call returns.
+     *
+     * @since 1.0
+     */
+    void remove(E element);
+
+    /**
+     * Removes all of the elements from this set. The set will be empty after this call returns.
+     *
+     * @since 1.0
+     */
+    void clear();
+
+    /**
+     * Adds all of the elements in {@code other} to this set if they're not already present.
+     *
+     * @since 1.0
+     */
+    default void addAll(EconomicSet<E> other) {
+        addAll(other.iterator());
+    }
+
+    /**
+     * Adds all of the elements in {@code values} to this set if they're not already present.
+     *
+     * @since 1.0
+     */
+    default void addAll(Iterable<E> values) {
+        addAll(values.iterator());
+    }
+
+    /**
+     * Adds all of the elements enumerated by {@code iterator} to this set if they're not already
+     * present.
+     *
+     * @since 1.0
+     */
+    default void addAll(Iterator<E> iterator) {
+        while (iterator.hasNext()) {
+            add(iterator.next());
+        }
+    }
+
+    /**
+     * Removes from this set all of its elements that are contained in {@code other}.
+     *
+     * @since 1.0
+     */
+    default void removeAll(EconomicSet<E> other) {
+        removeAll(other.iterator());
+    }
+
+    /**
+     * Removes from this set all of its elements that are contained in {@code values}.
+     *
+     * @since 1.0
+     */
+    default void removeAll(Iterable<E> values) {
+        removeAll(values.iterator());
+    }
+
+    /**
+     * Removes from this set all of its elements that are enumerated by {@code iterator}.
+     *
+     * @since 1.0
+     */
+    default void removeAll(Iterator<E> iterator) {
+        while (iterator.hasNext()) {
+            remove(iterator.next());
+        }
+    }
+
+    /**
+     * Removes from this set all of its elements that are not contained in {@code other}.
+     *
+     * @since 1.0
+     */
+    default void retainAll(EconomicSet<E> other) {
+        Iterator<E> iterator = iterator();
+        while (iterator.hasNext()) {
+            E key = iterator.next();
+            if (!other.contains(key)) {
+                iterator.remove();
+            }
+        }
+    }
+
+    /**
+     * Creates a new set guaranteeing insertion order when iterating over its elements with the
+     * default {@link Equivalence#DEFAULT} comparison strategy.
+     *
+     * @since 1.0
+     */
+    static <E> EconomicSet<E> create() {
+        return EconomicSet.create(Equivalence.DEFAULT);
+    }
+
+    /**
+     * Creates a new set guaranteeing insertion order when iterating over its elements.
+     *
+     * @since 1.0
+     */
+    static <E> EconomicSet<E> create(Equivalence strategy) {
+        return EconomicMapImpl.create(strategy, true);
+    }
+
+    /**
+     * Creates a new set guaranteeing insertion order when iterating over its elements with the
+     * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
+     * specified collection.
+     *
+     * @since 1.0
+     */
+    static <E> EconomicSet<E> create(int initialCapacity) {
+        return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
+    }
+
+    /**
+     * Creates a new set guaranteeing insertion order when iterating over its elements with the
+     * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
+     * specified collection.
+     *
+     * @since 1.0
+     */
+    static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
+        return EconomicSet.create(Equivalence.DEFAULT, c);
+    }
+
+    /**
+     * Creates a new set guaranteeing insertion order when iterating over its elements and
+     * initializes with the given capacity.
+     *
+     * @since 1.0
+     */
+    static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
+        return EconomicMapImpl.create(strategy, initialCapacity, true);
+    }
+
+    /**
+     * Creates a new set guaranteeing insertion order when iterating over its elements and inserts
+     * all elements of the specified collection.
+     *
+     * @since 1.0
+     */
+    static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E> c) {
+        return EconomicMapImpl.create(strategy, c, true);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Equivalence.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
+ * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
+ *
+ * @since 1.0
+ */
+public abstract class Equivalence {
+
+    /**
+     * Default equivalence calling {@link #equals(Object)} to check equality and {@link #hashCode()}
+     * for obtaining hash values. Do not change the logic of this class as it may be inlined in
+     * other places.
+     *
+     * @since 1.0
+     */
+    public static final Equivalence DEFAULT = new Equivalence() {
+
+        @Override
+        public boolean equals(Object a, Object b) {
+            return a.equals(b);
+        }
+
+        @Override
+        public int hashCode(Object o) {
+            return o.hashCode();
+        }
+    };
+
+    /**
+     * Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining
+     * hash values. Do not change the logic of this class as it may be inlined in other places.
+     *
+     * @since 1.0
+     */
+    public static final Equivalence IDENTITY = new Equivalence() {
+
+        @Override
+        public boolean equals(Object a, Object b) {
+            return a == b;
+        }
+
+        @Override
+        public int hashCode(Object o) {
+            return o.hashCode();
+        }
+    };
+
+    /**
+     * Identity equivalence using {@code ==} to check equality and
+     * {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of
+     * this class as it may be inlined in other places.
+     *
+     * @since 1.0
+     */
+    public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
+
+        @Override
+        public boolean equals(Object a, Object b) {
+            return a == b;
+        }
+
+        @Override
+        public int hashCode(Object o) {
+            return System.identityHashCode(o);
+        }
+    };
+
+    /**
+     * Subclass for creating custom equivalence definitions.
+     *
+     * @since 1.0
+     */
+    protected Equivalence() {
+    }
+
+    /**
+     * Returns {@code true} if the non-{@code null} arguments are equal to each other and
+     * {@code false} otherwise.
+     *
+     * @since 1.0
+     */
+    public abstract boolean equals(Object a, Object b);
+
+    /**
+     * Returns the hash code of a non-{@code null} argument {@code o}.
+     *
+     * @since 1.0
+     */
+    public abstract int hashCode(Object o);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/MapCursor.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Cursor to iterate over a mutable map.
+ *
+ * @since 1.0
+ */
+public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
+    /**
+     * Remove the current entry from the map. May only be called once. After calling
+     * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
+     * the current entry.
+     *
+     * @since 1.0
+     */
+    void remove();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/Pair.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+import java.util.Objects;
+
+/**
+ * Utility class representing a pair of values.
+ *
+ * @since 1.0
+ */
+public final class Pair<L, R> {
+
+    private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);
+
+    private final L left;
+    private final R right;
+
+    /**
+     * Returns an empty pair.
+     *
+     * @since 1.0
+     */
+    @SuppressWarnings("unchecked")
+    public static <L, R> Pair<L, R> empty() {
+        return (Pair<L, R>) EMPTY;
+    }
+
+    /**
+     * Constructs a pair with its left value being {@code left}, or returns an empty pair if
+     * {@code left} is null.
+     *
+     * @return the constructed pair or an empty pair if {@code left} is null.
+     * @since 1.0
+     */
+    public static <L, R> Pair<L, R> createLeft(L left) {
+        if (left == null) {
+            return empty();
+        } else {
+            return new Pair<>(left, null);
+        }
+    }
+
+    /**
+     * Constructs a pair with its right value being {@code right}, or returns an empty pair if
+     * {@code right} is null.
+     *
+     * @return the constructed pair or an empty pair if {@code right} is null.
+     * @since 1.0
+     */
+    public static <L, R> Pair<L, R> createRight(R right) {
+        if (right == null) {
+            return empty();
+        } else {
+            return new Pair<>(null, right);
+        }
+    }
+
+    /**
+     * Constructs a pair with its left value being {@code left}, and its right value being
+     * {@code right}, or returns an empty pair if both inputs are null.
+     *
+     * @return the constructed pair or an empty pair if both inputs are null.
+     * @since 1.0
+     */
+    public static <L, R> Pair<L, R> create(L left, R right) {
+        if (right == null && left == null) {
+            return empty();
+        } else {
+            return new Pair<>(left, right);
+        }
+    }
+
+    private Pair(L left, R right) {
+        this.left = left;
+        this.right = right;
+    }
+
+    /**
+     * Returns the left value of this pair.
+     *
+     * @since 1.0
+     */
+    public L getLeft() {
+        return left;
+    }
+
+    /**
+     * Returns the right value of this pair.
+     *
+     * @since 1.0
+     */
+    public R getRight() {
+        return right;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 1.0
+     */
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(left) + 31 * Objects.hashCode(right);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 1.0
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+
+        if (obj instanceof Pair) {
+            Pair<L, R> pair = (Pair<L, R>) obj;
+            return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
+        }
+
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @since 1.0
+     */
+    @Override
+    public String toString() {
+        return String.format("(%s, %s)", left, right);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicMap.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Unmodifiable memory efficient map data structure.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableEconomicMap<K, V> {
+
+    /**
+     * Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
+     * mapping for {@code key}.
+     *
+     * @since 1.0
+     */
+    V get(K key);
+
+    /**
+     * Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
+     * contains no mapping for {@code key}.
+     *
+     * @since 1.0
+     */
+    default V get(K key, V defaultValue) {
+        V v = get(key);
+        if (v == null) {
+            return defaultValue;
+        }
+        return v;
+    }
+
+    /**
+     * Returns {@code true} if this map contains a mapping for {@code key}.
+     *
+     * @since 1.0
+     */
+    boolean containsKey(K key);
+
+    /**
+     * Returns the number of key-value mappings in this map.
+     *
+     * @since 1.0
+     */
+    int size();
+
+    /**
+     * Returns {@code true} if this map contains no key-value mappings.
+     *
+     * @since 1.0
+     */
+    boolean isEmpty();
+
+    /**
+     * Returns a {@link Iterable} view of the values contained in this map.
+     *
+     * @since 1.0
+     */
+    Iterable<V> getValues();
+
+    /**
+     * Returns a {@link Iterable} view of the keys contained in this map.
+     *
+     * @since 1.0
+     */
+    Iterable<K> getKeys();
+
+    /**
+     * Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map.
+     *
+     * @since 1.0
+     */
+    UnmodifiableMapCursor<K, V> getEntries();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableEconomicSet.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Unmodifiable memory efficient set data structure.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
+
+    /**
+     * Returns {@code true} if this set contains a mapping for the {@code element}.
+     *
+     * @since 1.0
+     */
+    boolean contains(E element);
+
+    /**
+     * Returns the number of elements in this set.
+     *
+     * @since 1.0
+     */
+    int size();
+
+    /**
+     * Returns {@code true} if this set contains no elements.
+     *
+     * @since 1.0
+     */
+    boolean isEmpty();
+
+    /**
+     * Stores all of the elements in this set into {@code target}. An
+     * {@link UnsupportedOperationException} will be thrown if the length of {@code target} does not
+     * match the size of this set.
+     *
+     * @return an array containing all the elements in this set.
+     * @throws UnsupportedOperationException if the length of {@code target} does not equal the size
+     *             of this set.
+     * @since 1.0
+     */
+    default E[] toArray(E[] target) {
+        if (target.length != size()) {
+            throw new UnsupportedOperationException("Length of target array must equal the size of the set.");
+        }
+
+        int index = 0;
+        for (E element : this) {
+            target[index++] = element;
+        }
+
+        return target;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/UnmodifiableMapCursor.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.internal.vm.compiler.collections;
+
+/**
+ * Cursor to iterate over a map without changing its contents.
+ *
+ * @since 1.0
+ */
+public interface UnmodifiableMapCursor<K, V> {
+    /**
+     * Advances to the next entry.
+     *
+     * @return {@code true} if a next entry exists, {@code false} if there is no next entry.
+     * @since 1.0
+     */
+    boolean advance();
+
+    /**
+     * The key of the current entry.
+     *
+     * @since 1.0
+     */
+    K getKey();
+
+    /**
+     * The value of the current entry.
+     *
+     * @since 1.0
+     */
+    V getValue();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.collections/src/jdk/internal/vm/compiler/collections/package-info.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+/*
+ @ApiInfo(
+ group="Graal SDK"
+ )
+ */
+/**
+ * The Graal-SDK collections package contains memory efficient data structures.
+ *
+ * @see jdk.internal.vm.compiler.collections.EconomicMap
+ * @see jdk.internal.vm.compiler.collections.EconomicSet
+ *
+ * @since 1.0
+ */
+package jdk.internal.vm.compiler.collections;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/ComparableWord.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,53 @@
+/*
+ * 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 jdk.internal.vm.compiler.word;
+
+/**
+ * A machine-word-sized value that can be compared for equality.
+ *
+ * @since 1.0
+ */
+public interface ComparableWord extends WordBase {
+
+    /**
+     * Compares this word with the specified value.
+     *
+     * @param val value to which this word is to be compared.
+     * @return {@code this == val}
+     *
+     * @since 1.0
+     */
+    boolean equal(ComparableWord val);
+
+    /**
+     * Compares this word with the specified value.
+     *
+     * @param val value to which this word is to be compared.
+     * @return {@code this != val}
+     *
+     * @since 1.0
+     */
+    boolean notEqual(ComparableWord val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/LocationIdentity.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2011, 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.  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 jdk.internal.vm.compiler.word;
+
+// JaCoCo Exclude
+
+/**
+ * Marker interface for location identities. A different location identity of two memory accesses
+ * guarantees that the two accesses do not interfere.
+ * <p>
+ * Clients of {@link LocationIdentity} must use {@link #equals(Object)}, not {@code ==}, when
+ * comparing two {@link LocationIdentity} values for equality. Likewise, they must not use
+ * {@link java.util.IdentityHashMap}s with {@link LocationIdentity} values as keys.
+ *
+ * @since 1.0
+ */
+public abstract class LocationIdentity {
+
+    private static final class AnyLocationIdentity extends LocationIdentity {
+        @Override
+        public boolean isImmutable() {
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            return "ANY_LOCATION";
+        }
+    }
+
+    private static final class InitLocationIdentity extends LocationIdentity {
+        @Override
+        public boolean isImmutable() {
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return "INIT_LOCATION";
+        }
+    }
+
+    /**
+     * Creates a new location identity. Subclasses are responsible to provide proper implementations
+     * of {@link #equals} and {@link #hashCode}.
+     *
+     * @since 1.0
+     */
+    protected LocationIdentity() {
+    }
+
+    /**
+     * Indicates that the given location is the union of all possible mutable locations. A write to
+     * such a location kill all reads from mutable locations and a read from this location is killed
+     * by any write (except for initialization writes).
+     *
+     * @since 1.0
+     */
+    public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity();
+
+    /**
+     * Location only allowed to be used for writes. Indicates that a completely new memory location
+     * is written. Kills no read. The previous value at the given location must be either
+     * uninitialized or null. Writes to this location do not need a GC pre-barrier.
+     *
+     * @since 1.0
+     */
+    public static final LocationIdentity INIT_LOCATION = new InitLocationIdentity();
+
+    /**
+     * Indicates that the given location is the union of all possible mutable locations. A write to
+     * such a location kill all reads from mutable locations and a read from this location is killed
+     * by any write (except for initialization writes).
+     *
+     * @since 1.0
+     */
+    public static LocationIdentity any() {
+        return ANY_LOCATION;
+    }
+
+    /**
+     * Location only allowed to be used for writes. Indicates that a completely new memory location
+     * is written. Kills no read. The previous value at the given location must be either
+     * uninitialized or null. Writes to this location do not need a GC pre-barrier.
+     *
+     * @since 1.0
+     */
+    public static LocationIdentity init() {
+        return INIT_LOCATION;
+    }
+
+    /**
+     * Denotes a location is unchanging in all cases. Not that this is different than the Java
+     * notion of final which only requires definite assignment.
+     *
+     * @since 1.0
+     */
+    public abstract boolean isImmutable();
+
+    /**
+     * The inversion of {@link #isImmutable}.
+     *
+     * @since 1.0
+     */
+    public final boolean isMutable() {
+        return !isImmutable();
+    }
+
+    /**
+     * Returns true if this location identity is {@link #any}.
+     *
+     * @since 1.0
+     */
+    public final boolean isAny() {
+        return this == ANY_LOCATION;
+    }
+
+    /**
+     * Returns true if this location identity is {@link #init}.
+     *
+     * @since 1.0
+     */
+    public final boolean isInit() {
+        return this == INIT_LOCATION;
+    }
+
+    /**
+     * Returns true if this location identity is not {@link #any}.
+     *
+     * @since 1.0
+     */
+    public final boolean isSingle() {
+        return this != ANY_LOCATION;
+    }
+
+    /**
+     * Returns true if the memory slice denoted by this location identity may overlap with the
+     * provided other location identity.
+     *
+     * @since 1.0
+     */
+    public final boolean overlaps(LocationIdentity other) {
+        return isAny() || other.isAny() || this.equals(other);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/Pointer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,1415 @@
+/*
+ * Copyright (c) 2012, 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.  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 jdk.internal.vm.compiler.word;
+
+/**
+ * Lowest-level memory access of native C memory.
+ * <p>
+ * Do not use these methods to access Java objects. These methods access the raw memory without any
+ * null checks, read- or write barriers. Even when the VM uses compressed pointers, then readObject
+ * and writeObject methods access uncompressed pointers.
+ *
+ * @since 1.0
+ */
+public interface Pointer extends UnsignedWord, PointerBase {
+
+    /**
+     * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
+     * checks are performed. The caller must ensure that the Pointer contains a valid Java object
+     * that can i.e., processed by the garbage collector.
+     *
+     * @return this Pointer cast to Object.
+     *
+     * @since 1.0
+     */
+    Object toObject();
+
+    /**
+     * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
+     * checks are performed. The caller must ensure that the Pointer contains a valid Java object
+     * that can i.e., processed by the garbage collector and the Pointer does not contain 0.
+     *
+     * @return this Pointer cast to non-null Object.
+     *
+     * @since 1.0
+     */
+    Object toObjectNonNull();
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    byte readByte(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    char readChar(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    short readShort(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    int readInt(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    long readLong(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    float readFloat(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    double readDouble(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    <T extends WordBase> T readWord(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    Object readObject(WordBase offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    byte readByte(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    char readChar(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    short readShort(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    int readInt(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    long readLong(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    float readFloat(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    double readDouble(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the read
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    Object readObject(int offset, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeByte(int offset, byte val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeChar(int offset, char val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeShort(int offset, short val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeInt(int offset, int val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeLong(int offset, long val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeFloat(int offset, float val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeDouble(int offset, double val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
+
+    /**
+     * 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.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void initializeLong(int offset, long val, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param locationIdentity the identity of the write
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeObject(int offset, Object val, LocationIdentity locationIdentity);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    byte readByte(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    char readChar(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    short readShort(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    int readInt(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    long readLong(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    float readFloat(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    double readDouble(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    <T extends WordBase> T readWord(WordBase offset);
+
+    /**
+     * 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 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
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    Object readObject(WordBase offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    byte readByte(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    char readChar(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    short readShort(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    int readInt(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    long readLong(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    float readFloat(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    double readDouble(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    <T extends WordBase> T readWord(int offset);
+
+    /**
+     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @return the result of the memory access
+     *
+     * @since 1.0
+     */
+    Object readObject(int offset);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeByte(WordBase offset, byte val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeChar(WordBase offset, char val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeShort(WordBase offset, short val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeInt(WordBase offset, int val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeLong(WordBase offset, long val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeFloat(WordBase offset, float val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeDouble(WordBase offset, double val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeWord(WordBase offset, WordBase val);
+
+    /**
+     * 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 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
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeObject(WordBase offset, Object val);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    <T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     * <p>
+     * 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
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeByte(int offset, byte val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeChar(int offset, char val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeShort(int offset, short val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeInt(int offset, int val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeLong(int offset, long val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeFloat(int offset, float val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeDouble(int offset, double val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeWord(int offset, WordBase val);
+
+    /**
+     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
+     * bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param val the value to be written to memory
+     *
+     * @since 1.0
+     */
+    void writeObject(int offset, Object val);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return The value after the atomic exchange
+     *
+     * @since 1.0
+     */
+    Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
+
+    /**
+     * Atomically exchanges memory at address {@code (this + offset)}. Both the base address and
+     * offset are in bytes.
+     *
+     * @param offset the signed offset for the memory access
+     * @param expectedValue the expected value of the atomic exchange
+     * @param newValue the new value of the atomic exchange
+     * @param locationIdentity the identity of the memory location
+     * @return {@code true} if successful. False return indicates that the actual value was not
+     *         equal to the expected value.
+     *
+     * @since 1.0
+     */
+    boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
+
+    // Math functions that are defined in Unsigned, but known to preserve the
+    // pointer-characteristics.
+    // It is therefore safe that they return a static type of Pointer instead of Unsigned.
+
+    /**
+     * Returns a Pointer whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Pointer.
+     * @return {@code this + val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer add(UnsignedWord val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this + val)}.
+     *
+     * @param val value to be added to this Pointer.
+     * @return {@code this + val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer add(int val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Pointer.
+     * @return {@code this - val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer subtract(UnsignedWord val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this - val)}.
+     *
+     * @param val value to be subtracted from this Pointer.
+     * @return {@code this - val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer subtract(int val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this & val)}.
+     *
+     * @param val value to be AND'ed with this Pointer.
+     * @return {@code this & val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer and(UnsignedWord val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this & val)}.
+     *
+     * @param val value to be AND'ed with this Pointer.
+     * @return {@code this & val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer and(int val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this | val)}.
+     *
+     * @param val value to be OR'ed with this Pointer.
+     * @return {@code this | val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer or(UnsignedWord val);
+
+    /**
+     * Returns a Pointer whose value is {@code (this | val)}.
+     *
+     * @param val value to be OR'ed with this Pointer.
+     * @return {@code this | val}
+     *
+     * @since 1.0
+     */
+    @Override
+    Pointer or(int val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/PointerBase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 jdk.internal.vm.compiler.word;
+
+/**
+ * Marker interface for all {@link WordBase word types} that have the semantic of a pointer (but not
+ * necessarily all the memory access methods defined in {@link Pointer}).
+ *
+ * @since 1.0
+ */
+public interface PointerBase extends ComparableWord {
+
+    /**
+     * Returns true if this pointer is the {@link WordFactory#nullPointer null pointer}.
+     *
+     * @since 1.0
+     */
+    boolean isNull();
+
+    /**
+     * Returns true if this pointer is not the {@link WordFactory#nullPointer null pointer}.
+     *
+     * @since 1.0
+     */
+    boolean isNonNull();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/SignedWord.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,369 @@
+/*
+ * 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 jdk.internal.vm.compiler.word;
+
+/**
+ * Represents a signed word-sized value.
+ *
+ * @since 1.0
+ */
+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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    SignedWord signedRemainder(SignedWord val);
+
+    /**
+     * Returns a Signed whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    SignedWord not();
+
+    /**
+     * Compares this Signed with the specified value.
+     *
+     * @param val value to which this Signed is to be compared.
+     * @return {@code this == val}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    SignedWord signedRemainder(int val);
+
+    /**
+     * Returns a Signed whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    boolean greaterOrEqual(int val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/UnsignedWord.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,410 @@
+/*
+ * 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 jdk.internal.vm.compiler.word;
+
+/**
+ * Represents an unsigned word-sized value.
+ *
+ * @since 1.0
+ */
+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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    UnsignedWord unsignedRemainder(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (this << n)}.
+     *
+     * @param n shift distance, in bits.
+     * @return {@code this << n}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    UnsignedWord xor(UnsignedWord val);
+
+    /**
+     * Returns a Unsigned whose value is {@code (~this)}.
+     *
+     * @return {@code ~this}
+     *
+     * @since 1.0
+     */
+    UnsignedWord not();
+
+    /**
+     * Compares this Unsigned with the specified value.
+     *
+     * @param val value to which this Unsigned is to be compared.
+     * @return {@code this == val}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    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}
+     *
+     * @since 1.0
+     */
+    boolean aboveOrEqual(int val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordBase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,51 @@
+/*
+ * 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 jdk.internal.vm.compiler.word;
+
+/**
+ * The root of the interface hierarchy for machine-word-sized values.
+ *
+ * @since 1.0
+ */
+public interface WordBase {
+
+    /**
+     * Conversion to a Java primitive value.
+     *
+     * @since 1.0
+     */
+    long rawValue();
+
+    /**
+     * This is deprecated because of the easy to mistype name collision between {@link #equals} and
+     * the other word based equality routines. In general you should never be statically calling
+     * this method anyway.
+     *
+     * @since 1.0
+     */
+    @Override
+    @Deprecated
+    boolean equals(Object o);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/WordFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2012, 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.  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 jdk.internal.vm.compiler.word;
+
+import jdk.internal.vm.compiler.word.impl.WordBoxFactory;
+import jdk.internal.vm.compiler.word.impl.WordFactoryOpcode;
+import jdk.internal.vm.compiler.word.impl.WordFactoryOperation;
+
+/**
+ * Provides factory method to create machine-word-sized values.
+ *
+ * @since 1.0
+ */
+public final class WordFactory {
+
+    private WordFactory() {
+    }
+
+    /**
+     * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
+     * unsigned zero.
+     *
+     * @return the constant 0.
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.ZERO)
+    public static <T extends WordBase> T zero() {
+        return WordBoxFactory.box(0L);
+    }
+
+    /**
+     * The null pointer, i.e., the pointer with no bits set. There is no difference to a signed or
+     * unsigned {@link #zero}.
+     *
+     * @return the null pointer.
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.ZERO)
+    public static <T extends PointerBase> T nullPointer() {
+        return WordBoxFactory.box(0L);
+    }
+
+    /**
+     * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
+     * 64-bit value (in contrast to the semantics of a Java long).
+     *
+     * @param val a 64 bit unsigned value
+     * @return the value cast to Word
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
+    public static <T extends UnsignedWord> T unsigned(long val) {
+        return WordBoxFactory.box(val);
+    }
+
+    /**
+     * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
+     * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
+     *
+     * @param val a 64 bit unsigned value
+     * @return the value cast to PointerBase
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
+    public static <T extends PointerBase> T pointer(long val) {
+        return WordBoxFactory.box(val);
+    }
+
+    /**
+     * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
+     * 32-bit value (in contrast to the semantics of a Java int).
+     *
+     * @param val a 32 bit unsigned value
+     * @return the value cast to Word
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_UNSIGNED)
+    public static <T extends UnsignedWord> T unsigned(int val) {
+        return WordBoxFactory.box(val & 0xffffffffL);
+    }
+
+    /**
+     * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
+     * 64-bit value (unchanged semantics of a Java long).
+     *
+     * @param val a 64 bit signed value
+     * @return the value cast to Word
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_SIGNED)
+    public static <T extends SignedWord> T signed(long val) {
+        return WordBoxFactory.box(val);
+    }
+
+    /**
+     * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
+     * 32-bit value (unchanged semantics of a Java int).
+     *
+     * @param val a 32 bit signed value
+     * @return the value cast to Word
+     *
+     * @since 1.0
+     */
+    @WordFactoryOperation(opcode = WordFactoryOpcode.FROM_SIGNED)
+    public static <T extends SignedWord> T signed(int val) {
+        return WordBoxFactory.box(val);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/impl/WordBoxFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2012, 2018, 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 jdk.internal.vm.compiler.word.impl;
+
+import jdk.internal.vm.compiler.word.WordBase;
+
+/**
+ * Base class for a factory to create boxed {@link Word} instances. A concrete subclass must
+ * initialize {@link #boxFactory}.
+ */
+public abstract class WordBoxFactory {
+
+    protected static WordBoxFactory boxFactory;
+
+    protected abstract <T extends WordBase> T boxImpl(long val);
+
+    public static <T extends WordBase> T box(long val) {
+        return boxFactory.boxImpl(val);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/impl/WordFactoryOpcode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2012, 2018, 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 jdk.internal.vm.compiler.word.impl;
+
+/**
+ * The canonical {@link WordFactoryOperation} represented by a method in a word type.
+ */
+public enum WordFactoryOpcode {
+    ZERO,
+    FROM_UNSIGNED,
+    FROM_SIGNED,
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/impl/WordFactoryOperation.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012, 2018, 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 jdk.internal.vm.compiler.word.impl;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Links a method to a canonical operation represented by an {@link WordFactoryOpcode} val.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface WordFactoryOperation {
+    WordFactoryOpcode opcode();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/jdk.internal.vm.compiler.word/src/jdk/internal/vm/compiler/word/package-info.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, 2018, 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.
+ */
+/*
+ @ApiInfo(
+ group="Graal SDK"
+ )
+ */
+/**
+ * This package provides a low-level mechanism to use machine-word-sized values in Java. The package
+ * can only be used in the context of native images or Graal snippets.
+ *
+ * @since 1.0
+ */
+package jdk.internal.vm.compiler.word;
\ No newline at end of file
--- a/src/jdk.internal.vm.compiler/share/classes/module-info.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/module-info.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,9 +36,10 @@
     uses org.graalvm.compiler.hotspot.CompilerConfigurationFactory;
     uses org.graalvm.compiler.hotspot.HotSpotBackendFactory;
     uses org.graalvm.compiler.hotspot.HotSpotCodeCacheListener;
-    uses org.graalvm.compiler.options.OptionValuesAccess;
+    uses org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
     uses org.graalvm.compiler.nodes.graphbuilderconf.NodeIntrinsicPluginFactory;
 
+    exports jdk.internal.vm.compiler.collections        to jdk.internal.vm.compiler.management;
     exports org.graalvm.compiler.api.directives         to jdk.aot;
     exports org.graalvm.compiler.api.runtime            to jdk.aot;
     exports org.graalvm.compiler.api.replacements       to jdk.aot;
@@ -46,9 +47,13 @@
     exports org.graalvm.compiler.bytecode               to jdk.aot;
     exports org.graalvm.compiler.code                   to jdk.aot;
     exports org.graalvm.compiler.core                   to jdk.aot;
-    exports org.graalvm.compiler.core.common            to jdk.aot;
+    exports org.graalvm.compiler.core.common            to
+        jdk.aot,
+        jdk.internal.vm.compiler.management;
     exports org.graalvm.compiler.core.target            to jdk.aot;
-    exports org.graalvm.compiler.debug                  to jdk.aot;
+    exports org.graalvm.compiler.debug                  to
+        jdk.aot,
+        jdk.internal.vm.compiler.management;
     exports org.graalvm.compiler.graph                  to jdk.aot;
     exports org.graalvm.compiler.hotspot                to
         jdk.aot,
@@ -62,12 +67,17 @@
     exports org.graalvm.compiler.lir.phases             to jdk.aot;
     exports org.graalvm.compiler.nodes                  to jdk.aot;
     exports org.graalvm.compiler.nodes.graphbuilderconf to jdk.aot;
-    exports org.graalvm.compiler.options                to jdk.aot;
+    exports org.graalvm.compiler.options                to
+        jdk.aot,
+        jdk.internal.vm.compiler.management;
     exports org.graalvm.compiler.phases                 to jdk.aot;
     exports org.graalvm.compiler.phases.tiers           to jdk.aot;
     exports org.graalvm.compiler.printer                to jdk.aot;
     exports org.graalvm.compiler.runtime                to jdk.aot;
     exports org.graalvm.compiler.replacements           to jdk.aot;
+    exports org.graalvm.compiler.serviceprovider        to
+        jdk.aot,
+        jdk.internal.vm.compiler.management;
     exports org.graalvm.compiler.word                   to jdk.aot;
-    exports org.graalvm.word                            to jdk.aot;
+    exports jdk.internal.vm.compiler.word               to jdk.aot;
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapImplTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.Arrays;
-import java.util.Iterator;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicSet;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EconomicMapImplTest {
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testRemoveNull() {
-        EconomicMap<Integer, Integer> map = EconomicMap.create(10);
-        map.removeKey(null);
-    }
-
-    @Test
-    public void testInitFromHashSet() {
-        UnmodifiableEconomicSet<Integer> set = new UnmodifiableEconomicSet<Integer>() {
-
-            @Override
-            public boolean contains(Integer element) {
-                return element == 0;
-            }
-
-            @Override
-            public int size() {
-                return 1;
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return false;
-            }
-
-            @Override
-            public Iterator<Integer> iterator() {
-                return new Iterator<Integer>() {
-
-                    private boolean visited = false;
-
-                    @Override
-                    public boolean hasNext() {
-                        return !visited;
-                    }
-
-                    @Override
-                    public Integer next() {
-                        if (visited) {
-                            return null;
-                        } else {
-                            visited = true;
-                            return 1;
-                        }
-                    }
-                };
-            }
-        };
-
-        EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.DEFAULT, set);
-        Assert.assertEquals(newSet.size(), 1);
-    }
-
-    @Test
-    public void testCopyHash() {
-        EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
-        set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
-        EconomicSet<Integer> newSet = EconomicSet.create(Equivalence.IDENTITY, set);
-        Assert.assertEquals(newSet.size(), 10);
-        newSet.remove(8);
-        newSet.remove(9);
-        Assert.assertEquals(newSet.size(), 8);
-    }
-
-    @Test
-    public void testNewEquivalence() {
-        EconomicSet<Integer> set = EconomicSet.create(new Equivalence() {
-            @Override
-            public boolean equals(Object a, Object b) {
-                return false;
-            }
-
-            @Override
-            public int hashCode(Object o) {
-                return 0;
-            }
-        });
-        set.addAll(Arrays.asList(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
-        Assert.assertTrue(set.add(new Integer(0)));
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testMapPutNull() {
-        EconomicMap<Integer, Integer> map = EconomicMap.create();
-        map.put(null, null);
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapLargeTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,231 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Objects;
-import java.util.Random;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.UnmodifiableMapCursor;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-
-@RunWith(Parameterized.class)
-public class EconomicMapLargeTest {
-
-    @Parameter(value = 0) public EconomicMap<Object, Object> testMap;
-    @Parameter(value = 1) public EconomicMap<Object, Object> referenceMap;
-    @Parameter(value = 2) public String name;
-
-    @Parameters(name = "{2}")
-    public static Collection<Object[]> data() {
-        return Arrays.asList(new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.create(Equivalence.DEFAULT), "EconomicMap"},
-                        new Object[]{EconomicMap.create(Equivalence.IDENTITY), EconomicMap.create(Equivalence.IDENTITY), "EconomicMap(IDENTITY)"},
-                        new Object[]{EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE), EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE),
-                                        "EconomicMap(IDENTITY_WITH_SYSTEM_HASHCODE)"},
-                        new Object[]{EconomicMap.create(Equivalence.DEFAULT), EconomicMap.wrapMap(new LinkedHashMap<>()), "EconomicMap<->wrapMap"},
-                        new Object[]{EconomicMap.wrapMap(new LinkedHashMap<>()), EconomicMap.wrapMap(new LinkedHashMap<>()), "wrapMap"});
-    }
-
-    private static int[] createRandomRange(Random random, int count) {
-        int[] result = new int[count];
-        for (int i = 0; i < count; ++i) {
-            int range = random.nextInt(14);
-            if (range == 0 || range > 10) {
-                range = Integer.MAX_VALUE;
-            } else if (range == 10) {
-                range = 100;
-            }
-            result[i] = range;
-        }
-        return result;
-    }
-
-    private static final class BadHashClass {
-        private int value;
-
-        BadHashClass(int randomInt) {
-            this.value = randomInt;
-        }
-
-        @Override
-        public int hashCode() {
-            return 0;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (other instanceof BadHashClass) {
-                BadHashClass badHashClass = (BadHashClass) other;
-                return badHashClass.value == value;
-            }
-            return false;
-        }
-    }
-
-    interface MapAction {
-        Object perform(EconomicMap<Object, Object> map, int randomInt);
-    }
-
-    static final Object EXISTING_VALUE = new Object();
-
-    static final MapAction[] INCREASE_ACTIONS = new MapAction[]{
-                    (map, randomInt) -> map.put(randomInt, "value"),
-                    (map, randomInt) -> map.get(randomInt)
-    };
-
-    static final MapAction[] ACTIONS = new MapAction[]{
-                    (map, randomInt) -> map.removeKey(randomInt),
-                    (map, randomInt) -> map.put(randomInt, "value"),
-                    (map, randomInt) -> map.put(randomInt, null),
-                    (map, randomInt) -> map.put(EXISTING_VALUE, randomInt),
-                    (map, randomInt) -> {
-                        if (randomInt == 0) {
-                            map.clear();
-                        }
-                        return map.isEmpty();
-                    },
-                    (map, randomInt) -> map.containsKey(randomInt),
-                    (map, randomInt) -> map.get(randomInt),
-                    (map, randomInt) -> map.put(new BadHashClass(randomInt), "unique"),
-                    (map, randomInt) -> {
-                        if (randomInt == 0) {
-                            map.replaceAll((key, value) -> Objects.toString(value) + "!");
-                        }
-                        return map.isEmpty();
-                    }
-
-    };
-
-    @Test
-    public void testVeryLarge() {
-        testMap.clear();
-        referenceMap.clear();
-
-        Random random = new Random(0);
-        for (int i = 0; i < 200000; ++i) {
-            for (int j = 0; j < INCREASE_ACTIONS.length; ++j) {
-                int nextInt = random.nextInt(10000000);
-                MapAction action = INCREASE_ACTIONS[j];
-                Object result = action.perform(testMap, nextInt);
-                Object referenceResult = action.perform(referenceMap, nextInt);
-                Assert.assertEquals(result, referenceResult);
-            }
-        }
-    }
-
-    /**
-     * Tests a sequence of random operations on the map.
-     */
-    @Test
-    public void testAddRemove() {
-        testMap.clear();
-        referenceMap.clear();
-
-        for (int seed = 0; seed < 10; ++seed) {
-            Random random = new Random(seed);
-            int[] ranges = createRandomRange(random, ACTIONS.length);
-            int value = random.nextInt(10000);
-            for (int i = 0; i < value; ++i) {
-                for (int j = 0; j < ACTIONS.length; ++j) {
-                    if (random.nextInt(ranges[j]) == 0) {
-                        int nextInt = random.nextInt(100);
-                        MapAction action = ACTIONS[j];
-                        Object result = action.perform(testMap, nextInt);
-                        Object referenceResult = action.perform(referenceMap, nextInt);
-                        Assert.assertEquals(result, referenceResult);
-                        if (j % 100 == 0) {
-                            checkEquality(testMap, referenceMap);
-                        }
-                    }
-                }
-
-                if (random.nextInt(20) == 0) {
-                    removeElement(random.nextInt(100), testMap, referenceMap);
-                }
-            }
-        }
-    }
-
-    private static void removeElement(int index, EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
-        Assert.assertEquals(referenceMap.size(), map.size());
-        MapCursor<?, ?> cursor = map.getEntries();
-        MapCursor<?, ?> referenceCursor = referenceMap.getEntries();
-        int z = 0;
-        while (cursor.advance()) {
-            Assert.assertTrue(referenceCursor.advance());
-            Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
-            Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
-            if (index == z) {
-                cursor.remove();
-                referenceCursor.remove();
-            }
-            ++z;
-        }
-
-        Assert.assertFalse(referenceCursor.advance());
-    }
-
-    private static void checkEquality(EconomicMap<?, ?> map, EconomicMap<?, ?> referenceMap) {
-        Assert.assertEquals(referenceMap.size(), map.size());
-
-        // Check entries.
-        UnmodifiableMapCursor<?, ?> cursor = map.getEntries();
-        UnmodifiableMapCursor<?, ?> referenceCursor = referenceMap.getEntries();
-        while (cursor.advance()) {
-            Assert.assertTrue(referenceCursor.advance());
-            Assert.assertEquals(referenceCursor.getKey(), cursor.getKey());
-            Assert.assertEquals(referenceCursor.getValue(), cursor.getValue());
-        }
-
-        // Check keys.
-        Iterator<?> iterator = map.getKeys().iterator();
-        Iterator<?> referenceIterator = referenceMap.getKeys().iterator();
-        while (iterator.hasNext()) {
-            Assert.assertTrue(referenceIterator.hasNext());
-            Assert.assertEquals(iterator.next(), referenceIterator.next());
-        }
-
-        // Check values.
-        iterator = map.getValues().iterator();
-        referenceIterator = referenceMap.getValues().iterator();
-        while (iterator.hasNext()) {
-            Assert.assertTrue(referenceIterator.hasNext());
-            Assert.assertEquals(iterator.next(), referenceIterator.next());
-        }
-        Assert.assertFalse(referenceIterator.hasNext());
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicMapTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.LinkedHashMap;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EconomicMapTest {
-
-    @Test
-    public void testMapGetDefault() {
-        EconomicMap<Integer, Integer> map = EconomicMap.create();
-        map.put(0, 1);
-        Assert.assertEquals(map.get(0, 2), Integer.valueOf(1));
-        Assert.assertEquals(map.get(1, 2), Integer.valueOf(2));
-    }
-
-    @Test
-    public void testMapPutAll() {
-        EconomicMap<Integer, Integer> map = EconomicMap.create();
-        EconomicMap<Integer, Integer> newMap = EconomicMap.wrapMap(new LinkedHashMap<>());
-        newMap.put(1, 1);
-        newMap.put(2, 4);
-        map.putAll(newMap);
-        Assert.assertEquals(map.size(), 2);
-
-        UnmodifiableEconomicMap<Integer, Integer> unmodifiableEconomicMap = EconomicMap.create(newMap);
-
-        map.removeKey(1);
-        map.put(2, 2);
-        map.put(3, 9);
-
-        map.putAll(unmodifiableEconomicMap);
-        Assert.assertEquals(map.size(), 3);
-        Assert.assertEquals(map.get(2), Integer.valueOf(4));
-    }
-
-    @Test
-    public void testToString() {
-        EconomicMap<Integer, Integer> map = EconomicMap.create();
-        map.put(0, 0);
-        map.put(1, 1);
-        Assert.assertEquals(map.toString(), "map(size=2, {(0,0),(1,1)})");
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EconomicSetTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EconomicSetTest {
-
-    @Test
-    public void testUtilities() {
-        EconomicSet<Integer> set = EconomicSet.create(0);
-        set.add(0);
-        Assert.assertTrue(set.add(1));
-        Assert.assertEquals(set.size(), 2);
-        Assert.assertFalse(set.add(1));
-        Assert.assertEquals(set.size(), 2);
-        set.remove(1);
-        Assert.assertEquals(set.size(), 1);
-        set.remove(2);
-        Assert.assertEquals(set.size(), 1);
-        Assert.assertTrue(set.add(1));
-        set.clear();
-        Assert.assertEquals(set.size(), 0);
-    }
-
-    @Test
-    public void testAddAll() {
-        EconomicSet<Integer> set = EconomicSet.create();
-        set.addAll(Arrays.asList(0, 1, 0));
-        Assert.assertEquals(set.size(), 2);
-
-        EconomicSet<Integer> newSet = EconomicSet.create();
-        newSet.addAll(Arrays.asList(1, 2));
-        Assert.assertEquals(newSet.size(), 2);
-        newSet.addAll(set);
-        Assert.assertEquals(newSet.size(), 3);
-    }
-
-    @Test
-    public void testRemoveAll() {
-        EconomicSet<Integer> set = EconomicSet.create();
-        set.addAll(Arrays.asList(0, 1));
-
-        set.removeAll(Arrays.asList(1, 2));
-        Assert.assertEquals(set.size(), 1);
-
-        set.removeAll(EconomicSet.create(set));
-        Assert.assertEquals(set.size(), 0);
-    }
-
-    @Test
-    public void testRetainAll() {
-        EconomicSet<Integer> set = EconomicSet.create();
-        set.addAll(Arrays.asList(0, 1, 2));
-
-        EconomicSet<Integer> newSet = EconomicSet.create();
-        newSet.addAll(Arrays.asList(2, 3));
-
-        set.retainAll(newSet);
-        Assert.assertEquals(set.size(), 1);
-    }
-
-    @Test
-    public void testToArray() {
-        EconomicSet<Integer> set = EconomicSet.create();
-        set.addAll(Arrays.asList(0, 1));
-        Assert.assertArrayEquals(set.toArray(new Integer[2]), new Integer[]{0, 1});
-    }
-
-    @Test
-    public void testToString() {
-        EconomicSet<Integer> set = EconomicSet.create();
-        set.addAll(Arrays.asList(0, 1));
-        Assert.assertEquals(set.toString(), "set(size=2, {0,1})");
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testToUnalignedArray() {
-        Assert.assertArrayEquals(EconomicSet.create().toArray(new Integer[2]), new Integer[0]);
-    }
-
-    @Test
-    public void testSetRemoval() {
-        ArrayList<Integer> initialList = new ArrayList<>();
-        ArrayList<Integer> removalList = new ArrayList<>();
-        ArrayList<Integer> finalList = new ArrayList<>();
-        EconomicSet<Integer> set = EconomicSet.create(Equivalence.IDENTITY);
-        set.add(1);
-        set.add(2);
-        set.add(3);
-        set.add(4);
-        set.add(5);
-        set.add(6);
-        set.add(7);
-        set.add(8);
-        set.add(9);
-        Iterator<Integer> i1 = set.iterator();
-        while (i1.hasNext()) {
-            initialList.add(i1.next());
-        }
-        int size = 0;
-        Iterator<Integer> i2 = set.iterator();
-        while (i2.hasNext()) {
-            Integer elem = i2.next();
-            if (size++ < 8) {
-                i2.remove();
-            }
-            removalList.add(elem);
-        }
-        Iterator<Integer> i3 = set.iterator();
-        while (i3.hasNext()) {
-            finalList.add(i3.next());
-        }
-        Assert.assertEquals(initialList, removalList);
-        Assert.assertEquals(1, finalList.size());
-        Assert.assertEquals(new Integer(9), finalList.get(0));
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/EquivalenceTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import org.graalvm.collections.Equivalence;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class EquivalenceTest {
-
-    private static final String TEST_STRING = "Graal";
-    private static final String TEST_STRING2 = "Graal2";
-
-    @Test
-    public void testDEFAULT() {
-        Assert.assertTrue(Equivalence.DEFAULT.equals(TEST_STRING, new String(TEST_STRING)));
-        Assert.assertEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(new String(TEST_STRING)));
-        Assert.assertFalse(Equivalence.DEFAULT.equals(TEST_STRING, TEST_STRING2));
-        Assert.assertNotEquals(Equivalence.DEFAULT.hashCode(TEST_STRING), Equivalence.DEFAULT.hashCode(TEST_STRING2));
-    }
-
-    @Test
-    public void testIDENTITY() {
-        Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, new String(TEST_STRING)));
-        Assert.assertEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(new String(TEST_STRING)));
-        Assert.assertFalse(Equivalence.IDENTITY.equals(TEST_STRING, TEST_STRING2));
-        Assert.assertNotEquals(Equivalence.IDENTITY.hashCode(TEST_STRING), Equivalence.IDENTITY.hashCode(TEST_STRING2));
-    }
-
-    @Test
-    public void testIDENTITYWITHSYSTEMHASHCODE() {
-        Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, new String(TEST_STRING)));
-        Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(new String(TEST_STRING)));
-        Assert.assertFalse(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.equals(TEST_STRING, TEST_STRING2));
-        Assert.assertNotEquals(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING), Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE.hashCode(TEST_STRING2));
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections.test/src/org/graalvm/collections/test/PairTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections.test;
-
-import org.graalvm.collections.Pair;
-import org.junit.Assert;
-import org.junit.Test;
-
-public class PairTest {
-
-    @Test
-    public void testCreate() {
-        Assert.assertEquals(Pair.create(null, null), Pair.empty());
-        Assert.assertNotEquals(Pair.create(null, null), null);
-        Assert.assertEquals(Pair.createLeft(null), Pair.empty());
-        Assert.assertEquals(Pair.createRight(null), Pair.empty());
-        Assert.assertEquals(Pair.create(1, null), Pair.createLeft(1));
-        Assert.assertEquals(Pair.create(null, 1), Pair.createRight(1));
-    }
-
-    @Test
-    public void testUtilities() {
-        Pair<Integer, Integer> pair = Pair.create(1, null);
-        Assert.assertEquals(pair.getLeft(), Integer.valueOf(1));
-        Assert.assertEquals(pair.getRight(), null);
-        Assert.assertEquals(pair.toString(), "(1, null)");
-        Assert.assertEquals(pair.hashCode(), Pair.createLeft(1).hashCode());
-    }
-
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,265 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Iterator;
-import java.util.Map;
-import java.util.function.BiFunction;
-
-/**
- * Memory efficient map data structure.
- *
- * @since 1.0
- */
-public interface EconomicMap<K, V> extends UnmodifiableEconomicMap<K, V> {
-
-    /**
-     * Associates {@code value} with {@code key} in this map. If the map previously contained a
-     * mapping for {@code key}, the old value is replaced by {@code value}.
-     *
-     * @return the previous value associated with {@code key}, or {@code null} if there was no
-     *         mapping for {@code key}.
-     * @since 1.0
-     */
-    V put(K key, V value);
-
-    /**
-     * Copies all of the mappings from {@code other} to this map.
-     *
-     * @since 1.0
-     */
-    default void putAll(EconomicMap<K, V> other) {
-        MapCursor<K, V> e = other.getEntries();
-        while (e.advance()) {
-            put(e.getKey(), e.getValue());
-        }
-    }
-
-    /**
-     * Copies all of the mappings from {@code other} to this map.
-     *
-     * @since 1.0
-     */
-    default void putAll(UnmodifiableEconomicMap<? extends K, ? extends V> other) {
-        UnmodifiableMapCursor<? extends K, ? extends V> entry = other.getEntries();
-        while (entry.advance()) {
-            put(entry.getKey(), entry.getValue());
-        }
-    }
-
-    /**
-     * Removes all of the mappings from this map. The map will be empty after this call returns.
-     *
-     * @since 1.0
-     */
-    void clear();
-
-    /**
-     * Removes the mapping for {@code key} from this map if it is present. The map will not contain
-     * a mapping for {@code key} once the call returns.
-     *
-     * @return the previous value associated with {@code key}, or {@code null} if there was no
-     *         mapping for {@code key}.
-     * @since 1.0
-     */
-    V removeKey(K key);
-
-    /**
-     * Returns a {@link MapCursor} view of the mappings contained in this map.
-     *
-     * @since 1.0
-     */
-    @Override
-    MapCursor<K, V> getEntries();
-
-    /**
-     * Replaces each entry's value with the result of invoking {@code function} on that entry until
-     * all entries have been processed or the function throws an exception. Exceptions thrown by the
-     * function are relayed to the caller.
-     *
-     * @since 1.0
-     */
-    void replaceAll(BiFunction<? super K, ? super V, ? extends V> function);
-
-    /**
-     * Creates a new map that guarantees insertion order on the key set with the default
-     * {@link Equivalence#DEFAULT} comparison strategy for keys.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> create() {
-        return EconomicMap.create(Equivalence.DEFAULT);
-    }
-
-    /**
-     * Creates a new map that guarantees insertion order on the key set with the default
-     * {@link Equivalence#DEFAULT} comparison strategy for keys and initializes with a specified
-     * capacity.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> create(int initialCapacity) {
-        return EconomicMap.create(Equivalence.DEFAULT, initialCapacity);
-    }
-
-    /**
-     * Creates a new map that guarantees insertion order on the key set with the given comparison
-     * strategy for keys.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> create(Equivalence strategy) {
-        return EconomicMapImpl.create(strategy, false);
-    }
-
-    /**
-     * Creates a new map that guarantees insertion order on the key set with the default
-     * {@link Equivalence#DEFAULT} comparison strategy for keys and copies all elements from the
-     * specified existing map.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> create(UnmodifiableEconomicMap<K, V> m) {
-        return EconomicMap.create(Equivalence.DEFAULT, m);
-    }
-
-    /**
-     * Creates a new map that guarantees insertion order on the key set and copies all elements from
-     * the specified existing map.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> m) {
-        return EconomicMapImpl.create(strategy, m, false);
-    }
-
-    /**
-     * Creates a new map that guarantees insertion order on the key set and initializes with a
-     * specified capacity.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> create(Equivalence strategy, int initialCapacity) {
-        return EconomicMapImpl.create(strategy, initialCapacity, false);
-    }
-
-    /**
-     * Wraps an existing {@link Map} as an {@link EconomicMap}.
-     *
-     * @since 1.0
-     */
-    static <K, V> EconomicMap<K, V> wrapMap(Map<K, V> map) {
-        return new EconomicMap<K, V>() {
-
-            @Override
-            public V get(K key) {
-                V result = map.get(key);
-                return result;
-            }
-
-            @Override
-            public V put(K key, V value) {
-                V result = map.put(key, value);
-                return result;
-            }
-
-            @Override
-            public int size() {
-                int result = map.size();
-                return result;
-            }
-
-            @Override
-            public boolean containsKey(K key) {
-                return map.containsKey(key);
-            }
-
-            @Override
-            public void clear() {
-                map.clear();
-            }
-
-            @Override
-            public V removeKey(K key) {
-                V result = map.remove(key);
-                return result;
-            }
-
-            @Override
-            public Iterable<V> getValues() {
-                return map.values();
-            }
-
-            @Override
-            public Iterable<K> getKeys() {
-                return map.keySet();
-            }
-
-            @Override
-            public boolean isEmpty() {
-                return map.isEmpty();
-            }
-
-            @Override
-            public MapCursor<K, V> getEntries() {
-                Iterator<java.util.Map.Entry<K, V>> iterator = map.entrySet().iterator();
-                return new MapCursor<K, V>() {
-
-                    private Map.Entry<K, V> current;
-
-                    @Override
-                    public boolean advance() {
-                        boolean result = iterator.hasNext();
-                        if (result) {
-                            current = iterator.next();
-                        }
-
-                        return result;
-                    }
-
-                    @Override
-                    public K getKey() {
-                        return current.getKey();
-                    }
-
-                    @Override
-                    public V getValue() {
-                        return current.getValue();
-                    }
-
-                    @Override
-                    public void remove() {
-                        iterator.remove();
-                    }
-                };
-            }
-
-            @Override
-            public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
-                map.replaceAll(function);
-            }
-        };
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicMapImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,857 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Iterator;
-import java.util.Objects;
-import java.util.function.BiFunction;
-
-/**
- * Implementation of a map with a memory-efficient structure that always preserves insertion order
- * when iterating over keys. Particularly efficient when number of entries is 0 or smaller equal
- * {@link #INITIAL_CAPACITY} or smaller 256.
- *
- * The key/value pairs are kept in an expanding flat object array with keys at even indices and
- * values at odd indices. If the map has smaller or equal to {@link #HASH_THRESHOLD} entries, there
- * is no additional hash data structure and comparisons are done via linear checking of the
- * key/value pairs. For the case where the equality check is particularly cheap (e.g., just an
- * object identity comparison), this limit below which the map is without an actual hash table is
- * higher and configured at {@link #HASH_THRESHOLD_IDENTITY_COMPARE}.
- *
- * When the hash table needs to be constructed, the field {@link #hashArray} becomes a new hash
- * array where an entry of 0 means no hit and otherwise denotes the entry number in the
- * {@link #entries} array. The hash array is interpreted as an actual byte array if the indices fit
- * within 8 bit, or as an array of short values if the indices fit within 16 bit, or as an array of
- * integer values in other cases.
- *
- * Hash collisions are handled by chaining a linked list of {@link CollisionLink} objects that take
- * the place of the values in the {@link #entries} array.
- *
- * Removing entries will put {@code null} into the {@link #entries} array. If the occupation of the
- * map falls below a specific threshold, the map will be compressed via the
- * {@link #maybeCompress(int)} method.
- */
-final class EconomicMapImpl<K, V> implements EconomicMap<K, V>, EconomicSet<K> {
-
-    /**
-     * Initial number of key/value pair entries that is allocated in the first entries array.
-     */
-    private static final int INITIAL_CAPACITY = 4;
-
-    /**
-     * Maximum number of entries that are moved linearly forward if a key is removed.
-     */
-    private static final int COMPRESS_IMMEDIATE_CAPACITY = 8;
-
-    /**
-     * Minimum number of key/value pair entries added when the entries array is increased in size.
-     */
-    private static final int MIN_CAPACITY_INCREASE = 8;
-
-    /**
-     * Number of entries above which a hash table is created.
-     */
-    private static final int HASH_THRESHOLD = 4;
-
-    /**
-     * Number of entries above which a hash table is created when equality can be checked with
-     * object identity.
-     */
-    private static final int HASH_THRESHOLD_IDENTITY_COMPARE = 8;
-
-    /**
-     * Maximum number of entries allowed in the map.
-     */
-    private static final int MAX_ELEMENT_COUNT = Integer.MAX_VALUE >> 1;
-
-    /**
-     * Number of entries above which more than 1 byte is necessary for the hash index.
-     */
-    private static final int LARGE_HASH_THRESHOLD = ((1 << Byte.SIZE) << 1);
-
-    /**
-     * Number of entries above which more than 2 bytes are are necessary for the hash index.
-     */
-    private static final int VERY_LARGE_HASH_THRESHOLD = (LARGE_HASH_THRESHOLD << Byte.SIZE);
-
-    /**
-     * Total number of entries (actual entries plus deleted entries).
-     */
-    private int totalEntries;
-
-    /**
-     * Number of deleted entries.
-     */
-    private int deletedEntries;
-
-    /**
-     * Entries array with even indices storing keys and odd indices storing values.
-     */
-    private Object[] entries;
-
-    /**
-     * Hash array that is interpreted either as byte or short or int array depending on number of
-     * map entries.
-     */
-    private byte[] hashArray;
-
-    /**
-     * The strategy used for comparing keys or {@code null} for denoting special strategy
-     * {@link Equivalence#IDENTITY}.
-     */
-    private final Equivalence strategy;
-
-    /**
-     * Intercept method for debugging purposes.
-     */
-    private static <K, V> EconomicMapImpl<K, V> intercept(EconomicMapImpl<K, V> map) {
-        return map;
-    }
-
-    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, boolean isSet) {
-        return intercept(new EconomicMapImpl<>(strategy, isSet));
-    }
-
-    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, int initialCapacity, boolean isSet) {
-        return intercept(new EconomicMapImpl<>(strategy, initialCapacity, isSet));
-    }
-
-    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
-        return intercept(new EconomicMapImpl<>(strategy, other, isSet));
-    }
-
-    public static <K, V> EconomicMapImpl<K, V> create(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
-        return intercept(new EconomicMapImpl<>(strategy, other, isSet));
-    }
-
-    private EconomicMapImpl(Equivalence strategy, boolean isSet) {
-        if (strategy == Equivalence.IDENTITY) {
-            this.strategy = null;
-        } else {
-            this.strategy = strategy;
-        }
-        this.isSet = isSet;
-    }
-
-    private EconomicMapImpl(Equivalence strategy, int initialCapacity, boolean isSet) {
-        this(strategy, isSet);
-        init(initialCapacity);
-    }
-
-    private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicMap<K, V> other, boolean isSet) {
-        this(strategy, isSet);
-        if (!initFrom(other)) {
-            init(other.size());
-            putAll(other);
-        }
-    }
-
-    private EconomicMapImpl(Equivalence strategy, UnmodifiableEconomicSet<K> other, boolean isSet) {
-        this(strategy, isSet);
-        if (!initFrom(other)) {
-            init(other.size());
-            addAll(other);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private boolean initFrom(Object o) {
-        if (o instanceof EconomicMapImpl) {
-            EconomicMapImpl<K, V> otherMap = (EconomicMapImpl<K, V>) o;
-            // We are only allowed to directly copy if the strategies of the two maps are the same.
-            if (strategy == otherMap.strategy) {
-                totalEntries = otherMap.totalEntries;
-                deletedEntries = otherMap.deletedEntries;
-                if (otherMap.entries != null) {
-                    entries = otherMap.entries.clone();
-                }
-                if (otherMap.hashArray != null) {
-                    hashArray = otherMap.hashArray.clone();
-                }
-                return true;
-            }
-        }
-        return false;
-    }
-
-    private void init(int size) {
-        if (size > INITIAL_CAPACITY) {
-            entries = new Object[size << 1];
-        }
-    }
-
-    /**
-     * Links the collisions. Needs to be immutable class for allowing efficient shallow copy from
-     * other map on construction.
-     */
-    private static final class CollisionLink {
-
-        CollisionLink(Object value, int next) {
-            this.value = value;
-            this.next = next;
-        }
-
-        final Object value;
-
-        /**
-         * Index plus one of the next entry in the collision link chain.
-         */
-        final int next;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public V get(K key) {
-        Objects.requireNonNull(key);
-
-        int index = find(key);
-        if (index != -1) {
-            return (V) getValue(index);
-        }
-        return null;
-    }
-
-    private int find(K key) {
-        if (hasHashArray()) {
-            return findHash(key);
-        } else {
-            return findLinear(key);
-        }
-    }
-
-    private int findLinear(K key) {
-        for (int i = 0; i < totalEntries; i++) {
-            Object entryKey = entries[i << 1];
-            if (entryKey != null && compareKeys(key, entryKey)) {
-                return i;
-            }
-        }
-        return -1;
-    }
-
-    private boolean compareKeys(Object key, Object entryKey) {
-        if (key == entryKey) {
-            return true;
-        }
-        if (strategy != null && strategy != Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
-            if (strategy == Equivalence.DEFAULT) {
-                return key.equals(entryKey);
-            } else {
-                return strategy.equals(key, entryKey);
-            }
-        }
-        return false;
-    }
-
-    private int findHash(K key) {
-        int index = getHashArray(getHashIndex(key)) - 1;
-        if (index != -1) {
-            Object entryKey = getKey(index);
-            if (compareKeys(key, entryKey)) {
-                return index;
-            } else {
-                Object entryValue = getRawValue(index);
-                if (entryValue instanceof CollisionLink) {
-                    return findWithCollision(key, (CollisionLink) entryValue);
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    private int findWithCollision(K key, CollisionLink initialEntryValue) {
-        int index;
-        Object entryKey;
-        CollisionLink entryValue = initialEntryValue;
-        while (true) {
-            CollisionLink collisionLink = entryValue;
-            index = collisionLink.next;
-            entryKey = getKey(index);
-            if (compareKeys(key, entryKey)) {
-                return index;
-            } else {
-                Object value = getRawValue(index);
-                if (value instanceof CollisionLink) {
-                    entryValue = (CollisionLink) getRawValue(index);
-                } else {
-                    return -1;
-                }
-            }
-        }
-    }
-
-    private int getHashArray(int index) {
-        if (entries.length < LARGE_HASH_THRESHOLD) {
-            return (hashArray[index] & 0xFF);
-        } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
-            int adjustedIndex = index << 1;
-            return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8);
-        } else {
-            int adjustedIndex = index << 2;
-            return (hashArray[adjustedIndex] & 0xFF) | ((hashArray[adjustedIndex + 1] & 0xFF) << 8) | ((hashArray[adjustedIndex + 2] & 0xFF) << 16) | ((hashArray[adjustedIndex + 3] & 0xFF) << 24);
-        }
-    }
-
-    private void setHashArray(int index, int value) {
-        if (entries.length < LARGE_HASH_THRESHOLD) {
-            hashArray[index] = (byte) value;
-        } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
-            int adjustedIndex = index << 1;
-            hashArray[adjustedIndex] = (byte) value;
-            hashArray[adjustedIndex + 1] = (byte) (value >> 8);
-        } else {
-            int adjustedIndex = index << 2;
-            hashArray[adjustedIndex] = (byte) value;
-            hashArray[adjustedIndex + 1] = (byte) (value >> 8);
-            hashArray[adjustedIndex + 2] = (byte) (value >> 16);
-            hashArray[adjustedIndex + 3] = (byte) (value >> 24);
-        }
-    }
-
-    private int findAndRemoveHash(Object key) {
-        int hashIndex = getHashIndex(key);
-        int index = getHashArray(hashIndex) - 1;
-        if (index != -1) {
-            Object entryKey = getKey(index);
-            if (compareKeys(key, entryKey)) {
-                Object value = getRawValue(index);
-                int nextIndex = -1;
-                if (value instanceof CollisionLink) {
-                    CollisionLink collisionLink = (CollisionLink) value;
-                    nextIndex = collisionLink.next;
-                }
-                setHashArray(hashIndex, nextIndex + 1);
-                return index;
-            } else {
-                Object entryValue = getRawValue(index);
-                if (entryValue instanceof CollisionLink) {
-                    return findAndRemoveWithCollision(key, (CollisionLink) entryValue, index);
-                }
-            }
-        }
-
-        return -1;
-    }
-
-    private int findAndRemoveWithCollision(Object key, CollisionLink initialEntryValue, int initialIndexValue) {
-        int index;
-        Object entryKey;
-        CollisionLink entryValue = initialEntryValue;
-        int lastIndex = initialIndexValue;
-        while (true) {
-            CollisionLink collisionLink = entryValue;
-            index = collisionLink.next;
-            entryKey = getKey(index);
-            if (compareKeys(key, entryKey)) {
-                Object value = getRawValue(index);
-                if (value instanceof CollisionLink) {
-                    CollisionLink thisCollisionLink = (CollisionLink) value;
-                    setRawValue(lastIndex, new CollisionLink(collisionLink.value, thisCollisionLink.next));
-                } else {
-                    setRawValue(lastIndex, collisionLink.value);
-                }
-                return index;
-            } else {
-                Object value = getRawValue(index);
-                if (value instanceof CollisionLink) {
-                    entryValue = (CollisionLink) getRawValue(index);
-                    lastIndex = index;
-                } else {
-                    return -1;
-                }
-            }
-        }
-    }
-
-    private int getHashIndex(Object key) {
-        int hash;
-        if (strategy != null && strategy != Equivalence.DEFAULT) {
-            if (strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
-                hash = System.identityHashCode(key);
-            } else {
-                hash = strategy.hashCode(key);
-            }
-        } else {
-            hash = key.hashCode();
-        }
-        hash = hash ^ (hash >>> 16);
-        return hash & (getHashTableSize() - 1);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public V put(K key, V value) {
-        if (key == null) {
-            throw new UnsupportedOperationException("null not supported as key!");
-        }
-        int index = find(key);
-        if (index != -1) {
-            Object oldValue = getValue(index);
-            setValue(index, value);
-            return (V) oldValue;
-        }
-
-        int nextEntryIndex = totalEntries;
-        if (entries == null) {
-            entries = new Object[INITIAL_CAPACITY << 1];
-        } else if (entries.length == nextEntryIndex << 1) {
-            grow();
-
-            assert entries.length > totalEntries << 1;
-            // Can change if grow is actually compressing.
-            nextEntryIndex = totalEntries;
-        }
-
-        setKey(nextEntryIndex, key);
-        setValue(nextEntryIndex, value);
-        totalEntries++;
-
-        if (hasHashArray()) {
-            // Rehash on collision if hash table is more than three quarters full.
-            boolean rehashOnCollision = (getHashTableSize() < (size() + (size() >> 1)));
-            putHashEntry(key, nextEntryIndex, rehashOnCollision);
-        } else if (totalEntries > getHashThreshold()) {
-            createHash();
-        }
-
-        return null;
-    }
-
-    /**
-     * Number of entries above which a hash table should be constructed.
-     */
-    private int getHashThreshold() {
-        if (strategy == null || strategy == Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE) {
-            return HASH_THRESHOLD_IDENTITY_COMPARE;
-        } else {
-            return HASH_THRESHOLD;
-        }
-    }
-
-    private void grow() {
-        int entriesLength = entries.length;
-        int newSize = (entriesLength >> 1) + Math.max(MIN_CAPACITY_INCREASE, entriesLength >> 2);
-        if (newSize > MAX_ELEMENT_COUNT) {
-            throw new UnsupportedOperationException("map grown too large!");
-        }
-        Object[] newEntries = new Object[newSize << 1];
-        System.arraycopy(entries, 0, newEntries, 0, entriesLength);
-        entries = newEntries;
-        if ((entriesLength < LARGE_HASH_THRESHOLD && newEntries.length >= LARGE_HASH_THRESHOLD) ||
-                        (entriesLength < VERY_LARGE_HASH_THRESHOLD && newEntries.length > VERY_LARGE_HASH_THRESHOLD)) {
-            // Rehash in order to change number of bits reserved for hash indices.
-            createHash();
-        }
-    }
-
-    /**
-     * Compresses the graph if there is a large number of deleted entries and returns the translated
-     * new next index.
-     */
-    private int maybeCompress(int nextIndex) {
-        if (entries.length != INITIAL_CAPACITY << 1 && deletedEntries >= (totalEntries >> 1) + (totalEntries >> 2)) {
-            return compressLarge(nextIndex);
-        }
-        return nextIndex;
-    }
-
-    /**
-     * Compresses the graph and returns the translated new next index.
-     */
-    private int compressLarge(int nextIndex) {
-        int size = INITIAL_CAPACITY;
-        int remaining = totalEntries - deletedEntries;
-
-        while (size <= remaining) {
-            size += Math.max(MIN_CAPACITY_INCREASE, size >> 1);
-        }
-
-        Object[] newEntries = new Object[size << 1];
-        int z = 0;
-        int newNextIndex = remaining;
-        for (int i = 0; i < totalEntries; ++i) {
-            Object key = getKey(i);
-            if (i == nextIndex) {
-                newNextIndex = z;
-            }
-            if (key != null) {
-                newEntries[z << 1] = key;
-                newEntries[(z << 1) + 1] = getValue(i);
-                z++;
-            }
-        }
-
-        this.entries = newEntries;
-        totalEntries = z;
-        deletedEntries = 0;
-        if (z <= getHashThreshold()) {
-            this.hashArray = null;
-        } else {
-            createHash();
-        }
-        return newNextIndex;
-    }
-
-    private int getHashTableSize() {
-        if (entries.length < LARGE_HASH_THRESHOLD) {
-            return hashArray.length;
-        } else if (entries.length < VERY_LARGE_HASH_THRESHOLD) {
-            return hashArray.length >> 1;
-        } else {
-            return hashArray.length >> 2;
-        }
-    }
-
-    private void createHash() {
-        int entryCount = size();
-
-        // Calculate smallest 2^n that is greater number of entries.
-        int size = getHashThreshold();
-        while (size <= entryCount) {
-            size <<= 1;
-        }
-
-        // Give extra size to avoid collisions.
-        size <<= 1;
-
-        if (this.entries.length >= VERY_LARGE_HASH_THRESHOLD) {
-            // Every entry has 4 bytes.
-            size <<= 2;
-        } else if (this.entries.length >= LARGE_HASH_THRESHOLD) {
-            // Every entry has 2 bytes.
-            size <<= 1;
-        } else {
-            // Entries are very small => give extra size to further reduce collisions.
-            size <<= 1;
-        }
-
-        hashArray = new byte[size];
-        for (int i = 0; i < totalEntries; i++) {
-            Object entryKey = getKey(i);
-            if (entryKey != null) {
-                putHashEntry(entryKey, i, false);
-            }
-        }
-    }
-
-    private void putHashEntry(Object key, int entryIndex, boolean rehashOnCollision) {
-        int hashIndex = getHashIndex(key);
-        int oldIndex = getHashArray(hashIndex) - 1;
-        if (oldIndex != -1 && rehashOnCollision) {
-            this.createHash();
-            return;
-        }
-        setHashArray(hashIndex, entryIndex + 1);
-        Object value = getRawValue(entryIndex);
-        if (oldIndex != -1) {
-            assert entryIndex != oldIndex : "this cannot happend and would create an endless collision link cycle";
-            if (value instanceof CollisionLink) {
-                CollisionLink collisionLink = (CollisionLink) value;
-                setRawValue(entryIndex, new CollisionLink(collisionLink.value, oldIndex));
-            } else {
-                setRawValue(entryIndex, new CollisionLink(getRawValue(entryIndex), oldIndex));
-            }
-        } else {
-            if (value instanceof CollisionLink) {
-                CollisionLink collisionLink = (CollisionLink) value;
-                setRawValue(entryIndex, collisionLink.value);
-            }
-        }
-    }
-
-    @Override
-    public int size() {
-        return totalEntries - deletedEntries;
-    }
-
-    @Override
-    public boolean containsKey(K key) {
-        return find(key) != -1;
-    }
-
-    @Override
-    public void clear() {
-        entries = null;
-        hashArray = null;
-        totalEntries = deletedEntries = 0;
-    }
-
-    private boolean hasHashArray() {
-        return hashArray != null;
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public V removeKey(K key) {
-        if (key == null) {
-            throw new UnsupportedOperationException("null not supported as key!");
-        }
-        int index;
-        if (hasHashArray()) {
-            index = this.findAndRemoveHash(key);
-        } else {
-            index = this.findLinear(key);
-        }
-
-        if (index != -1) {
-            Object value = getValue(index);
-            remove(index);
-            return (V) value;
-        }
-        return null;
-    }
-
-    /**
-     * Removes the element at the specific index and returns the index of the next element. This can
-     * be a different value if graph compression was triggered.
-     */
-    private int remove(int indexToRemove) {
-        int index = indexToRemove;
-        int entriesAfterIndex = totalEntries - index - 1;
-        int result = index + 1;
-
-        // Without hash array, compress immediately.
-        if (entriesAfterIndex <= COMPRESS_IMMEDIATE_CAPACITY && !hasHashArray()) {
-            while (index < totalEntries - 1) {
-                setKey(index, getKey(index + 1));
-                setRawValue(index, getRawValue(index + 1));
-                index++;
-            }
-            result--;
-        }
-
-        setKey(index, null);
-        setRawValue(index, null);
-        if (index == totalEntries - 1) {
-            // Make sure last element is always non-null.
-            totalEntries--;
-            while (index > 0 && getKey(index - 1) == null) {
-                totalEntries--;
-                deletedEntries--;
-                index--;
-            }
-        } else {
-            deletedEntries++;
-            result = maybeCompress(result);
-        }
-
-        return result;
-    }
-
-    private abstract class SparseMapIterator<E> implements Iterator<E> {
-
-        protected int current;
-
-        @Override
-        public boolean hasNext() {
-            return current < totalEntries;
-        }
-
-        @Override
-        public void remove() {
-            if (hasHashArray()) {
-                EconomicMapImpl.this.findAndRemoveHash(getKey(current - 1));
-            }
-            current = EconomicMapImpl.this.remove(current - 1);
-        }
-    }
-
-    @Override
-    public Iterable<V> getValues() {
-        return new Iterable<V>() {
-            @Override
-            public Iterator<V> iterator() {
-                return new SparseMapIterator<V>() {
-                    @SuppressWarnings("unchecked")
-                    @Override
-                    public V next() {
-                        Object result;
-                        while (true) {
-                            result = getValue(current);
-                            if (result == null && getKey(current) == null) {
-                                // values can be null, double-check if key is also null
-                                current++;
-                            } else {
-                                current++;
-                                break;
-                            }
-                        }
-                        return (V) result;
-                    }
-                };
-            }
-        };
-    }
-
-    @Override
-    public Iterable<K> getKeys() {
-        return this;
-    }
-
-    @Override
-    public boolean isEmpty() {
-        return this.size() == 0;
-    }
-
-    @Override
-    public MapCursor<K, V> getEntries() {
-        return new MapCursor<K, V>() {
-            int current = -1;
-
-            @Override
-            public boolean advance() {
-                current++;
-                if (current >= totalEntries) {
-                    return false;
-                } else {
-                    while (EconomicMapImpl.this.getKey(current) == null) {
-                        // Skip over null entries
-                        current++;
-                    }
-                    return true;
-                }
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public K getKey() {
-                return (K) EconomicMapImpl.this.getKey(current);
-            }
-
-            @SuppressWarnings("unchecked")
-            @Override
-            public V getValue() {
-                return (V) EconomicMapImpl.this.getValue(current);
-            }
-
-            @Override
-            public void remove() {
-                if (hasHashArray()) {
-                    EconomicMapImpl.this.findAndRemoveHash(EconomicMapImpl.this.getKey(current));
-                }
-                current = EconomicMapImpl.this.remove(current) - 1;
-            }
-        };
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
-        for (int i = 0; i < totalEntries; i++) {
-            Object entryKey = getKey(i);
-            if (entryKey != null) {
-                Object newValue = function.apply((K) entryKey, (V) getValue(i));
-                setValue(i, newValue);
-            }
-        }
-    }
-
-    private Object getKey(int index) {
-        return entries[index << 1];
-    }
-
-    private void setKey(int index, Object newValue) {
-        entries[index << 1] = newValue;
-    }
-
-    private void setValue(int index, Object newValue) {
-        Object oldValue = getRawValue(index);
-        if (oldValue instanceof CollisionLink) {
-            CollisionLink collisionLink = (CollisionLink) oldValue;
-            setRawValue(index, new CollisionLink(newValue, collisionLink.next));
-        } else {
-            setRawValue(index, newValue);
-        }
-    }
-
-    private void setRawValue(int index, Object newValue) {
-        entries[(index << 1) + 1] = newValue;
-    }
-
-    private Object getRawValue(int index) {
-        return entries[(index << 1) + 1];
-    }
-
-    private Object getValue(int index) {
-        Object object = getRawValue(index);
-        if (object instanceof CollisionLink) {
-            return ((CollisionLink) object).value;
-        }
-        return object;
-    }
-
-    private final boolean isSet;
-
-    @Override
-    public String toString() {
-        StringBuilder builder = new StringBuilder();
-        builder.append(isSet ? "set(size=" : "map(size=").append(size()).append(", {");
-        String sep = "";
-        MapCursor<K, V> cursor = getEntries();
-        while (cursor.advance()) {
-            builder.append(sep);
-            if (isSet) {
-                builder.append(cursor.getKey());
-            } else {
-                builder.append("(").append(cursor.getKey()).append(",").append(cursor.getValue()).append(")");
-            }
-            sep = ",";
-        }
-        builder.append("})");
-        return builder.toString();
-    }
-
-    @Override
-    public Iterator<K> iterator() {
-        return new SparseMapIterator<K>() {
-            @SuppressWarnings("unchecked")
-            @Override
-            public K next() {
-                Object result;
-                while ((result = getKey(current++)) == null) {
-                    // skip null entries
-                }
-                return (K) result;
-            }
-        };
-    }
-
-    @Override
-    public boolean contains(K element) {
-        return containsKey(element);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public boolean add(K element) {
-        return put(element, (V) element) == null;
-    }
-
-    @Override
-    public void remove(K element) {
-        removeKey(element);
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Iterator;
-
-/**
- * Memory efficient set data structure.
- *
- * @since 1.0
- */
-public interface EconomicSet<E> extends UnmodifiableEconomicSet<E> {
-
-    /**
-     * Adds {@code element} to this set if it is not already present.
-     *
-     * @return {@code true} if this set did not already contain {@code element}.
-     * @since 1.0
-     */
-    boolean add(E element);
-
-    /**
-     * Removes {@code element} from this set if it is present. This set will not contain
-     * {@code element} once the call returns.
-     *
-     * @since 1.0
-     */
-    void remove(E element);
-
-    /**
-     * Removes all of the elements from this set. The set will be empty after this call returns.
-     *
-     * @since 1.0
-     */
-    void clear();
-
-    /**
-     * Adds all of the elements in {@code other} to this set if they're not already present.
-     *
-     * @since 1.0
-     */
-    default void addAll(EconomicSet<E> other) {
-        addAll(other.iterator());
-    }
-
-    /**
-     * Adds all of the elements in {@code values} to this set if they're not already present.
-     *
-     * @since 1.0
-     */
-    default void addAll(Iterable<E> values) {
-        addAll(values.iterator());
-    }
-
-    /**
-     * Adds all of the elements enumerated by {@code iterator} to this set if they're not already
-     * present.
-     *
-     * @since 1.0
-     */
-    default void addAll(Iterator<E> iterator) {
-        while (iterator.hasNext()) {
-            add(iterator.next());
-        }
-    }
-
-    /**
-     * Removes from this set all of its elements that are contained in {@code other}.
-     *
-     * @since 1.0
-     */
-    default void removeAll(EconomicSet<E> other) {
-        removeAll(other.iterator());
-    }
-
-    /**
-     * Removes from this set all of its elements that are contained in {@code values}.
-     *
-     * @since 1.0
-     */
-    default void removeAll(Iterable<E> values) {
-        removeAll(values.iterator());
-    }
-
-    /**
-     * Removes from this set all of its elements that are enumerated by {@code iterator}.
-     *
-     * @since 1.0
-     */
-    default void removeAll(Iterator<E> iterator) {
-        while (iterator.hasNext()) {
-            remove(iterator.next());
-        }
-    }
-
-    /**
-     * Removes from this set all of its elements that are not contained in {@code other}.
-     *
-     * @since 1.0
-     */
-    default void retainAll(EconomicSet<E> other) {
-        Iterator<E> iterator = iterator();
-        while (iterator.hasNext()) {
-            E key = iterator.next();
-            if (!other.contains(key)) {
-                iterator.remove();
-            }
-        }
-    }
-
-    /**
-     * Creates a new set guaranteeing insertion order when iterating over its elements with the
-     * default {@link Equivalence#DEFAULT} comparison strategy.
-     *
-     * @since 1.0
-     */
-    static <E> EconomicSet<E> create() {
-        return EconomicSet.create(Equivalence.DEFAULT);
-    }
-
-    /**
-     * Creates a new set guaranteeing insertion order when iterating over its elements.
-     *
-     * @since 1.0
-     */
-    static <E> EconomicSet<E> create(Equivalence strategy) {
-        return EconomicMapImpl.create(strategy, true);
-    }
-
-    /**
-     * Creates a new set guaranteeing insertion order when iterating over its elements with the
-     * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
-     * specified collection.
-     *
-     * @since 1.0
-     */
-    static <E> EconomicSet<E> create(int initialCapacity) {
-        return EconomicSet.create(Equivalence.DEFAULT, initialCapacity);
-    }
-
-    /**
-     * Creates a new set guaranteeing insertion order when iterating over its elements with the
-     * default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
-     * specified collection.
-     *
-     * @since 1.0
-     */
-    static <E> EconomicSet<E> create(UnmodifiableEconomicSet<E> c) {
-        return EconomicSet.create(Equivalence.DEFAULT, c);
-    }
-
-    /**
-     * Creates a new set guaranteeing insertion order when iterating over its elements and
-     * initializes with the given capacity.
-     *
-     * @since 1.0
-     */
-    static <E> EconomicSet<E> create(Equivalence strategy, int initialCapacity) {
-        return EconomicMapImpl.create(strategy, initialCapacity, true);
-    }
-
-    /**
-     * Creates a new set guaranteeing insertion order when iterating over its elements and inserts
-     * all elements of the specified collection.
-     *
-     * @since 1.0
-     */
-    static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E> c) {
-        return EconomicMapImpl.create(strategy, c, true);
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Equivalence.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Strategy for comparing two objects. Default predefined strategies are {@link #DEFAULT},
- * {@link #IDENTITY}, and {@link #IDENTITY_WITH_SYSTEM_HASHCODE}.
- *
- * @since 1.0
- */
-public abstract class Equivalence {
-
-    /**
-     * Default equivalence calling {@link #equals(Object)} to check equality and {@link #hashCode()}
-     * for obtaining hash values. Do not change the logic of this class as it may be inlined in
-     * other places.
-     *
-     * @since 1.0
-     */
-    public static final Equivalence DEFAULT = new Equivalence() {
-
-        @Override
-        public boolean equals(Object a, Object b) {
-            return a.equals(b);
-        }
-
-        @Override
-        public int hashCode(Object o) {
-            return o.hashCode();
-        }
-    };
-
-    /**
-     * Identity equivalence using {@code ==} to check equality and {@link #hashCode()} for obtaining
-     * hash values. Do not change the logic of this class as it may be inlined in other places.
-     *
-     * @since 1.0
-     */
-    public static final Equivalence IDENTITY = new Equivalence() {
-
-        @Override
-        public boolean equals(Object a, Object b) {
-            return a == b;
-        }
-
-        @Override
-        public int hashCode(Object o) {
-            return o.hashCode();
-        }
-    };
-
-    /**
-     * Identity equivalence using {@code ==} to check equality and
-     * {@link System#identityHashCode(Object)} for obtaining hash values. Do not change the logic of
-     * this class as it may be inlined in other places.
-     *
-     * @since 1.0
-     */
-    public static final Equivalence IDENTITY_WITH_SYSTEM_HASHCODE = new Equivalence() {
-
-        @Override
-        public boolean equals(Object a, Object b) {
-            return a == b;
-        }
-
-        @Override
-        public int hashCode(Object o) {
-            return System.identityHashCode(o);
-        }
-    };
-
-    /**
-     * Subclass for creating custom equivalence definitions.
-     *
-     * @since 1.0
-     */
-    protected Equivalence() {
-    }
-
-    /**
-     * Returns {@code true} if the non-{@code null} arguments are equal to each other and
-     * {@code false} otherwise.
-     *
-     * @since 1.0
-     */
-    public abstract boolean equals(Object a, Object b);
-
-    /**
-     * Returns the hash code of a non-{@code null} argument {@code o}.
-     *
-     * @since 1.0
-     */
-    public abstract int hashCode(Object o);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/MapCursor.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Cursor to iterate over a mutable map.
- *
- * @since 1.0
- */
-public interface MapCursor<K, V> extends UnmodifiableMapCursor<K, V> {
-    /**
-     * Remove the current entry from the map. May only be called once. After calling
-     * {@link #remove()}, it is no longer valid to call {@link #getKey()} or {@link #getValue()} on
-     * the current entry.
-     *
-     * @since 1.0
-     */
-    void remove();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/Pair.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,158 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-import java.util.Objects;
-
-/**
- * Utility class representing a pair of values.
- *
- * @since 1.0
- */
-public final class Pair<L, R> {
-
-    private static final Pair<Object, Object> EMPTY = new Pair<>(null, null);
-
-    private final L left;
-    private final R right;
-
-    /**
-     * Returns an empty pair.
-     *
-     * @since 1.0
-     */
-    @SuppressWarnings("unchecked")
-    public static <L, R> Pair<L, R> empty() {
-        return (Pair<L, R>) EMPTY;
-    }
-
-    /**
-     * Constructs a pair with its left value being {@code left}, or returns an empty pair if
-     * {@code left} is null.
-     *
-     * @return the constructed pair or an empty pair if {@code left} is null.
-     * @since 1.0
-     */
-    public static <L, R> Pair<L, R> createLeft(L left) {
-        if (left == null) {
-            return empty();
-        } else {
-            return new Pair<>(left, null);
-        }
-    }
-
-    /**
-     * Constructs a pair with its right value being {@code right}, or returns an empty pair if
-     * {@code right} is null.
-     *
-     * @return the constructed pair or an empty pair if {@code right} is null.
-     * @since 1.0
-     */
-    public static <L, R> Pair<L, R> createRight(R right) {
-        if (right == null) {
-            return empty();
-        } else {
-            return new Pair<>(null, right);
-        }
-    }
-
-    /**
-     * Constructs a pair with its left value being {@code left}, and its right value being
-     * {@code right}, or returns an empty pair if both inputs are null.
-     *
-     * @return the constructed pair or an empty pair if both inputs are null.
-     * @since 1.0
-     */
-    public static <L, R> Pair<L, R> create(L left, R right) {
-        if (right == null && left == null) {
-            return empty();
-        } else {
-            return new Pair<>(left, right);
-        }
-    }
-
-    private Pair(L left, R right) {
-        this.left = left;
-        this.right = right;
-    }
-
-    /**
-     * Returns the left value of this pair.
-     *
-     * @since 1.0
-     */
-    public L getLeft() {
-        return left;
-    }
-
-    /**
-     * Returns the right value of this pair.
-     *
-     * @since 1.0
-     */
-    public R getRight() {
-        return right;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @since 1.0
-     */
-    @Override
-    public int hashCode() {
-        return Objects.hashCode(left) + 31 * Objects.hashCode(right);
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @since 1.0
-     */
-    @SuppressWarnings("unchecked")
-    @Override
-    public boolean equals(Object obj) {
-        if (obj == this) {
-            return true;
-        }
-
-        if (obj instanceof Pair) {
-            Pair<L, R> pair = (Pair<L, R>) obj;
-            return Objects.equals(left, pair.left) && Objects.equals(right, pair.right);
-        }
-
-        return false;
-    }
-
-    /**
-     * {@inheritDoc}
-     *
-     * @since 1.0
-     */
-    @Override
-    public String toString() {
-        return String.format("(%s, %s)", left, right);
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicMap.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Unmodifiable memory efficient map data structure.
- *
- * @since 1.0
- */
-public interface UnmodifiableEconomicMap<K, V> {
-
-    /**
-     * Returns the value to which {@code key} is mapped, or {@code null} if this map contains no
-     * mapping for {@code key}.
-     *
-     * @since 1.0
-     */
-    V get(K key);
-
-    /**
-     * Returns the value to which {@code key} is mapped, or {@code defaultValue} if this map
-     * contains no mapping for {@code key}.
-     *
-     * @since 1.0
-     */
-    default V get(K key, V defaultValue) {
-        V v = get(key);
-        if (v == null) {
-            return defaultValue;
-        }
-        return v;
-    }
-
-    /**
-     * Returns {@code true} if this map contains a mapping for {@code key}.
-     *
-     * @since 1.0
-     */
-    boolean containsKey(K key);
-
-    /**
-     * Returns the number of key-value mappings in this map.
-     *
-     * @since 1.0
-     */
-    int size();
-
-    /**
-     * Returns {@code true} if this map contains no key-value mappings.
-     *
-     * @since 1.0
-     */
-    boolean isEmpty();
-
-    /**
-     * Returns a {@link Iterable} view of the values contained in this map.
-     *
-     * @since 1.0
-     */
-    Iterable<V> getValues();
-
-    /**
-     * Returns a {@link Iterable} view of the keys contained in this map.
-     *
-     * @since 1.0
-     */
-    Iterable<K> getKeys();
-
-    /**
-     * Returns a {@link UnmodifiableMapCursor} view of the mappings contained in this map.
-     *
-     * @since 1.0
-     */
-    UnmodifiableMapCursor<K, V> getEntries();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableEconomicSet.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Unmodifiable memory efficient set data structure.
- *
- * @since 1.0
- */
-public interface UnmodifiableEconomicSet<E> extends Iterable<E> {
-
-    /**
-     * Returns {@code true} if this set contains a mapping for the {@code element}.
-     *
-     * @since 1.0
-     */
-    boolean contains(E element);
-
-    /**
-     * Returns the number of elements in this set.
-     *
-     * @since 1.0
-     */
-    int size();
-
-    /**
-     * Returns {@code true} if this set contains no elements.
-     *
-     * @since 1.0
-     */
-    boolean isEmpty();
-
-    /**
-     * Stores all of the elements in this set into {@code target}. An
-     * {@link UnsupportedOperationException} will be thrown if the length of {@code target} does not
-     * match the size of this set.
-     *
-     * @return an array containing all the elements in this set.
-     * @throws UnsupportedOperationException if the length of {@code target} does not equal the size
-     *             of this set.
-     * @since 1.0
-     */
-    default E[] toArray(E[] target) {
-        if (target.length != size()) {
-            throw new UnsupportedOperationException("Length of target array must equal the size of the set.");
-        }
-
-        int index = 0;
-        for (E element : this) {
-            target[index++] = element;
-        }
-
-        return target;
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/UnmodifiableMapCursor.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.collections;
-
-/**
- * Cursor to iterate over a map without changing its contents.
- *
- * @since 1.0
- */
-public interface UnmodifiableMapCursor<K, V> {
-    /**
-     * Advances to the next entry.
-     *
-     * @return {@code true} if a next entry exists, {@code false} if there is no next entry.
-     * @since 1.0
-     */
-    boolean advance();
-
-    /**
-     * The key of the current entry.
-     *
-     * @since 1.0
-     */
-    K getKey();
-
-    /**
-     * The value of the current entry.
-     *
-     * @since 1.0
-     */
-    V getValue();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.collections/src/org/graalvm/collections/package-info.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,33 +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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-/**
- * The Graal-SDK collections package contains memory efficient data structures.
- *
- * @see org.graalvm.collections.EconomicMap
- * @see org.graalvm.collections.EconomicSet
- *
- * @since 1.0
- */
-package org.graalvm.collections;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64.test/src/org/graalvm/compiler/asm/aarch64/test/TestProtectedAssembler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -206,12 +206,12 @@
     }
 
     @Override
-    protected void bfm(int size, Register dst, Register src, int r, int s) {
+    public void bfm(int size, Register dst, Register src, int r, int s) {
         super.bfm(size, dst, src, r, s);
     }
 
     @Override
-    protected void ubfm(int size, Register dst, Register src, int r, int s) {
+    public void ubfm(int size, Register dst, Register src, int r, int s) {
         super.ubfm(size, dst, src, r, s);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.asm.aarch64/src/org/graalvm/compiler/asm/aarch64/AArch64Assembler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BLR;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BR;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.BRK;
+import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CAS;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLREX;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLS;
 import static org.graalvm.compiler.asm.aarch64.AArch64Assembler.Instruction.CLZ;
@@ -118,6 +119,9 @@
 import org.graalvm.compiler.asm.aarch64.AArch64Address.AddressingMode;
 import org.graalvm.compiler.debug.GraalError;
 
+import jdk.vm.ci.aarch64.AArch64;
+import jdk.vm.ci.aarch64.AArch64.CPUFeature;
+import jdk.vm.ci.aarch64.AArch64.Flag;
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.TargetDescription;
 
@@ -471,6 +475,9 @@
     private static final int BarrierOp = 0xD503301F;
     private static final int BarrierKindOffset = 8;
 
+    private static final int CASAcquireOffset = 22;
+    private static final int CASReleaseOffset = 15;
+
     /**
      * Encoding for all instructions.
      */
@@ -501,6 +508,8 @@
         LDP(0b1 << 22),
         STP(0b0 << 22),
 
+        CAS(0x08A07C00),
+
         ADR(0x00000000),
         ADRP(0x80000000),
 
@@ -740,6 +749,14 @@
         super(target);
     }
 
+    public boolean supports(CPUFeature feature) {
+        return ((AArch64) target.arch).getFeatures().contains(feature);
+    }
+
+    public boolean isFlagSet(Flag flag) {
+        return ((AArch64) target.arch).getFlags().contains(flag);
+    }
+
     /* Conditional Branch (5.2.1) */
 
     /**
@@ -1311,6 +1328,20 @@
         emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt));
     }
 
+    /* Compare And Swap */
+    public void cas(int size, Register rs, Register rt, Register rn, boolean acquire, boolean release) {
+        assert size == 32 || size == 64;
+        int transferSize = NumUtil.log2Ceil(size / 8);
+        compareAndSwapInstruction(CAS, rs, rt, rn, transferSize, acquire, release);
+    }
+
+    private void compareAndSwapInstruction(Instruction instr, Register rs, Register rt, Register rn, int log2TransferSize, boolean acquire, boolean release) {
+        assert log2TransferSize >= 0 && log2TransferSize < 4;
+        assert rt.getRegisterCategory().equals(CPU) && rs.getRegisterCategory().equals(CPU) && !rs.equals(rt);
+        int transferSizeEncoding = log2TransferSize << LoadStoreTransferSizeOffset;
+        emitInt(transferSizeEncoding | instr.encoding | rs2(rs) | rn(rn) | rt(rt) | (acquire ? 1 : 0) << CASAcquireOffset | (release ? 1 : 0) << CASReleaseOffset);
+    }
+
     /* PC-relative Address Calculation (5.4.4) */
 
     /**
@@ -1576,7 +1607,7 @@
      * @param r must be in the range 0 to size - 1
      * @param s must be in the range 0 to size - 1
      */
-    protected void bfm(int size, Register dst, Register src, int r, int s) {
+    public void bfm(int size, Register dst, Register src, int r, int s) {
         bitfieldInstruction(BFM, dst, src, r, s, generalFromSize(size));
     }
 
@@ -1589,7 +1620,7 @@
      * @param r must be in the range 0 to size - 1
      * @param s must be in the range 0 to size - 1
      */
-    protected void ubfm(int size, Register dst, Register src, int r, int s) {
+    public void ubfm(int size, Register dst, Register src, int r, int s) {
         bitfieldInstruction(UBFM, dst, src, r, s, generalFromSize(size));
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/CompilationResult.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import java.util.List;
 import java.util.Objects;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.graph.NodeSourcePosition;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.code/src/org/graalvm/compiler/code/SourceStackTraceBailoutException.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
 public abstract class SourceStackTraceBailoutException extends PermanentBailoutException {
     private static final long serialVersionUID = 2144811793442316776L;
 
-    public static SourceStackTraceBailoutException create(Throwable cause, String format, StackTraceElement[] elements) {
-        return new SourceStackTraceBailoutException(cause, format) {
+    public static SourceStackTraceBailoutException create(Throwable cause, String reason, StackTraceElement[] elements) {
+        return new SourceStackTraceBailoutException(cause, reason) {
 
             private static final long serialVersionUID = 6279381376051787907L;
 
@@ -46,7 +46,7 @@
         };
     }
 
-    private SourceStackTraceBailoutException(Throwable cause, String format) {
-        super(cause, format);
+    private SourceStackTraceBailoutException(Throwable cause, String reason) {
+        super(cause, "%s", reason);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64LIRGenerator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,6 +42,7 @@
 import org.graalvm.compiler.lir.Variable;
 import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
 import org.graalvm.compiler.lir.aarch64.AArch64ArithmeticOp;
+import org.graalvm.compiler.lir.aarch64.AArch64ArrayCompareToOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ArrayEqualsOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ByteSwapOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Compare;
@@ -51,13 +52,14 @@
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.StrategySwitchOp;
 import org.graalvm.compiler.lir.aarch64.AArch64ControlFlow.TableSwitchOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Move;
-import org.graalvm.compiler.lir.aarch64.AArch64Move.CompareAndSwapOp;
+import org.graalvm.compiler.lir.aarch64.AArch64AtomicMove.CompareAndSwapOp;
 import org.graalvm.compiler.lir.aarch64.AArch64Move.MembarOp;
 import org.graalvm.compiler.lir.aarch64.AArch64PauseOp;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.gen.LIRGenerator;
 import org.graalvm.compiler.phases.util.Providers;
 
+import jdk.vm.ci.aarch64.AArch64;
 import jdk.vm.ci.aarch64.AArch64Kind;
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.RegisterValue;
@@ -423,6 +425,21 @@
     }
 
     @Override
+    public Variable emitArrayCompareTo(JavaKind kind1, JavaKind kind2, Value array1, Value array2, Value length1, Value length2) {
+        LIRKind resultKind = LIRKind.value(AArch64Kind.DWORD);
+        // DMS TODO: check calling conversion and registers used
+        RegisterValue res = AArch64.r0.asValue(resultKind);
+        RegisterValue cnt1 = AArch64.r1.asValue(length1.getValueKind());
+        RegisterValue cnt2 = AArch64.r2.asValue(length2.getValueKind());
+        emitMove(cnt1, length1);
+        emitMove(cnt2, length2);
+        append(new AArch64ArrayCompareToOp(this, kind1, kind2, res, array1, array2, cnt1, cnt2));
+        Variable result = newVariable(resultKind);
+        emitMove(result, res);
+        return result;
+    }
+
+    @Override
     public Variable emitArrayEquals(JavaKind kind, Value array1, Value array2, Value length) {
         Variable result = newVariable(LIRKind.value(AArch64Kind.DWORD));
         append(new AArch64ArrayEqualsOp(this, kind, result, array1, array2, asAllocatable(length)));
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,102 @@
+/*
+ * 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.core.aarch64;
+
+import jdk.vm.ci.aarch64.AArch64Kind;
+
+import org.graalvm.compiler.core.common.type.IntegerStamp;
+import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.graph.NodeClass;
+import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
+import org.graalvm.compiler.nodeinfo.NodeInfo;
+import org.graalvm.compiler.nodes.FrameState;
+import org.graalvm.compiler.nodes.NodeView;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.ValueNode;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.extended.GuardingNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.nodes.memory.address.AddressNode;
+import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+
+/**
+ * AArch64-specific subclass of ReadNode that knows how to merge ZeroExtend and SignExtend into the
+ * read.
+ */
+
+@NodeInfo
+public class AArch64ReadNode extends ReadNode {
+    public static final NodeClass<AArch64ReadNode> TYPE = NodeClass.create(AArch64ReadNode.class);
+    private final IntegerStamp accessStamp;
+    private final boolean isSigned;
+
+    public AArch64ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
+                    FrameState stateBefore, IntegerStamp accessStamp, boolean isSigned) {
+        super(TYPE, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
+        this.accessStamp = accessStamp;
+        this.isSigned = isSigned;
+    }
+
+    @Override
+    public void generate(NodeLIRBuilderTool gen) {
+        AArch64LIRGenerator lirgen = (AArch64LIRGenerator) gen.getLIRGeneratorTool();
+        AArch64ArithmeticLIRGenerator arithgen = (AArch64ArithmeticLIRGenerator) lirgen.getArithmetic();
+        AArch64Kind readKind = (AArch64Kind) lirgen.getLIRKind(accessStamp).getPlatformKind();
+        int resultBits = ((IntegerStamp) stamp(NodeView.DEFAULT)).getBits();
+        gen.setResult(this, arithgen.emitExtendMemory(isSigned, readKind, resultBits, (AArch64AddressValue) gen.operand(getAddress()), gen.state(this)));
+    }
+
+    /**
+     * replace a ReadNode with an AArch64-specific variant which knows how to merge a downstream
+     * zero or sign extend into the read operation.
+     *
+     * @param readNode
+     */
+    public static void replace(ReadNode readNode) {
+        assert readNode.getUsageCount() == 1;
+        assert readNode.getUsageAt(0) instanceof ZeroExtendNode || readNode.getUsageAt(0) instanceof SignExtendNode;
+
+        ValueNode usage = (ValueNode) readNode.getUsageAt(0);
+        boolean isSigned = usage instanceof SignExtendNode;
+        IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
+
+        AddressNode address = readNode.getAddress();
+        LocationIdentity location = readNode.getLocationIdentity();
+        Stamp stamp = usage.stamp(NodeView.DEFAULT);
+        GuardingNode guard = readNode.getGuard();
+        BarrierType barrierType = readNode.getBarrierType();
+        boolean nullCheck = readNode.getNullCheck();
+        FrameState stateBefore = readNode.stateBefore();
+        AArch64ReadNode clone = new AArch64ReadNode(address, location, stamp, guard, barrierType, nullCheck, stateBefore, accessStamp, isSigned);
+        StructuredGraph graph = readNode.graph();
+        graph.add(clone);
+        // splice out the extend node
+        usage.replaceAtUsagesAndDelete(readNode);
+        // swap the clone for the read
+        graph.replaceFixedWithFixed(readNode, clone);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64ReadReplacementPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, Red Hat Inc. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package org.graalvm.compiler.core.aarch64;
+
+import org.graalvm.compiler.graph.Node;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.calc.SignExtendNode;
+import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
+import org.graalvm.compiler.nodes.memory.ReadNode;
+import org.graalvm.compiler.phases.Phase;
+
+/**
+ * AArch64-specific phase which substitutes certain read nodes with arch-specific variants in order
+ * to allow merging of zero and sign extension into the read operation.
+ */
+
+public class AArch64ReadReplacementPhase extends Phase {
+    @Override
+    protected void run(StructuredGraph graph) {
+        for (Node node : graph.getNodes()) {
+            // don't process nodes we just added
+            if (node instanceof AArch64ReadNode) {
+                continue;
+            }
+            if (node instanceof ReadNode) {
+                ReadNode readNode = (ReadNode) node;
+                if (readNode.hasExactlyOneUsage()) {
+                    Node usage = readNode.getUsageAt(0);
+                    if (usage instanceof ZeroExtendNode || usage instanceof SignExtendNode) {
+                        AArch64ReadNode.replace(readNode);
+                    }
+                }
+            }
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.aarch64/src/org/graalvm/compiler/core/aarch64/AArch64SuitesCreator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,14 +22,37 @@
  */
 package org.graalvm.compiler.core.aarch64;
 
+import java.util.ListIterator;
+
 import org.graalvm.compiler.java.DefaultSuitesCreator;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.BasePhase;
+import org.graalvm.compiler.phases.Phase;
+import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.Suites;
 
 public class AArch64SuitesCreator extends DefaultSuitesCreator {
+    private final Class<? extends Phase> insertReadReplacementBefore;
 
-    public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins) {
+    public AArch64SuitesCreator(CompilerConfiguration compilerConfiguration, Plugins plugins, Class<? extends Phase> insertReadReplacementBefore) {
         super(compilerConfiguration, plugins);
+        this.insertReadReplacementBefore = insertReadReplacementBefore;
     }
 
+    @Override
+    public Suites createSuites(OptionValues options) {
+        Suites suites = super.createSuites(options);
+
+        ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(insertReadReplacementBefore);
+        // Put AArch64ReadReplacementPhase right before the SchedulePhase
+        while (PhaseSuite.findNextPhase(findPhase, insertReadReplacementBefore)) {
+            // Search for last occurrence of SchedulePhase
+        }
+        findPhase.previous();
+        findPhase.add(new AArch64ReadReplacementPhase());
+        return suites;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.amd64/src/org/graalvm/compiler/core/amd64/AMD64MoveFactoryBase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.QWORD;
 import static org.graalvm.compiler.asm.amd64.AMD64Assembler.OperandSize.WORD;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.lir.VirtualStackSlot;
 import org.graalvm.compiler.lir.amd64.AMD64LIRInstruction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/GraalOptions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -262,6 +262,9 @@
     @Option(help = "Track the NodeSourcePosition.", type = OptionType.Debug)
     public static final OptionKey<Boolean> TrackNodeSourcePosition = new OptionKey<>(false);
 
+    @Option(help = "Track source stack trace where a node was inserted into the graph.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> TrackNodeInsertion = new OptionKey<>(false);
+
     @Option(help = "Allow backend to match complex expressions.", type = OptionType.Debug)
     public static final OptionKey<Boolean> MatchExpressions = new OptionKey<>(true);
 
@@ -276,7 +279,10 @@
 
     @Option(help = "Enable experimental Trace Register Allocation.", type = OptionType.Debug)
     public static final OptionKey<Boolean> TraceRA = new OptionKey<>(false);
-    @Option(help = "Enable tracing of inlining decision.", type = OptionType.Debug)
+
+    @Option(help = "file:doc-files/TraceInliningHelp.txt", type = OptionType.Debug)
     public static final OptionKey<Boolean> TraceInlining = new OptionKey<>(false);
 
+    @Option(help = "Enable inlining decision tracing in stubs and snippets.", type = OptionType.Debug)
+    public static final OptionKey<Boolean> TraceInliningForStubsAndSnippets = new OptionKey<>(false);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/PermanentBailoutException.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
     }
 
     public PermanentBailoutException(String reason) {
-        super(true, reason);
+        super(true, "%s", reason);
     }
 
     public PermanentBailoutException(Throwable cause, String format, Object... args) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/alloc/RegisterAllocationConfig.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
  */
 package org.graalvm.compiler.core.common.alloc;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.GraalOptions;
 
 import jdk.vm.ci.code.Register;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/doc-files/TraceInliningHelp.txt	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,8 @@
+Enable tracing of inlining decisions.
+Output format:
+  compilation of 'Signature of the compilation root method':
+    at 'Signature of the root method' ['Bytecode index']: <'Phase'> 'Child method signature': 'Decision made about this callsite'
+      at 'Signature of the child method' ['Bytecode index']: 
+         |--<'Phase 1'> 'Grandchild method signature': 'First decision made about this callsite'
+         \--<'Phase 2'> 'Grandchild method signature': 'Second decision made about this callsite'
+      at 'Signature of the child method' ['Bytecode index']: <'Phase'> 'Another grandchild method signature': 'The only decision made about this callsite.'
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/spi/ForeignCallsProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
 package org.graalvm.compiler.core.common.spi;
 
 import org.graalvm.compiler.core.common.LIRKind;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.ValueKindFactory;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/FrequencyEncoder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 
 /**
  * Creates an array of T objects order by the occurrence frequency of each object. The most
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.common/src/org/graalvm/compiler/core/common/util/ModuleAPI.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,126 +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.core.common.util;
-
-import static org.graalvm.compiler.serviceprovider.JDK9Method.JAVA_SPECIFICATION_VERSION;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-import org.graalvm.compiler.debug.GraalError;
-
-/**
- * Reflection based access to the Module API introduced by JDK 9. This allows the API to be used in
- * code that must be compiled on a JDK prior to 9. Use of this class must be guarded by a test for
- * JDK 9 or later. For example:
- *
- * <pre>
- * if (Util.JAVA_SPECIFICATION_VERSION >= 9) {
- *     // Use of ModuleAPI
- * }
- * </pre>
- */
-public final class ModuleAPI {
-
-    public ModuleAPI(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
-        try {
-            this.method = declaringClass.getMethod(name, parameterTypes);
-        } catch (Exception e) {
-            throw new GraalError(e);
-        }
-    }
-
-    public final Method method;
-
-    public Class<?> getReturnType() {
-        return method.getReturnType();
-    }
-
-    /**
-     * {@code Class.getModule()}.
-     */
-    public static final ModuleAPI getModule;
-
-    /**
-     * {@code java.lang.Module.getResourceAsStream(String)}.
-     */
-    public static final ModuleAPI getResourceAsStream;
-
-    /**
-     * {@code java.lang.Module.isExported(String, Module)}.
-     */
-    public static final ModuleAPI isExportedTo;
-
-    /**
-     * Invokes the static Module API method represented by this object.
-     */
-    @SuppressWarnings("unchecked")
-    public <T> T invokeStatic(Object... args) {
-        checkAvailability();
-        assert Modifier.isStatic(method.getModifiers());
-        try {
-            return (T) method.invoke(null, args);
-        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-            throw new GraalError(e);
-        }
-    }
-
-    /**
-     * Invokes the non-static Module API method represented by this object.
-     */
-    @SuppressWarnings("unchecked")
-    public <T> T invoke(Object receiver, Object... args) {
-        checkAvailability();
-        assert !Modifier.isStatic(method.getModifiers());
-        try {
-            return (T) method.invoke(receiver, args);
-        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
-            throw new GraalError(e);
-        }
-    }
-
-    private void checkAvailability() throws GraalError {
-        if (method == null) {
-            throw new GraalError("Cannot use Module API on JDK " + JAVA_SPECIFICATION_VERSION);
-        }
-    }
-
-    static {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            getModule = new ModuleAPI(Class.class, "getModule");
-            Class<?> moduleClass = getModule.getReturnType();
-            getResourceAsStream = new ModuleAPI(moduleClass, "getResourceAsStream", String.class);
-            isExportedTo = new ModuleAPI(moduleClass, "isExported", String.class, moduleClass);
-        } else {
-            ModuleAPI unavailable = new ModuleAPI();
-            getModule = unavailable;
-            getResourceAsStream = unavailable;
-            isExportedTo = unavailable;
-        }
-    }
-
-    private ModuleAPI() {
-        method = null;
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.match.processor/src/org/graalvm/compiler/core/match/processor/MatchProcessor.java	Thu Apr 26 17:59:02 2018 +0200
@@ -58,9 +58,9 @@
 import javax.tools.JavaFileObject;
 import javax.tools.StandardLocation;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.gen.NodeMatchRules;
 import org.graalvm.compiler.core.match.ComplexMatchResult;
 import org.graalvm.compiler.core.match.MatchRule;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java	Thu Apr 26 17:59:02 2018 +0200
@@ -80,7 +80,7 @@
 import org.graalvm.compiler.phases.verify.VerifyUsageWithEquals;
 import org.graalvm.compiler.phases.verify.VerifyVirtualizableUsage;
 import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.Test;
@@ -103,14 +103,6 @@
  */
 public class CheckGraalInvariants extends GraalCompilerTest {
 
-    public CheckGraalInvariants() {
-        try {
-            Class.forName("java.lang.management.ManagementFactory");
-        } catch (ClassNotFoundException ex) {
-            Assume.assumeNoException("cannot run without java.management JDK9 module", ex);
-        }
-    }
-
     private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
         if (m.getName().equals("identityEquals")) {
             ResolvedJavaType c = m.getDeclaringClass();
@@ -148,7 +140,7 @@
         }
 
         protected boolean shouldLoadClass(String className) {
-            return !className.equals("module-info");
+            return !className.equals("module-info") && !className.startsWith("META-INF.versions.");
         }
 
         protected void handleClassLoadingException(Throwable t) {
@@ -191,7 +183,7 @@
                     for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
                         final ZipEntry zipEntry = entry.nextElement();
                         String name = zipEntry.getName();
-                        if (name.endsWith(".class")) {
+                        if (name.endsWith(".class") && !name.startsWith("META-INF/versions/")) {
                             String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
                             if (isInNativeImage(className)) {
                                 /*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/DumpPathTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
 import java.nio.file.Files;
 import java.nio.file.Path;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/GraphResetDebugTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.core.test;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Scope;
 import org.graalvm.compiler.debug.DebugOptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/InfopointReasonTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,6 @@
 import static org.graalvm.compiler.core.common.GraalOptions.OptAssumptions;
 import static org.junit.Assert.assertNotNull;
 
-import org.junit.Test;
-
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
 import org.graalvm.compiler.nodes.FullInfopointNode;
@@ -37,6 +35,7 @@
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Test;
 
 import jdk.vm.ci.code.site.Call;
 import jdk.vm.ci.code.site.Infopoint;
@@ -50,6 +49,11 @@
 
     public static final String[] STRINGS = new String[]{"world", "everyone", "you"};
 
+    public InfopointReasonTest() {
+        // Call testMethod to ensure all method references are resolved.
+        testMethod();
+    }
+
     public String testMethod() {
         StringBuilder sb = new StringBuilder("Hello ");
         for (String s : STRINGS) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/MarkUnsafeAccessTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -116,6 +116,7 @@
 
     @Test
     public void testCompiled() throws IOException {
+        Assume.assumeFalse("Crashes on AArch64 (GR-8351)", System.getProperty("os.arch").equalsIgnoreCase("aarch64"));
         ResolvedJavaMethod getMethod = asResolvedJavaMethod(getMethod(ByteBuffer.class, "get", new Class<?>[]{}));
         ResolvedJavaType mbbClass = getMetaAccess().lookupJavaType(MappedByteBuffer.class);
         ResolvedJavaMethod getMethodImpl = mbbClass.findUniqueConcreteMethod(getMethod).getResult();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReferenceGetLoopTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.nodes.FieldLocationIdentity;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.memory.Access;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ResolvedJavaField;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ReflectionOptionDescriptors.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,12 +31,13 @@
 import java.util.Map;
 import java.util.Properties;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionDescriptor;
 import org.graalvm.compiler.options.OptionDescriptors;
 import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 
 /**
@@ -108,8 +109,8 @@
             ParameterizedType pt = (ParameterizedType) declaredType;
             Type[] actualTypeArguments = pt.getActualTypeArguments();
             assert actualTypeArguments.length == 1;
-            Class<?> optionType = (Class<?>) actualTypeArguments[0];
-            descriptors.put(fieldName, OptionDescriptor.create(fieldName, optionType, help, declaringClass, fieldName, (OptionKey<?>) f.get(null)));
+            Class<?> optionValueType = (Class<?>) actualTypeArguments[0];
+            descriptors.put(fieldName, OptionDescriptor.create(fieldName, OptionType.Debug, optionValueType, help, declaringClass, fieldName, (OptionKey<?>) f.get(null)));
         } catch (IllegalAccessException | NoSuchFieldException e) {
             throw new IllegalArgumentException(e);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/StampMemoryAccessTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,6 @@
 
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import jdk.vm.ci.meta.JavaConstant;
@@ -36,21 +35,23 @@
  */
 public class StampMemoryAccessTest extends GraalCompilerTest {
 
-    @Ignore("not all JVMCI versions are safe yet")
     @Test
     public void testReadPrimitive() {
         MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider();
-        JavaConstant base = getSnippetReflection().forObject("");
         Stamp stamp = StampFactory.forKind(JavaKind.Long);
-        assertTrue(stamp.readConstant(memory, base, 128) == null);
+        JavaConstant objectBase = getSnippetReflection().forObject("");
+        assertTrue(stamp.readConstant(memory, objectBase, 128) == null);
+        JavaConstant arrayBase = getSnippetReflection().forObject(new int[]{});
+        assertTrue(stamp.readConstant(memory, arrayBase, 128) == null);
     }
 
-    @Ignore("not all JVMCI versions are safe yet")
     @Test
     public void testReadObject() {
         MemoryAccessProvider memory = getConstantReflection().getMemoryAccessProvider();
-        JavaConstant base = getSnippetReflection().forObject("");
         Stamp stamp = StampFactory.forKind(JavaKind.Object);
-        assertTrue(stamp.readConstant(memory, base, 128) == null);
+        JavaConstant objectBase = getSnippetReflection().forObject("");
+        assertTrue(stamp.readConstant(memory, objectBase, 128) == null);
+        JavaConstant arrayBase = getSnippetReflection().forObject(new int[]{});
+        assertTrue(stamp.readConstant(memory, arrayBase, 128) == null);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/ea/EscapeAnalysisTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -39,6 +39,7 @@
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.compiler.virtual.phases.ea.PartialEscapePhase;
 import org.junit.Assert;
+import org.junit.Assume;
 import org.junit.Test;
 
 import jdk.vm.ci.meta.JavaConstant;
@@ -405,6 +406,8 @@
      */
     @Test
     public void testNewNode() {
+        // Trackking of creation interferes with escape analysis
+        Assume.assumeFalse(Node.TRACK_CREATION_POSITION);
         testEscapeAnalysis("testNewNodeSnippet", null, false);
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/InliningTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,9 +22,11 @@
  */
 package org.graalvm.compiler.core.test.inlining;
 
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugDumpScope;
+import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.FullInfopointNode;
 import org.graalvm.compiler.nodes.Invoke;
@@ -32,18 +34,22 @@
 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
 import org.graalvm.compiler.nodes.StructuredGraph.Builder;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
+import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
 import org.junit.Ignore;
 import org.junit.Test;
 
 import jdk.vm.ci.code.site.InfopointReason;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
+import java.util.regex.Pattern;
+
 public class InliningTest extends GraalCompilerTest {
 
     @Test
@@ -198,6 +204,40 @@
         assertFewMethodInfopoints(assertNotInlined(getGraph("invokeOverriddenInterfaceMethodSnippet", true)));
     }
 
+    public static void traceInliningTest() {
+        callTrivial();
+    }
+
+    private static void callTrivial() {
+        callNonTrivial();
+    }
+
+    private static double callNonTrivial() {
+        double x = 0.0;
+        for (int i = 0; i < 10; i++) {
+            x += i * 1.21;
+        }
+        return x;
+    }
+
+    @Test
+    @SuppressWarnings("try")
+    public void testTracing() {
+        OptionValues options = new OptionValues(getInitialOptions(), GraalOptions.TraceInlining, true);
+        StructuredGraph graph;
+        try (TTY.Filter f = new TTY.Filter()) {
+            graph = getGraph("traceInliningTest", options, false);
+        }
+        String inliningTree = graph.getInliningLog().formatAsTree(false);
+        String expectedRegex = "compilation of org.graalvm.compiler.core.test.inlining.InliningTest.traceInliningTest.*: \\R" +
+                        "  at .*org.graalvm.compiler.core.test.inlining.InliningTest.traceInliningTest.*: <GraphBuilderPhase> org.graalvm.compiler.core.test.inlining.InliningTest.callTrivial.*: yes, inline method\\R" +
+                        "    at .*org.graalvm.compiler.core.test.inlining.InliningTest.callTrivial.*: .*\\R" +
+                        "       .*<GraphBuilderPhase> org.graalvm.compiler.core.test.inlining.InliningTest.callNonTrivial.*: .*(.*\\R)*" +
+                        "       .*<InliningPhase> org.graalvm.compiler.core.test.inlining.InliningTest.callNonTrivial.*: .*(.*\\R)*";
+        Pattern expectedPattern = Pattern.compile(expectedRegex, Pattern.MULTILINE);
+        Assert.assertTrue("Got: " + inliningTree, expectedPattern.matcher(inliningTree).matches());
+    }
+
     @SuppressWarnings("all")
     public static int invokeLeafClassMethodSnippet(SubClassA subClassA) {
         return subClassA.publicFinalMethod() + subClassA.publicNotOverriddenMethod() + subClassA.publicOverriddenMethod();
@@ -233,9 +273,13 @@
         return superClass.protectedOverriddenMethod();
     }
 
+    private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
+        return getGraph(snippet, null, eagerInfopointMode);
+    }
+
     @SuppressWarnings("try")
-    private StructuredGraph getGraph(final String snippet, final boolean eagerInfopointMode) {
-        DebugContext debug = getDebugContext();
+    private StructuredGraph getGraph(final String snippet, OptionValues options, final boolean eagerInfopointMode) {
+        DebugContext debug = options == null ? getDebugContext() : getDebugContext(options, null, null);
         try (DebugContext.Scope s = debug.scope("InliningTest", new DebugDumpScope(snippet, true))) {
             ResolvedJavaMethod method = getResolvedJavaMethod(snippet);
             Builder builder = builder(method, AllowAssumptions.YES, debug);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/inlining/NestedLoopEffectsPhaseComplexityTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Optional;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.TTY;
@@ -137,7 +137,8 @@
         ResolvedJavaMethod calleeMethod = next.callTarget().targetMethod();
         for (int i = 0; i < inliningCount; i++) {
             next = callerGraph.getNodes(MethodCallTargetNode.TYPE).first().invoke();
-            EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod);
+            EconomicSet<Node> canonicalizeNodes = InliningUtil.inlineForCanonicalization(next, calleeGraph, false, calleeMethod, null,
+                            "Called explicitly from a unit test.", "Test case");
             canonicalizer.applyIncremental(callerGraph, context, canonicalizeNodes);
             callerGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, callerGraph, "After inlining %s into %s iteration %d", calleeMethod, callerMethod, i);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationPrinter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,10 +23,11 @@
 package org.graalvm.compiler.core;
 
 import static org.graalvm.compiler.core.GraalCompilerOptions.PrintCompilation;
+import static org.graalvm.compiler.serviceprovider.GraalServices.getCurrentThreadAllocatedBytes;
+import static org.graalvm.compiler.serviceprovider.GraalServices.isThreadAllocatedMemorySupported;
 
 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;
 
@@ -58,11 +59,6 @@
      */
     public static CompilationPrinter begin(OptionValues options, CompilationIdentifier id, JavaMethod method, int entryBCI) {
         if (PrintCompilation.getValue(options) && !TTY.isSuppressed()) {
-            try {
-                Class.forName("java.lang.management.ManagementFactory");
-            } catch (ClassNotFoundException ex) {
-                throw new IllegalArgumentException("PrintCompilation option requires java.management module");
-            }
             return new CompilationPrinter(id, method, entryBCI);
         }
         return DISABLED;
@@ -83,9 +79,8 @@
         this.id = id;
         this.entryBCI = entryBCI;
 
-        final long threadId = Thread.currentThread().getId();
         start = System.nanoTime();
-        allocatedBytesBefore = getAllocatedBytes(threadId);
+        allocatedBytesBefore = isThreadAllocatedMemorySupported() ? getCurrentThreadAllocatedBytes() : -1;
     }
 
     private String getMethodDescription() {
@@ -101,24 +96,17 @@
      */
     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));
+            if (allocatedBytesBefore == -1) {
+                TTY.println(getMethodDescription() + String.format(" | %4dms %5dB %5dB", duration, bytecodeSize, targetCodeSize));
+            } else {
+                final long allocatedBytesAfter = getCurrentThreadAllocatedBytes();
+                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);
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/CompilationWrapper.java	Thu Apr 26 17:59:02 2018 +0200
@@ -122,8 +122,10 @@
      *
      * 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.
+     *
+     * @param cause the cause of the bailout or failure
      */
-    protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey) {
+    protected ExceptionAction lookupAction(OptionValues options, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
         if (actionKey == CompilationFailureAction) {
             if (ExitVMOnException.getValue(options)) {
                 assert CompilationFailureAction.getDefaultValue() != ExceptionAction.ExitVM;
@@ -175,7 +177,7 @@
                 actionKey = CompilationFailureAction;
                 causeType = "failure";
             }
-            ExceptionAction action = lookupAction(initialOptions, actionKey);
+            ExceptionAction action = lookupAction(initialOptions, actionKey, cause);
 
             action = adjustAction(initialOptions, actionKey, action);
 
@@ -262,22 +264,34 @@
                                 DumpPath, dumpPath.getPath());
 
                 try (DebugContext retryDebug = createRetryDebugContext(retryOptions)) {
-                    return performCompilation(retryDebug);
+                    T res = performCompilation(retryDebug);
+                    maybeExitVM(action);
+                    return res;
                 } 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);
-                        }
-                    }
+                    T res = handleException(cause);
+                    maybeExitVM(action);
+                    return res;
                 }
             }
         }
     }
 
+    private void maybeExitVM(ExceptionAction action) {
+        if (action == ExitVM) {
+            synchronized (ExceptionAction.class) {
+                try {
+                    // Give other compiler threads a chance to flush
+                    // error handling output.
+                    ExceptionAction.class.wait(2000);
+                } catch (InterruptedException e) {
+                }
+                TTY.println("Exiting VM after retry compilation of " + this);
+                System.exit(-1);
+            }
+        }
+    }
+
     /**
      * Adjusts {@code initialAction} if necessary based on
      * {@link GraalCompilerOptions#MaxCompilationProblemsPerAction}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompiler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,10 +25,12 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.core.LIRGenerationPhase.LIRGenerationContext;
 import org.graalvm.compiler.core.common.GraalOptions;
+import org.graalvm.compiler.core.common.PermanentBailoutException;
+import org.graalvm.compiler.core.common.RetryableBailoutException;
 import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
@@ -188,8 +190,18 @@
      *             {@code graph.method()} or {@code graph.name}
      */
     private static void checkForRequestedCrash(StructuredGraph graph) {
-        String methodPattern = GraalCompilerOptions.CrashAt.getValue(graph.getOptions());
-        if (methodPattern != null) {
+        String value = GraalCompilerOptions.CrashAt.getValue(graph.getOptions());
+        if (value != null) {
+            boolean bailout = false;
+            boolean permanentBailout = false;
+            String methodPattern = value;
+            if (value.endsWith(":Bailout")) {
+                methodPattern = value.substring(0, value.length() - ":Bailout".length());
+                bailout = true;
+            } else if (value.endsWith(":PermanentBailout")) {
+                methodPattern = value.substring(0, value.length() - ":PermanentBailout".length());
+                permanentBailout = true;
+            }
             String crashLabel = null;
             if (graph.name != null && graph.name.contains(methodPattern)) {
                 crashLabel = graph.name;
@@ -204,6 +216,12 @@
                 }
             }
             if (crashLabel != null) {
+                if (permanentBailout) {
+                    throw new PermanentBailoutException("Forced crash after compiling " + crashLabel);
+                }
+                if (bailout) {
+                    throw new RetryableBailoutException("Forced crash after compiling " + crashLabel);
+                }
                 throw new RuntimeException("Forced crash after compiling " + crashLabel);
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/GraalCompilerOptions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,12 +38,14 @@
     public static final OptionKey<Boolean> PrintCompilation = new OptionKey<>(false);
     @Option(help = "Pattern for method(s) that will trigger an exception when compiled. " +
                    "This option exists to test handling compilation crashes gracefully. " +
-                   "See the MethodFilter option for the pattern syntax. ", type = OptionType.Debug)
+                   "See the MethodFilter option for the pattern syntax. A ':Bailout' " +
+                   "suffix will raise a bailout exception and a ':PermanentBailout' " +
+                   "suffix will raise a permanent bailout exception.", type = OptionType.Debug)
     public static final OptionKey<String> CrashAt = new OptionKey<>(null);
     @Option(help = "file:doc-files/CompilationBailoutActionHelp.txt", type = OptionType.User)
     public static final EnumOptionKey<ExceptionAction> CompilationBailoutAction = new EnumOptionKey<>(ExceptionAction.Silent);
     @Option(help = "Specifies the action to take when compilation fails with a bailout exception. " +
-                    "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
+                   "The accepted values are the same as for CompilationBailoutAction.", type = OptionType.User)
      public static final EnumOptionKey<ExceptionAction> CompilationFailureAction = new EnumOptionKey<>(ExceptionAction.Diagnose);
     @Option(help = "The maximum number of compilation failures or bailouts to handle with the action specified " +
                    "by CompilationFailureAction or CompilationBailoutAction before changing to a less verbose action.", type = OptionType.User)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/DebugInfoBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import java.util.Arrays;
 import java.util.Queue;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/gen/NodeLIRBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,8 +33,8 @@
 import java.util.Collection;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchContext.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
 import java.util.Arrays;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.gen.NodeLIRBuilder;
 import org.graalvm.compiler.core.match.MatchPattern.Result;
 import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/match/MatchRuleRegistry.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,9 +27,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.core.gen.NodeMatchRules;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CommunityCompilerConfiguration.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.core.phases;
+
+import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
+import org.graalvm.compiler.lir.phases.AllocationStage;
+import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
+import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
+import org.graalvm.compiler.lir.phases.PostAllocationOptimizationStage;
+import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
+import org.graalvm.compiler.lir.phases.PreAllocationOptimizationStage;
+import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.graalvm.compiler.phases.tiers.LowTierContext;
+import org.graalvm.compiler.phases.tiers.MidTierContext;
+
+/**
+ * The default configuration for the community edition of Graal.
+ */
+public class CommunityCompilerConfiguration implements CompilerConfiguration {
+
+    @Override
+    public PhaseSuite<HighTierContext> createHighTier(OptionValues options) {
+        return new HighTier(options);
+    }
+
+    @Override
+    public PhaseSuite<MidTierContext> createMidTier(OptionValues options) {
+        return new MidTier(options);
+    }
+
+    @Override
+    public PhaseSuite<LowTierContext> createLowTier(OptionValues options) {
+        return new LowTier(options);
+    }
+
+    @Override
+    public LIRPhaseSuite<PreAllocationOptimizationContext> createPreAllocationOptimizationStage(OptionValues options) {
+        return new PreAllocationOptimizationStage(options);
+    }
+
+    @Override
+    public LIRPhaseSuite<AllocationContext> createAllocationStage(OptionValues options) {
+        return new AllocationStage(options);
+    }
+
+    @Override
+    public LIRPhaseSuite<PostAllocationOptimizationContext> createPostAllocationOptimizationStage(OptionValues options) {
+        return new PostAllocationOptimizationStage(options);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/CoreCompilerConfiguration.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.core.phases;
-
-import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
-import org.graalvm.compiler.lir.phases.AllocationStage;
-import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
-import org.graalvm.compiler.lir.phases.PostAllocationOptimizationPhase.PostAllocationOptimizationContext;
-import org.graalvm.compiler.lir.phases.PostAllocationOptimizationStage;
-import org.graalvm.compiler.lir.phases.PreAllocationOptimizationPhase.PreAllocationOptimizationContext;
-import org.graalvm.compiler.lir.phases.PreAllocationOptimizationStage;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.PhaseSuite;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.compiler.phases.tiers.LowTierContext;
-import org.graalvm.compiler.phases.tiers.MidTierContext;
-
-public class CoreCompilerConfiguration implements CompilerConfiguration {
-
-    @Override
-    public PhaseSuite<HighTierContext> createHighTier(OptionValues options) {
-        return new HighTier(options);
-    }
-
-    @Override
-    public PhaseSuite<MidTierContext> createMidTier(OptionValues options) {
-        return new MidTier(options);
-    }
-
-    @Override
-    public PhaseSuite<LowTierContext> createLowTier(OptionValues options) {
-        return new LowTier(options);
-    }
-
-    @Override
-    public LIRPhaseSuite<PreAllocationOptimizationContext> createPreAllocationOptimizationStage(OptionValues options) {
-        return new PreAllocationOptimizationStage(options);
-    }
-
-    @Override
-    public LIRPhaseSuite<AllocationContext> createAllocationStage(OptionValues options) {
-        return new AllocationStage(options);
-    }
-
-    @Override
-    public LIRPhaseSuite<PostAllocationOptimizationContext> createPostAllocationOptimizationStage(OptionValues options) {
-        return new PostAllocationOptimizationStage(options);
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/EconomyCompilerConfiguration.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,6 +36,10 @@
 import org.graalvm.compiler.phases.tiers.LowTierContext;
 import org.graalvm.compiler.phases.tiers.MidTierContext;
 
+/**
+ * A compiler configuration that performs fewer Graal IR optimizations while using the same backend
+ * as the {@link CommunityCompilerConfiguration}.
+ */
 public class EconomyCompilerConfiguration implements CompilerConfiguration {
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/phases/GraphChangeMonitoringPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
  */
 package org.graalvm.compiler.core.phases;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.Graph.NodeEvent;
 import org.graalvm.compiler.graph.Graph.NodeEventScope;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core/src/org/graalvm/compiler/core/target/Backend.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.ArrayList;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
@@ -41,6 +41,7 @@
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
 import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.GraphSpeculationLog;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.phases.tiers.SuitesProvider;
 import org.graalvm.compiler.phases.tiers.TargetProvider;
@@ -209,7 +210,7 @@
             try {
                 preCodeInstallationTasks(tasks, compilationResult, predefinedInstalledCode);
                 CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult);
-                installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, speculationLog, isDefault);
+                installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, GraphSpeculationLog.unwrap(speculationLog), isDefault);
                 assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode;
             } catch (Throwable t) {
                 failCodeInstallationTasks(tasks, t);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/DebugContextTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
 import java.util.Formatter;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug.test/src/org/graalvm/compiler/debug/test/TimerKeyTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,16 +28,14 @@
 import static org.graalvm.compiler.debug.DebugContext.NO_GLOBAL_METRIC_VALUES;
 import static org.junit.Assert.assertEquals;
 
-import java.lang.management.ThreadMXBean;
-
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.debug.Management;
 import org.graalvm.compiler.debug.TimerKey;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.junit.Assume;
 import org.junit.Before;
 import org.junit.Test;
@@ -47,12 +45,7 @@
 
     @Before
     public void checkCapabilities() {
-        try {
-            ThreadMXBean threadMXBean = Management.getThreadMXBean();
-            Assume.assumeTrue("skipping management interface test", threadMXBean.isCurrentThreadCpuTimeSupported());
-        } catch (LinkageError err) {
-            Assume.assumeNoException("Cannot run without java.management JDK9 module", err);
-        }
+        Assume.assumeTrue("skipping management interface test", GraalServices.isCurrentThreadCpuTimeSupported());
     }
 
     /**
@@ -63,10 +56,9 @@
      *         {@code ms}
      */
     private static long spin(long ms) {
-        ThreadMXBean threadMXBean = Management.getThreadMXBean();
-        long start = threadMXBean.getCurrentThreadCpuTime();
+        long start = GraalServices.getCurrentThreadCpuTime();
         do {
-            long durationMS = (threadMXBean.getCurrentThreadCpuTime() - start) / 1000;
+            long durationMS = (GraalServices.getCurrentThreadCpuTime() - start) / 1000;
             if (durationMS >= ms) {
                 return durationMS;
             }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/CounterKeyImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.debug;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 
 class CounterKeyImpl extends AbstractKey implements CounterKey {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugConfigImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -264,9 +264,8 @@
                     firstSeen.put(o, o);
                     if (DebugOptions.DumpOnError.getValue(options) || DebugOptions.Dump.getValue(options) != null) {
                         debug.dump(DebugContext.BASIC_LEVEL, o, "Exception: %s", e);
-                    } else {
-                        debug.log("Context obj %s", o);
                     }
+                    debug.log("Context obj %s", o);
                 }
             }
         } finally {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugContext.java	Thu Apr 26 17:59:02 2018 +0200
@@ -56,11 +56,12 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.graalvm.graphio.GraphOutput;
 
 import jdk.vm.ci.meta.JavaMethod;
@@ -236,14 +237,15 @@
             this.unscopedTimers = parseUnscopedMetricSpec(Timers.getValue(options), "".equals(timeValue), true);
             this.unscopedMemUseTrackers = parseUnscopedMetricSpec(MemUseTrackers.getValue(options), "".equals(trackMemUseValue), true);
 
-            if (unscopedTimers != null ||
-                            unscopedMemUseTrackers != null ||
-                            timeValue != null ||
-                            trackMemUseValue != null) {
-                try {
-                    Class.forName("java.lang.management.ManagementFactory");
-                } catch (ClassNotFoundException ex) {
-                    throw new IllegalArgumentException("Time, Timers, MemUseTrackers and TrackMemUse options require java.management module");
+            if (unscopedTimers != null || timeValue != null) {
+                if (!GraalServices.isCurrentThreadCpuTimeSupported()) {
+                    throw new IllegalArgumentException("Time and Timers options require VM support for querying CPU time");
+                }
+            }
+
+            if (unscopedMemUseTrackers != null || trackMemUseValue != null) {
+                if (!GraalServices.isThreadAllocatedMemorySupported()) {
+                    throw new IllegalArgumentException("MemUseTrackers and TrackMemUse options require VM support for querying thread allocated memory");
                 }
             }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DebugOptions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,11 +27,12 @@
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 /**
  * Options that configure a {@link DebugContext} and related functionality.
@@ -133,9 +134,7 @@
 
     @Option(help = "Host part of the address to which graphs are dumped.", type = OptionType.Debug)
     public static final OptionKey<String> PrintGraphHost = new OptionKey<>("127.0.0.1");
-    @Option(help = "Port part of the address to which graphs are dumped in XML format (ignored if PrintBinaryGraphs=true).", type = OptionType.Debug)
-    public static final OptionKey<Integer> PrintXmlGraphPort = new OptionKey<>(4444);
-    @Option(help = "Port part of the address to which graphs are dumped in binary format (ignored if PrintBinaryGraphs=false).", type = OptionType.Debug)
+    @Option(help = "Port part of the address to which graphs are dumped in binary format.", type = OptionType.Debug)
     public static final OptionKey<Integer> PrintBinaryGraphPort = new OptionKey<>(4445);
     @Option(help = "Schedule graphs as they are dumped.", type = OptionType.Debug)
     public static final OptionKey<Boolean> PrintGraphWithSchedule = new OptionKey<>(false);
@@ -164,23 +163,10 @@
     @Option(help = "Do not compile anything on bootstrap but just initialize the compiler.", type = OptionType.Debug)
     public static final OptionKey<Boolean> BootstrapInitializeOnly = new OptionKey<>(false);
 
-    // These will be removed at some point
-    @Option(help = "Deprecated - use PrintGraphHost instead.", type = OptionType.Debug)
-    static final OptionKey<String> PrintIdealGraphAddress = new DebugOptions.DeprecatedOptionKey<>(PrintGraphHost);
-    @Option(help = "Deprecated - use PrintGraphWithSchedule instead.", type = OptionType.Debug)
-    static final OptionKey<Boolean> PrintIdealGraphSchedule = new DebugOptions.DeprecatedOptionKey<>(PrintGraphWithSchedule);
-    @Option(help = "Deprecated - use PrintGraph instead.", type = OptionType.Debug)
-    static final OptionKey<Boolean> PrintIdealGraph = new DebugOptions.DeprecatedOptionKey<>(PrintGraph);
-    @Option(help = "Deprecated - use PrintGraphFile instead.", type = OptionType.Debug)
-    static final OptionKey<Boolean> PrintIdealGraphFile = new DebugOptions.DeprecatedOptionKey<>(PrintGraphFile);
-    @Option(help = "Deprecated - use PrintXmlGraphPort instead.", type = OptionType.Debug)
-    static final OptionKey<Integer> PrintIdealGraphPort = new DebugOptions.DeprecatedOptionKey<>(PrintXmlGraphPort);
-    // @formatter:on
-
     /**
      * 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 PathUtilities#getGlobalTimeStamp()}.
+     * the default value of {@link #DumpPath} and {@link GraalServices#getGlobalTimeStamp()}.
      *
      * This method will ensure the returned directory exists, printing a message to {@link TTY} if
      * it creates it.
@@ -193,14 +179,16 @@
         if (DumpPath.hasBeenSet(options)) {
             dumpDir = Paths.get(DumpPath.getValue(options));
         } else {
-            dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(PathUtilities.getGlobalTimeStamp()));
+            dumpDir = Paths.get(DumpPath.getValue(options), String.valueOf(GraalServices.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.toString());
+                    if (ShowDumpFiles.getValue(options)) {
+                        TTY.println("Dumping debug output in %s", dumpDir.toString());
+                    }
                 }
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/DiagnosticsOutputDirectory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -39,6 +39,7 @@
 import java.util.zip.ZipOutputStream;
 
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 /**
  * Manages a directory into which diagnostics such crash reports and dumps should be written. The
@@ -69,26 +70,6 @@
         return getPath(true);
     }
 
-    /**
-     * Gets a unique identifier for this execution such as a process ID.
-     */
-    protected String getExecutionID() {
-        try {
-            String runtimeName = java.lang.management.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;
-        } catch (LinkageError err) {
-            return String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
-        }
-    }
-
     private synchronized String getPath(boolean createIfNull) {
         if (path == null && createIfNull) {
             path = createPath();
@@ -120,7 +101,7 @@
             // directory specified by the DumpPath option.
             baseDir = Paths.get(".");
         }
-        return baseDir.resolve("graal_diagnostics_" + getExecutionID()).toAbsolutePath().toString();
+        return baseDir.resolve("graal_diagnostics_" + GraalServices.getExecutionID()).toAbsolutePath().toString();
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/GlobalMetrics.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,9 +29,9 @@
 import java.util.Collections;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.options.OptionValues;
 
 /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/KeyRegistry.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 
 /**
  * Registry for allocating a globally unique integer id to each {@link AbstractKey}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/Management.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +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.
- *
- * 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 static java.lang.Thread.currentThread;
-
-public class Management {
-
-    private static final com.sun.management.ThreadMXBean threadMXBean = Management.initThreadMXBean();
-
-    /**
-     * The amount of memory allocated by
-     * {@link com.sun.management.ThreadMXBean#getThreadAllocatedBytes(long)} itself.
-     */
-    private static final long threadMXBeanOverhead = -getCurrentThreadAllocatedBytes() + getCurrentThreadAllocatedBytes();
-
-    public static long getCurrentThreadAllocatedBytes() {
-        return threadMXBean.getThreadAllocatedBytes(currentThread().getId()) - threadMXBeanOverhead;
-    }
-
-    private static com.sun.management.ThreadMXBean initThreadMXBean() {
-        try {
-            return (com.sun.management.ThreadMXBean) java.lang.management.ManagementFactory.getThreadMXBean();
-        } catch (Error err) {
-            return new UnimplementedBean();
-        }
-    }
-
-    public static java.lang.management.ThreadMXBean getThreadMXBean() {
-        return threadMXBean;
-    }
-
-    private static class UnimplementedBean implements java.lang.management.ThreadMXBean, com.sun.management.ThreadMXBean {
-
-        @Override
-        public javax.management.ObjectName getObjectName() {
-            return null;
-        }
-
-        @Override
-        public long getThreadAllocatedBytes(long arg0) {
-            return 0;
-        }
-
-        @Override
-        public long[] getThreadAllocatedBytes(long[] arg0) {
-            return null;
-        }
-
-        @Override
-        public long[] getThreadCpuTime(long[] arg0) {
-            return null;
-        }
-
-        @Override
-        public long[] getThreadUserTime(long[] arg0) {
-            return null;
-        }
-
-        @Override
-        public boolean isThreadAllocatedMemoryEnabled() {
-            return false;
-        }
-
-        @Override
-        public boolean isThreadAllocatedMemorySupported() {
-            return false;
-        }
-
-        @Override
-        public void setThreadAllocatedMemoryEnabled(boolean arg0) {
-        }
-
-        @Override
-        public int getThreadCount() {
-            return 0;
-        }
-
-        @Override
-        public int getPeakThreadCount() {
-            return 0;
-        }
-
-        @Override
-        public long getTotalStartedThreadCount() {
-            return 0;
-        }
-
-        @Override
-        public int getDaemonThreadCount() {
-            return 0;
-        }
-
-        @Override
-        public long[] getAllThreadIds() {
-            return null;
-        }
-
-        @Override
-        public java.lang.management.ThreadInfo getThreadInfo(long id) {
-            return null;
-        }
-
-        @Override
-        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids) {
-            return null;
-        }
-
-        @Override
-        public java.lang.management.ThreadInfo getThreadInfo(long id, int maxDepth) {
-            return null;
-        }
-
-        @Override
-        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) {
-            return null;
-        }
-
-        @Override
-        public boolean isThreadContentionMonitoringSupported() {
-            return false;
-        }
-
-        @Override
-        public boolean isThreadContentionMonitoringEnabled() {
-            return false;
-        }
-
-        @Override
-        public void setThreadContentionMonitoringEnabled(boolean enable) {
-        }
-
-        @Override
-        public long getCurrentThreadCpuTime() {
-            return 0;
-        }
-
-        @Override
-        public long getCurrentThreadUserTime() {
-            return 0;
-        }
-
-        @Override
-        public long getThreadCpuTime(long id) {
-            return 0;
-        }
-
-        @Override
-        public long getThreadUserTime(long id) {
-            return 0;
-        }
-
-        @Override
-        public boolean isThreadCpuTimeSupported() {
-            return false;
-        }
-
-        @Override
-        public boolean isCurrentThreadCpuTimeSupported() {
-            return false;
-        }
-
-        @Override
-        public boolean isThreadCpuTimeEnabled() {
-            return false;
-        }
-
-        @Override
-        public void setThreadCpuTimeEnabled(boolean enable) {
-        }
-
-        @Override
-        public long[] findMonitorDeadlockedThreads() {
-            return null;
-        }
-
-        @Override
-        public void resetPeakThreadCount() {
-        }
-
-        @Override
-        public long[] findDeadlockedThreads() {
-            return null;
-        }
-
-        @Override
-        public boolean isObjectMonitorUsageSupported() {
-            return false;
-        }
-
-        @Override
-        public boolean isSynchronizerUsageSupported() {
-            return false;
-        }
-
-        @Override
-        public java.lang.management.ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) {
-            return null;
-        }
-
-        @Override
-        public java.lang.management.ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) {
-            return null;
-        }
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKey.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,8 @@
  */
 package org.graalvm.compiler.debug;
 
+import org.graalvm.compiler.serviceprovider.GraalServices;
+
 /**
  * Tracks memory usage within a scope using {@link com.sun.management.ThreadMXBean}. This facility
  * should be employed using the try-with-resources pattern:
@@ -52,6 +54,6 @@
     MemUseTrackerKey doc(String string);
 
     static long getCurrentThreadAllocatedBytes() {
-        return Management.getCurrentThreadAllocatedBytes();
+        return GraalServices.getCurrentThreadAllocatedBytes();
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MemUseTrackerKeyImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.debug.DebugCloseable.VOID_CLOSEABLE;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 
 class MemUseTrackerKeyImpl extends AccumulatedKey implements MemUseTrackerKey {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/MetricKey.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.Comparator;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 
 /**
  * A key for a metric.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/PathUtilities.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,6 @@
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.concurrent.atomic.AtomicLong;
 
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
@@ -39,19 +38,6 @@
  */
 public class PathUtilities {
 
-    private static final AtomicLong globalTimeStamp = new AtomicLong();
-
-    /**
-     * 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();
-    }
-
     /**
      * Gets a value based on {@code name} that can be passed to {@link Paths#get(String, String...)}
      * without causing an {@link InvalidPathException}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimeSource.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,21 +22,13 @@
  */
 package org.graalvm.compiler.debug;
 
+import org.graalvm.compiler.serviceprovider.GraalServices;
+
 /**
  * A consistent source of timing data that should be used by all facilities in the debug package.
  */
 public class TimeSource {
-    private static final boolean USING_BEAN;
-    private static final java.lang.management.ThreadMXBean threadMXBean;
-
-    static {
-        threadMXBean = Management.getThreadMXBean();
-        if (threadMXBean.isThreadCpuTimeSupported()) {
-            USING_BEAN = true;
-        } else {
-            USING_BEAN = false;
-        }
-    }
+    private static final boolean USING_THREAD_CPU_TIME = GraalServices.isCurrentThreadCpuTimeSupported();
 
     /**
      * Gets the current time of this thread in nanoseconds from the most accurate timer available on
@@ -50,7 +42,7 @@
      * @return the current thread's time in nanoseconds
      */
     public static long getTimeNS() {
-        return USING_BEAN ? threadMXBean.getCurrentThreadCpuTime() : System.nanoTime();
+        return USING_THREAD_CPU_TIME ? GraalServices.getCurrentThreadCpuTime() : System.nanoTime();
     }
 
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.debug/src/org/graalvm/compiler/debug/TimerKeyImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 
 import java.util.concurrent.TimeUnit;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 
 final class TimerKeyImpl extends AccumulatedKey implements TimerKey {
     static class FlatTimer extends AbstractKey implements TimerKey {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/.checkstyle_checks.xml	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
-    This configuration file was written by the eclipse-cs plugin configuration editor
--->
-<!--
-    Checkstyle-Configuration: Checks
-    Description: none
--->
-<module name="Checker">
-  <property name="severity" value="error"/>
-  <module name="TreeWalker">
-    <module name="AvoidStarImport">
-      <property name="allowClassImports" value="false"/>
-      <property name="allowStaticMemberImports" value="false"/>
-    </module>
-    <property name="tabWidth" value="4"/>
-    <module name="FileContentsHolder"/>
-    <module name="JavadocStyle">
-      <property name="checkHtml" value="false"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-    <module name="ParameterName"/>
-    <module name="TypeName">
-      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
-    </module>
-    <module name="RedundantImport"/>
-    <module name="LineLength">
-      <property name="max" value="250"/>
-    </module>
-    <module name="MethodParamPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <module name="NoWhitespaceBefore">
-      <property name="tokens" value="SEMI,DOT,POST_DEC,POST_INC"/>
-    </module>
-    <module name="ParenPad"/>
-    <module name="TypecastParenPad">
-      <property name="tokens" value="RPAREN,TYPECAST"/>
-    </module>
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
-    </module>
-    <module name="RedundantModifier"/>
-    <module name="AvoidNestedBlocks">
-      <property name="allowInSwitchCase" value="true"/>
-    </module>
-    <module name="EmptyBlock">
-      <property name="option" value="text"/>
-      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly"/>
-    <module name="NeedBraces"/>
-    <module name="RightCurly"/>
-    <module name="EmptyStatement"/>
-    <module name="HiddenField">
-      <property name="severity" value="ignore"/>
-      <property name="ignoreConstructorParameter" value="true"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="FinalClass"/>
-    <module name="HideUtilityClassConstructor">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ArrayTypeStyle"/>
-    <module name="UpperEll"/>
-    <module name="FallThrough"/>
-    <module name="FinalLocalVariable">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="MultipleVariableDeclarations"/>
-    <module name="StringLiteralEquality">
-      <property name="severity" value="error"/>
-    </module>
-    <module name="SuperFinalize"/>
-    <module name="UnnecessaryParentheses">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="Indentation">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="StaticVariableName">
-      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="EmptyForInitializerPad"/>
-    <module name="EmptyForIteratorPad"/>
-    <module name="ModifierOrder"/>
-    <module name="DefaultComesLast"/>
-    <module name="InnerAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ModifiedControlVariable"/>
-    <module name="MutableException">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ParameterAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="format" value="\s$"/>
-      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="ignoreComments" value="false"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
-      <property name="format" value=" ,"/>
-      <property name="message" value="illegal space before a comma"/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="[^\x00-\x7F]"/>
-      <property name="message" value="Only use ASCII characters."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
-      <property name="message" value="Don't use old synchronized collection classes"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="instanceof MoveOp"/>
-      <property name="message" value="Do not use `op instanceof MoveOp`. Use `MoveOp.isMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="instanceof ValueMoveOp"/>
-      <property name="message" value="Do not use `op instanceof ValueMoveOp`. Use `ValueMoveOp.isValueMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="instanceof LoadConstantOp"/>
-      <property name="message" value="Do not use `op instanceof LoadConstantOp`. Use `LoadConstantOp.isLoadConstantOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="\(MoveOp\)"/>
-      <property name="message" value="Do not cast directly to `MoveOp`. Use `MoveOp.asMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="\(ValueMoveOp\)"/>
-      <property name="message" value="Do not cast directly to `ValueMoveOp`. Use `ValueMoveOp.asValueMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="\(LoadConstantOp\)"/>
-      <property name="message" value="Do not cast directly to `LoadConstantOp`. Use `LoadConstantOp.asLoadConstantOp(op)` instead!"/>
-    </module>
-  </module>
-  <module name="RegexpHeader">
-    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates\. All rights reserved\.\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], .*\. All rights reserved\.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER\.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation\.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE\.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\)\.\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc\., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www\.oracle\.com if you need additional information or have any\n \* questions\.\n \*/\n"/>
-    <property name="multiLines" value="3"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="FileTabCharacter">
-    <property name="severity" value="error"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="NewlineAtEndOfFile">
-    <property name="lineSeparator" value="lf"/>
-  </module>
-  <module name="Translation"/>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
-    <property name="checkFormat" value="ConstantNameCheck"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
-    <property name="checkFormat" value="MethodName"/>
-    <property name="checkC" value="false"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
-    <property name="checkFormat" value="ParameterAssignment"/>
-    <property name="checkC" value="false"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
-    <property name="checkFormat" value="FinalLocalVariable"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop"/>
-    <property name="onCommentFormat" value="Checkstyle: resume"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
-    <property name="checkFormat" value="InnerAssignment"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
-    <property name="checkFormat" value="MemberName"/>
-    <property name="checkC" value="false"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
-  </module>
-  <module name="RegexpMultiline">
-    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
-    <property name="format" value="\r\n"/>
-    <property name="message" value="illegal Windows line ending"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
-    <property name="checkFormat" value=".*Header"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
-    <property name="checkFormat" value="LineLength"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: start generated"/>
-    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-    <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
-  </module>
-</module>
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/CachedGraph.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.function.Consumer;
 
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 
 /**
  * This class is a container of a graph that needs to be readonly and optionally a lazily created
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Graph.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,7 @@
  */
 package org.graalvm.compiler.graph;
 
+import static org.graalvm.compiler.core.common.GraalOptions.TrackNodeInsertion;
 import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.Default;
 import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.Track;
 import static org.graalvm.compiler.graph.Graph.SourcePositionTracking.UpdateOnly;
@@ -33,15 +34,16 @@
 import java.util.Iterator;
 import java.util.function.Consumer;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TimerKey;
+import org.graalvm.compiler.graph.Node.NodeInsertionStackTrace;
 import org.graalvm.compiler.graph.Node.ValueNumberable;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.options.Option;
@@ -49,6 +51,8 @@
 import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
 /**
  * This class is a graph container, it contains the set of nodes that belong to this graph.
  */
@@ -195,7 +199,7 @@
      *         was opened
      */
     public DebugCloseable withNodeSourcePosition(Node node) {
-        return withNodeSourcePosition(node.sourcePosition);
+        return withNodeSourcePosition(node.getNodeSourcePosition());
     }
 
     /**
@@ -719,6 +723,9 @@
         assert node.getNodeClass().valueNumberable();
         T other = this.findDuplicate(node);
         if (other != null) {
+            if (other.getNodeSourcePosition() == null) {
+                other.setNodeSourcePosition(node.getNodeSourcePosition());
+            }
             return other;
         } else {
             T result = addHelper(node);
@@ -1097,6 +1104,9 @@
         if (currentNodeSourcePosition != null && trackNodeSourcePosition()) {
             node.setNodeSourcePosition(currentNodeSourcePosition);
         }
+        if (TrackNodeInsertion.getValue(getOptions())) {
+            node.setInsertionPosition(new NodeInsertionStackTrace());
+        }
 
         updateNodeCaches(node);
 
@@ -1189,6 +1199,23 @@
         return true;
     }
 
+    public boolean verifySourcePositions() {
+        if (trackNodeSourcePosition()) {
+            ResolvedJavaMethod root = null;
+            for (Node node : getNodes()) {
+                NodeSourcePosition pos = node.getNodeSourcePosition();
+                if (pos != null) {
+                    if (root == null) {
+                        root = pos.getRootMethod();
+                    } else {
+                        assert pos.verifyRootMethod(root) : node;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
     public Node getNode(int id) {
         return nodes[id];
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/Node.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,7 @@
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Formattable;
@@ -84,7 +85,8 @@
 public abstract class Node implements Cloneable, Formattable, NodeInterface {
 
     public static final NodeClass<?> TYPE = null;
-    public static final boolean USE_UNSAFE_TO_CLONE = true;
+
+    public static final boolean TRACK_CREATION_POSITION = Boolean.getBoolean("debug.graal.TrackNodeCreationPosition");
 
     static final int DELETED_ID_START = -1000000000;
     static final int INITIAL_ID = -1;
@@ -230,6 +232,40 @@
     public static final int NODE_LIST = -2;
     public static final int NOT_ITERABLE = -1;
 
+    static class NodeStackTrace {
+        final StackTraceElement[] stackTrace;
+
+        NodeStackTrace() {
+            this.stackTrace = new Throwable().getStackTrace();
+        }
+
+        private String getString(String label) {
+            StringBuilder sb = new StringBuilder();
+            if (label != null) {
+                sb.append(label).append(": ");
+            }
+            for (StackTraceElement ste : stackTrace) {
+                sb.append("at ").append(ste.toString()).append('\n');
+            }
+            return sb.toString();
+        }
+
+        String getStrackTraceString() {
+            return getString(null);
+        }
+
+        @Override
+        public String toString() {
+            return getString(getClass().getSimpleName());
+        }
+    }
+
+    static class NodeCreationStackTrace extends NodeStackTrace {
+    }
+
+    static class NodeInsertionStackTrace extends NodeStackTrace {
+    }
+
     public Node(NodeClass<? extends Node> c) {
         init(c);
     }
@@ -239,6 +275,9 @@
         this.nodeClass = c;
         id = INITIAL_ID;
         extraUsages = NO_NODES;
+        if (TRACK_CREATION_POSITION) {
+            setCreationPosition(new NodeCreationStackTrace());
+        }
     }
 
     final int id() {
@@ -577,32 +616,95 @@
     }
 
     /**
-     * The position of the bytecode that generated this node.
+     * Information associated with this node. A single value is stored directly in the field.
+     * Multiple values are stored by creating an Object[].
      */
-    NodeSourcePosition sourcePosition;
+    private Object annotation;
+
+    private <T> T getNodeInfo(Class<T> clazz) {
+        assert clazz != Object[].class;
+        if (annotation == null) {
+            return null;
+        }
+        if (clazz.isInstance(annotation)) {
+            return clazz.cast(annotation);
+        }
+        if (annotation.getClass() == Object[].class) {
+            Object[] annotations = (Object[]) annotation;
+            for (Object ann : annotations) {
+                if (clazz.isInstance(ann)) {
+                    return clazz.cast(ann);
+                }
+            }
+        }
+        return null;
+    }
+
+    private <T> void setNodeInfo(Class<T> clazz, T value) {
+        assert clazz != Object[].class;
+        if (annotation == null || clazz.isInstance(annotation)) {
+            // Replace the current value
+            this.annotation = value;
+        } else if (annotation.getClass() == Object[].class) {
+            Object[] annotations = (Object[]) annotation;
+            for (int i = 0; i < annotations.length; i++) {
+                if (clazz.isInstance(annotations[i])) {
+                    annotations[i] = value;
+                    return;
+                }
+            }
+            Object[] newAnnotations = Arrays.copyOf(annotations, annotations.length + 1);
+            newAnnotations[annotations.length] = value;
+            this.annotation = newAnnotations;
+        } else {
+            this.annotation = new Object[]{this.annotation, value};
+        }
+    }
 
     /**
      * Gets the source position information for this node or null if it doesn't exist.
      */
 
     public NodeSourcePosition getNodeSourcePosition() {
-        return sourcePosition;
+        return getNodeInfo(NodeSourcePosition.class);
     }
 
     /**
-     * Set the source position to {@code sourcePosition}.
+     * Set the source position to {@code sourcePosition}. Setting it to null is ignored so that it's
+     * not accidentally cleared. Use {@link #clearNodeSourcePosition()} instead.
      */
     public void setNodeSourcePosition(NodeSourcePosition sourcePosition) {
-        assert sourcePosition != null || this.sourcePosition == null || this.sourcePosition.isPlaceholder() : "Invalid source position at node with id " + id;
-        this.sourcePosition = sourcePosition;
-        // assert sourcePosition == null || graph == null || graph.trackNodeSourcePosition;
+        if (sourcePosition == null) {
+            return;
+        }
+        setNodeInfo(NodeSourcePosition.class, sourcePosition);
+    }
+
+    public void clearNodeSourcePosition() {
+        setNodeInfo(NodeSourcePosition.class, null);
+    }
+
+    public NodeCreationStackTrace getCreationPosition() {
+        return getNodeInfo(NodeCreationStackTrace.class);
+    }
+
+    public void setCreationPosition(NodeCreationStackTrace trace) {
+        setNodeInfo(NodeCreationStackTrace.class, trace);
+    }
+
+    public NodeInsertionStackTrace getInsertionPosition() {
+        return getNodeInfo(NodeInsertionStackTrace.class);
+    }
+
+    public void setInsertionPosition(NodeInsertionStackTrace trace) {
+        setNodeInfo(NodeInsertionStackTrace.class, trace);
     }
 
     /**
      * Update the source position only if it is null.
      */
     public void updateNodeSourcePosition(Supplier<NodeSourcePosition> sourcePositionSupp) {
-        if (this.sourcePosition == null) {
+        if (this.getNodeSourcePosition() == null) {
             setNodeSourcePosition(sourcePositionSupp.get());
         }
     }
@@ -919,8 +1021,8 @@
         }
         newNode.graph = into;
         newNode.id = INITIAL_ID;
-        if (sourcePosition != null && (into == null || into.updateNodeSourcePosition())) {
-            newNode.setNodeSourcePosition(sourcePosition);
+        if (getNodeSourcePosition() != null && (into == null || into.updateNodeSourcePosition())) {
+            newNode.setNodeSourcePosition(getNodeSourcePosition());
         }
         if (into != null) {
             into.register(newNode);
@@ -1077,6 +1179,14 @@
         if (pos != null) {
             map.put("nodeSourcePosition", pos);
         }
+        NodeCreationStackTrace creation = getCreationPosition();
+        if (creation != null) {
+            map.put("nodeCreationPosition", creation.getStrackTraceString());
+        }
+        NodeInsertionStackTrace insertion = getInsertionPosition();
+        if (insertion != null) {
+            map.put("nodeInsertionPosition", insertion.getStrackTraceString());
+        }
         return map;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeClass.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,8 +42,8 @@
 import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.FieldIntrospection;
 import org.graalvm.compiler.core.common.Fields;
 import org.graalvm.compiler.core.common.FieldsScanner;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeMap.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import java.util.Iterator;
 import java.util.function.BiFunction;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
 
 public class NodeMap<T> extends NodeIdAccessor implements EconomicMap<Node, T> {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/NodeSourcePosition.java	Thu Apr 26 17:59:02 2018 +0200
@@ -64,6 +64,21 @@
         return this;
     }
 
+    public ResolvedJavaMethod getRootMethod() {
+        NodeSourcePosition cur = this;
+        while (cur.getCaller() != null) {
+            cur = cur.getCaller();
+        }
+        return cur.getMethod();
+    }
+
+    public boolean verifyRootMethod(ResolvedJavaMethod root) {
+        JavaMethod currentRoot = getRootMethod();
+        assert root.equals(currentRoot) || root.getName().equals(currentRoot.getName()) && root.getSignature().toMethodDescriptor().equals(currentRoot.getSignature().toMethodDescriptor()) &&
+                        root.getDeclaringClass().getName().equals(currentRoot.getDeclaringClass().getName()) : root + " " + currentRoot;
+        return true;
+    }
+
     enum Marker {
         None,
         Placeholder,
@@ -107,11 +122,11 @@
     }
 
     public static NodeSourcePosition substitution(ResolvedJavaMethod method) {
-        return new NodeSourcePosition(null, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
+        return substitution(null, method);
     }
 
-    public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method, int bci) {
-        return new NodeSourcePosition(caller, method, bci, Substitution);
+    public static NodeSourcePosition substitution(NodeSourcePosition caller, ResolvedJavaMethod method) {
+        return new NodeSourcePosition(caller, method, BytecodeFrame.INVALID_FRAMESTATE_BCI, Substitution);
     }
 
     public boolean isSubstitution() {
@@ -151,7 +166,7 @@
         return d;
     }
 
-    public SourceLanguagePosition getSourceLanauage() {
+    public SourceLanguagePosition getSourceLanguage() {
         return sourceLanguagePosition;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePosition.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.graph/src/org/graalvm/compiler/graph/SourceLanguagePosition.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.graph;
 
-import java.util.Map;
+import java.net.URI;
 
 /**
  * Provides a path to report information about a high level language source position to the Graph
@@ -31,14 +31,22 @@
 public interface SourceLanguagePosition {
 
     /**
-     * This is called during dumping of Nodes. The implementation should add any properties which
-     * describe this source position. The actual keys and values used are a private contract between
-     * the language implementation and the Graph Visualizer.
-     */
-    void addSourceInformation(Map<String, Object> props);
-
-    /**
      * Produce a compact description of this position suitable for printing.
      */
     String toShortString();
+
+    /** Mimics GraphLocations operation. */
+    int getOffsetEnd();
+
+    /** Mimics GraphLocations operation. */
+    int getOffsetStart();
+
+    /** Mimics GraphLocations operation. */
+    int getLineNumber();
+
+    /** Mimics GraphLocations operation. */
+    URI getURI();
+
+    /** Mimics GraphLocations operation. */
+    String getLanguage();
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackend.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
 import static jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig.fp;
 import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.aarch64.AArch64Address;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotBackendFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.hotspot.HotSpotBackendFactory;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.hotspot.HotSpotReplacementsImpl;
+import org.graalvm.compiler.hotspot.meta.AddressLoweringHotSpotSuitesProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotConstantFieldProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
 import org.graalvm.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider;
@@ -50,7 +51,11 @@
 import org.graalvm.compiler.hotspot.word.HotSpotWordTypes;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
+import org.graalvm.compiler.nodes.spi.Replacements;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.Phase;
+import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
+import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.replacements.aarch64.AArch64GraphBuilderPlugins;
@@ -77,7 +82,7 @@
 
     @Override
     public String getName() {
-        return "core";
+        return "community";
     }
 
     @Override
@@ -141,7 +146,7 @@
                 replacements.setGraphBuilderPlugins(plugins);
             }
             try (InitTimer rt = timer("create Suites provider")) {
-                suites = createSuites(config, graalRuntime, compilerConfiguration, plugins);
+                suites = createSuites(config, graalRuntime, compilerConfiguration, plugins, replacements);
             }
             providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, suites, registers,
                             snippetReflection, wordTypes,
@@ -178,8 +183,11 @@
         return new AArch64HotSpotForeignCallsProvider(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters);
     }
 
-    protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins) {
-        return new AArch64HotSpotSuitesProvider(new AArch64SuitesCreator(compilerConfiguration, plugins), config, runtime, new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
+    protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
+                    @SuppressWarnings("unused") Replacements replacements) {
+        AArch64SuitesCreator suitesCreator = new AArch64SuitesCreator(compilerConfiguration, plugins, SchedulePhase.class);
+        Phase addressLoweringPhase = new AddressLoweringByUsePhase(new AArch64AddressLoweringByUse(new AArch64LIRKindTool()));
+        return new AddressLoweringHotSpotSuitesProvider(suitesCreator, config, runtime, addressLoweringPhase);
     }
 
     protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotForeignCallsProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF;
 import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
 import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotJumpToExceptionHandlerInCallerOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
@@ -68,11 +69,12 @@
     public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
         leaveFrame(crb, masm, /* emitSafepoint */false);
 
-        if (System.getProperty("java.specification.version").compareTo("1.8") < 0) {
+        if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
             // Restore sp from fp if the exception PC is a method handle call site.
             try (ScratchRegister sc = masm.getScratchRegister()) {
                 Register scratch = sc.getRegister();
-                AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, /* allowOverwrite */false);
+                final boolean allowOverwrite = false;
+                AArch64Address address = masm.makeAddress(thread, isMethodHandleReturnOffset, scratch, 4, allowOverwrite);
                 masm.ldr(32, scratch, address);
                 Label noRestore = new Label();
                 masm.cbz(32, scratch, noRestore);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotRegisterAllocationConfig.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,6 @@
 import static jdk.vm.ci.aarch64.AArch64.r24;
 import static jdk.vm.ci.aarch64.AArch64.r25;
 import static jdk.vm.ci.aarch64.AArch64.r26;
-import static jdk.vm.ci.aarch64.AArch64.r27;
 import static jdk.vm.ci.aarch64.AArch64.r28;
 import static jdk.vm.ci.aarch64.AArch64.r3;
 import static jdk.vm.ci.aarch64.AArch64.r4;
@@ -100,7 +99,7 @@
         r0,  r1,  r2,  r3,  r4,  r5,  r6,  r7,
         r8,  r9,  r10, r11, r12, r13, r14, r15,
         r16, r17, r18, r19, r20, r21, r22, r23,
-        r24, r25, r26, r27, r28, /* r29, r30, r31 */
+        r24, r25, r26, /* r27, */ r28, /* r29, r30, r31 */
 
         v0,  v1,  v2,  v3,  v4,  v5,  v6,  v7,
         v8,  v9,  v10, v11, v12, v13, v14, v15,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.aarch64/src/org/graalvm/compiler/hotspot/aarch64/AArch64HotSpotSuitesProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2017, Red Hat Inc. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.hotspot.aarch64;
-
-import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
-import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
-import org.graalvm.compiler.hotspot.meta.HotSpotSuitesProvider;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.common.AddressLoweringByUsePhase;
-import org.graalvm.compiler.phases.common.ExpandLogicPhase;
-import org.graalvm.compiler.phases.common.FixReadsPhase;
-import org.graalvm.compiler.phases.common.PropagateDeoptimizeProbabilityPhase;
-import org.graalvm.compiler.phases.tiers.LowTierContext;
-import org.graalvm.compiler.phases.tiers.Suites;
-import org.graalvm.compiler.phases.tiers.SuitesCreator;
-import org.graalvm.compiler.replacements.aarch64.AArch64ReadReplacementPhase;
-
-import java.util.ListIterator;
-
-/**
- * Subclass to factor out management of address lowering.
- */
-public class AArch64HotSpotSuitesProvider extends HotSpotSuitesProvider {
-
-    private final AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse;
-
-    public AArch64HotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime,
-                    AddressLoweringByUsePhase.AddressLoweringByUse addressLoweringByUse) {
-        super(defaultSuitesCreator, config, runtime);
-        this.addressLoweringByUse = addressLoweringByUse;
-    }
-
-    @Override
-    public Suites createSuites(OptionValues options) {
-        Suites suites = super.createSuites(options);
-
-        ListIterator<BasePhase<? super LowTierContext>> findPhase = suites.getLowTier().findPhase(FixReadsPhase.class);
-        if (findPhase == null) {
-            findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
-        }
-        findPhase.add(new AddressLoweringByUsePhase(addressLoweringByUse));
-
-        findPhase = suites.getLowTier().findPhase(PropagateDeoptimizeProbabilityPhase.class);
-        findPhase.add(new AArch64ReadReplacementPhase());
-
-        return suites;
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotAddressLowering.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.asm.amd64.AMD64Address.Scale;
 import org.graalvm.compiler.core.amd64.AMD64AddressNode;
 import org.graalvm.compiler.core.amd64.AMD64CompressAddressLowering;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackend.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
 import static org.graalvm.compiler.core.common.GraalOptions.GeneratePIC;
 import static org.graalvm.compiler.core.common.GraalOptions.ZapStackOnMethodEntry;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.amd64.AMD64Address;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotBackendFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -52,6 +52,7 @@
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 import org.graalvm.compiler.nodes.spi.Replacements;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.phases.common.AddressLoweringPhase;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.replacements.amd64.AMD64GraphBuilderPlugins;
@@ -77,7 +78,7 @@
 
     @Override
     public String getName() {
-        return "core";
+        return "community";
     }
 
     @Override
@@ -186,7 +187,7 @@
     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
                     HotSpotRegistersProvider registers, Replacements replacements, OptionValues options) {
         return new AddressLoweringHotSpotSuitesProvider(new AMD64HotSpotSuitesCreator(compilerConfiguration, plugins), config, runtime,
-                        new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options));
+                        new AddressLoweringPhase(new AMD64HotSpotAddressLowering(config, registers.getHeapBaseRegister(), options)));
     }
 
     protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, WordTypes wordTypes) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
 import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
 import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.amd64/src/org/graalvm/compiler/hotspot/amd64/AMD64HotSpotJumpToExceptionHandlerInCallerOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,6 +33,7 @@
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
 import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.meta.AllocatableValue;
@@ -68,7 +69,7 @@
         // Discard the return address, thus completing restoration of caller frame
         masm.incrementq(rsp, 8);
 
-        if (System.getProperty("java.specification.version").compareTo("1.8") < 0) {
+        if (GraalServices.JAVA_SPECIFICATION_VERSION < 8) {
             // Restore rsp from rbp if the exception PC is a method handle call site.
             AMD64Address dst = new AMD64Address(thread, isMethodHandleReturnOffset);
             masm.cmpl(dst, 0);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackend.java	Thu Apr 26 17:59:02 2018 +0200
@@ -46,9 +46,9 @@
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.sparc.SPARCAddress;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotBackendFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -49,6 +49,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 import org.graalvm.compiler.nodes.spi.Replacements;
+import org.graalvm.compiler.phases.common.AddressLoweringPhase;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.replacements.classfile.ClassfileBytecodeProvider;
@@ -72,7 +73,7 @@
 
     @Override
     public String getName() {
-        return "core";
+        return "community";
     }
 
     @Override
@@ -125,7 +126,7 @@
      */
     protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, Plugins plugins,
                     Replacements replacements) {
-        return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new SPARCAddressLowering());
+        return new AddressLoweringHotSpotSuitesProvider(new SPARCSuitesCreator(compilerConfiguration, plugins), config, runtime, new AddressLoweringPhase(new SPARCAddressLowering()));
     }
 
     protected SPARCHotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.sparc/src/org/graalvm/compiler/hotspot/sparc/SPARCHotSpotForeignCallsProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition.LEAF_NOFP;
 import static org.graalvm.compiler.hotspot.replacements.CRC32Substitutions.UPDATE_BYTES_CRC32;
 import static org.graalvm.compiler.hotspot.replacements.CRC32CSubstitutions.UPDATE_BYTES_CRC32C;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CheckGraalIntrinsics.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
 import java.util.TreeSet;
 import java.util.stream.Collectors;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.api.test.Graal;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
@@ -43,7 +43,7 @@
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins.Binding;
 import org.graalvm.compiler.runtime.RuntimeProvider;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.graalvm.compiler.test.GraalTest;
 import org.junit.Test;
 
@@ -542,11 +542,11 @@
     }
 
     private static boolean isJDK9OrHigher() {
-        return JDK9Method.JAVA_SPECIFICATION_VERSION >= 9;
+        return GraalServices.JAVA_SPECIFICATION_VERSION >= 9;
     }
 
     private static boolean isJDK10OrHigher() {
-        return JDK9Method.JAVA_SPECIFICATION_VERSION >= 10;
+        return GraalServices.JAVA_SPECIFICATION_VERSION >= 10;
     }
 
     private static String getHostArchitectureName() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompilationWrapperTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -105,7 +105,6 @@
     public void testVMCompilation3() throws IOException, InterruptedException {
         final int maxProblems = 4;
         Probe[] probes = {
-                        new Probe("To capture more information for diagnosing or reporting a compilation", maxProblems),
                         new Probe("Retrying compilation of", maxProblems) {
                             @Override
                             String test() {
@@ -131,6 +130,7 @@
         testHelper(Collections.emptyList(),
                         Arrays.asList(
                                         "-Dgraal.CompilationFailureAction=ExitVM",
+                                        "-Dgraal.TrufflePerformanceWarningsAreFatal=true",
                                         "-Dgraal.CrashAt=root test1"),
                         "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
     }
@@ -151,6 +151,22 @@
                         "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
     }
 
+    /**
+     * Tests that TrufflePerformanceWarningsAreFatal generates diagnostic output.
+     */
+    @Test
+    public void testTruffleCompilation3() throws IOException, InterruptedException {
+        Probe[] probes = {
+                        new Probe("Exiting VM due to TrufflePerformanceWarningsAreFatal=true", 1),
+        };
+        testHelper(Arrays.asList(probes),
+                        Arrays.asList(
+                                        "-Dgraal.CompilationFailureAction=Silent",
+                                        "-Dgraal.TrufflePerformanceWarningsAreFatal=true",
+                                        "-Dgraal.CrashAt=root test1:PermanentBailout"),
+                        "org.graalvm.compiler.truffle.test.SLTruffleGraalTestSuite", "test");
+    }
+
     private static final boolean VERBOSE = Boolean.getBoolean(CompilationWrapperTest.class.getSimpleName() + ".verbose");
 
     private static void testHelper(List<Probe> initialProbes, List<String> extraVmArgs, String... mainClassAndArgs) throws IOException, InterruptedException {
@@ -225,7 +241,7 @@
                     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));
+                    Assert.fail(String.format("Expected at least one .cfg file in %s: %s%n%s", diagnosticOutputZip, entries, proc));
                 }
             } finally {
                 zip.delete();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorld.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 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;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import java.io.Closeable;
 import java.io.File;
@@ -66,10 +66,12 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.bytecode.Bytecodes;
 import org.graalvm.compiler.core.CompilerThreadFactory;
@@ -86,7 +88,7 @@
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
@@ -107,8 +109,8 @@
 
     /**
      * Magic token to denote that JDK classes are to be compiled. If
-     * {@link JDK9Method#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled. Otherwise
-     * the classes in the Java runtime image are compiled.
+     * {@link GraalServices#Java8OrEarlier}, then the classes in {@code rt.jar} are compiled.
+     * Otherwise the classes in the Java runtime image are compiled.
      */
     public static final String SUN_BOOT_CLASS_PATH = "sun.boot.class.path";
 
@@ -379,6 +381,11 @@
             return new URLClassLoader(new URL[]{url});
         }
 
+        /**
+         * @see "https://docs.oracle.com/javase/9/docs/specs/jar/jar.html#Multi-release"
+         */
+        static Pattern MultiReleaseJarVersionedClassRE = Pattern.compile("META-INF/versions/[1-9][0-9]*/(.+)");
+
         @Override
         public List<String> getClassNames() throws IOException {
             Enumeration<JarEntry> e = jarFile.entries();
@@ -389,6 +396,17 @@
                     continue;
                 }
                 String className = je.getName().substring(0, je.getName().length() - ".class".length());
+                if (className.equals("module-info")) {
+                    continue;
+                }
+                if (className.startsWith("META-INF/versions/")) {
+                    Matcher m = MultiReleaseJarVersionedClassRE.matcher(className);
+                    if (m.matches()) {
+                        className = m.group(1);
+                    } else {
+                        continue;
+                    }
+                }
                 classNames.add(className.replace('/', '.'));
             }
             return classNames;
@@ -562,6 +580,10 @@
                         continue;
                     }
 
+                    if (!isClassIncluded(className)) {
+                        continue;
+                    }
+
                     try {
                         // Load and initialize class
                         Class<?> javaClass = Class.forName(className, true, loader);
@@ -581,14 +603,6 @@
                             continue;
                         }
 
-                        /*
-                         * Only check filters after class loading and resolution to mitigate impact
-                         * on reproducibility.
-                         */
-                        if (!isClassIncluded(className)) {
-                            continue;
-                        }
-
                         // Are we compiling this class?
                         MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
                         if (classFileCounter >= startAt) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/CompileTheWorldTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationBailoutAction;
 import static org.graalvm.compiler.core.GraalCompilerOptions.CompilationFailureAction;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.hotspot.HotSpotGraalCompiler;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRLockTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,6 @@
 
 import java.lang.management.ManagementFactory;
 import java.lang.management.MonitorInfo;
-import java.lang.management.RuntimeMXBean;
 import java.lang.management.ThreadInfo;
 import java.lang.management.ThreadMXBean;
 import java.util.Collection;
@@ -32,7 +31,7 @@
 import java.util.HashSet;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.core.phases.HighTier;
 import org.graalvm.compiler.debug.DebugContext;
@@ -41,6 +40,7 @@
 import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.junit.Assert;
 import org.junit.Assume;
 import org.junit.BeforeClass;
@@ -58,11 +58,6 @@
 
     @BeforeClass
     public static void checkVMArguments() {
-        try {
-            Class.forName("java.lang.management.ManagementFactory");
-        } catch (ClassNotFoundException ex) {
-            Assume.assumeNoException("cannot check for monitors without java.management JDK9 module", ex);
-        }
         /*
          * Note: The -Xcomp execution mode of the VM will stop most of the OSR test cases from
          * working as every method is compiled at level3 (followed by level4 on the second
@@ -71,8 +66,8 @@
          * installed nmethod at a given BCI.
          *
          */
-        RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
-        List<String> arguments = runtimeMxBean.getInputArguments();
+        List<String> arguments = GraalServices.getInputArguments();
+        Assume.assumeTrue("cannot check for monitors without", arguments != null);
         for (String arg : arguments) {
             Assume.assumeFalse(arg.equals(COMPILE_ONLY_FLAG));
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,9 @@
 import org.junit.Assert;
 import org.junit.Test;
 
+import jdk.vm.ci.meta.ProfilingInfo;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
 /**
  * Test on-stack-replacement with Graal. The test manually triggers a Graal OSR-compilation which is
  * later invoked when hitting the backedge counter overflow.
@@ -99,4 +102,57 @@
         return ret;
     }
 
+    @Test
+    public void testOSR04() {
+        testFunnyOSR("testDoWhile", GraalOSRTest::testDoWhile);
+    }
+
+    @Test
+    public void testOSR05() {
+        testFunnyOSR("testDoWhileLocked", GraalOSRTest::testDoWhileLocked);
+    }
+
+    /**
+     * Because of a bug in C1 profile collection HotSpot can sometimes request an OSR compilation
+     * for a backedge which isn't ever taken. This test synthetically creates that situation.
+     */
+    private void testFunnyOSR(String name, Runnable warmup) {
+        ResolvedJavaMethod method = getResolvedJavaMethod(name);
+        int iterations = 0;
+        while (true) {
+            ProfilingInfo profilingInfo = method.getProfilingInfo();
+            if (profilingInfo.isMature()) {
+                break;
+            }
+
+            warmup.run();
+            if (iterations++ % 1000 == 0) {
+                System.err.print('.');
+            }
+            if (iterations > 200000) {
+                throw new AssertionError("no profile");
+            }
+        }
+        compileOSR(getInitialOptions(), method);
+        Result result = executeExpected(method, null);
+        checkResult(result);
+    }
+
+    private static boolean repeatLoop;
+
+    public static ReturnValue testDoWhile() {
+        do {
+            sideEffect++;
+        } while (repeatLoop);
+        return ReturnValue.SUCCESS;
+    }
+
+    public static synchronized ReturnValue testDoWhileLocked() {
+        // synchronized (GraalOSRTest.class) {
+        do {
+            sideEffect++;
+        } while (repeatLoop);
+        // }
+        return ReturnValue.SUCCESS;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/GraalOSRTestBase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,8 @@
 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
 import org.graalvm.compiler.bytecode.BytecodeStream;
 import org.graalvm.compiler.bytecode.ResolvedJavaMethodBytecode;
+import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
+import org.graalvm.compiler.core.GraalCompilerOptions;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.debug.DebugContext;
@@ -95,18 +97,18 @@
      * Returns the target BCI of the first bytecode backedge. This is where HotSpot triggers
      * on-stack-replacement in case the backedge counter overflows.
      */
-    private static int getBackedgeBCI(DebugContext debug, ResolvedJavaMethod method) {
+    static int getBackedgeBCI(DebugContext debug, ResolvedJavaMethod method) {
         Bytecode code = new ResolvedJavaMethodBytecode(method);
         BytecodeStream stream = new BytecodeStream(code.getCode());
         OptionValues options = debug.getOptions();
         BciBlockMapping bciBlockMapping = BciBlockMapping.create(stream, code, options, debug);
 
         for (BciBlock block : bciBlockMapping.getBlocks()) {
-            if (block.startBci != -1) {
-                int bci = block.startBci;
+            if (block.getStartBci() != -1) {
+                int bci = block.getEndBci();
                 for (BciBlock succ : block.getSuccessors()) {
-                    if (succ.startBci != -1) {
-                        int succBci = succ.startBci;
+                    if (succ.getStartBci() != -1) {
+                        int succBci = succ.getStartBci();
                         if (succBci < bci) {
                             // back edge
                             return succBci;
@@ -120,16 +122,22 @@
         return -1;
     }
 
-    private static void checkResult(Result result) {
+    protected static void checkResult(Result result) {
         Assert.assertNull("Unexpected exception", result.exception);
         Assert.assertNotNull(result.returnValue);
         Assert.assertTrue(result.returnValue instanceof ReturnValue);
         Assert.assertEquals(ReturnValue.SUCCESS, result.returnValue);
     }
 
-    private void compileOSR(OptionValues options, ResolvedJavaMethod method) {
+    protected void compileOSR(OptionValues options, ResolvedJavaMethod method) {
+        OptionValues goptions = options;
+        // Silence diagnostics for permanent bailout errors as they
+        // are expected for some OSR tests.
+        if (!GraalCompilerOptions.CompilationBailoutAction.hasBeenSet(options)) {
+            goptions = new OptionValues(options, GraalCompilerOptions.CompilationBailoutAction, ExceptionAction.Silent);
+        }
         // ensure eager resolving
-        StructuredGraph graph = parseEager(method, AllowAssumptions.YES, options);
+        StructuredGraph graph = parseEager(method, AllowAssumptions.YES, goptions);
         DebugContext debug = graph.getDebug();
         int bci = getBackedgeBCI(debug, method);
         assert bci != -1;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalMBeanTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,241 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.hotspot.test;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNotSame;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.lang.management.ManagementFactory;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-
-import javax.management.Attribute;
-import javax.management.MBeanAttributeInfo;
-import javax.management.MBeanInfo;
-import javax.management.MBeanOperationInfo;
-import javax.management.MBeanServer;
-import javax.management.ObjectInstance;
-import javax.management.ObjectName;
-
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.hotspot.HotSpotGraalMBean;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.test.GraalTest;
-import org.junit.Assume;
-import org.junit.Test;
-
-import jdk.vm.ci.meta.MetaAccessProvider;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-
-public class HotSpotGraalMBeanTest {
-
-    public HotSpotGraalMBeanTest() {
-        // No support for registering Graal MBean yet on JDK9 (GR-4025). We cannot
-        // rely on an exception being thrown when accessing ManagementFactory.platformMBeanServer
-        // via reflection as recent JDK9 changes now allow this and issue a warning instead.
-        Assume.assumeTrue(GraalTest.Java8OrEarlier);
-    }
-
-    @Test
-    public void registration() throws Exception {
-        ObjectName name;
-
-        Field field = null;
-        try {
-            field = stopMBeanServer();
-        } catch (Exception ex) {
-            if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
-                // skip on JDK9
-                return;
-            }
-        }
-        assertNull("The platformMBeanServer isn't initialized now", field.get(null));
-
-        HotSpotGraalMBean bean = HotSpotGraalMBean.create(null);
-        assertNotNull("Bean created", bean);
-
-        assertNull("It is not registered yet", bean.ensureRegistered(true));
-
-        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
-        assertNotNull("Now the bean thinks it is registered", name = bean.ensureRegistered(true));
-
-        assertNotNull("And the bean is found", server.getObjectInstance(name));
-    }
-
-    private static Field stopMBeanServer() throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException {
-        final Field field = ManagementFactory.class.getDeclaredField("platformMBeanServer");
-        field.setAccessible(true);
-        field.set(null, null);
-        return field;
-    }
-
-    @Test
-    public void readBeanInfo() throws Exception {
-        ObjectName name;
-
-        assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
-
-        HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
-        assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
-        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
-        ObjectInstance bean = server.getObjectInstance(name);
-        assertNotNull("Bean is registered", bean);
-        MBeanInfo info = server.getMBeanInfo(name);
-        assertNotNull("Info is found", info);
-
-        MBeanAttributeInfo printCompilation = (MBeanAttributeInfo) findAttributeInfo("PrintCompilation", info);
-        assertNotNull("PrintCompilation found", printCompilation);
-        assertEquals("true/false", Boolean.class.getName(), printCompilation.getType());
-
-        Attribute printOn = new Attribute(printCompilation.getName(), Boolean.TRUE);
-
-        Object before = server.getAttribute(name, printCompilation.getName());
-        server.setAttribute(name, printOn);
-        Object after = server.getAttribute(name, printCompilation.getName());
-
-        assertNull("Default value was not set", before);
-        assertEquals("Changed to on", Boolean.TRUE, after);
-    }
-
-    private static Object findAttributeInfo(String attrName, Object info) {
-        MBeanAttributeInfo printCompilation = null;
-        for (MBeanAttributeInfo attr : ((MBeanInfo) info).getAttributes()) {
-            if (attr.getName().equals(attrName)) {
-                assertTrue("Readable", attr.isReadable());
-                assertTrue("Writable", attr.isWritable());
-                printCompilation = attr;
-                break;
-            }
-        }
-        return printCompilation;
-    }
-
-    @Test
-    public void optionsAreCached() throws Exception {
-        ObjectName name;
-
-        assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
-
-        HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
-
-        OptionValues original = new OptionValues(EconomicMap.create());
-
-        assertSame(original, realBean.optionsFor(original, null));
-
-        assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
-        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
-        ObjectInstance bean = server.getObjectInstance(name);
-        assertNotNull("Bean is registered", bean);
-        MBeanInfo info = server.getMBeanInfo(name);
-        assertNotNull("Info is found", info);
-
-        MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
-
-        Attribute dumpTo1 = new Attribute(dump.getName(), 1);
-
-        server.setAttribute(name, dumpTo1);
-        Object after = server.getAttribute(name, dump.getName());
-        assertEquals(1, after);
-
-        final OptionValues modified1 = realBean.optionsFor(original, null);
-        assertNotSame(original, modified1);
-        final OptionValues modified2 = realBean.optionsFor(original, null);
-        assertSame("Options are cached", modified1, modified2);
-
-    }
-
-    @Test
-    public void dumpOperation() throws Exception {
-        Field field = null;
-        try {
-            field = stopMBeanServer();
-        } catch (Exception ex) {
-            if (ex.getClass().getName().equals("java.lang.reflect.InaccessibleObjectException")) {
-                // skip on JDK9
-                return;
-            }
-        }
-        assertNull("The platformMBeanServer isn't initialized now", field.get(null));
-
-        ObjectName name;
-
-        assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
-
-        HotSpotGraalMBean realBean = HotSpotGraalMBean.create(null);
-
-        assertNotNull("Bean is registered", name = realBean.ensureRegistered(false));
-        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
-
-        ObjectInstance bean = server.getObjectInstance(name);
-        assertNotNull("Bean is registered", bean);
-
-        MBeanInfo info = server.getMBeanInfo(name);
-        assertNotNull("Info is found", info);
-
-        final MBeanOperationInfo[] arr = info.getOperations();
-        assertEquals("Currently three overloads", 3, arr.length);
-        MBeanOperationInfo dumpOp = null;
-        for (int i = 0; i < arr.length; i++) {
-            assertEquals("dumpMethod", arr[i].getName());
-            if (arr[i].getSignature().length == 3) {
-                dumpOp = arr[i];
-            }
-        }
-        assertNotNull("three args variant found", dumpOp);
-
-        server.invoke(name, "dumpMethod", new Object[]{
-                        "java.util.Arrays", "asList", ":3"
-        }, null);
-
-        MBeanAttributeInfo dump = (MBeanAttributeInfo) findAttributeInfo("Dump", info);
-        Attribute dumpTo1 = new Attribute(dump.getName(), "");
-        server.setAttribute(name, dumpTo1);
-        Object after = server.getAttribute(name, dump.getName());
-        assertEquals("", after);
-
-        OptionValues empty = new OptionValues(EconomicMap.create());
-        OptionValues unsetDump = realBean.optionsFor(empty, null);
-        final MetaAccessProvider metaAccess = jdk.vm.ci.runtime.JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess();
-        ResolvedJavaMethod method = metaAccess.lookupJavaMethod(Arrays.class.getMethod("asList", Object[].class));
-        final OptionValues forMethod = realBean.optionsFor(unsetDump, method);
-        assertNotSame(unsetDump, forMethod);
-        Object nothing = unsetDump.getMap().get(DebugOptions.Dump);
-        assertEquals("Empty string", "", nothing);
-
-        Object specialValue = forMethod.getMap().get(DebugOptions.Dump);
-        assertEquals(":3", specialValue);
-
-        OptionValues normalMethod = realBean.optionsFor(unsetDump, null);
-        Object noSpecialValue = normalMethod.getMap().get(DebugOptions.Dump);
-        assertEquals("Empty string", "", noSpecialValue);
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotGraalManagementTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.test;
+
+import static org.graalvm.compiler.hotspot.test.HotSpotGraalManagementTest.JunitShield.findAttributeInfo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.AttributeNotFoundException;
+import javax.management.InvalidAttributeValueException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerFactory;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.graalvm.compiler.api.test.Graal;
+import org.graalvm.compiler.hotspot.HotSpotGraalManagementRegistration;
+import org.graalvm.compiler.hotspot.HotSpotGraalRuntime;
+import org.graalvm.compiler.options.EnumOptionKey;
+import org.graalvm.compiler.options.NestedBooleanOptionKey;
+import org.graalvm.compiler.options.OptionDescriptor;
+import org.graalvm.compiler.options.OptionDescriptors;
+import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionsParser;
+import org.junit.Assert;
+import org.junit.AssumptionViolatedException;
+import org.junit.Test;
+
+public class HotSpotGraalManagementTest {
+
+    private static final boolean DEBUG = Boolean.getBoolean(HotSpotGraalManagementTest.class.getSimpleName() + ".debug");
+
+    public HotSpotGraalManagementTest() {
+        try {
+            MBeanServerFactory.findMBeanServer(null);
+        } catch (NoClassDefFoundError e) {
+            throw new AssumptionViolatedException("Management classes/module(s) not available: " + e);
+        }
+    }
+
+    @Test
+    public void registration() throws Exception {
+        HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) Graal.getRuntime();
+        HotSpotGraalManagementRegistration management = runtime.getManagement();
+        if (management == null) {
+            return;
+        }
+
+        MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+        ObjectName name;
+        assertNotNull("Now the bean thinks it is registered", name = (ObjectName) management.poll(true));
+
+        assertNotNull("And the bean is found", server.getObjectInstance(name));
+    }
+
+    @Test
+    public void readBeanInfo() throws Exception {
+
+        assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
+
+        HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) Graal.getRuntime();
+        HotSpotGraalManagementRegistration management = runtime.getManagement();
+        if (management == null) {
+            return;
+        }
+
+        ObjectName mbeanName;
+        assertNotNull("Bean is registered", mbeanName = (ObjectName) management.poll(true));
+        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+        ObjectInstance bean = server.getObjectInstance(mbeanName);
+        assertNotNull("Bean is registered", bean);
+        MBeanInfo info = server.getMBeanInfo(mbeanName);
+        assertNotNull("Info is found", info);
+
+        AttributeList originalValues = new AttributeList();
+        AttributeList newValues = new AttributeList();
+        for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
+            for (OptionDescriptor option : set) {
+                JunitShield.testOption(info, mbeanName, server, runtime, option, newValues, originalValues);
+            }
+        }
+
+        String[] attributeNames = new String[originalValues.size()];
+        for (int i = 0; i < attributeNames.length; i++) {
+            attributeNames[i] = ((Attribute) originalValues.get(i)).getName();
+        }
+        AttributeList actualValues = server.getAttributes(mbeanName, attributeNames);
+        assertEquals(originalValues.size(), actualValues.size());
+        for (int i = 0; i < attributeNames.length; i++) {
+            Object expect = String.valueOf(((Attribute) originalValues.get(i)).getValue());
+            Object actual = String.valueOf(((Attribute) actualValues.get(i)).getValue());
+            assertEquals(attributeNames[i], expect, actual);
+        }
+
+        try {
+            server.setAttributes(mbeanName, newValues);
+        } finally {
+            server.setAttributes(mbeanName, originalValues);
+        }
+    }
+
+    /**
+     * Junit scans all methods of a test class and tries to resolve all method parameter and return
+     * types. We hide such methods in an inner class to prevent errors such as:
+     *
+     * <pre>
+     * java.lang.NoClassDefFoundError: javax/management/MBeanInfo
+     *     at java.base/java.lang.Class.getDeclaredMethods0(Native Method)
+     *     at java.base/java.lang.Class.privateGetDeclaredMethods(Class.java:3119)
+     *     at java.base/java.lang.Class.getDeclaredMethods(Class.java:2268)
+     *     at org.junit.internal.MethodSorter.getDeclaredMethods(MethodSorter.java:54)
+     *     at org.junit.runners.model.TestClass.scanAnnotatedMembers(TestClass.java:65)
+     *     at org.junit.runners.model.TestClass.<init>(TestClass.java:57)
+     *
+     * </pre>
+     */
+    static class JunitShield {
+
+        /**
+         * Tests changing the value of {@code option} via the management interface to a) a new legal
+         * value and b) an illegal value.
+         */
+        static void testOption(MBeanInfo mbeanInfo,
+                        ObjectName mbeanName,
+                        MBeanServer server,
+                        HotSpotGraalRuntime runtime,
+                        OptionDescriptor option,
+                        AttributeList newValues,
+                        AttributeList originalValues) throws Exception {
+            OptionKey<?> optionKey = option.getOptionKey();
+            Object currentValue = optionKey.getValue(runtime.getOptions());
+            Class<?> optionType = option.getOptionValueType();
+            String name = option.getName();
+            if (DEBUG) {
+                System.out.println("Testing option " + name);
+            }
+            MBeanAttributeInfo attrInfo = findAttributeInfo(name, mbeanInfo);
+            assertNotNull("Attribute not found for option " + name, attrInfo);
+
+            String expectAttributeValue = stringValue(currentValue, option.getOptionValueType() == String.class);
+            Object actualAttributeValue = server.getAttribute(mbeanName, name);
+            assertEquals(expectAttributeValue, actualAttributeValue);
+
+            Map<String, String> legalValues = new HashMap<>();
+            List<String> illegalValues = new ArrayList<>();
+            if (optionKey instanceof EnumOptionKey) {
+                EnumOptionKey<?> enumOptionKey = (EnumOptionKey<?>) optionKey;
+                for (Object obj : enumOptionKey.getAllValues()) {
+                    if (obj != currentValue) {
+                        legalValues.put(obj.toString(), obj.toString());
+                    }
+                }
+                illegalValues.add(String.valueOf(42));
+            } else if (optionType == Boolean.class) {
+                Object defaultValue;
+                if (optionKey instanceof NestedBooleanOptionKey) {
+                    NestedBooleanOptionKey nbok = (NestedBooleanOptionKey) optionKey;
+                    defaultValue = nbok.getMasterOption().getValue(runtime.getOptions());
+                } else {
+                    defaultValue = optionKey.getDefaultValue();
+                }
+                legalValues.put("", unquotedStringValue(defaultValue));
+                illegalValues.add(String.valueOf(42));
+                illegalValues.add("true");
+                illegalValues.add("false");
+            } else if (optionType == String.class) {
+                legalValues.put("", quotedStringValue(optionKey.getDefaultValue()));
+                legalValues.put("\"" + currentValue + "Prime\"", "\"" + currentValue + "Prime\"");
+                legalValues.put("\"quoted string\"", "\"quoted string\"");
+                illegalValues.add("\"unbalanced quotes");
+                illegalValues.add("\"");
+                illegalValues.add("non quoted string");
+            } else if (optionType == Float.class) {
+                legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+                String value = unquotedStringValue(currentValue == null ? 33F : ((float) currentValue) + 11F);
+                legalValues.put(value, value);
+                illegalValues.add("string");
+            } else if (optionType == Double.class) {
+                legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+                String value = unquotedStringValue(currentValue == null ? 33D : ((double) currentValue) + 11D);
+                legalValues.put(value, value);
+                illegalValues.add("string");
+            } else if (optionType == Integer.class) {
+                legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+                String value = unquotedStringValue(currentValue == null ? 33 : ((int) currentValue) + 11);
+                legalValues.put(value, value);
+                illegalValues.add("42.42");
+                illegalValues.add("string");
+            } else if (optionType == Long.class) {
+                legalValues.put("", unquotedStringValue(optionKey.getDefaultValue()));
+                String value = unquotedStringValue(currentValue == null ? 33L : ((long) currentValue) + 11L);
+                legalValues.put(value, value);
+                illegalValues.add("42.42");
+                illegalValues.add("string");
+            }
+
+            Attribute originalAttributeValue = new Attribute(name, expectAttributeValue);
+            try {
+                for (Map.Entry<String, String> e : legalValues.entrySet()) {
+                    String legalValue = e.getKey();
+                    if (DEBUG) {
+                        System.out.printf("Changing %s from %s to %s%n", name, currentValue, legalValue);
+                    }
+                    Attribute newAttributeValue = new Attribute(name, legalValue);
+                    newValues.add(newAttributeValue);
+                    server.setAttribute(mbeanName, newAttributeValue);
+                    Object actual = optionKey.getValue(runtime.getOptions());
+                    actual = server.getAttribute(mbeanName, name);
+                    String expectValue = e.getValue();
+                    if (option.getOptionValueType() == String.class && expectValue == null) {
+                        expectValue = "";
+                    } else if (option.getOptionKey() instanceof NestedBooleanOptionKey && null == expectValue) {
+                        NestedBooleanOptionKey nbok = (NestedBooleanOptionKey) option.getOptionKey();
+                        expectValue = String.valueOf(nbok.getValue(runtime.getOptions()));
+                        actual = server.getAttribute(mbeanName, name);
+                    }
+                    assertEquals(expectValue, actual);
+                }
+            } finally {
+                if (DEBUG) {
+                    System.out.printf("Resetting %s to %s%n", name, currentValue);
+                }
+                originalValues.add(originalAttributeValue);
+                server.setAttribute(mbeanName, originalAttributeValue);
+            }
+
+            try {
+                for (Object illegalValue : illegalValues) {
+                    if (DEBUG) {
+                        System.out.printf("Changing %s from %s to illegal value %s%n", name, currentValue, illegalValue);
+                    }
+                    server.setAttribute(mbeanName, new Attribute(name, illegalValue));
+                    Assert.fail("Expected setting " + name + " to " + illegalValue + " to fail");
+                }
+            } catch (InvalidAttributeValueException e) {
+                // Expected
+            } finally {
+                if (DEBUG) {
+                    System.out.printf("Resetting %s to %s%n", name, currentValue);
+                }
+                server.setAttribute(mbeanName, originalAttributeValue);
+            }
+
+            try {
+
+                String unknownOptionName = "definitely not an option name";
+                server.setAttribute(mbeanName, new Attribute(unknownOptionName, ""));
+                Assert.fail("Expected setting option with name \"" + unknownOptionName + "\" to fail");
+            } catch (AttributeNotFoundException e) {
+                // Expected
+            }
+        }
+
+        static MBeanAttributeInfo findAttributeInfo(String attrName, MBeanInfo info) {
+            for (MBeanAttributeInfo attr : info.getAttributes()) {
+                if (attr.getName().equals(attrName)) {
+                    assertTrue("Readable", attr.isReadable());
+                    assertTrue("Writable", attr.isWritable());
+                    return attr;
+                }
+            }
+            return null;
+        }
+    }
+
+    private static String quotedStringValue(Object optionValue) {
+        return stringValue(optionValue, true);
+    }
+
+    private static String unquotedStringValue(Object optionValue) {
+        return stringValue(optionValue, false);
+    }
+
+    private static String stringValue(Object optionValue, boolean withQuoting) {
+        if (optionValue == null) {
+            return "";
+        }
+        if (withQuoting) {
+            return "\"" + optionValue + "\"";
+        }
+        return String.valueOf(optionValue);
+    }
+
+    private static String quoted(Object s) {
+        return "\"" + s + "\"";
+    }
+
+    /**
+     * Tests publicaly visible names and identifiers used by tools developed and distributed on an
+     * independent schedule (like VisualVM). Consider keeping the test passing without any semantic
+     * modifications. The cost of changes is higher than you estimate. Include all available
+     * stakeholders as reviewers to give them a chance to stop you before causing too much damage.
+     */
+    @Test
+    public void publicJmxApiOfGraalDumpOperation() throws Exception {
+        assertNotNull("Server is started", ManagementFactory.getPlatformMBeanServer());
+
+        HotSpotGraalRuntime runtime = (HotSpotGraalRuntime) Graal.getRuntime();
+        HotSpotGraalManagementRegistration management = runtime.getManagement();
+        if (management == null) {
+            return;
+        }
+
+        ObjectName mbeanName;
+        assertNotNull("Bean is registered", mbeanName = (ObjectName) management.poll(true));
+        final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
+
+        assertEquals("Domain name is used to lookup the beans by VisualVM", "org.graalvm.compiler.hotspot", mbeanName.getDomain());
+        assertEquals("type can be used to identify the Graal bean", "HotSpotGraalRuntime_VM", mbeanName.getKeyProperty("type"));
+
+        ObjectInstance bean = server.getObjectInstance(mbeanName);
+        assertNotNull("Bean is registered", bean);
+
+        MBeanInfo info = server.getMBeanInfo(mbeanName);
+        assertNotNull("Info is found", info);
+
+        final MBeanOperationInfo[] arr = info.getOperations();
+        assertEquals("Currently three overloads", 3, arr.length);
+        MBeanOperationInfo dumpOp = null;
+        for (int i = 0; i < arr.length; i++) {
+            assertEquals("dumpMethod", arr[i].getName());
+            if (arr[i].getSignature().length == 3) {
+                dumpOp = arr[i];
+            }
+        }
+        assertNotNull("three args variant (as used by VisualVM) found", dumpOp);
+
+        MBeanAttributeInfo dumpPath = findAttributeInfo("DumpPath", info);
+        MBeanAttributeInfo printGraphFile = findAttributeInfo("PrintGraphFile", info);
+        MBeanAttributeInfo showDumpFiles = findAttributeInfo("ShowDumpFiles", info);
+        Object originalDumpPath = server.getAttribute(mbeanName, dumpPath.getName());
+        Object originalPrintGraphFile = server.getAttribute(mbeanName, printGraphFile.getName());
+        Object originalShowDumpFiles = server.getAttribute(mbeanName, showDumpFiles.getName());
+        final File tmpDir = new File(HotSpotGraalManagementTest.class.getSimpleName() + "_" + System.currentTimeMillis()).getAbsoluteFile();
+
+        server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), quoted(tmpDir)));
+        // Force output to a file even if there's a running IGV instance available.
+        server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), true));
+        server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), false));
+        Object[] params = {"java.util.Arrays", "asList", ":3"};
+        try {
+            server.invoke(mbeanName, "dumpMethod", params, null);
+            boolean found = false;
+            String expectedIgvDumpSuffix = "[Arrays.asList(Object[])List].bgv";
+            List<String> dumpPathEntries = Arrays.asList(tmpDir.list());
+            for (String entry : dumpPathEntries) {
+                if (entry.endsWith(expectedIgvDumpSuffix)) {
+                    found = true;
+                }
+            }
+            if (!found) {
+                Assert.fail(String.format("Expected file ending with \"%s\" in %s but only found:%n%s", expectedIgvDumpSuffix, tmpDir,
+                                dumpPathEntries.stream().collect(Collectors.joining(System.lineSeparator()))));
+            }
+        } finally {
+            deleteDirectory(tmpDir.toPath());
+            server.setAttribute(mbeanName, new Attribute(dumpPath.getName(), originalDumpPath));
+            server.setAttribute(mbeanName, new Attribute(printGraphFile.getName(), originalPrintGraphFile));
+            server.setAttribute(mbeanName, new Attribute(showDumpFiles.getName(), originalShowDumpFiles));
+        }
+    }
+
+    static void deleteDirectory(Path toDelete) throws IOException {
+        Files.walk(toDelete).sorted(Comparator.reverseOrder()).map(Path::toFile).forEach(File::delete);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotMethodSubstitutionTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -46,6 +46,17 @@
 
         test("getClass0", "a string");
         test("objectHashCode", obj);
+
+        testGraph("objectNotify", "Object.notify");
+        testGraph("objectNotifyAll", "Object.notifyAll");
+
+        synchronized (obj) {
+            test("objectNotify", obj);
+            test("objectNotifyAll", obj);
+        }
+        // Test with IllegalMonitorStateException (no synchronized block)
+        test("objectNotify", obj);
+        test("objectNotifyAll", obj);
     }
 
     @SuppressWarnings("all")
@@ -58,6 +69,16 @@
         return obj.hashCode();
     }
 
+    @SuppressWarnings("all")
+    public static void objectNotify(Object obj) {
+        obj.notify();
+    }
+
+    @SuppressWarnings("all")
+    public static void objectNotifyAll(Object obj) {
+        obj.notifyAll();
+    }
+
     @Test
     public void testClassSubstitutions() {
         testGraph("getModifiers");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/HotSpotStampMemoryAccessTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,6 @@
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.hotspot.nodes.type.HotSpotNarrowOopStamp;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import jdk.vm.ci.meta.JavaConstant;
@@ -37,7 +36,6 @@
 
 public class HotSpotStampMemoryAccessTest extends HotSpotGraalCompilerTest {
 
-    @Ignore("not all versions are safe yet")
     @Test
     public void testReadNarrowObject() {
         CompressEncoding oopEncoding = runtime().getVMConfig().getOopEncoding();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/TestIntrinsicCompiles.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.api.test.Graal;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
 import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/WriteBarrierVerificationTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Scope;
@@ -59,7 +59,7 @@
 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.phases.tiers.MidTierContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 import org.junit.Assert;
 import org.junit.Test;
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot.test/src/org/graalvm/compiler/hotspot/test/aaa	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot.test;
+
+import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.hotspot.meta.HotSpotClassInitializationPlugin;
+import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
+import org.graalvm.compiler.java.GraphBuilderPhase;
+import org.graalvm.compiler.nodes.StructuredGraph;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
+import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
+import org.graalvm.compiler.phases.PhaseSuite;
+import org.graalvm.compiler.phases.tiers.HighTierContext;
+import org.junit.Assert;
+import org.junit.Assume;
+import org.junit.Before;
+import org.junit.Test;
+
+import jdk.vm.ci.meta.ConstantPool;
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
+public class HotSpotLazyInitializationTest extends GraalCompilerTest {
+
+    HotSpotClassInitializationPlugin classInitPlugin = new HotSpotClassInitializationPlugin();
+
+    @Override
+    protected Plugins getDefaultGraphBuilderPlugins() {
+        Plugins plugins = super.getDefaultGraphBuilderPlugins();
+        plugins.setClassInitializationPlugin(classInitPlugin);
+        return plugins;
+    }
+
+    static boolean X_initialized = false;
+
+    static class X {
+        static {
+            X_initialized = true;
+        }
+        static void foo() {}
+    }
+
+    public static void invokeStatic() {
+        X.foo();
+    }
+
+    private void test(String name) {
+        ResolvedJavaMethod method = getResolvedJavaMethod(name);
+        Assume.assumeTrue("skipping for old JVMCI", classInitPlugin.supportsLazyInitialization(method.getConstantPool()));
+        StructuredGraph graph = parseEager(method, AllowAssumptions.NO);
+        Assert.assertFalse(X_initialized);
+    }
+
+    @Test
+    public void test1() {
+        test("invokeStatic");
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CommunityCompilerConfigurationFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import org.graalvm.compiler.core.phases.CommunityCompilerConfiguration;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+import org.graalvm.compiler.serviceprovider.ServiceProvider;
+
+/**
+ * Factory for creating the default configuration for the community edition of Graal.
+ */
+@ServiceProvider(CompilerConfigurationFactory.class)
+public class CommunityCompilerConfigurationFactory extends CompilerConfigurationFactory {
+
+    public static final String NAME = "community";
+
+    /**
+     * Must be greater than {@link EconomyCompilerConfigurationFactory#AUTO_SELECTION_PRIORITY}.
+     */
+    public static final int AUTO_SELECTION_PRIORITY = 2;
+
+    public CommunityCompilerConfigurationFactory() {
+        super(NAME, AUTO_SELECTION_PRIORITY);
+        assert AUTO_SELECTION_PRIORITY > EconomyCompilerConfigurationFactory.AUTO_SELECTION_PRIORITY;
+    }
+
+    @Override
+    public CompilerConfiguration createCompilerConfiguration() {
+        return new CommunityCompilerConfiguration();
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationStatistics.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,10 +42,10 @@
 import java.util.concurrent.ConcurrentLinkedDeque;
 
 import org.graalvm.compiler.debug.CSVUtil;
-import org.graalvm.compiler.debug.Management;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.hotspot.HotSpotInstalledCode;
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
@@ -87,8 +87,7 @@
     private static long zeroTime = System.nanoTime();
 
     private static long getThreadAllocatedBytes() {
-        com.sun.management.ThreadMXBean thread = (com.sun.management.ThreadMXBean) Management.getThreadMXBean();
-        return thread.getThreadAllocatedBytes(currentThread().getId());
+        return GraalServices.getCurrentThreadAllocatedBytes();
     }
 
     @NotReported private final long startTime;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilationTask.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,14 +22,16 @@
  */
 package org.graalvm.compiler.hotspot;
 
+import static org.graalvm.compiler.core.CompilationWrapper.ExceptionAction.Diagnose;
 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.phases.HighTier.Options.Inline;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.code.CompilationResult;
 import org.graalvm.compiler.core.CompilationPrinter;
@@ -140,17 +142,25 @@
         }
 
         @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.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
-                    return ExitVM;
+        protected ExceptionAction lookupAction(OptionValues values, EnumOptionKey<ExceptionAction> actionKey, Throwable cause) {
+            // Respect current action if it has been explicitly set.
+            if (!actionKey.hasBeenSet(values)) {
+                if (actionKey == CompilationFailureAction) {
+                    // Automatically exit on non-bailout during bootstrap
+                    // or when assertions are enabled.
+                    if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+                        return ExitVM;
+                    }
+                } else if (actionKey == CompilationBailoutAction && ((BailoutException) cause).isPermanent()) {
+                    // Get more info for permanent bailouts during bootstrap
+                    // or when assertions are enabled.
+                    assert CompilationBailoutAction.getDefaultValue() == ExceptionAction.Silent;
+                    if (Assertions.assertionsEnabled() || compiler.getGraalRuntime().isBootstrapping()) {
+                        return Diagnose;
+                    }
                 }
             }
-            return super.lookupAction(values, actionKey);
+            return super.lookupAction(values, actionKey, cause);
         }
 
         @SuppressWarnings("try")
@@ -187,6 +197,7 @@
             }
             return null;
         }
+
     }
 
     public CompilationTask(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalCompiler compiler, HotSpotCompilationRequest request, boolean useProfilingInfo, boolean installAsDefault,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CompilerConfigurationFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
 import java.util.List;
 import java.util.stream.Collectors;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.lir.phases.LIRPhase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/CoreCompilerConfigurationFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package org.graalvm.compiler.hotspot;
-
-import org.graalvm.compiler.core.phases.CoreCompilerConfiguration;
-import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.serviceprovider.ServiceProvider;
-
-@ServiceProvider(CompilerConfigurationFactory.class)
-public class CoreCompilerConfigurationFactory extends CompilerConfigurationFactory {
-
-    public static final String NAME = "core";
-
-    public static final int AUTO_SELECTION_PRIORITY = 2;
-
-    public CoreCompilerConfigurationFactory() {
-        super(NAME, AUTO_SELECTION_PRIORITY);
-    }
-
-    @Override
-    public CompilerConfiguration createCompilerConfiguration() {
-        return new CoreCompilerConfiguration();
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/EconomyCompilerConfigurationFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,9 @@
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.serviceprovider.ServiceProvider;
 
+/**
+ * Factory that creates a {@link EconomyCompilerConfiguration}.
+ */
 @ServiceProvider(CompilerConfigurationFactory.class)
 public class EconomyCompilerConfigurationFactory extends CompilerConfigurationFactory {
 
@@ -44,7 +47,7 @@
 
     @Override
     public BackendMap createBackendMap() {
-        // the economy configuration only differs in the frontend, it reuses the "core" backend
-        return new DefaultBackendMap(CoreCompilerConfigurationFactory.NAME);
+        // the economy configuration only differs in the frontend, it reuses the "community" backend
+        return new DefaultBackendMap(CommunityCompilerConfigurationFactory.NAME);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,33 +25,16 @@
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 
-import org.graalvm.compiler.api.replacements.Fold;
-import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
 import org.graalvm.compiler.core.common.CompressEncoding;
 import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
 
 import jdk.vm.ci.common.JVMCIError;
-import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
 
 /**
  * Used to access native configuration details.
  */
-public class GraalHotSpotVMConfig extends HotSpotVMConfigAccess {
-
-    /**
-     * Sentinel value to use for an {@linkplain InjectedParameter injected}
-     * {@link GraalHotSpotVMConfig} parameter to a {@linkplain Fold foldable} method.
-     */
-    public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
-
-    // this uses `1.9` which will give the correct result with `1.9`, `9`, `10` etc.
-    private final boolean isJDK8 = System.getProperty("java.specification.version").compareTo("1.9") < 0;
-    private final int jdkVersion = isJDK8 ? 8 : Integer.parseInt(System.getProperty("java.specification.version"));
-    public final String osName = getHostOSName();
-    public final String osArch = getHostArchitectureName();
-    public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
-    public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigBase {
 
     GraalHotSpotVMConfig(HotSpotVMConfigStore store) {
         super(store);
@@ -64,29 +47,6 @@
         assert check();
     }
 
-    /**
-     * Gets the value of a static C++ field under two possible names. {@code name} is the preferred
-     * name and will be checked first.
-     *
-     * @param name fully qualified name of the field
-     * @param alternateName fully qualified alternate name of the field
-     * @param type the boxed type to which the constant value will be converted
-     * @param cppType if non-null, the expected C++ type of the field (e.g., {@code "HeapWord*"})
-     * @return the value of the requested field
-     * @throws JVMCIError if the field is not static or not present
-     */
-    public <T> T getFieldValueWithAlternate(String name, String alternateName, Class<T> type, String cppType) {
-        try {
-            return getFieldValue(name, type, cppType);
-        } catch (JVMCIError e) {
-            try {
-                return getFieldValue(alternateName, type, cppType);
-            } catch (JVMCIError e2) {
-                throw new JVMCIError("expected VM field not found: " + name + " or " + alternateName);
-            }
-        }
-    }
-
     private final CompressEncoding oopEncoding;
     private final CompressEncoding klassEncoding;
 
@@ -98,50 +58,6 @@
         return klassEncoding;
     }
 
-    /**
-     * Gets the host operating system name.
-     */
-    private static String getHostOSName() {
-        String osName = System.getProperty("os.name");
-        switch (osName) {
-            case "Linux":
-                osName = "linux";
-                break;
-            case "SunOS":
-                osName = "solaris";
-                break;
-            case "Mac OS X":
-                osName = "bsd";
-                break;
-            default:
-                // Of course Windows is different...
-                if (osName.startsWith("Windows")) {
-                    osName = "windows";
-                } else {
-                    throw new JVMCIError("Unexpected OS name: " + osName);
-                }
-        }
-        return osName;
-    }
-
-    private static String getHostArchitectureName() {
-        String arch = System.getProperty("os.arch");
-        switch (arch) {
-            case "x86_64":
-                arch = "amd64";
-                break;
-            case "sparcv9":
-                arch = "sparc";
-                break;
-        }
-        return arch;
-    }
-
-    private final Integer intRequiredOnAMD64 = osArch.equals("amd64") ? null : 0;
-    private final Long longRequiredOnAMD64 = osArch.equals("amd64") ? null : 0L;
-    private final Integer intNotPresentInJDK8 = isJDK8 ? 0 : null;
-    private final Long longNotPresentInJDK8 = isJDK8 ? 0L : null;
-
     public final boolean cAssertions = getConstant("ASSERT", Boolean.class);
 
     public final int codeEntryAlignment = getFlag("CodeEntryAlignment", Integer.class);
@@ -157,6 +73,7 @@
     public final int hugeMethodLimit = getFlag("HugeMethodLimit", Integer.class);
     public final boolean printInlining = getFlag("PrintInlining", Boolean.class);
     public final boolean inline = getFlag("Inline", Boolean.class);
+    public final boolean inlineNotify = versioned.inlineNotify;
     public final boolean useFastLocking = getFlag("JVMCIUseFastLocking", Boolean.class);
     public final boolean forceUnreachable = getFlag("ForceUnreachable", Boolean.class);
     public final int codeSegmentSize = getFlag("CodeCacheSegmentSize", Integer.class);
@@ -168,7 +85,7 @@
     public final boolean usePopCountInstruction = getFlag("UsePopCountInstruction", Boolean.class);
     public final boolean useAESIntrinsics = getFlag("UseAESIntrinsics", Boolean.class);
     public final boolean useCRC32Intrinsics = getFlag("UseCRC32Intrinsics", Boolean.class);
-    public final boolean useCRC32CIntrinsics = isJDK8 ? false : getFlag("UseCRC32CIntrinsics", Boolean.class);
+    public final boolean useCRC32CIntrinsics = versioned.useCRC32CIntrinsics;
     public final boolean threadLocalHandshakes = getFlag("ThreadLocalHandshakes", Boolean.class, false);
 
     private final boolean useMultiplyToLenIntrinsic = getFlag("UseMultiplyToLenIntrinsic", Boolean.class);
@@ -216,6 +133,14 @@
         return useSquareToLenIntrinsic && squareToLen != 0;
     }
 
+    public boolean inlineNotify() {
+        return inlineNotify && notifyAddress != 0;
+    }
+
+    public boolean inlineNotifyAll() {
+        return inlineNotify && notifyAllAddress != 0;
+    }
+
     public final boolean useG1GC = getFlag("UseG1GC", Boolean.class);
     public final boolean useCMSGC = getFlag("UseConcMarkSweepGC", Boolean.class);
 
@@ -383,7 +308,7 @@
     public final int threadIsMethodHandleReturnOffset = getFieldOffset("JavaThread::_is_method_handle_return", Integer.class, "int");
     public final int threadObjectResultOffset = getFieldOffset("JavaThread::_vm_result", Integer.class, "oop");
     public final int jvmciCountersThreadOffset = getFieldOffset("JavaThread::_jvmci_counters", Integer.class, "jlong*");
-    public final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address", intNotPresentInJDK8);
+    public final int javaThreadReservedStackActivationOffset = versioned.javaThreadReservedStackActivationOffset;
 
     /**
      * An invalid value for {@link #rtldDefault}.
@@ -504,14 +429,14 @@
 
     public final int methodAccessFlagsOffset = getFieldOffset("Method::_access_flags", Integer.class, "AccessFlags");
     public final int methodConstMethodOffset = getFieldOffset("Method::_constMethod", Integer.class, "ConstMethod*");
-    public final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, isJDK8 ? "u1" : "u2");
-    public final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, isJDK8 ? "u1" : "u2");
+    public final int methodIntrinsicIdOffset = versioned.methodIntrinsicIdOffset;
+    public final int methodFlagsOffset = versioned.methodFlagsOffset;
     public final int methodVtableIndexOffset = getFieldOffset("Method::_vtable_index", Integer.class, "int");
 
     public final int methodCountersOffset = getFieldOffset("Method::_method_counters", Integer.class, "MethodCounters*");
     public final int methodDataOffset = getFieldOffset("Method::_method_data", Integer.class, "MethodData*");
     public final int methodCompiledEntryOffset = getFieldOffset("Method::_from_compiled_entry", Integer.class, "address");
-    public final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, isJDK8 ? "nmethod*" : "CompiledMethod*");
+    public final int methodCodeOffset = versioned.methodCodeOffset;
 
     public final int methodFlagsCallerSensitive = getConstant("Method::_caller_sensitive", Integer.class);
     public final int methodFlagsForceInline = getConstant("Method::_force_inline", Integer.class);
@@ -522,8 +447,8 @@
 
     public final int invocationCounterOffset = getFieldOffset("MethodCounters::_invocation_counter", Integer.class, "InvocationCounter");
     public final int backedgeCounterOffset = getFieldOffset("MethodCounters::_backedge_counter", Integer.class, "InvocationCounter");
-    public final int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class, intNotPresentInJDK8);
-    public final int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class, intNotPresentInJDK8);
+    public final int invocationCounterIncrement = versioned.invocationCounterIncrement;
+    public final int invocationCounterShift = versioned.invocationCounterShift;
 
     public final int nmethodEntryOffset = getFieldOffset("nmethod::_verified_entry_point",
                     Integer.class, "address");
@@ -548,11 +473,6 @@
 
     public final int logOfHRGrainBytes = getFieldValue("HeapRegion::LogOfHRGrainBytes", Integer.class, "int");
 
-    public final byte dirtyCardValue = jdkVersion >= 11 ? getConstant("CardTable::dirty_card", Byte.class)
-                    : (jdkVersion > 8 ? getConstant("CardTableModRefBS::dirty_card", Byte.class) : getFieldValue("CompilerToVM::Data::dirty_card", Byte.class, "int"));
-    public final byte g1YoungCardValue = jdkVersion >= 11 ? getConstant("G1CardTable::g1_young_gen", Byte.class)
-                    : (jdkVersion > 8 ? getConstant("G1SATBCardTableModRefBS::g1_young_gen", Byte.class) : getFieldValue("CompilerToVM::Data::g1_young_card", Byte.class, "int"));
-
     public final long cardtableStartAddress = getFieldValue("CompilerToVM::Data::cardtable_start_address", Long.class, "jbyte*");
     public final int cardtableShift = getFieldValue("CompilerToVM::Data::cardtable_shift", Integer.class, "int");
 
@@ -560,17 +480,20 @@
      * This is the largest stack offset encodeable in an OopMapValue. Offsets larger than this will
      * throw an exception during code installation.
      */
-    public final int maxOopMapStackOffset = getFieldValueWithAlternate("CompilerToVM::Data::_max_oop_map_stack_offset", "JVMCIRuntime::max_oop_map_stack_offset", Integer.class, "int");
+    public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int");
 
     public final long safepointPollingAddress = getFieldValue("os::_polling_page", Long.class, "address");
 
     // G1 Collector Related Values.
 
-    public final int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
-    public final int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
-    public final int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
-    public final int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
-    public final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
+    public final byte dirtyCardValue = versioned.dirtyCardValue;
+    public final byte g1YoungCardValue = versioned.g1YoungCardValue;
+
+    public final int g1SATBQueueMarkingOffset = versioned.g1SATBQueueMarkingOffset;
+    public final int g1SATBQueueIndexOffset = versioned.g1SATBQueueIndexOffset;
+    public final int g1SATBQueueBufferOffset = versioned.g1SATBQueueBufferOffset;
+    public final int g1CardQueueIndexOffset = versioned.g1CardQueueIndexOffset;
+    public final int g1CardQueueBufferOffset = versioned.g1CardQueueBufferOffset;
 
     public final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
     public final int arrayKlassOffset = getFieldValue("java_lang_Class::_array_klass_offset", Integer.class, "int");
@@ -636,7 +559,7 @@
     // FIXME This is only temporary until the GC code is changed.
     public final boolean inlineContiguousAllocationSupported = getFieldValue("CompilerToVM::Data::_supports_inline_contig_alloc", Boolean.class);
     public final long heapEndAddress = getFieldValue("CompilerToVM::Data::_heap_end_addr", Long.class, "HeapWord**");
-    public final long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, isJDK8 ? "HeapWord**" : "HeapWord* volatile*");
+    public final long heapTopAddress = versioned.heapTopAddress;
 
     public final boolean cmsIncrementalMode = getFlag("CMSIncrementalMode", Boolean.class, false);
 
@@ -646,8 +569,8 @@
     public final long handleDeoptStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_unpack", Long.class, "address");
     public final long uncommonTrapStub = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", Long.class, "address");
 
-    public final long codeCacheLowBound = getFieldValue(isJDK8 ? "CompilerToVM::Data::CodeCache_low_bound" : "CodeCache::_low_bound", Long.class, "address");
-    public final long codeCacheHighBound = getFieldValue(isJDK8 ? "CompilerToVM::Data::CodeCache_high_bound" : "CodeCache::_high_bound", Long.class, "address");
+    public final long codeCacheLowBound = versioned.codeCacheLowBound;
+    public final long codeCacheHighBound = versioned.codeCacheHighBound;
 
     public final long aescryptEncryptBlockStub = getFieldValue("StubRoutines::_aescrypt_encryptBlock", Long.class, "address");
     public final long aescryptDecryptBlockStub = getFieldValue("StubRoutines::_aescrypt_decryptBlock", Long.class, "address");
@@ -675,7 +598,7 @@
     public final long montgomerySquare = getFieldValue("StubRoutines::_montgomerySquare", Long.class, "address", longRequiredOnAMD64);
     public final long vectorizedMismatch = getFieldValue("StubRoutines::_vectorizedMismatch", Long.class, "address", 0L);
 
-    public final long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address", longNotPresentInJDK8);
+    public final long throwDelayedStackOverflowErrorEntry = versioned.throwDelayedStackOverflowErrorEntry;
 
     public final long jbyteArraycopy = getFieldValue("StubRoutines::_jbyte_arraycopy", Long.class, "address");
     public final long jshortArraycopy = getFieldValue("StubRoutines::_jshort_arraycopy", Long.class, "address");
@@ -718,6 +641,8 @@
     public final long exceptionHandlerForPcAddress = getAddress("JVMCIRuntime::exception_handler_for_pc");
     public final long monitorenterAddress = getAddress("JVMCIRuntime::monitorenter");
     public final long monitorexitAddress = getAddress("JVMCIRuntime::monitorexit");
+    public final long notifyAddress = getAddress("JVMCIRuntime::object_notify", 0L);
+    public final long notifyAllAddress = getAddress("JVMCIRuntime::object_notifyAll", 0L);
     public final long throwAndPostJvmtiExceptionAddress = getAddress("JVMCIRuntime::throw_and_post_jvmti_exception");
     public final long throwKlassExternalNameExceptionAddress = getAddress("JVMCIRuntime::throw_klass_external_name_exception");
     public final long throwClassCastExceptionAddress = getAddress("JVMCIRuntime::throw_class_cast_exception");
@@ -735,7 +660,7 @@
     public final long registerFinalizerAddress = getAddress("SharedRuntime::register_finalizer");
     public final long exceptionHandlerForReturnAddressAddress = getAddress("SharedRuntime::exception_handler_for_return_address");
     public final long osrMigrationEndAddress = getAddress("SharedRuntime::OSR_migration_end");
-    public final long enableStackReservedZoneAddress = getAddress("SharedRuntime::enable_stack_reserved_zone", longNotPresentInJDK8);
+    public final long enableStackReservedZoneAddress = versioned.enableStackReservedZoneAddress;
 
     public final long javaTimeMillisAddress = getAddress("os::javaTimeMillis");
     public final long javaTimeNanosAddress = getAddress("os::javaTimeNanos");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigBase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import org.graalvm.compiler.api.replacements.Fold;
+import org.graalvm.compiler.api.replacements.Fold.InjectedParameter;
+
+import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * This is a source with different versions for various JDKs.
+ */
+public abstract class GraalHotSpotVMConfigBase extends HotSpotVMConfigAccess {
+
+    GraalHotSpotVMConfigBase(HotSpotVMConfigStore store) {
+        super(store);
+        assert this instanceof GraalHotSpotVMConfig;
+        versioned = new GraalHotSpotVMConfigVersioned(store);
+    }
+
+    /**
+     * Contains values that are different between JDK versions.
+     */
+    protected final GraalHotSpotVMConfigVersioned versioned;
+
+    /**
+     * Sentinel value to use for an {@linkplain InjectedParameter injected}
+     * {@link GraalHotSpotVMConfig} parameter to a {@linkplain Fold foldable} method.
+     */
+    public static final GraalHotSpotVMConfig INJECTED_VMCONFIG = null;
+
+    public final String osName = getHostOSName();
+    public final String osArch = getHostArchitectureName();
+    public final boolean windowsOs = System.getProperty("os.name", "").startsWith("Windows");
+    public final boolean linuxOs = System.getProperty("os.name", "").startsWith("Linux");
+
+    /**
+     * Gets the host operating system name.
+     */
+    private static String getHostOSName() {
+        String osName = System.getProperty("os.name");
+        switch (osName) {
+            case "Linux":
+                osName = "linux";
+                break;
+            case "SunOS":
+                osName = "solaris";
+                break;
+            case "Mac OS X":
+                osName = "bsd";
+                break;
+            default:
+                // Of course Windows is different...
+                if (osName.startsWith("Windows")) {
+                    osName = "windows";
+                } else {
+                    throw new JVMCIError("Unexpected OS name: " + osName);
+                }
+        }
+        return osName;
+    }
+
+    private static String getHostArchitectureName() {
+        String arch = System.getProperty("os.arch");
+        switch (arch) {
+            case "x86_64":
+                arch = "amd64";
+                break;
+            case "sparcv9":
+                arch = "sparc";
+                break;
+        }
+        return arch;
+    }
+
+    protected final Integer intRequiredOnAMD64 = osArch.equals("amd64") ? null : 0;
+    protected final Long longRequiredOnAMD64 = osArch.equals("amd64") ? null : 0L;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfigVersioned.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotVMConfigAccess;
+import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
+
+/**
+ * This is a source with different versions for various JDKs. When modifying/adding a field in this
+ * class accessed from outside this class, be sure to update the field appropriately in all source
+ * files named {@code GraalHotSpotVMConfigVersioned.java}.
+ *
+ * Fields are grouped according to the most recent JBS issue showing why they are versioned.
+ *
+ * JDK Version: 11+
+ */
+final class GraalHotSpotVMConfigVersioned extends HotSpotVMConfigAccess {
+
+    GraalHotSpotVMConfigVersioned(HotSpotVMConfigStore store) {
+        super(store);
+    }
+
+    // JDK-8073583
+    final boolean useCRC32CIntrinsics = getFlag("UseCRC32CIntrinsics", Boolean.class);
+
+    // JDK-8075171
+    final boolean inlineNotify = getFlag("InlineNotify", Boolean.class);
+
+    // JDK-8046936
+    final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address");
+    final int methodFlagsOffset = getFieldOffset("Method::_flags", Integer.class, "u2");
+    final long throwDelayedStackOverflowErrorEntry = getFieldValue("StubRoutines::_throw_delayed_StackOverflowError_entry", Long.class, "address");
+    final long enableStackReservedZoneAddress = getAddress("SharedRuntime::enable_stack_reserved_zone");
+
+    // JDK-8135085
+    final int methodIntrinsicIdOffset = getFieldOffset("Method::_intrinsic_id", Integer.class, "u2");
+
+    // JDK-8151956
+    final int methodCodeOffset = getFieldOffset("Method::_code", Integer.class, "CompiledMethod*");
+
+    // JDK-8059606
+    final int invocationCounterIncrement = getConstant("InvocationCounter::count_increment", Integer.class);
+    final int invocationCounterShift = getConstant("InvocationCounter::count_shift", Integer.class);
+
+    // JDK-8195142
+    final byte dirtyCardValue = getConstant("CardTable::dirty_card", Byte.class);
+    final byte g1YoungCardValue = getConstant("G1CardTable::g1_young_gen", Byte.class);
+
+    // JDK-8201318
+    final int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
+    final int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
+    final int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
+    final int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
+    final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
+
+    // JDK-8033552
+    final long heapTopAddress = getFieldValue("CompilerToVM::Data::_heap_top_addr", Long.class, "HeapWord* volatile*");
+
+    // JDK-8015774
+    final long codeCacheLowBound = getFieldValue("CodeCache::_low_bound", Long.class, "address");
+    final long codeCacheHighBound = getFieldValue("CodeCache::_high_bound", Long.class, "address");
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotBackend.java	Thu Apr 26 17:59:02 2018 +0200
@@ -64,11 +64,11 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.tiers.SuitesProvider;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.word.Pointer;
 
 import jdk.vm.ci.code.CompilationRequest;
 import jdk.vm.ci.code.CompiledCode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCompiledCodeBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -221,6 +221,10 @@
             List<Site> sourcePositionSites = new ArrayList<>();
             for (SourceMapping source : target.getSourceMappings()) {
                 NodeSourcePosition sourcePosition = source.getSourcePosition();
+                if (sourcePosition.isPlaceholder() || sourcePosition.isSubstitution()) {
+                    // HotSpot doesn't understand any of the special positions so just drop them.
+                    continue;
+                }
                 assert sourcePosition.verify();
                 sourcePosition = sourcePosition.trim();
                 /*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotCounterOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
 
 import java.util.Arrays;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.core.common.NumUtil;
 import org.graalvm.compiler.debug.GraalError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkage.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
 import org.graalvm.compiler.core.common.spi.ForeignCallLinkage;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.hotspot.stubs.Stub;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * The details required to link a HotSpot runtime or stub call.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotForeignCallLinkageImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,13 +25,13 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 import static org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect.DESTROYS_REGISTERS;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.core.target.Backend;
 import org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProvider;
 import org.graalvm.compiler.hotspot.stubs.Stub;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CallingConvention.Type;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompiler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,9 +38,9 @@
 import org.graalvm.compiler.core.GraalCompiler;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.util.CompilationAlarm;
-import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Activation;
+import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.hotspot.CompilationCounters.Options;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
@@ -105,17 +105,16 @@
 
     @Override
     public CompilationRequestResult compileMethod(CompilationRequest request) {
-        return compileMethod(request, true);
+        return compileMethod(request, true, graalRuntime.getOptions());
     }
 
     @SuppressWarnings("try")
-    CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault) {
+    CompilationRequestResult compileMethod(CompilationRequest request, boolean installAsDefault, OptionValues options) {
         if (graalRuntime.isShutdown()) {
             return HotSpotCompilationRequestResult.failure(String.format("Shutdown entered"), false);
         }
 
         ResolvedJavaMethod method = request.getMethod();
-        OptionValues options = graalRuntime.getOptions(method);
 
         if (graalRuntime.isBootstrapping()) {
             if (DebugOptions.BootstrapInitializeOnly.getValue(options)) {
@@ -282,13 +281,6 @@
         return suite;
     }
 
-    public Object mbean() {
-        if (graalRuntime instanceof HotSpotGraalRuntime) {
-            return ((HotSpotGraalRuntime) graalRuntime).getMBean();
-        }
-        return null;
-    }
-
     /**
      * Converts {@code method} to a String with {@link JavaMethod#format(String)} and the format
      * string {@code "%H.%n(%p)"}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalCompilerFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,9 +26,8 @@
 import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
 
 import java.io.PrintStream;
-import java.util.Collections;
-import java.util.Map;
 
+import org.graalvm.compiler.api.runtime.GraalRuntime;
 import org.graalvm.compiler.debug.MethodFilter;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
@@ -36,7 +35,6 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.options.OptionsParser;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
 
 import jdk.vm.ci.common.InitTimer;
 import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
@@ -49,21 +47,7 @@
     private static MethodFilter[] graalCompileOnlyFilter;
     private static boolean compileGraalWithC1Only;
 
-    /**
-     * Module containing {@link HotSpotJVMCICompilerFactory}.
-     */
-    private Object jvmciModule;
-
-    /**
-     * Module containing {@link HotSpotGraalCompilerFactory}.
-     */
-    private Object graalModule;
-
-    /**
-     * Module containing the {@linkplain CompilerConfigurationFactory#selectFactory selected}
-     * configuration.
-     */
-    private Object compilerConfigurationModule;
+    private IsGraalPredicate isGraalPredicate;
 
     private final HotSpotGraalJVMCIServiceLocator locator;
 
@@ -87,10 +71,7 @@
         assert options == null : "cannot select " + getClass() + " service more than once";
         options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
         initializeGraalCompilePolicyFields(options);
-        if (!JDK9Method.Java8OrEarlier) {
-            jvmciModule = JDK9Method.getModule(HotSpotJVMCICompilerFactory.class);
-            graalModule = JDK9Method.getModule(HotSpotGraalCompilerFactory.class);
-        }
+        isGraalPredicate = compileGraalWithC1Only ? new IsGraalPredicate() : null;
         /*
          * Exercise this code path early to encourage loading now. This doesn't solve problem of
          * deadlock during class loading but seems to eliminate it in practice.
@@ -134,10 +115,10 @@
     @Override
     public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) {
         CompilerConfigurationFactory factory = CompilerConfigurationFactory.selectFactory(null, options);
-        if (!JDK9Method.Java8OrEarlier) {
-            compilerConfigurationModule = JDK9Method.getModule(factory.getClass());
+        if (isGraalPredicate != null) {
+            isGraalPredicate.onCompilerConfigurationFactorySelection(factory);
         }
-        HotSpotGraalCompiler compiler = createCompiler(runtime, options, factory);
+        HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory);
         // Only the HotSpotGraalRuntime associated with the compiler created via
         // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving
         // VM events.
@@ -149,14 +130,17 @@
      * Creates a new {@link HotSpotGraalRuntime} object and a new {@link HotSpotGraalCompiler} and
      * returns the latter.
      *
+     * @param runtimeNameQualifier a qualifier to be added to the {@linkplain GraalRuntime#getName()
+     *            name} of the {@linkplain HotSpotGraalCompiler#getGraalRuntime() runtime} created
+     *            by this method
      * @param runtime the JVMCI runtime on which the {@link HotSpotGraalRuntime} is built
      * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration}
      */
     @SuppressWarnings("try")
-    public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) {
+    public static HotSpotGraalCompiler createCompiler(String runtimeNameQualifier, JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) {
         HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime;
         try (InitTimer t = timer("HotSpotGraalRuntime.<init>")) {
-            HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options);
+            HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(runtimeNameQualifier, jvmciRuntime, compilerConfigurationFactory, options);
             return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions());
         }
     }
@@ -187,54 +171,11 @@
         assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory");
     }
 
-    static final ClassLoader JVMCI_LOADER = HotSpotGraalCompilerFactory.class.getClassLoader();
-
-    /*
-     * This method is static so it can be exercised during initialization.
-     */
     private CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) {
         if (compileGraalWithC1Only) {
             if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
-                if (JDK9Method.Java8OrEarlier) {
-                    if (JVMCI_LOADER != null) {
-                        // When running with +UseJVMCIClassLoader all classes in
-                        // the JVMCI loader should be compiled with C1.
-                        try {
-                            if (declaringClass.getClassLoader() == JVMCI_LOADER) {
-                                return CompilationLevel.Simple;
-                            }
-                        } catch (SecurityException e) {
-                            // This is definitely not a JVMCI or Graal class
-                        }
-                    } else {
-                        // JVMCI and Graal are on the bootclasspath so match based on the package.
-                        String declaringClassName = declaringClass.getName();
-                        if (declaringClassName.startsWith("jdk.vm.ci")) {
-                            return CompilationLevel.Simple;
-                        }
-                        if (declaringClassName.startsWith("org.graalvm.") &&
-                                        (declaringClassName.startsWith("org.graalvm.compiler.") ||
-                                                        declaringClassName.startsWith("org.graalvm.collections.") ||
-                                                        declaringClassName.startsWith("org.graalvm.compiler.word.") ||
-                                                        declaringClassName.startsWith("org.graalvm.graphio."))) {
-                            return CompilationLevel.Simple;
-                        }
-                        if (declaringClassName.startsWith("com.oracle.graal") &&
-                                        (declaringClassName.startsWith("com.oracle.graal.enterprise") ||
-                                                        declaringClassName.startsWith("com.oracle.graal.vector") ||
-                                                        declaringClassName.startsWith("com.oracle.graal.asm"))) {
-                            return CompilationLevel.Simple;
-                        }
-                    }
-                } else {
-                    try {
-                        Object module = JDK9Method.getModule(declaringClass);
-                        if (jvmciModule == module || graalModule == module || compilerConfigurationModule == module) {
-                            return CompilationLevel.Simple;
-                        }
-                    } catch (Throwable e) {
-                        throw new InternalError(e);
-                    }
+                if (isGraalPredicate.apply(declaringClass)) {
+                    return CompilationLevel.Simple;
                 }
             }
         }
@@ -258,11 +199,4 @@
         }
         return level;
     }
-
-    public Map<String, Object> mbeans() {
-        HotSpotGraalCompiler compiler = createCompiler(HotSpotJVMCIRuntime.runtime());
-        String name = "org.graalvm.compiler.hotspot:type=Options";
-        Object bean = ((HotSpotGraalRuntime) compiler.getGraalRuntime()).getMBean();
-        return Collections.singletonMap(name, bean);
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalMBean.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,362 +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 java.lang.ref.Reference;
-import java.lang.ref.WeakReference;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
-import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
-import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
-import jdk.vm.ci.meta.MetaUtil;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.meta.ResolvedJavaType;
-import jdk.vm.ci.runtime.JVMCI;
-
-import org.graalvm.compiler.debug.DebugOptions;
-import org.graalvm.compiler.options.OptionDescriptor;
-import org.graalvm.compiler.options.OptionDescriptors;
-import org.graalvm.compiler.options.OptionKey;
-import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-
-public final class HotSpotGraalMBean implements javax.management.DynamicMBean {
-    private static Object mBeanServerField;
-    private final HotSpotGraalCompiler compiler;
-    private final OptionValues options;
-    private final EconomicMap<OptionKey<?>, Object> changes;
-    private final EconomicSet<Dump> methodDumps;
-    private volatile EconomicSet<Reference<ClassLoader>> loaders;
-    private javax.management.ObjectName registered;
-    private OptionValues cachedOptions;
-
-    private HotSpotGraalMBean(HotSpotGraalCompiler compiler, OptionValues options) {
-        this.compiler = compiler;
-        this.options = options;
-        this.changes = EconomicMap.create();
-        this.methodDumps = EconomicSet.create();
-        EconomicSet<Reference<ClassLoader>> systemLoaderSet = EconomicSet.create(RefEquivalence.INSTANCE);
-        systemLoaderSet.add(new WeakReference<>(ClassLoader.getSystemClassLoader()));
-        this.loaders = systemLoaderSet;
-    }
-
-    private static boolean isMXServerOn() {
-        if (mBeanServerField == null) {
-            try {
-                final Field field = java.lang.management.ManagementFactory.class.getDeclaredField("platformMBeanServer");
-                field.setAccessible(true);
-                mBeanServerField = field;
-            } catch (Exception ex) {
-                mBeanServerField = java.lang.management.ManagementFactory.class;
-            }
-        }
-        if (mBeanServerField instanceof Field) {
-            try {
-                return ((Field) mBeanServerField).get(null) != null;
-            } catch (Exception ex) {
-                return true;
-            }
-        } else {
-            return false;
-        }
-    }
-
-    public static HotSpotGraalMBean create(HotSpotGraalCompiler compiler) {
-        OptionValues options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
-        HotSpotGraalMBean mbean = new HotSpotGraalMBean(compiler, options);
-        return mbean;
-    }
-
-    public javax.management.ObjectName ensureRegistered(boolean check) {
-        for (int cnt = 0;; cnt++) {
-            if (registered != null) {
-                return registered;
-            }
-            if (check && !isMXServerOn()) {
-                return null;
-            }
-            try {
-                javax.management.MBeanServer mbs = java.lang.management.ManagementFactory.getPlatformMBeanServer();
-                javax.management.ObjectName name = new javax.management.ObjectName("org.graalvm.compiler.hotspot:type=Options" + (cnt == 0 ? "" : cnt));
-                mbs.registerMBean(this, name);
-                registered = name;
-                break;
-            } catch (javax.management.MalformedObjectNameException | javax.management.MBeanRegistrationException | javax.management.NotCompliantMBeanException ex) {
-                throw new IllegalStateException(ex);
-            } catch (javax.management.InstanceAlreadyExistsException ex) {
-                continue;
-            }
-        }
-        return registered;
-    }
-
-    public OptionValues optionsFor(OptionValues initialValues, ResolvedJavaMethod forMethod) {
-        ensureRegistered(true);
-        if (forMethod instanceof HotSpotResolvedJavaMethod) {
-            HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) forMethod).getDeclaringClass();
-            if (type instanceof HotSpotResolvedJavaType) {
-                Class<?> clazz = ((HotSpotResolvedJavaType) type).mirror();
-                Reference<ClassLoader> addNewRef = new WeakReference<>(clazz.getClassLoader());
-                if (!loaders.contains(addNewRef)) {
-                    EconomicSet<Reference<ClassLoader>> newLoaders = EconomicSet.create(RefEquivalence.INSTANCE, loaders);
-                    newLoaders.add(addNewRef);
-                    this.loaders = newLoaders;
-                }
-            }
-        }
-        return currentMap(initialValues, forMethod);
-    }
-
-    private OptionValues currentMap(OptionValues initialValues, ResolvedJavaMethod method) {
-        if (changes.isEmpty() && methodDumps.isEmpty()) {
-            return initialValues;
-        }
-        OptionValues current = cachedOptions;
-        if (current == null) {
-            current = new OptionValues(initialValues, changes);
-            cachedOptions = current;
-        }
-        if (method != null) {
-            for (Dump request : methodDumps) {
-                final String clazzName = method.getDeclaringClass().getName();
-                if (method.getName().equals(request.method) && clazzName.equals(request.clazz)) {
-                    current = new OptionValues(current, DebugOptions.Dump, request.filter,
-                                    DebugOptions.PrintGraphHost, request.host,
-                                    DebugOptions.PrintBinaryGraphPort, request.port);
-                    break;
-                }
-            }
-        }
-        return current;
-    }
-
-    @Override
-    public Object getAttribute(String attribute) {
-        UnmodifiableEconomicMap<OptionKey<?>, Object> map = currentMap(options, null).getMap();
-        for (OptionKey<?> k : map.getKeys()) {
-            if (k.getName().equals(attribute)) {
-                return map.get(k);
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public void setAttribute(javax.management.Attribute attribute) throws javax.management.AttributeNotFoundException {
-        javax.management.Attribute newAttr = setImpl(attribute);
-        if (newAttr == null) {
-            throw new javax.management.AttributeNotFoundException();
-        }
-    }
-
-    private javax.management.Attribute setImpl(javax.management.Attribute attribute) {
-        cachedOptions = null;
-        for (OptionDescriptor option : allOptionDescriptors()) {
-            if (option.getName().equals(attribute.getName())) {
-                changes.put(option.getOptionKey(), attribute.getValue());
-                return attribute;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public javax.management.AttributeList getAttributes(String[] names) {
-        javax.management.AttributeList list = new javax.management.AttributeList();
-        for (String name : names) {
-            Object value = getAttribute(name);
-            if (value != null) {
-                list.add(new javax.management.Attribute(name, value));
-            }
-        }
-        return list;
-    }
-
-    @Override
-    public javax.management.AttributeList setAttributes(javax.management.AttributeList attributes) {
-        javax.management.AttributeList setOk = new javax.management.AttributeList();
-        for (javax.management.Attribute attr : attributes.asList()) {
-            javax.management.Attribute newAttr = setImpl(attr);
-            if (newAttr != null) {
-                setOk.add(newAttr);
-            }
-        }
-        return setOk;
-    }
-
-    @Override
-    public Object invoke(String actionName, Object[] params, String[] signature) throws javax.management.MBeanException, javax.management.ReflectionException {
-        if ("dumpMethod".equals(actionName)) {
-            try {
-                String className = param(params, 0, "className", String.class, null);
-                String methodName = param(params, 1, "methodName", String.class, null);
-                String filter = param(params, 2, "filter", String.class, ":3");
-                String host = param(params, 3, "host", String.class, "localhost");
-                Number port = param(params, 4, "port", Number.class, 4445);
-                dumpMethod(className, methodName, filter, host, port.intValue());
-            } catch (Exception ex) {
-                throw new javax.management.ReflectionException(ex);
-            }
-        }
-        return null;
-    }
-
-    private static <T> T param(Object[] arr, int index, String name, Class<T> type, T defaultValue) {
-        Object value = arr.length > index ? arr[index] : null;
-        if (value == null || (value instanceof String && ((String) value).isEmpty())) {
-            if (defaultValue == null) {
-                throw new IllegalArgumentException(name + " must be specified");
-            }
-            value = defaultValue;
-        }
-        if (type.isInstance(value)) {
-            return type.cast(value);
-        }
-        throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
-    }
-
-    public void dumpMethod(String className, String methodName, String filter, String host, int port) throws javax.management.MBeanException {
-        String jvmName = MetaUtil.toInternalName(className);
-        methodDumps.add(new Dump(host, port, jvmName, methodName, filter));
-
-        ClassNotFoundException last = null;
-        EconomicSet<Class<?>> found = EconomicSet.create();
-        Iterator<Reference<ClassLoader>> it = loaders.iterator();
-        while (it.hasNext()) {
-            Reference<ClassLoader> ref = it.next();
-            ClassLoader loader = ref.get();
-            if (loader == null) {
-                it.remove();
-                continue;
-            }
-            try {
-                Class<?> clazz = Class.forName(className, false, loader);
-                if (found.add(clazz)) {
-                    ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz);
-                    if (compiler != null) {
-                        for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
-                            if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) {
-                                HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method;
-                                compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false);
-                            }
-                        }
-                    }
-                }
-            } catch (ClassNotFoundException ex) {
-                last = ex;
-            }
-        }
-        if (found.isEmpty()) {
-            throw new javax.management.MBeanException(last, "Cannot find class " + className + " to schedule recompilation");
-        }
-    }
-
-    @Override
-    public javax.management.MBeanInfo getMBeanInfo() {
-        List<javax.management.MBeanAttributeInfo> attrs = new ArrayList<>();
-        for (OptionDescriptor descr : allOptionDescriptors()) {
-            attrs.add(new javax.management.MBeanAttributeInfo(descr.getName(), descr.getType().getName(), descr.getHelp(), true, true, false));
-        }
-        javax.management.MBeanOperationInfo[] ops = {
-                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
-                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                        }, "void", javax.management.MBeanOperationInfo.ACTION),
-                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
-                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                                        new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
-                        }, "void", javax.management.MBeanOperationInfo.ACTION),
-                        new javax.management.MBeanOperationInfo("dumpMethod", "Enable IGV dumps for provided method", new javax.management.MBeanParameterInfo[]{
-                                        new javax.management.MBeanParameterInfo("className", "java.lang.String", "Class to observe"),
-                                        new javax.management.MBeanParameterInfo("methodName", "java.lang.String", "Method to observe"),
-                                        new javax.management.MBeanParameterInfo("filter", "java.lang.String", "The parameter for Dump option"),
-                                        new javax.management.MBeanParameterInfo("host", "java.lang.String", "The host where the IGV tool is running at"),
-                                        new javax.management.MBeanParameterInfo("port", "int", "The port where the IGV tool is listening at"),
-                        }, "void", javax.management.MBeanOperationInfo.ACTION)
-        };
-
-        return new javax.management.MBeanInfo(
-                        HotSpotGraalMBean.class.getName(),
-                        "Graal",
-                        attrs.toArray(new javax.management.MBeanAttributeInfo[attrs.size()]),
-                        null, ops, null);
-    }
-
-    private static Iterable<OptionDescriptor> allOptionDescriptors() {
-        List<OptionDescriptor> arr = new ArrayList<>();
-        for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
-            for (OptionDescriptor descr : set) {
-                arr.add(descr);
-            }
-        }
-        return arr;
-    }
-
-    private static final class Dump {
-        final String host;
-        final int port;
-        final String clazz;
-        final String method;
-        final String filter;
-
-        Dump(String host, int port, String clazz, String method, String filter) {
-            this.host = host;
-            this.port = port;
-            this.clazz = clazz;
-            this.method = method;
-            this.filter = filter;
-        }
-    }
-
-    private static final class RefEquivalence extends Equivalence {
-        static final Equivalence INSTANCE = new RefEquivalence();
-
-        private RefEquivalence() {
-        }
-
-        @Override
-        public boolean equals(Object a, Object b) {
-            Reference<?> refA = (Reference<?>) a;
-            Reference<?> refB = (Reference<?>) b;
-            return Objects.equals(refA.get(), refB.get());
-        }
-
-        @Override
-        public int hashCode(Object o) {
-            Reference<?> ref = (Reference<?>) o;
-            Object obj = ref.get();
-            return obj == null ? 0 : obj.hashCode();
-        }
-
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalManagementRegistration.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,49 @@
+/*
+ * 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;
+
+/**
+ * Communicates with an MBean providing a JMX interface to a {@link HotSpotGraalRuntime} instance.
+ * The MBean will be dynamically created when a JMX client attaches or some other event causes the
+ * platform MBean server to be started.
+ */
+public interface HotSpotGraalManagementRegistration {
+
+    /**
+     * Completes the initialization of this registration by recording the
+     * {@link HotSpotGraalRuntime} the MBean will provide an JMX interface to.
+     */
+    void initialize(HotSpotGraalRuntime runtime);
+
+    /**
+     * Polls this registration to see if the MBean is registered in a MBean server.
+     *
+     * @param sync synchronize with other threads that may be processing this registration. This is
+     *            useful when the caller knows the server is active (e.g., it has a reference to
+     *            server) and expects this poll to therefore return a non-null value.
+     * @return an {@link javax.management.ObjectName} that can be used to access the MBean or
+     *         {@code null} if the MBean has not been registered with an MBean server (e.g., no JMX
+     *         client has attached to the VM)
+     */
+    Object poll(boolean sync);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalOptionValues.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,14 +30,12 @@
 import java.util.Map;
 import java.util.Properties;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionDescriptors;
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.compiler.options.OptionValuesAccess;
 import org.graalvm.compiler.options.OptionsParser;
-import org.graalvm.compiler.serviceprovider.ServiceProvider;
 
 import jdk.vm.ci.common.InitTimer;
 
@@ -45,8 +43,7 @@
  * The {@link #HOTSPOT_OPTIONS} value contains the options values initialized in a HotSpot VM. The
  * values are set via system properties with the {@value #GRAAL_OPTION_PROPERTY_PREFIX} prefix.
  */
-@ServiceProvider(OptionValuesAccess.class)
-public class HotSpotGraalOptionValues implements OptionValuesAccess {
+public class HotSpotGraalOptionValues {
 
     /**
      * The name of the system property specifying a file containing extra Graal option settings.
@@ -131,9 +128,4 @@
             return new OptionValues(values);
         }
     }
-
-    @Override
-    public OptionValues getOptions() {
-        return HOTSPOT_OPTIONS;
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntime.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,9 +33,12 @@
 import java.util.EnumMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.api.runtime.GraalRuntime;
 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
@@ -45,6 +48,7 @@
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Description;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
+import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.debug.DiagnosticsOutputDirectory;
 import org.graalvm.compiler.debug.GlobalMetrics;
 import org.graalvm.compiler.debug.GraalError;
@@ -54,19 +58,31 @@
 import org.graalvm.compiler.hotspot.debug.BenchmarkCounters;
 import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
 import org.graalvm.compiler.nodes.spi.StampProvider;
+import org.graalvm.compiler.options.EnumOptionKey;
+import org.graalvm.compiler.options.OptionDescriptor;
+import org.graalvm.compiler.options.OptionDescriptors;
+import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.options.OptionsParser;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.replacements.SnippetCounter;
 import org.graalvm.compiler.replacements.SnippetCounter.Group;
 import org.graalvm.compiler.runtime.RuntimeProvider;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.code.Architecture;
 import jdk.vm.ci.code.stack.StackIntrospection;
 import jdk.vm.ci.common.InitTimer;
+import jdk.vm.ci.hotspot.HotSpotCompilationRequest;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
+import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
+import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
 import jdk.vm.ci.hotspot.HotSpotVMConfigStore;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
+import jdk.vm.ci.meta.ResolvedJavaType;
+import jdk.vm.ci.runtime.JVMCI;
 import jdk.vm.ci.runtime.JVMCIBackend;
 
 //JaCoCo Exclude
@@ -88,6 +104,7 @@
         return true;
     }
 
+    private final String runtimeName;
     private final HotSpotBackend hostBackend;
     private final GlobalMetrics metricValues = new GlobalMetrics();
     private final List<SnippetCounter.Group> snippetCounterGroups;
@@ -96,25 +113,42 @@
 
     private final GraalHotSpotVMConfig config;
 
-    private final OptionValues options;
+    /**
+     * The options can be {@linkplain #setOptionValues(String[], String[]) updated} by external
+     * interfaces such as JMX. This comes with the risk that inconsistencies can arise as an
+     * {@link OptionValues} object can be cached by various parts of Graal instead of always
+     * obtaining them from this object. However, concurrent updates are never lost.
+     */
+    private AtomicReference<OptionValues> optionsRef = new AtomicReference<>();
+
+    private final HotSpotGraalCompiler compiler;
+
     private final DiagnosticsOutputDirectory outputDirectory;
     private final Map<ExceptionAction, Integer> compilationProblemsPerAction;
-    private final HotSpotGraalMBean mBean;
 
     /**
+     * @param nameQualifier a qualifier to be added to this runtime's {@linkplain #getName() name}
      * @param compilerConfigurationFactory factory for the compiler configuration
      *            {@link CompilerConfigurationFactory#selectFactory(String, OptionValues)}
      */
     @SuppressWarnings("try")
-    HotSpotGraalRuntime(HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) {
+    HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) {
+        this.runtimeName = getClass().getSimpleName() + ":" + nameQualifier;
         HotSpotVMConfigStore store = jvmciRuntime.getConfigStore();
         config = GeneratePIC.getValue(initialOptions) ? new AOTGraalHotSpotVMConfig(store) : new GraalHotSpotVMConfig(store);
 
         // Only set HotSpotPrintInlining if it still has its default value (false).
         if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) {
-            options = new OptionValues(initialOptions, HotSpotPrintInlining, true);
+            optionsRef.set(new OptionValues(initialOptions, HotSpotPrintInlining, true));
         } else {
-            options = initialOptions;
+            optionsRef.set(initialOptions);
+        }
+        OptionValues options = optionsRef.get();
+
+        if (config.useCMSGC) {
+            // Graal doesn't work with the CMS collector (e.g. GR-6777)
+            // and is deprecated (http://openjdk.java.net/jeps/291).
+            throw new GraalError("Graal does not support the CMS collector");
         }
 
         outputDirectory = new DiagnosticsOutputDirectory(options);
@@ -122,8 +156,11 @@
         snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null;
         CompilerConfiguration compilerConfiguration = compilerConfigurationFactory.createCompilerConfiguration();
 
-        HotSpotGraalCompiler compiler = new HotSpotGraalCompiler(jvmciRuntime, this, initialOptions);
-        this.mBean = createHotSpotGraalMBean(compiler);
+        compiler = new HotSpotGraalCompiler(jvmciRuntime, this, options);
+        management = GraalServices.loadSingle(HotSpotGraalManagementRegistration.class, false);
+        if (management != null) {
+            management.initialize(this);
+        }
 
         BackendMap backendMap = compilerConfigurationFactory.createBackendMap();
 
@@ -172,14 +209,6 @@
         bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class);
     }
 
-    private static HotSpotGraalMBean createHotSpotGraalMBean(HotSpotGraalCompiler compiler) {
-        try {
-            return HotSpotGraalMBean.create(compiler);
-        } catch (LinkageError ex) {
-            return null;
-        }
-    }
-
     private HotSpotBackend registerBackend(HotSpotBackend backend) {
         Class<? extends Architecture> arch = backend.getTarget().arch.getClass();
         HotSpotBackend oldValue = backends.put(arch, backend);
@@ -199,24 +228,35 @@
 
     @Override
     public DebugContext openDebugContext(OptionValues compilationOptions, CompilationIdentifier compilationId, Object compilable, Iterable<DebugHandlersFactory> factories) {
+        if (management != null && management.poll(false) != null) {
+            if (compilable instanceof HotSpotResolvedJavaMethod) {
+                HotSpotResolvedObjectType type = ((HotSpotResolvedJavaMethod) compilable).getDeclaringClass();
+                if (type instanceof HotSpotResolvedJavaType) {
+                    Class<?> clazz = ((HotSpotResolvedJavaType) type).mirror();
+                    try {
+                        ClassLoader cl = clazz.getClassLoader();
+                        if (cl != null) {
+                            loaders.add(cl);
+                        }
+                    } catch (SecurityException e) {
+                        // This loader can obviously not be used for resolving class names
+                    }
+                }
+            }
+        }
         Description description = new Description(compilable, compilationId.toString(CompilationIdentifier.Verbosity.ID));
         return DebugContext.create(compilationOptions, description, metricValues, DEFAULT_LOG_STREAM, factories);
     }
 
     @Override
     public OptionValues getOptions() {
-        return mBean == null ? options : mBean.optionsFor(options, null);
+        return optionsRef.get();
     }
 
     @Override
-    public OptionValues getOptions(ResolvedJavaMethod forMethod) {
-        return mBean == null ? options : mBean.optionsFor(options, forMethod);
-    }
-
-    @Override
-    public Group createSnippetCounterGroup(String name) {
+    public Group createSnippetCounterGroup(String groupName) {
         if (snippetCounterGroups != null) {
-            Group group = new Group(name);
+            Group group = new Group(groupName);
             snippetCounterGroups.add(group);
             return group;
         }
@@ -225,7 +265,7 @@
 
     @Override
     public String getName() {
-        return getClass().getSimpleName();
+        return runtimeName;
     }
 
     @SuppressWarnings("unchecked")
@@ -234,7 +274,7 @@
         if (clazz == RuntimeProvider.class) {
             return (T) this;
         } else if (clazz == OptionValues.class) {
-            return (T) options;
+            return (T) optionsRef.get();
         } else if (clazz == StackIntrospection.class) {
             return (T) this;
         } else if (clazz == SnippetReflectionProvider.class) {
@@ -265,14 +305,14 @@
      * @param phase the execution phase being entered
      */
     void phaseTransition(String phase) {
-        if (Options.UseCompilationStatistics.getValue(options)) {
+        if (Options.UseCompilationStatistics.getValue(optionsRef.get())) {
             CompilationStatistics.clear(phase);
         }
     }
 
     void shutdown() {
         shutdown = true;
-        metricValues.print(options);
+        metricValues.print(optionsRef.get());
 
         phaseTransition("final");
 
@@ -281,7 +321,7 @@
                 TTY.out().out().println(group);
             }
         }
-        BenchmarkCounters.shutdown(runtime(), options, runtimeStartTime);
+        BenchmarkCounters.shutdown(runtime(), optionsRef.get(), runtimeStartTime);
 
         outputDirectory.close();
     }
@@ -317,7 +357,193 @@
         return compilationProblemsPerAction;
     }
 
-    Object getMBean() {
-        return mBean;
+    // ------- Management interface ---------
+
+    private final HotSpotGraalManagementRegistration management;
+
+    /**
+     * @returns the management object for this runtime or {@code null}
+     */
+    public HotSpotGraalManagementRegistration getManagement() {
+        return management;
+    }
+
+    /**
+     * Set of weak references to {@link ClassLoader}s available for resolving class names present in
+     * management {@linkplain #invokeManagementAction(String, Object[]) action} arguments.
+     */
+    private final WeakClassLoaderSet loaders = new WeakClassLoaderSet(ClassLoader.getSystemClassLoader());
+
+    /**
+     * Sets or updates this object's {@linkplain #getOptions() options} from {@code names} and
+     * {@code values}.
+     *
+     * @param values the values to set. The empty string represents {@code null} which resets an
+     *            option to its default value. For string type options, a non-empty value must be
+     *            enclosed in double quotes.
+     * @return an array of Strings where the element at index i is {@code names[i]} if setting the
+     *         denoted option succeeded, {@code null} if the option is unknown otherwise an error
+     *         message describing the failure to set the option
+     */
+    public String[] setOptionValues(String[] names, String[] values) {
+        EconomicMap<String, OptionDescriptor> optionDescriptors = getOptionDescriptors();
+        EconomicMap<OptionKey<?>, Object> newValues = EconomicMap.create(names.length);
+        EconomicSet<OptionKey<?>> resetValues = EconomicSet.create(names.length);
+        String[] result = new String[names.length];
+        for (int i = 0; i < names.length; i++) {
+            String name = names[i];
+            OptionDescriptor option = optionDescriptors.get(name);
+            if (option != null) {
+                String svalue = values[i];
+                Class<?> optionValueType = option.getOptionValueType();
+                OptionKey<?> optionKey = option.getOptionKey();
+                if (svalue == null || svalue.isEmpty() && !(optionKey instanceof EnumOptionKey)) {
+                    resetValues.add(optionKey);
+                    result[i] = name;
+                } else {
+                    String valueToParse;
+                    if (optionValueType == String.class) {
+                        if (svalue.length() < 2 || svalue.charAt(0) != '"' || svalue.charAt(svalue.length() - 1) != '"') {
+                            result[i] = "Invalid value for String option '" + name + "': must be the empty string or be enclosed in double quotes: " + svalue;
+                            continue;
+                        } else {
+                            valueToParse = svalue.substring(1, svalue.length() - 1);
+                        }
+                    } else {
+                        valueToParse = svalue;
+                    }
+                    try {
+                        OptionsParser.parseOption(name, valueToParse, newValues, OptionsParser.getOptionsLoader());
+                        result[i] = name;
+                    } catch (IllegalArgumentException e) {
+                        result[i] = e.getMessage();
+                        continue;
+                    }
+                }
+            } else {
+                result[i] = null;
+            }
+        }
+
+        OptionValues currentOptions;
+        OptionValues newOptions;
+        do {
+            currentOptions = optionsRef.get();
+            UnmodifiableMapCursor<OptionKey<?>, Object> cursor = currentOptions.getMap().getEntries();
+            while (cursor.advance()) {
+                OptionKey<?> key = cursor.getKey();
+                if (!resetValues.contains(key) && !newValues.containsKey(key)) {
+                    newValues.put(key, OptionValues.decodeNull(cursor.getValue()));
+                }
+            }
+            newOptions = new OptionValues(newValues);
+        } while (!optionsRef.compareAndSet(currentOptions, newOptions));
+
+        return result;
+    }
+
+    /**
+     * Gets the values for the options corresponding to {@code names} encoded as strings. The empty
+     * string represents {@code null}. For string type options, non-{@code null} values will be
+     * enclosed in double quotes.
+     *
+     * @param names a list of option names
+     * @return the values for each named option. If an element in {@code names} does not denote an
+     *         existing option, the corresponding element in the returned array will be {@code null}
+     */
+    public String[] getOptionValues(String... names) {
+        String[] values = new String[names.length];
+        EconomicMap<String, OptionDescriptor> optionDescriptors = getOptionDescriptors();
+        for (int i = 0; i < names.length; i++) {
+            OptionDescriptor option = optionDescriptors.get(names[i]);
+            if (option != null) {
+                OptionKey<?> optionKey = option.getOptionKey();
+                Object value = optionKey.getValue(getOptions());
+                String svalue;
+                if (option.getOptionValueType() == String.class && value != null) {
+                    svalue = "\"" + value + "\"";
+                } else if (value == null) {
+                    svalue = "";
+                } else {
+                    svalue = String.valueOf(value);
+                }
+                values[i] = svalue;
+            } else {
+                // null denotes the option does not exist
+                values[i] = null;
+            }
+        }
+        return values;
+    }
+
+    private static EconomicMap<String, OptionDescriptor> getOptionDescriptors() {
+        EconomicMap<String, OptionDescriptor> result = EconomicMap.create();
+        for (OptionDescriptors set : OptionsParser.getOptionsLoader()) {
+            for (OptionDescriptor option : set) {
+                result.put(option.getName(), option);
+            }
+        }
+        return result;
+    }
+
+    private void dumpMethod(String className, String methodName, String filter, String host, int port) throws Exception {
+        EconomicSet<ClassNotFoundException> failures = EconomicSet.create();
+        EconomicSet<Class<?>> found = loaders.resolve(className, failures);
+        if (found.isEmpty()) {
+            ClassNotFoundException cause = failures.isEmpty() ? new ClassNotFoundException(className) : failures.iterator().next();
+            throw new Exception("Cannot find class " + className + " to schedule recompilation", cause);
+        }
+        for (Class<?> clazz : found) {
+            ResolvedJavaType type = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess().lookupJavaType(clazz);
+            for (ResolvedJavaMethod method : type.getDeclaredMethods()) {
+                if (methodName.equals(method.getName()) && method instanceof HotSpotResolvedJavaMethod) {
+                    HotSpotResolvedJavaMethod hotSpotMethod = (HotSpotResolvedJavaMethod) method;
+                    dumpMethod(hotSpotMethod, filter, host, port);
+                }
+            }
+        }
+    }
+
+    private void dumpMethod(HotSpotResolvedJavaMethod hotSpotMethod, String filter, String host, int port) throws Exception {
+        EconomicMap<OptionKey<?>, Object> extra = EconomicMap.create();
+        extra.put(DebugOptions.Dump, filter);
+        extra.put(DebugOptions.PrintGraphHost, host);
+        extra.put(DebugOptions.PrintBinaryGraphPort, port);
+        OptionValues compileOptions = new OptionValues(getOptions(), extra);
+        compiler.compileMethod(new HotSpotCompilationRequest(hotSpotMethod, -1, 0L), false, compileOptions);
+    }
+
+    public Object invokeManagementAction(String actionName, Object[] params) throws Exception {
+        if ("dumpMethod".equals(actionName)) {
+            if (params.length != 0 && params[0] instanceof HotSpotResolvedJavaMethod) {
+                HotSpotResolvedJavaMethod method = param(params, 0, "method", HotSpotResolvedJavaMethod.class, null);
+                String filter = param(params, 1, "filter", String.class, ":3");
+                String host = param(params, 2, "host", String.class, "localhost");
+                Number port = param(params, 3, "port", Number.class, 4445);
+                dumpMethod(method, filter, host, port.intValue());
+            } else {
+                String className = param(params, 0, "className", String.class, null);
+                String methodName = param(params, 1, "methodName", String.class, null);
+                String filter = param(params, 2, "filter", String.class, ":3");
+                String host = param(params, 3, "host", String.class, "localhost");
+                Number port = param(params, 4, "port", Number.class, 4445);
+                dumpMethod(className, methodName, filter, host, port.intValue());
+            }
+        }
+        return null;
+    }
+
+    private static <T> T param(Object[] arr, int index, String name, Class<T> type, T defaultValue) {
+        Object value = arr.length > index ? arr[index] : null;
+        if (value == null || (value instanceof String && ((String) value).isEmpty())) {
+            if (defaultValue == null) {
+                throw new IllegalArgumentException(name + " must be specified");
+            }
+            value = defaultValue;
+        }
+        if (type.isInstance(value)) {
+            return type.cast(value);
+        }
+        throw new IllegalArgumentException("Expecting " + type.getName() + " for " + name + " but was " + value);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotGraalRuntimeProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,16 +27,15 @@
 import org.graalvm.compiler.api.runtime.GraalRuntime;
 import org.graalvm.compiler.core.CompilationWrapper.ExceptionAction;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
+import org.graalvm.compiler.debug.DebugContext;
 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;
 import org.graalvm.compiler.replacements.SnippetCounter.Group;
 import org.graalvm.compiler.runtime.RuntimeProvider;
 
 import jdk.vm.ci.code.TargetDescription;
-import jdk.vm.ci.meta.ResolvedJavaMethod;
 
 //JaCoCo Exclude
 
@@ -77,14 +76,6 @@
     OptionValues getOptions();
 
     /**
-     * Gets the option values associated with this runtime that are applicable for a given method.
-     *
-     * @param forMethod the method we are seeking for options for
-     * @return the options applicable for compiling {@code method}
-     */
-    OptionValues getOptions(ResolvedJavaMethod forMethod);
-
-    /**
      * Determines if the VM is currently bootstrapping the JVMCI compiler.
      */
     boolean isBootstrapping();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/HotSpotLIRGenerationResult.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
  */
 package org.graalvm.compiler.hotspot;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.hotspot.stubs.Stub;
 import org.graalvm.compiler.lir.LIR;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/IsGraalPredicate.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.hotspot;
+
+import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
+
+/**
+ * Determines if a given class is a JVMCI or Graal class for the purpose of
+ * {@link HotSpotGraalCompilerFactory.Options#CompileGraalWithC1Only}.
+ */
+public class IsGraalPredicate {
+    /**
+     * Module containing {@link HotSpotJVMCICompilerFactory}.
+     */
+    private final Module jvmciModule;
+
+    /**
+     * Module containing {@link HotSpotGraalCompilerFactory}.
+     */
+    private final Module graalModule;
+
+    /**
+     * Module containing the {@linkplain CompilerConfigurationFactory#selectFactory selected}
+     * configuration.
+     */
+    private Module compilerConfigurationModule;
+
+    public IsGraalPredicate() {
+        jvmciModule = HotSpotJVMCICompilerFactory.class.getModule();
+        graalModule = HotSpotGraalCompilerFactory.class.getModule();
+    }
+
+    void onCompilerConfigurationFactorySelection(CompilerConfigurationFactory factory) {
+        compilerConfigurationModule = factory.getClass().getModule();
+    }
+
+    boolean apply(Class<?> declaringClass) {
+        Module module = declaringClass.getModule();
+        return jvmciModule == module || graalModule == module || compilerConfigurationModule == module;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/PrintStreamOptionKey.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,15 +27,19 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.PrintStream;
+import java.util.List;
 
 import org.graalvm.compiler.options.OptionKey;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
 
 /**
- * An option that encapsulates and configures a print stream.
+ * An option for a configurable file name that can also open a {@link PrintStream} on the file. If
+ * no value is given for the option, the stream will output to HotSpot's
+ * {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream
  */
 public class PrintStreamOptionKey extends OptionKey<String> {
 
@@ -44,27 +48,13 @@
     }
 
     /**
-     * Replace any instance of %p with an identifying name. Try to get it from the RuntimeMXBean
-     * name.
-     *
-     * @return the name of the file to log to
+     * @return {@code nameTemplate} with all instances of %p replaced by
+     *         {@link GraalServices#getExecutionID()} and %t by {@link System#currentTimeMillis()}
      */
-    private String getFilename(OptionValues options) {
-        String name = getValue(options);
+    private static String makeFilename(String nameTemplate) {
+        String name = nameTemplate;
         if (name.contains("%p")) {
-            try {
-                String runtimeName = java.lang.management.ManagementFactory.getRuntimeMXBean().getName();
-                int index = runtimeName.indexOf('@');
-                if (index != -1) {
-                    long pid = Long.parseLong(runtimeName.substring(0, index));
-                    runtimeName = Long.toString(pid);
-                }
-                name = name.replaceAll("%p", runtimeName);
-            } catch (NumberFormatException e) {
-
-            } catch (LinkageError err) {
-                name = String.valueOf(org.graalvm.compiler.debug.PathUtilities.getGlobalTimeStamp());
-            }
+            name = name.replaceAll("%p", GraalServices.getExecutionID());
         }
         if (name.contains("%t")) {
             name = name.replaceAll("%t", String.valueOf(System.currentTimeMillis()));
@@ -118,22 +108,26 @@
      * will output to HotSpot's {@link HotSpotJVMCIRuntimeProvider#getLogStream() log} stream.
      */
     public PrintStream getStream(OptionValues options) {
-        if (getValue(options) != null) {
+        String nameTemplate = getValue(options);
+        if (nameTemplate != null) {
+            String name = makeFilename(nameTemplate);
             try {
                 final boolean enableAutoflush = true;
-                PrintStream ps = new PrintStream(new FileOutputStream(getFilename(options)), enableAutoflush);
+                PrintStream ps = new PrintStream(new FileOutputStream(name), enableAutoflush);
                 /*
                  * Add the JVM and Java arguments to the log file to help identity it.
                  */
-                String inputArguments = String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
-                ps.println("VM Arguments: " + inputArguments);
+                List<String> inputArguments = GraalServices.getInputArguments();
+                if (inputArguments != null) {
+                    ps.println("VM Arguments: " + String.join(" ", inputArguments));
+                }
                 String cmd = System.getProperty("sun.java.command");
                 if (cmd != null) {
                     ps.println("sun.java.command=" + cmd);
                 }
                 return ps;
             } catch (FileNotFoundException e) {
-                throw new RuntimeException("couldn't open file: " + getValue(options), e);
+                throw new RuntimeException("couldn't open file: " + name, e);
             }
         } else {
             return new PrintStream(new DelayedOutputStream());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/WeakClassLoaderSet.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,118 @@
+/*
+ * 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 java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.UnaryOperator;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+
+/**
+ * A set of weak references to {@link ClassLoader}s.
+ */
+public final class WeakClassLoaderSet {
+
+    /**
+     * Copy-on-write set of loaders.
+     */
+    private volatile AtomicReference<EconomicSet<Reference<ClassLoader>>> loaders = new AtomicReference<>(EconomicSet.create(RefEquivalence.INSTANCE));
+
+    public WeakClassLoaderSet(ClassLoader... initialEntries) {
+        for (ClassLoader loader : initialEntries) {
+            loaders.get().add(new WeakReference<>(loader));
+        }
+    }
+
+    /**
+     * Adds {@code loader} to this set.
+     */
+    public void add(ClassLoader loader) {
+        Reference<ClassLoader> addNewRef = new WeakReference<>(loader);
+        EconomicSet<Reference<ClassLoader>> currentLoaders = loaders.get();
+        if (!currentLoaders.contains(addNewRef)) {
+            this.loaders.getAndUpdate(new UnaryOperator<EconomicSet<Reference<ClassLoader>>>() {
+                @Override
+                public EconomicSet<Reference<ClassLoader>> apply(EconomicSet<Reference<ClassLoader>> t) {
+                    EconomicSet<Reference<ClassLoader>> newLoaders = EconomicSet.create(RefEquivalence.INSTANCE, t);
+                    newLoaders.add(addNewRef);
+                    return newLoaders;
+                }
+            });
+        }
+    }
+
+    /**
+     * Tries to resolve {@code className} to {@link Class} instances with the loaders in this set.
+     *
+     * @param className name of a class to resolve
+     * @param resolutionFailures all resolution failures are returned in this set
+     * @return the set of classes successfully resolved
+     */
+    public EconomicSet<Class<?>> resolve(String className, EconomicSet<ClassNotFoundException> resolutionFailures) {
+        EconomicSet<Class<?>> found = EconomicSet.create();
+        Iterator<Reference<ClassLoader>> it = loaders.get().iterator();
+        while (it.hasNext()) {
+            Reference<ClassLoader> ref = it.next();
+            ClassLoader loader = ref.get();
+            if (loader == null) {
+                it.remove();
+                continue;
+            }
+            try {
+                Class<?> clazz = Class.forName(className, false, loader);
+                found.add(clazz);
+            } catch (ClassNotFoundException ex) {
+                resolutionFailures.add(ex);
+            }
+        }
+        return found;
+    }
+
+    private static final class RefEquivalence extends Equivalence {
+        static final Equivalence INSTANCE = new RefEquivalence();
+
+        private RefEquivalence() {
+        }
+
+        @Override
+        public boolean equals(Object a, Object b) {
+            Reference<?> refA = (Reference<?>) a;
+            Reference<?> refB = (Reference<?>) b;
+            Object referentA = refA.get();
+            Object referentB = refB.get();
+            return Objects.equals(referentA, referentB);
+        }
+
+        @Override
+        public int hashCode(Object o) {
+            Reference<?> ref = (Reference<?>) o;
+            Object obj = ref.get();
+            return obj == null ? 0 : obj.hashCode();
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/AddressLoweringHotSpotSuitesProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 import org.graalvm.compiler.hotspot.HotSpotGraalRuntimeProvider;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.BasePhase;
-import org.graalvm.compiler.phases.common.AddressLoweringPhase;
+import org.graalvm.compiler.phases.Phase;
 import org.graalvm.compiler.phases.common.ExpandLogicPhase;
 import org.graalvm.compiler.phases.common.FixReadsPhase;
 import org.graalvm.compiler.phases.tiers.LowTierContext;
@@ -41,10 +41,10 @@
  */
 public class AddressLoweringHotSpotSuitesProvider extends HotSpotSuitesProvider {
 
-    private final AddressLoweringPhase.AddressLowering addressLowering;
+    private final Phase addressLowering;
 
     public AddressLoweringHotSpotSuitesProvider(SuitesCreator defaultSuitesCreator, GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime,
-                    AddressLoweringPhase.AddressLowering addressLowering) {
+                    Phase addressLowering) {
         super(defaultSuitesCreator, config, runtime);
         this.addressLowering = addressLowering;
     }
@@ -57,7 +57,7 @@
         if (findPhase == null) {
             findPhase = suites.getLowTier().findPhase(ExpandLogicPhase.class);
         }
-        findPhase.add(new AddressLoweringPhase(addressLowering));
+        findPhase.add(addressLowering);
 
         return suites;
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.KLASS_LAYOUT_HELPER_LOCATION;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJ_ARRAY_KLASS_ELEMENT_KLASS_LOCATION;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.lang.ref.Reference;
 
@@ -155,7 +155,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.replacements.DefaultJavaLoweringProvider;
 import org.graalvm.compiler.replacements.nodes.AssertionNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
@@ -43,7 +43,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CallingConvention;
 import jdk.vm.ci.code.CodeCacheProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 import static org.graalvm.compiler.hotspot.meta.HotSpotAOTProfilingPlugin.Options.TieredAOT;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.JAVA_THREAD_THREAD_OBJECT_LOCATION;
 import static org.graalvm.compiler.java.BytecodeParserOptions.InlineDuringParsing;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import java.lang.invoke.ConstantCallSite;
 import java.lang.invoke.MutableCallSite;
@@ -100,10 +100,9 @@
 import org.graalvm.compiler.replacements.ReplacementsImpl;
 import org.graalvm.compiler.replacements.StandardGraphBuilderPlugins;
 import org.graalvm.compiler.serviceprovider.GraalServices;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
 import org.graalvm.compiler.word.WordOperationPlugin;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -160,7 +159,7 @@
             @Override
             public void run() {
                 BytecodeProvider replacementBytecodeProvider = replacements.getDefaultReplacementBytecodeProvider();
-                registerObjectPlugins(invocationPlugins, options, replacementBytecodeProvider);
+                registerObjectPlugins(invocationPlugins, options, config, replacementBytecodeProvider);
                 registerClassPlugins(plugins, config, replacementBytecodeProvider);
                 registerSystemPlugins(invocationPlugins, foreignCalls);
                 registerThreadPlugins(invocationPlugins, metaAccess, wordTypes, config, replacementBytecodeProvider);
@@ -186,7 +185,7 @@
         return plugins;
     }
 
-    private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, BytecodeProvider bytecodeProvider) {
+    private static void registerObjectPlugins(InvocationPlugins plugins, OptionValues options, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
         Registration r = new Registration(plugins, Object.class, bytecodeProvider);
         if (!GeneratePIC.getValue(options)) {
             // FIXME: clone() requires speculation and requires a fix in here (to check that
@@ -210,6 +209,12 @@
             });
         }
         r.registerMethodSubstitution(ObjectSubstitutions.class, "hashCode", Receiver.class);
+        if (config.inlineNotify()) {
+            r.registerMethodSubstitution(ObjectSubstitutions.class, "notify", Receiver.class);
+        }
+        if (config.inlineNotifyAll()) {
+            r.registerMethodSubstitution(ObjectSubstitutions.class, "notifyAll", Receiver.class);
+        }
     }
 
     private static void registerClassPlugins(Plugins plugins, GraalHotSpotVMConfig config, BytecodeProvider bytecodeProvider) {
@@ -440,7 +445,7 @@
     public static final String constantPoolClass;
 
     static {
-        if (JDK9Method.Java8OrEarlier) {
+        if (Java8OrEarlier) {
             cbcEncryptName = "encrypt";
             cbcDecryptName = "decrypt";
             aesEncryptName = "encryptBlock";
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -97,11 +97,11 @@
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.util.EnumMap;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
 import org.graalvm.compiler.core.common.spi.ForeignCallsProvider;
 import org.graalvm.compiler.debug.GraalError;
@@ -124,7 +124,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeCacheProvider;
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
@@ -140,6 +140,9 @@
     public static final ForeignCallDescriptor JAVA_TIME_MILLIS = new ForeignCallDescriptor("javaTimeMillis", long.class);
     public static final ForeignCallDescriptor JAVA_TIME_NANOS = new ForeignCallDescriptor("javaTimeNanos", long.class);
 
+    public static final ForeignCallDescriptor NOTIFY = new ForeignCallDescriptor("object_notify", boolean.class, Object.class);
+    public static final ForeignCallDescriptor NOTIFY_ALL = new ForeignCallDescriptor("object_notifyAll", boolean.class, Object.class);
+
     public HotSpotHostForeignCallsProvider(HotSpotJVMCIRuntimeProvider jvmciRuntime, HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, CodeCacheProvider codeCache,
                     WordTypes wordTypes) {
         super(jvmciRuntime, runtime, metaAccess, codeCache, wordTypes);
@@ -292,6 +295,8 @@
         linkForeignCall(options, providers, MONITORENTER, c.monitorenterAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
         linkForeignCall(options, providers, MONITOREXIT, c.monitorexitAddress, PREPEND_THREAD, STACK_INSPECTABLE_LEAF, NOT_REEXECUTABLE, any());
         linkForeignCall(options, providers, NEW_MULTI_ARRAY, c.newMultiArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE, TLAB_TOP_LOCATION, TLAB_END_LOCATION);
+        linkForeignCall(options, providers, NOTIFY, c.notifyAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
+        linkForeignCall(options, providers, NOTIFY_ALL, c.notifyAllAddress, PREPEND_THREAD, SAFEPOINT, NOT_REEXECUTABLE, any());
         linkForeignCall(options, providers, DYNAMIC_NEW_ARRAY, c.dynamicNewArrayAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
         linkForeignCall(options, providers, DYNAMIC_NEW_INSTANCE, c.dynamicNewInstanceAddress, PREPEND_THREAD, SAFEPOINT, REEXECUTABLE);
         linkForeignCall(options, providers, LOG_PRINTF, c.logPrintfAddress, PREPEND_THREAD, LEAF, REEXECUTABLE, NO_LOCATIONS);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotInvocationPlugins.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,15 +22,9 @@
  */
 package org.graalvm.compiler.hotspot.meta;
 
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import java.lang.reflect.Type;
 
-import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Type;
-import java.util.Set;
-
-import org.graalvm.collections.EconomicSet;
 import org.graalvm.compiler.core.common.GraalOptions;
-import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.iterators.NodeIterable;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -43,7 +37,6 @@
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
 import org.graalvm.compiler.replacements.nodes.MacroNode;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
 
 import jdk.vm.ci.hotspot.HotSpotResolvedJavaType;
 import jdk.vm.ci.meta.JavaKind;
@@ -54,18 +47,11 @@
  */
 final class HotSpotInvocationPlugins extends InvocationPlugins {
     private final GraalHotSpotVMConfig config;
-    private final EconomicSet<Object> trustedModules;
-    private final ClassLoader extLoader;
+    private final IntrinsificationPredicate intrinsificationPredicate;
 
     HotSpotInvocationPlugins(GraalHotSpotVMConfig config, CompilerConfiguration compilerConfiguration) {
         this.config = config;
-        if (Java8OrEarlier) {
-            extLoader = getExtLoader();
-            trustedModules = null;
-        } else {
-            extLoader = null;
-            trustedModules = initTrustedModules(compilerConfiguration);
-        }
+        intrinsificationPredicate = new IntrinsificationPredicate(compilerConfiguration);
     }
 
     @Override
@@ -114,79 +100,12 @@
         return type != null && "Ljava/lang/Class;".equals(type.getName());
     }
 
-    /**
-     * {@inheritDoc}
-     *
-     * On JDK 8, only classes loaded by the boot, JVMCI or extension class loaders are trusted.
-     *
-     * On JDK 9 and later, only classes in the {@link CompilerConfiguration} defining module or any
-     * of its module dependencies are trusted.
-     */
     @Override
     public boolean canBeIntrinsified(ResolvedJavaType declaringClass) {
         if (declaringClass instanceof HotSpotResolvedJavaType) {
-            Class<?> javaClass = ((HotSpotResolvedJavaType) declaringClass).mirror();
-            if (Java8OrEarlier) {
-                ClassLoader cl = javaClass.getClassLoader();
-                return cl == null || cl == getClass().getClassLoader() || cl == extLoader;
-            } else {
-                Object module = JDK9Method.getModule(javaClass);
-                return trustedModules.contains(module);
-            }
+            HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) declaringClass;
+            return intrinsificationPredicate.apply(type.mirror());
         }
         return false;
     }
-
-    private static ClassLoader getExtLoader() {
-        try {
-            Object launcher = Class.forName("sun.misc.Launcher").getMethod("getLauncher").invoke(null);
-            ClassLoader appLoader = (ClassLoader) launcher.getClass().getMethod("getClassLoader").invoke(launcher);
-            ClassLoader extLoader = appLoader.getParent();
-            assert extLoader.getClass().getName().equals("sun.misc.Launcher$ExtClassLoader") : extLoader;
-            return extLoader;
-        } catch (Exception e) {
-            throw new GraalError(e);
-        }
-    }
-
-    /**
-     * Gets the set of modules whose methods can be intrinsified. This set is the module owning the
-     * class of {@code compilerConfiguration} and all its dependencies.
-     */
-    private static EconomicSet<Object> initTrustedModules(CompilerConfiguration compilerConfiguration) throws GraalError {
-        try {
-            EconomicSet<Object> res = EconomicSet.create();
-            Object compilerConfigurationModule = JDK9Method.getModule(compilerConfiguration.getClass());
-            res.add(compilerConfigurationModule);
-            Class<?> moduleClass = compilerConfigurationModule.getClass();
-            Object layer = JDK9Method.lookupMethodHandle(moduleClass, "getLayer").invoke(compilerConfigurationModule);
-            Class<? extends Object> layerClass = layer.getClass();
-            MethodHandle getName = JDK9Method.lookupMethodHandle(moduleClass, "getName");
-            Set<Object> modules = (Set<Object>) JDK9Method.lookupMethodHandle(layerClass, "modules").invoke(layer);
-            Object descriptor = JDK9Method.lookupMethodHandle(moduleClass, "getDescriptor").invoke(compilerConfigurationModule);
-            Class<?> moduleDescriptorClass = descriptor.getClass();
-            Set<Object> requires = (Set<Object>) JDK9Method.lookupMethodHandle(moduleDescriptorClass, "requires").invoke(descriptor);
-            boolean isAutomatic = (Boolean) JDK9Method.lookupMethodHandle(moduleDescriptorClass, "isAutomatic").invoke(descriptor);
-            if (isAutomatic) {
-                throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
-                                getName.invoke(compilerConfigurationModule), compilerConfiguration.getClass().getName()));
-            }
-            MethodHandle requireNameGetter = null;
-            for (Object require : requires) {
-                if (requireNameGetter == null) {
-                    requireNameGetter = JDK9Method.lookupMethodHandle(require.getClass(), "name");
-                }
-                String name = (String) requireNameGetter.invoke(require);
-                for (Object module : modules) {
-                    String moduleName = (String) getName.invoke(module);
-                    if (moduleName.equals(name)) {
-                        res.add(module);
-                    }
-                }
-            }
-            return res;
-        } catch (Throwable e) {
-            throw new GraalError(e);
-        }
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotUnsafeSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,14 +22,14 @@
  */
 package org.graalvm.compiler.hotspot.meta;
 
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.hotspot.HotSpotBackend;
 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 @ClassSubstitution(className = {"jdk.internal.misc.Unsafe", "sun.misc.Unsafe"})
 public class HotSpotUnsafeSubstitutions {
@@ -41,7 +41,7 @@
     static void copyMemory(Object receiver, Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes) {
         Word srcAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(srcBase, srcOffset));
         Word dstAddr = WordFactory.unsigned(ComputeObjectAddressNode.get(destBase, destOffset));
-        Word size = Word.signed(bytes);
+        Word size = WordFactory.signed(bytes);
         HotSpotBackend.unsafeArraycopy(srcAddr, dstAddr, size);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/HotSpotWordOperationPlugin.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_EQ;
 import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE;
 import static org.graalvm.compiler.nodes.ConstantNode.forBoolean;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.BridgeMethodUtils;
@@ -53,7 +53,7 @@
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.word.WordOperationPlugin;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/meta/IntrinsificationPredicate.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, 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.meta;
+
+import java.lang.module.ModuleDescriptor.Requires;
+
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
+
+/**
+ * Determines if methods in a given class can be intrinsified.
+ *
+ * Only classes loaded from the module defining the compiler configuration or any of its transitive
+ * dependencies can be intrinsified.
+ *
+ * This version of the class must be used on JDK 9 or later.
+ */
+public final class IntrinsificationPredicate {
+    /**
+     * Set of modules composed of the module defining the compiler configuration and its transitive
+     * dependencies.
+     */
+    private final EconomicSet<Module> trustedModules;
+
+    IntrinsificationPredicate(CompilerConfiguration compilerConfiguration) {
+        trustedModules = EconomicSet.create();
+        Module compilerConfigurationModule = compilerConfiguration.getClass().getModule();
+        if (compilerConfigurationModule.getDescriptor().isAutomatic()) {
+            throw new IllegalArgumentException(String.format("The module '%s' defining the Graal compiler configuration class '%s' must not be an automatic module",
+                            compilerConfigurationModule.getName(), compilerConfiguration.getClass().getName()));
+        }
+        trustedModules.add(compilerConfigurationModule);
+        for (Requires require : compilerConfigurationModule.getDescriptor().requires()) {
+            for (Module module : compilerConfigurationModule.getLayer().modules()) {
+                if (module.getName().equals(require.name())) {
+                    trustedModules.add(module);
+                }
+            }
+        }
+    }
+
+    public boolean apply(Class<?> declaringClass) {
+        Module module = declaringClass.getModule();
+        return trustedModules.contains(module);
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/BeginLockScopeNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,7 +38,7 @@
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/EndLockScopeNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Intrinsic for closing a {@linkplain BeginLockScopeNode scope} binding a stack-based lock with an
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/StubForeignCallNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Value;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 @NodeInfo(cycles = CYCLES_4, size = SIZE_16, allowedUsageTypes = {Memory})
 public class InitializeKlassNode extends DeoptimizingFixedWithNextNode implements Lowerable, MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/InitializeKlassStubCall.java	Thu Apr 26 17:59:02 2018 +0200
@@ -43,7 +43,7 @@
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant;
 import jdk.vm.ci.meta.Constant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicConstantNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_4;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_16;
 
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.InputType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/nodes/aot/ResolveDynamicStubCall.java	Thu Apr 26 17:59:02 2018 +0200
@@ -43,7 +43,7 @@
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.nodes.memory.AbstractMemoryCheckpoint;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/OnStackReplacementPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,15 +25,12 @@
 import static jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
 
-import jdk.vm.ci.meta.DeoptimizationAction;
-import jdk.vm.ci.meta.DeoptimizationReason;
-import jdk.vm.ci.meta.JavaConstant;
-import jdk.vm.ci.meta.JavaKind;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.debug.CounterKey;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
@@ -74,6 +71,10 @@
 import org.graalvm.compiler.phases.Phase;
 import org.graalvm.compiler.phases.common.DeadCodeEliminationPhase;
 
+import jdk.vm.ci.meta.DeoptimizationAction;
+import jdk.vm.ci.meta.DeoptimizationReason;
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.runtime.JVMCICompiler;
 
 public class OnStackReplacementPhase extends Phase {
@@ -97,6 +98,7 @@
     }
 
     @Override
+    @SuppressWarnings("try")
     protected void run(StructuredGraph graph) {
         DebugContext debug = graph.getDebug();
         if (graph.getEntryBCI() == JVMCICompiler.INVOCATION_ENTRY_BCI) {
@@ -158,64 +160,67 @@
             debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement loop peeling result");
         } while (true);
 
+        StartNode start = graph.start();
         FrameState osrState = osr.stateAfter();
-        osr.setStateAfter(null);
-        OSRStartNode osrStart = graph.add(new OSRStartNode());
-        StartNode start = graph.start();
-        FixedNode next = osr.next();
-        osr.setNext(null);
-        osrStart.setNext(next);
-        graph.setStart(osrStart);
-        osrStart.setStateAfter(osrState);
+        OSRStartNode osrStart;
+        try (DebugCloseable context = osr.withNodeSourcePosition()) {
+            osr.setStateAfter(null);
+            osrStart = graph.add(new OSRStartNode());
+            FixedNode next = osr.next();
+            osr.setNext(null);
+            osrStart.setNext(next);
+            graph.setStart(osrStart);
+            osrStart.setStateAfter(osrState);
+
+            debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
+            final int localsSize = osrState.localsSize();
+            final int locksSize = osrState.locksSize();
 
-        debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after setting OSR start");
-        final int localsSize = osrState.localsSize();
-        final int locksSize = osrState.locksSize();
+            for (int i = 0; i < localsSize + locksSize; i++) {
+                ValueNode value = null;
+                if (i >= localsSize) {
+                    value = osrState.lockAt(i - localsSize);
+                } else {
+                    value = osrState.localAt(i);
+                }
+                if (value instanceof EntryProxyNode) {
+                    EntryProxyNode proxy = (EntryProxyNode) value;
+                    /*
+                     * We need to drop the stamp since the types we see during OSR may be too
+                     * precise (if a branch was not parsed for example). In cases when this is
+                     * possible, we insert a guard and narrow the OSRLocal stamp at its usages.
+                     */
+                    Stamp narrowedStamp = proxy.value().stamp(NodeView.DEFAULT);
+                    Stamp unrestrictedStamp = proxy.stamp(NodeView.DEFAULT).unrestricted();
+                    ValueNode osrLocal;
+                    if (i >= localsSize) {
+                        osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp));
+                    } else {
+                        osrLocal = graph.addOrUnique(new OSRLocalNode(i, unrestrictedStamp));
+                    }
+                    // Speculate on the OSRLocal stamps that could be more precise.
+                    OSRLocalSpeculationReason reason = new OSRLocalSpeculationReason(osrState.bci, narrowedStamp, i);
+                    if (graph.getSpeculationLog().maySpeculate(reason) && osrLocal instanceof OSRLocalNode && value.getStackKind().equals(JavaKind.Object) && !narrowedStamp.isUnrestricted()) {
+                        // Add guard.
+                        LogicNode check = graph.addOrUniqueWithInputs(InstanceOfNode.createHelper((ObjectStamp) narrowedStamp, osrLocal, null, null));
+                        JavaConstant constant = graph.getSpeculationLog().speculate(reason);
+                        FixedGuardNode guard = graph.add(new FixedGuardNode(check, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, constant, false));
+                        graph.addAfterFixed(osrStart, guard);
 
-        for (int i = 0; i < localsSize + locksSize; i++) {
-            ValueNode value = null;
-            if (i >= localsSize) {
-                value = osrState.lockAt(i - localsSize);
-            } else {
-                value = osrState.localAt(i);
+                        // Replace with a more specific type at usages.
+                        // We know that we are at the root,
+                        // so we need to replace the proxy in the state.
+                        proxy.replaceAtMatchingUsages(osrLocal, n -> n == osrState);
+                        osrLocal = graph.addOrUnique(new PiNode(osrLocal, narrowedStamp, guard));
+                    }
+                    proxy.replaceAndDelete(osrLocal);
+                } else {
+                    assert value == null || value instanceof OSRLocalNode;
+                }
             }
-            if (value instanceof EntryProxyNode) {
-                EntryProxyNode proxy = (EntryProxyNode) value;
-                /*
-                 * We need to drop the stamp since the types we see during OSR may be too precise
-                 * (if a branch was not parsed for example). In cases when this is possible, we
-                 * insert a guard and narrow the OSRLocal stamp at its usages.
-                 */
-                Stamp narrowedStamp = proxy.value().stamp(NodeView.DEFAULT);
-                Stamp unrestrictedStamp = proxy.stamp(NodeView.DEFAULT).unrestricted();
-                ValueNode osrLocal;
-                if (i >= localsSize) {
-                    osrLocal = graph.addOrUnique(new OSRLockNode(i - localsSize, unrestrictedStamp));
-                } else {
-                    osrLocal = graph.addOrUnique(new OSRLocalNode(i, unrestrictedStamp));
-                }
-                // Speculate on the OSRLocal stamps that could be more precise.
-                OSRLocalSpeculationReason reason = new OSRLocalSpeculationReason(osrState.bci, narrowedStamp, i);
-                if (graph.getSpeculationLog().maySpeculate(reason) && osrLocal instanceof OSRLocalNode && value.getStackKind().equals(JavaKind.Object) && !narrowedStamp.isUnrestricted()) {
-                    // Add guard.
-                    LogicNode check = graph.addOrUniqueWithInputs(InstanceOfNode.createHelper((ObjectStamp) narrowedStamp, osrLocal, null, null));
-                    JavaConstant constant = graph.getSpeculationLog().speculate(reason);
-                    FixedGuardNode guard = graph.add(new FixedGuardNode(check, DeoptimizationReason.OptimizedTypeCheckViolated, DeoptimizationAction.InvalidateRecompile, constant, false));
-                    graph.addAfterFixed(osrStart, guard);
 
-                    // Replace with a more specific type at usages.
-                    // We know that we are at the root,
-                    // so we need to replace the proxy in the state.
-                    proxy.replaceAtMatchingUsages(osrLocal, n -> n == osrState);
-                    osrLocal = graph.addOrUnique(new PiNode(osrLocal, narrowedStamp, guard));
-                }
-                proxy.replaceAndDelete(osrLocal);
-            } else {
-                assert value == null || value instanceof OSRLocalNode;
-            }
+            osr.replaceAtUsages(InputType.Guard, osrStart);
         }
-
-        osr.replaceAtUsages(InputType.Guard, osrStart);
         debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement after replacing entry proxies");
         GraphUtil.killCFG(start);
         debug.dump(DebugContext.DETAILED_LEVEL, graph, "OnStackReplacement result");
@@ -223,21 +228,24 @@
 
         if (currentOSRWithLocks) {
             OsrWithLocksCount.increment(debug);
-            for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) {
-                MonitorIdNode id = osrState.monitorIdAt(i);
-                ValueNode lockedObject = osrState.lockAt(i);
-                OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id));
-                for (Node usage : id.usages()) {
-                    if (usage instanceof AccessMonitorNode) {
-                        AccessMonitorNode access = (AccessMonitorNode) usage;
-                        access.setObject(lockedObject);
+            try (DebugCloseable context = osrStart.withNodeSourcePosition()) {
+                for (int i = osrState.monitorIdCount() - 1; i >= 0; --i) {
+                    MonitorIdNode id = osrState.monitorIdAt(i);
+                    ValueNode lockedObject = osrState.lockAt(i);
+                    OSRMonitorEnterNode osrMonitorEnter = graph.add(new OSRMonitorEnterNode(lockedObject, id));
+                    for (Node usage : id.usages()) {
+                        if (usage instanceof AccessMonitorNode) {
+                            AccessMonitorNode access = (AccessMonitorNode) usage;
+                            access.setObject(lockedObject);
+                        }
                     }
+                    FixedNode oldNext = osrStart.next();
+                    oldNext.replaceAtPredecessor(null);
+                    osrMonitorEnter.setNext(oldNext);
+                    osrStart.setNext(osrMonitorEnter);
                 }
-                FixedNode oldNext = osrStart.next();
-                oldNext.replaceAtPredecessor(null);
-                osrMonitorEnter.setNext(oldNext);
-                osrStart.setNext(osrMonitorEnter);
             }
+
             debug.dump(DebugContext.DETAILED_LEVEL, graph, "After inserting OSR monitor enters");
             /*
              * Ensure balanced monitorenter - monitorexit
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/WriteBarrierAdditionPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,7 @@
  */
 package org.graalvm.compiler.hotspot.phases;
 
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.hotspot.GraalHotSpotVMConfig;
@@ -53,22 +54,25 @@
         this.config = config;
     }
 
+    @SuppressWarnings("try")
     @Override
     protected void run(StructuredGraph graph) {
         for (Node n : graph.getNodes()) {
-            if (n instanceof ReadNode) {
-                addReadNodeBarriers((ReadNode) n, graph);
-            } else if (n instanceof WriteNode) {
-                addWriteNodeBarriers((WriteNode) n, graph);
-            } else if (n instanceof LoweredAtomicReadAndWriteNode) {
-                LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n;
-                addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph);
-            } else if (n instanceof AbstractCompareAndSwapNode) {
-                addCASBarriers((AbstractCompareAndSwapNode) n, graph);
-            } else if (n instanceof ArrayRangeWrite) {
-                ArrayRangeWrite node = (ArrayRangeWrite) n;
-                if (node.writesObjectArray()) {
-                    addArrayRangeBarriers(node, graph);
+            try (DebugCloseable scope = n.graph().withNodeSourcePosition(n)) {
+                if (n instanceof ReadNode) {
+                    addReadNodeBarriers((ReadNode) n, graph);
+                } else if (n instanceof WriteNode) {
+                    addWriteNodeBarriers((WriteNode) n, graph);
+                } else if (n instanceof LoweredAtomicReadAndWriteNode) {
+                    LoweredAtomicReadAndWriteNode loweredAtomicReadAndWriteNode = (LoweredAtomicReadAndWriteNode) n;
+                    addAtomicReadWriteNodeBarriers(loweredAtomicReadAndWriteNode, graph);
+                } else if (n instanceof AbstractCompareAndSwapNode) {
+                    addCASBarriers((AbstractCompareAndSwapNode) n, graph);
+                } else if (n instanceof ArrayRangeWrite) {
+                    ArrayRangeWrite node = (ArrayRangeWrite) n;
+                    if (node.writesObjectArray()) {
+                        addArrayRangeBarriers(node, graph);
+                    }
                 }
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/AOTInliningPolicy.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,6 +27,7 @@
 
 import java.util.Map;
 
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.spi.Replacements;
 import org.graalvm.compiler.options.Option;
@@ -36,6 +37,7 @@
 import org.graalvm.compiler.phases.common.inlining.InliningUtil;
 import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
+import org.graalvm.compiler.phases.common.inlining.policy.InliningPolicy;
 import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
 
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
@@ -61,13 +63,14 @@
     }
 
     @Override
-    public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+        final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions());
         final InlineInfo info = invocation.callee();
 
         for (int i = 0; i < info.numberOfMethods(); ++i) {
             HotSpotResolvedObjectType t = (HotSpotResolvedObjectType) info.methodAt(i).getDeclaringClass();
             if (t.getFingerprint() == 0) {
-                return false;
+                return InliningPolicy.Decision.NO;
             }
         }
 
@@ -77,17 +80,17 @@
         OptionValues options = info.graph().getOptions();
         if (InlineEverything.getValue(options)) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything");
         }
 
         if (isIntrinsic(replacements, info)) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "intrinsic");
         }
 
         if (info.shouldInline()) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "forced inlining");
         }
 
         double inliningBonus = getInliningBonus(info);
@@ -95,17 +98,18 @@
 
         if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
         }
 
         double maximumNodes = computeMaximumSize(relevance, (int) (maxInliningSize(inliningDepth, options) * inliningBonus));
         if (nodes <= maximumNodes) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
                             nodes, maximumNodes);
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
+                            nodes, maximumNodes);
         }
 
         InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
-        return false;
+        return InliningPolicy.Decision.NO.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/EliminateRedundantInitializationPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.ResolvedJavaType;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.hotspot.nodes.aot.InitializeKlassNode;
 import org.graalvm.compiler.hotspot.nodes.aot.ResolveConstantNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/phases/aot/ReplaceConstantNodesPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 import java.util.HashSet;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/AESCryptSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -41,9 +41,9 @@
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.DeoptimizationAction;
 import jdk.vm.ci.meta.DeoptimizationReason;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32CSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32CSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
 import org.graalvm.compiler.hotspot.nodes.ComputeObjectAddressNode;
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CRC32Substitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,9 +38,9 @@
 import org.graalvm.compiler.hotspot.nodes.GraalHotSpotVMConfigNode;
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/CipherBlockChainingSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,9 +40,9 @@
 import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ClassGetHubNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -48,7 +48,7 @@
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HashCodeSnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -47,7 +47,7 @@
 import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.TargetDescription;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Thu Apr 26 17:59:02 2018 +0200
@@ -59,8 +59,8 @@
 import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
 import org.graalvm.compiler.replacements.nodes.WriteRegisterNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/IdentityHashCodeNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.hotspot.HotSpotObjectConstant;
 import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/LoadExceptionObjectSnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -51,7 +51,7 @@
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/MonitorSnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -120,10 +120,10 @@
 import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.code.Register;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/NewObjectSnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -117,8 +117,8 @@
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.code.MemoryBarriers;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ObjectSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,11 @@
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
+import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
+import org.graalvm.compiler.graph.Node.ConstantNodeParameter;
+import org.graalvm.compiler.graph.Node.NodeIntrinsic;
+import org.graalvm.compiler.nodes.extended.ForeignCallNode;
 
 // JaCoCo Exclude
 
@@ -37,4 +42,21 @@
     public static int hashCode(final Object thisObj) {
         return IdentityHashCodeNode.identityHashCode(thisObj);
     }
+
+    @MethodSubstitution(isStatic = false)
+    public static void notify(final Object thisObj) {
+        if (!fastNotifyStub(HotSpotHostForeignCallsProvider.NOTIFY, thisObj)) {
+            notify(thisObj);
+        }
+    }
+
+    @MethodSubstitution(isStatic = false)
+    public static void notifyAll(final Object thisObj) {
+        if (!fastNotifyStub(HotSpotHostForeignCallsProvider.NOTIFY_ALL, thisObj)) {
+            notifyAll(thisObj);
+        }
+    }
+
+    @NodeIntrinsic(ForeignCallNode.class)
+    public static native boolean fastNotifyStub(@ConstantNodeParameter ForeignCallDescriptor descriptor, Object o);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA2Substitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
 package org.graalvm.compiler.hotspot.replacements;
 
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -33,8 +33,8 @@
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHA5Substitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
 package org.graalvm.compiler.hotspot.replacements;
 
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -33,8 +33,8 @@
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/SHASubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
 package org.graalvm.compiler.hotspot.replacements;
 
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider.getArrayBaseOffset;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
@@ -33,8 +33,8 @@
 import org.graalvm.compiler.nodes.PiNode;
 import org.graalvm.compiler.nodes.extended.RawLoadNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/StringToBytesSnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,7 @@
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.replacements.nodes.CStringConstant;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/ThreadSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.osThreadInterruptedOffset;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.osThreadOffset;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.threadObjectOffset;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.api.replacements.ClassSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/WriteBarrierSnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -87,10 +87,10 @@
 import org.graalvm.compiler.replacements.Snippets;
 import org.graalvm.compiler.replacements.nodes.DirectStoreNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.code.TargetDescription;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyCallNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -58,7 +58,7 @@
 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopyNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.hotspot.replacements.arraycopy;
 
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
@@ -31,7 +31,7 @@
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/ArrayCopySnippets.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,7 +40,7 @@
 import java.lang.reflect.Method;
 import java.util.EnumMap;
 
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.Snippet;
@@ -77,8 +77,8 @@
 import org.graalvm.compiler.replacements.nodes.BasicArrayCopyNode;
 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.DeoptimizationAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/CheckcastArrayCopyCallNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -52,7 +52,7 @@
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/arraycopy/GenericArrayCopyCallNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,7 +42,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/CreateExceptionStub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
 import static org.graalvm.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.REEXECUTABLE;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.clearPendingException;
 import static org.graalvm.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ExceptionHandlerStub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -51,7 +51,7 @@
 import org.graalvm.compiler.hotspot.nodes.StubForeignCallNode;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.Register;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/ForeignCallStub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,11 +34,9 @@
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
-import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.JavaMethodContext;
-import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkage.Transition;
 import org.graalvm.compiler.hotspot.HotSpotForeignCallLinkageImpl;
@@ -57,7 +55,7 @@
 import org.graalvm.compiler.replacements.nodes.ReadRegisterNode;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
 import jdk.vm.ci.hotspot.HotSpotSignature;
@@ -232,33 +230,30 @@
         WordTypes wordTypes = providers.getWordTypes();
         Class<?>[] args = linkage.getDescriptor().getArgumentTypes();
         boolean isObjectResult = !LIRKind.isValue(linkage.getOutgoingCallingConvention().getReturn());
-        StructuredGraph graph = new StructuredGraph.Builder(options, debug).name(toString()).compilationId(compilationId).build();
-        graph.disableUnsafeAccessTracking();
-        graph.setTrackNodeSourcePosition();
+
         try {
             ResolvedJavaMethod thisMethod = providers.getMetaAccess().lookupJavaMethod(ForeignCallStub.class.getDeclaredMethod("getGraph", DebugContext.class, CompilationIdentifier.class));
-            try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(thisMethod))) {
-                GraphKit kit = new GraphKit(graph, providers, wordTypes, providers.getGraphBuilderPlugins());
-                ParameterNode[] params = createParameters(kit, args);
-                ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
-                ValueNode result = createTargetCall(kit, params, thread);
-                kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
-                if (isObjectResult) {
-                    InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
-                    result = kit.createInvoke(StubUtil.class, "verifyObject", object);
-                }
-                kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
-                debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
+            GraphKit kit = new GraphKit(debug, thisMethod, providers, wordTypes, providers.getGraphBuilderPlugins(), compilationId, toString());
+            StructuredGraph graph = kit.getGraph();
+            ParameterNode[] params = createParameters(kit, args);
+            ReadRegisterNode thread = kit.append(new ReadRegisterNode(providers.getRegisters().getThreadRegister(), wordTypes.getWordKind(), true, false));
+            ValueNode result = createTargetCall(kit, params, thread);
+            kit.createInvoke(StubUtil.class, "handlePendingException", thread, ConstantNode.forBoolean(isObjectResult, graph));
+            if (isObjectResult) {
+                InvokeNode object = kit.createInvoke(HotSpotReplacementsUtil.class, "getAndClearObjectResult", thread);
+                result = kit.createInvoke(StubUtil.class, "verifyObject", object);
+            }
+            kit.append(new ReturnNode(linkage.getDescriptor().getResultType() == void.class ? null : result));
+            debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Initial stub graph");
 
-                kit.inlineInvokes();
-                new RemoveValueProxyPhase().apply(graph);
+            kit.inlineInvokes("Foreign call stub.", "Backend");
+            new RemoveValueProxyPhase().apply(graph);
 
-                debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation");
-            }
+            debug.dump(DebugContext.VERBOSE_LEVEL, graph, "Stub graph before compilation");
+            return graph;
         } catch (Exception e) {
             throw GraalError.shouldNotReachHere(e);
         }
-        return graph;
     }
 
     private ParameterNode[] createParameters(GraphKit kit, Class<?>[] args) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewArrayStub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -59,7 +59,7 @@
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/NewInstanceStub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -81,7 +81,7 @@
 import org.graalvm.compiler.nodes.ConstantNode;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.code.Register;
 import jdk.vm.ci.hotspot.HotSpotResolvedObjectType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/Stub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -48,9 +48,10 @@
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.TriState;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.code.CompilationResult;
 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.DebugContext;
 import org.graalvm.compiler.debug.DebugContext.Description;
@@ -137,7 +138,7 @@
      */
     public Stub(OptionValues options, HotSpotProviders providers, HotSpotForeignCallLinkage linkage) {
         this.linkage = linkage;
-        this.options = options;
+        this.options = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options));
         this.providers = providers;
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/StubUtil.java	Thu Apr 26 17:59:02 2018 +0200
@@ -50,8 +50,8 @@
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.replacements.Log;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.DeoptimizationAction;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/stubs/UnwindExceptionToCallerStub.java	Thu Apr 26 17:59:02 2018 +0200
@@ -47,7 +47,7 @@
 import org.graalvm.compiler.nodes.UnwindNode;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.Pointer;
 
 import jdk.vm.ci.code.Register;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/KlassPointer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,8 +29,8 @@
 
 import org.graalvm.compiler.word.Word.Opcode;
 import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
 
 /**
  * Marker type for a metaspace pointer to a type.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MetaspacePointer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,11 +29,11 @@
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.Word.Opcode;
 import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
 
 /**
  * Marker type for a metaspace pointer.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/word/MethodPointer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.POINTER_NE;
 import static org.graalvm.compiler.hotspot.word.HotSpotOperation.HotspotOpcode.TO_METHOD_POINTER;
 
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.Pointer;
 
 /**
  * Marker type for a metaspace pointer to a method.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BciBlockMapping.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,6 +38,7 @@
 import static org.graalvm.compiler.bytecode.Bytecodes.FASTORE;
 import static org.graalvm.compiler.bytecode.Bytecodes.FRETURN;
 import static org.graalvm.compiler.bytecode.Bytecodes.GETFIELD;
+import static org.graalvm.compiler.bytecode.Bytecodes.GETSTATIC;
 import static org.graalvm.compiler.bytecode.Bytecodes.GOTO;
 import static org.graalvm.compiler.bytecode.Bytecodes.GOTO_W;
 import static org.graalvm.compiler.bytecode.Bytecodes.IALOAD;
@@ -71,6 +72,7 @@
 import static org.graalvm.compiler.bytecode.Bytecodes.LOOKUPSWITCH;
 import static org.graalvm.compiler.bytecode.Bytecodes.LRETURN;
 import static org.graalvm.compiler.bytecode.Bytecodes.PUTFIELD;
+import static org.graalvm.compiler.bytecode.Bytecodes.PUTSTATIC;
 import static org.graalvm.compiler.bytecode.Bytecodes.RET;
 import static org.graalvm.compiler.bytecode.Bytecodes.RETURN;
 import static org.graalvm.compiler.bytecode.Bytecodes.SALOAD;
@@ -81,13 +83,12 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.TreeSet;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeLookupSwitch;
 import org.graalvm.compiler.bytecode.BytecodeStream;
@@ -142,20 +143,20 @@
 
     public static class BciBlock implements Cloneable {
 
-        protected int id;
-        public int startBci;
-        public int endBci;
-        public boolean isExceptionEntry;
-        public boolean isLoopHeader;
-        public int loopId;
-        public int loopEnd;
-        protected List<BciBlock> successors;
+        int id;
+        final int startBci;
+        int endBci;
+        private boolean isExceptionEntry;
+        private boolean isLoopHeader;
+        int loopId;
+        int loopEnd;
+        List<BciBlock> successors;
         private int predecessorCount;
 
         private boolean visited;
         private boolean active;
-        public long loops;
-        public JSRData jsrData;
+        long loops;
+        JSRData jsrData;
 
         public static class JSRData implements Cloneable {
             public EconomicMap<JsrScope, BciBlock> jsrAlternatives;
@@ -174,8 +175,21 @@
             }
         }
 
-        public BciBlock() {
-            this.successors = new ArrayList<>(4);
+        BciBlock(int startBci) {
+            this.startBci = startBci;
+            this.successors = new ArrayList<>();
+        }
+
+        public int getStartBci() {
+            return startBci;
+        }
+
+        public int getEndBci() {
+            return endBci;
+        }
+
+        public long getLoops() {
+            return loops;
         }
 
         public BciBlock exceptionDispatchBlock() {
@@ -216,14 +230,16 @@
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder("B").append(getId());
-            sb.append('[').append(startBci).append("->").append(endBci);
-            if (isLoopHeader || isExceptionEntry) {
+            sb.append('[').append(startBci).append("..").append(endBci);
+            if (isLoopHeader || isExceptionEntry || this instanceof ExceptionDispatchBlock) {
                 sb.append(' ');
                 if (isLoopHeader) {
                     sb.append('L');
                 }
                 if (isExceptionEntry) {
                     sb.append('!');
+                } else if (this instanceof ExceptionDispatchBlock) {
+                    sb.append("<!>");
                 }
             }
             sb.append(']');
@@ -412,11 +428,40 @@
             }
             successors.clear();
         }
+
+        public boolean isExceptionDispatch() {
+            return false;
+        }
     }
 
     public static class ExceptionDispatchBlock extends BciBlock {
-        public ExceptionHandler handler;
-        public int deoptBci;
+        public final ExceptionHandler handler;
+        public final int deoptBci;
+
+        /**
+         * Constructor for a normal dispatcher.
+         */
+        ExceptionDispatchBlock(ExceptionHandler handler, int deoptBci) {
+            super(handler.getHandlerBCI());
+            this.endBci = startBci;
+            this.deoptBci = deoptBci;
+            this.handler = handler;
+        }
+
+        /**
+         * Constructor for the method unwind dispatcher.
+         */
+        ExceptionDispatchBlock(int deoptBci) {
+            super(deoptBci);
+            this.endBci = deoptBci;
+            this.deoptBci = deoptBci;
+            this.handler = null;
+        }
+
+        @Override
+        public boolean isExceptionDispatch() {
+            return true;
+        }
     }
 
     /**
@@ -480,7 +525,6 @@
     private boolean verify() {
         for (BciBlock block : blocks) {
             assert blocks[block.getId()] == block;
-
             for (int i = 0; i < block.getSuccessorCount(); i++) {
                 BciBlock sux = block.getSuccessor(i);
                 if (sux instanceof ExceptionDispatchBlock) {
@@ -623,6 +667,8 @@
                 case CALOAD:
                 case SALOAD:
                 case ARRAYLENGTH:
+                case PUTSTATIC:
+                case GETSTATIC:
                 case PUTFIELD:
                 case GETFIELD: {
                     ExceptionDispatchBlock handler = handleExceptions(blockMap, bci);
@@ -640,18 +686,16 @@
     private BciBlock makeBlock(BciBlock[] blockMap, int startBci) {
         BciBlock oldBlock = blockMap[startBci];
         if (oldBlock == null) {
-            BciBlock newBlock = new BciBlock();
+            BciBlock newBlock = new BciBlock(startBci);
             blocksNotYetAssignedId++;
-            newBlock.startBci = startBci;
             blockMap[startBci] = newBlock;
             return newBlock;
 
         } else if (oldBlock.startBci != startBci) {
             // Backward branch into the middle of an already processed block.
             // Add the correct fall-through successor.
-            BciBlock newBlock = new BciBlock();
+            BciBlock newBlock = new BciBlock(startBci);
             blocksNotYetAssignedId++;
-            newBlock.startBci = startBci;
             newBlock.endBci = oldBlock.endBci;
             for (BciBlock oldSuccessor : oldBlock.getSuccessors()) {
                 newBlock.addSuccessor(oldSuccessor);
@@ -747,6 +791,7 @@
 
     private ExceptionDispatchBlock handleExceptions(BciBlock[] blockMap, int bci) {
         ExceptionDispatchBlock lastHandler = null;
+        int dispatchBlocks = 0;
 
         for (int i = exceptionHandlers.length - 1; i >= 0; i--) {
             ExceptionHandler h = exceptionHandlers[i];
@@ -754,17 +799,14 @@
                 if (h.isCatchAll()) {
                     // Discard all information about succeeding exception handlers, since they can
                     // never be reached.
+                    dispatchBlocks = 0;
                     lastHandler = null;
                 }
 
                 // We do not reuse exception dispatch blocks, because nested exception handlers
                 // might have problems reasoning about the correct frame state.
-                ExceptionDispatchBlock curHandler = new ExceptionDispatchBlock();
-                blocksNotYetAssignedId++;
-                curHandler.startBci = -1;
-                curHandler.endBci = -1;
-                curHandler.deoptBci = bci;
-                curHandler.handler = h;
+                ExceptionDispatchBlock curHandler = new ExceptionDispatchBlock(h, bci);
+                dispatchBlocks++;
                 curHandler.addSuccessor(blockMap[h.getHandlerBCI()]);
                 if (lastHandler != null) {
                     curHandler.addSuccessor(lastHandler);
@@ -772,6 +814,7 @@
                 lastHandler = curHandler;
             }
         }
+        blocksNotYetAssignedId += dispatchBlocks;
         return lastHandler;
     }
 
@@ -827,10 +870,8 @@
         assert next == newBlocks.length - 1;
 
         // Add unwind block.
-        ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock();
-        unwindBlock.startBci = -1;
-        unwindBlock.endBci = -1;
-        unwindBlock.deoptBci = code.getMethod().isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI;
+        int deoptBci = code.getMethod().isSynchronized() ? BytecodeFrame.UNWIND_BCI : BytecodeFrame.AFTER_EXCEPTION_BCI;
+        ExceptionDispatchBlock unwindBlock = new ExceptionDispatchBlock(deoptBci);
         unwindBlock.setId(newBlocks.length - 1);
         newBlocks[newBlocks.length - 1] = unwindBlock;
 
@@ -858,42 +899,54 @@
 
     public void log(BciBlock[] blockMap, String name) {
         if (debug.isLogEnabled()) {
-            String n = System.lineSeparator();
-            StringBuilder sb = new StringBuilder(debug.getCurrentScopeName()).append("BlockMap ").append(name).append(" :");
-            sb.append(n);
-            Iterable<BciBlock> it;
-            if (blocks == null) {
-                it = new HashSet<>(Arrays.asList(blockMap));
-            } else {
-                it = Arrays.asList(blocks);
+            debug.log("%sBlockMap %s: %n%s", debug.getCurrentScopeName(), name, toString(blockMap, loopHeaders));
+        }
+    }
+
+    public static String toString(BciBlock[] blockMap, BciBlock[] loopHeadersMap) {
+        StringBuilder sb = new StringBuilder();
+        for (BciBlock b : blockMap) {
+            if (b == null) {
+                continue;
+            }
+            sb.append("B").append(b.getId()).append("[").append(b.startBci).append("..").append(b.endBci).append("]");
+            if (b.isLoopHeader) {
+                sb.append(" LoopHeader");
             }
-            for (BciBlock b : it) {
-                if (b == null) {
-                    continue;
-                }
-                sb.append("B").append(b.getId()).append(" (").append(b.startBci).append(" -> ").append(b.endBci).append(")");
-                if (b.isLoopHeader) {
-                    sb.append(" LoopHeader");
+            if (b.isExceptionEntry) {
+                sb.append(" ExceptionEntry");
+            }
+            if (b instanceof ExceptionDispatchBlock) {
+                sb.append(" ExceptionDispatch");
+            }
+            if (!b.successors.isEmpty()) {
+                sb.append(" Successors=[");
+                for (BciBlock s : b.getSuccessors()) {
+                    if (sb.charAt(sb.length() - 1) != '[') {
+                        sb.append(", ");
+                    }
+                    sb.append("B").append(s.getId());
                 }
-                if (b.isExceptionEntry) {
-                    sb.append(" ExceptionEntry");
-                }
-                sb.append(n).append("  Sux : ");
-                for (BciBlock s : b.getSuccessors()) {
-                    sb.append("B").append(s.getId()).append(" (").append(s.startBci).append(" -> ").append(s.endBci).append(")");
-                    if (s.isExceptionEntry) {
-                        sb.append("!");
+                sb.append("]");
+            }
+            if (b.loops != 0L) {
+                sb.append(" Loops=[");
+                for (int pos : b.loopIdIterable()) {
+                    if (sb.charAt(sb.length() - 1) == '[') {
+                        sb.append(", ");
                     }
-                    sb.append(" ");
+                    sb.append("B").append(loopHeadersMap[pos].getId());
                 }
-                sb.append(n).append("  Loop : ");
-                for (int pos : b.loopIdIterable()) {
-                    sb.append("B").append(loopHeaders[pos].getId()).append(" ");
-                }
-                sb.append(n);
+                sb.append("]");
             }
-            debug.log("%s", sb);
+            sb.append(System.lineSeparator());
         }
+        return sb.toString();
+    }
+
+    @Override
+    public String toString() {
+        return toString(blocks, loopHeaders);
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParser.java	Thu Apr 26 17:59:02 2018 +0200
@@ -265,8 +265,8 @@
 import java.util.Formatter;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
@@ -297,8 +297,10 @@
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
+import org.graalvm.compiler.debug.DebugOptions;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.Indent;
+import org.graalvm.compiler.debug.MethodFilter;
 import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.graph.Graph.Mark;
 import org.graalvm.compiler.graph.Node;
@@ -325,6 +327,7 @@
 import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.FullInfopointNode;
 import org.graalvm.compiler.nodes.IfNode;
+import org.graalvm.compiler.nodes.InliningLog;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.InvokeNode;
 import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
@@ -414,7 +417,7 @@
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.OptimisticOptimizations;
 import org.graalvm.compiler.phases.util.ValueMergeUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.code.BytecodeFrame;
@@ -454,11 +457,17 @@
 
     /**
      * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
-     * to trace the frame state before each bytecode instruction as it is parsed.
+     * to emit the frame state for each traced bytecode instruction.
      */
     public static final int TRACELEVEL_STATE = 2;
 
     /**
+     * The minimum value to which {@link BytecodeParserOptions#TraceBytecodeParserLevel} must be set
+     * to emit the block map for each traced method.
+     */
+    public static final int TRACELEVEL_BLOCKMAP = 3;
+
+    /**
      * Meters the number of actual bytecodes parsed.
      */
     public static final CounterKey BytecodesParsed = DebugContext.counter("BytecodesParsed");
@@ -681,6 +690,7 @@
     private ValueNode originalReceiver;
     private final boolean eagerInitializing;
     private final boolean uninitializedIsError;
+    private final int traceLevel;
 
     protected BytecodeParser(GraphBuilderPhase.Instance graphBuilderInstance, StructuredGraph graph, BytecodeParser parent, ResolvedJavaMethod method,
                     int entryBCI, IntrinsicContext intrinsicContext) {
@@ -714,12 +724,6 @@
 
         assert code.getCode() != null : "method must contain bytecodes: " + method;
 
-        if (TraceBytecodeParserLevel.getValue(options) != 0) {
-            if (!Assertions.assertionsEnabled()) {
-                throw new IllegalArgumentException("A non-zero " + TraceBytecodeParserLevel.getName() + " value requires assertions to be enabled");
-            }
-        }
-
         if (graphBuilderConfig.insertFullInfopoints() && !parsingIntrinsic()) {
             lnt = code.getLineNumberTable();
             previousLineNumber = -1;
@@ -729,6 +733,24 @@
         if (graphBuilderConfig.trackNodeSourcePosition() || (parent != null && parent.graph.trackNodeSourcePosition())) {
             graph.setTrackNodeSourcePosition();
         }
+
+        int level = TraceBytecodeParserLevel.getValue(options);
+        this.traceLevel = level != 0 ? refineTraceLevel(level) : 0;
+    }
+
+    private int refineTraceLevel(int level) {
+        ResolvedJavaMethod tmethod = graph.method();
+        if (tmethod == null) {
+            tmethod = method;
+        }
+        String filterValue = DebugOptions.MethodFilter.getValue(options);
+        if (filterValue != null) {
+            MethodFilter[] filters = MethodFilter.parse(filterValue);
+            if (!MethodFilter.matches(filters, tmethod)) {
+                return 0;
+            }
+        }
+        return level;
     }
 
     protected GraphBuilderPhase.Instance getGraphBuilderInstance() {
@@ -847,7 +869,7 @@
 
             currentBlock = blockMap.getStartBlock();
             setEntryState(startBlock, frameState);
-            if (startBlock.isLoopHeader) {
+            if (startBlock.isLoopHeader()) {
                 appendGoto(startBlock);
             } else {
                 setFirstInstruction(startBlock, lastInstr);
@@ -1676,6 +1698,7 @@
             targetMethod = originalMethod;
         }
         Invoke invoke = createNonInlinedInvoke(edgeAction, invokeBci, args, targetMethod, invokeKind, resultType, returnType, profile);
+        graph.getInliningLog().addDecision(invoke, false, "GraphBuilderPhase", null, null, "bytecode parser did not replace invoke");
         if (partialIntrinsicExit) {
             // This invoke must never be later inlined as it might select the intrinsic graph.
             // Until there is a mechanism to guarantee that any late inlining will not select
@@ -2172,60 +2195,80 @@
     }
 
     private boolean inline(ResolvedJavaMethod targetMethod, ResolvedJavaMethod inlinedMethod, BytecodeProvider intrinsicBytecodeProvider, ValueNode[] args) {
-        IntrinsicContext intrinsic = this.intrinsicContext;
-
-        if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() &&
-                        targetMethod.equals(inlinedMethod) &&
-                        (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 &&
-                        tryFastInlineAccessor(args, targetMethod)) {
-            return true;
-        }
-
-        if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
-            if (intrinsic.isCompilationRoot()) {
-                // A root compiled intrinsic needs to deoptimize
-                // if the slow path is taken. During frame state
-                // assignment, the deopt node will get its stateBefore
-                // from the start node of the intrinsic
-                append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
-                printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
+        try (InliningLog.RootScope scope = graph.getInliningLog().openRootScope(targetMethod, bci())) {
+            IntrinsicContext intrinsic = this.intrinsicContext;
+
+            if (intrinsic == null && !graphBuilderConfig.insertFullInfopoints() &&
+                            targetMethod.equals(inlinedMethod) &&
+                            (targetMethod.getModifiers() & (STATIC | SYNCHRONIZED)) == 0 &&
+                            tryFastInlineAccessor(args, targetMethod)) {
                 return true;
-            } else {
-                if (intrinsic.getOriginalMethod().isNative()) {
-                    printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
-                    return false;
-                }
-                if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
-                    // Otherwise inline the original method. Any frame state created
-                    // during the inlining will exclude frame(s) in the
-                    // intrinsic method (see FrameStateBuilder.create(int bci)).
-                    notifyBeforeInline(inlinedMethod);
-                    printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
-                    parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
-                    notifyAfterInline(inlinedMethod);
+            }
+
+            if (intrinsic != null && intrinsic.isCallToOriginal(targetMethod)) {
+                if (intrinsic.isCompilationRoot()) {
+                    // A root compiled intrinsic needs to deoptimize
+                    // if the slow path is taken. During frame state
+                    // assignment, the deopt node will get its stateBefore
+                    // from the start node of the intrinsic
+                    append(new DeoptimizeNode(InvalidateRecompile, RuntimeConstraint));
+                    printInlining(targetMethod, inlinedMethod, true, "compilation root (bytecode parsing)");
+                    if (scope != null) {
+                        graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "compilation root");
+                    }
                     return true;
                 } else {
-                    printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
+                    if (intrinsic.getOriginalMethod().isNative()) {
+                        printInlining(targetMethod, inlinedMethod, false, "native method (bytecode parsing)");
+                        if (scope != null) {
+                            graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "native method");
+                        }
+                        return false;
+                    }
+                    if (canInlinePartialIntrinsicExit() && InlinePartialIntrinsicExitDuringParsing.getValue(options)) {
+                        // Otherwise inline the original method. Any frame state created
+                        // during the inlining will exclude frame(s) in the
+                        // intrinsic method (see FrameStateBuilder.create(int bci)).
+                        notifyBeforeInline(inlinedMethod);
+                        printInlining(targetMethod, inlinedMethod, true, "partial intrinsic exit (bytecode parsing)");
+                        if (scope != null) {
+                            graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "partial intrinsic exit");
+                        }
+                        parseAndInlineCallee(intrinsic.getOriginalMethod(), args, null);
+                        notifyAfterInline(inlinedMethod);
+                        return true;
+                    } else {
+                        printInlining(targetMethod, inlinedMethod, false, "partial intrinsic exit (bytecode parsing)");
+                        if (scope != null) {
+                            graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "partial intrinsic exit");
+                        }
+                        return false;
+                    }
+                }
+            } else {
+                boolean isIntrinsic = intrinsicBytecodeProvider != null;
+                if (intrinsic == null && isIntrinsic) {
+                    assert !inlinedMethod.equals(targetMethod);
+                    intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
+                }
+                if (inlinedMethod.hasBytecodes()) {
+                    notifyBeforeInline(inlinedMethod);
+                    printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
+                    if (scope != null) {
+                        graph.getInliningLog().addDecision(scope.getInvoke(), true, "GraphBuilderPhase", null, null, "inline method");
+                    }
+                    parseAndInlineCallee(inlinedMethod, args, intrinsic);
+                    notifyAfterInline(inlinedMethod);
+                } else {
+                    printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
+                    if (scope != null) {
+                        graph.getInliningLog().addDecision(scope.getInvoke(), false, "GraphBuilderPhase", null, null, "no bytecodes (abstract or native)");
+                    }
                     return false;
                 }
             }
-        } else {
-            boolean isIntrinsic = intrinsicBytecodeProvider != null;
-            if (intrinsic == null && isIntrinsic) {
-                assert !inlinedMethod.equals(targetMethod);
-                intrinsic = new IntrinsicContext(targetMethod, inlinedMethod, intrinsicBytecodeProvider, INLINE_DURING_PARSING);
-            }
-            if (inlinedMethod.hasBytecodes()) {
-                notifyBeforeInline(inlinedMethod);
-                printInlining(targetMethod, inlinedMethod, true, "inline method (bytecode parsing)");
-                parseAndInlineCallee(inlinedMethod, args, intrinsic);
-                notifyAfterInline(inlinedMethod);
-            } else {
-                printInlining(targetMethod, inlinedMethod, false, "no bytecodes (abstract or native) (bytecode parsing)");
-                return false;
-            }
-        }
-        return true;
+            return true;
+        }
     }
 
     protected void notifyBeforeInline(ResolvedJavaMethod inlinedMethod) {
@@ -2700,7 +2743,7 @@
     @SuppressWarnings("try")
     private FixedNode createTarget(BciBlock block, FrameStateBuilder state, boolean canReuseInstruction, boolean canReuseState) {
         assert block != null && state != null;
-        assert !block.isExceptionEntry || state.stackSize() == 1;
+        assert !block.isExceptionEntry() || state.stackSize() == 1;
 
         try (DebugCloseable context = openNodeContext(state, block.startBci)) {
             if (getFirstInstruction(block) == null) {
@@ -2710,7 +2753,7 @@
                  * again.
                  */
                 FixedNode targetNode;
-                if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader && (currentBlock.loops & ~block.loops) == 0) {
+                if (canReuseInstruction && (block.getPredecessorCount() == 1 || !controlFlowSplit) && !block.isLoopHeader() && (currentBlock.loops & ~block.loops) == 0) {
                     setFirstInstruction(block, lastInstr);
                     lastInstr = null;
                 } else {
@@ -2729,11 +2772,11 @@
 
             // We already saw this block before, so we have to merge states.
             if (!getEntryState(block).isCompatibleWith(state)) {
-                throw bailout("stacks do not match; bytecodes would not verify");
+                throw bailout(String.format("stacks do not match on merge from %d into %s; bytecodes would not verify:%nexpect: %s%nactual: %s", bci(), block, getEntryState(block), state));
             }
 
             if (getFirstInstruction(block) instanceof LoopBeginNode) {
-                assert (block.isLoopHeader && currentBlock.getId() >= block.getId()) : "must be backward branch";
+                assert (block.isLoopHeader() && currentBlock.getId() >= block.getId()) : "must be backward branch";
                 /*
                  * Backward loop edge. We need to create a special LoopEndNode and merge with the
                  * loop begin node created before.
@@ -2820,7 +2863,7 @@
             debug.log("Ignoring block %s", block);
             return;
         }
-        try (Indent indent = debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, firstInstruction, block.isLoopHeader)) {
+        try (Indent indent = debug.logAndIndent("Parsing block %s  firstInstruction: %s  loopHeader: %b", block, firstInstruction, block.isLoopHeader())) {
 
             lastInstr = firstInstruction;
             frameState = getEntryState(block);
@@ -2949,11 +2992,11 @@
 
     @SuppressWarnings("try")
     protected void iterateBytecodesForBlock(BciBlock block) {
-        if (block.isLoopHeader) {
+        if (block.isLoopHeader()) {
             // Create the loop header block, which later will merge the backward branches of
             // the loop.
             controlFlowSplit = true;
-            LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr);
+            LoopBeginNode loopBegin = appendLoopBegin(this.lastInstr, block.startBci);
             lastInstr = loopBegin;
 
             // Create phi functions for all local variables and operand stack slots.
@@ -3007,8 +3050,9 @@
 
                 // read the opcode
                 int opcode = stream.currentBC();
-                assert traceState();
-                assert traceInstruction(bci, opcode, bci == block.startBci);
+                if (traceLevel != 0) {
+                    traceInstruction(bci, opcode, bci == block.startBci);
+                }
                 if (parent == null && bci == entryBCI) {
                     if (block.getJsrScope() != JsrScope.EMPTY_SCOPE) {
                         throw new JsrNotSupportedBailout("OSR into a JSR scope is not supported");
@@ -3038,7 +3082,7 @@
             lastInstr = finishInstruction(lastInstr, frameState);
             if (bci < endBCI) {
                 if (bci > block.endBci) {
-                    assert !block.getSuccessor(0).isExceptionEntry;
+                    assert !block.getSuccessor(0).isExceptionEntry();
                     assert block.numNormalSuccessors() == 1;
                     // we fell through to the next block, add a goto and break
                     appendGoto(block.getSuccessor(0));
@@ -3097,16 +3141,19 @@
         return parsingIntrinsic();
     }
 
-    private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext) {
-        EndNode preLoopEnd = graph.add(new EndNode());
-        LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
-        if (disableLoopSafepoint()) {
-            loopBegin.disableSafepoint();
-        }
-        fixedWithNext.setNext(preLoopEnd);
-        // Add the single non-loop predecessor of the loop header.
-        loopBegin.addForwardEnd(preLoopEnd);
-        return loopBegin;
+    @SuppressWarnings("try")
+    private LoopBeginNode appendLoopBegin(FixedWithNextNode fixedWithNext, int startBci) {
+        try (DebugCloseable context = openNodeContext(frameState, startBci)) {
+            EndNode preLoopEnd = graph.add(new EndNode());
+            LoopBeginNode loopBegin = graph.add(new LoopBeginNode());
+            if (disableLoopSafepoint()) {
+                loopBegin.disableSafepoint();
+            }
+            fixedWithNext.setNext(preLoopEnd);
+            // Add the single non-loop predecessor of the loop header.
+            loopBegin.addForwardEnd(preLoopEnd);
+            return loopBegin;
+        }
     }
 
     /**
@@ -3126,13 +3173,6 @@
         }
     }
 
-    private boolean traceState() {
-        if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_STATE) {
-            frameState.traceState();
-        }
-        return true;
-    }
-
     protected void genIf(ValueNode x, Condition cond, ValueNode y) {
         assert x.getStackKind() == y.getStackKind();
         assert currentBlock.getSuccessorCount() == 2;
@@ -3249,19 +3289,23 @@
             }
 
             if (isNeverExecutedCode(probability)) {
-                append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
-                if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
-                    profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
+                if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != trueBlock.startBci) {
+                    append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, true));
+                    if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
+                        profilingPlugin.profileGoto(this, method, bci(), falseBlock.startBci, stateBefore);
+                    }
+                    appendGoto(falseBlock);
+                    return;
                 }
-                appendGoto(falseBlock);
-                return;
             } else if (isNeverExecutedCode(1 - probability)) {
-                append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
-                if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
-                    profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
+                if (!graph.isOSR() || getParent() != null || graph.getEntryBCI() != falseBlock.startBci) {
+                    append(new FixedGuardNode(condition, UnreachedCode, InvalidateReprofile, false));
+                    if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
+                        profilingPlugin.profileGoto(this, method, bci(), trueBlock.startBci, stateBefore);
+                    }
+                    appendGoto(trueBlock);
+                    return;
                 }
-                appendGoto(trueBlock);
-                return;
             }
 
             if (profilingPlugin != null && profilingPlugin.shouldProfile(this, method)) {
@@ -4677,15 +4721,25 @@
         return frameState;
     }
 
-    protected boolean traceInstruction(int bci, int opcode, boolean blockStart) {
-        if (TraceBytecodeParserLevel.getValue(options) >= TRACELEVEL_INSTRUCTIONS) {
-            traceInstructionHelper(bci, opcode, blockStart);
-        }
-        return true;
-    }
-
-    private void traceInstructionHelper(int bci, int opcode, boolean blockStart) {
+    private boolean firstTraceEmitted;
+
+    protected void traceInstruction(int bci, int opcode, boolean blockStart) {
+        String indent = new String(new char[getDepth() * 2]).replace('\0', ' ');
         StringBuilder sb = new StringBuilder(40);
+        String nl = System.lineSeparator();
+        if (!firstTraceEmitted) {
+            sb.append(indent).append(method.format("Parsing %H.%n(%p)%r")).append(nl);
+            if (traceLevel >= TRACELEVEL_BLOCKMAP) {
+                sb.append(indent).append("Blocks:").append(nl);
+                String bm = blockMap.toString().replace(nl, nl + indent + "  ");
+                sb.append(indent).append("  ").append(bm).append(nl);
+            }
+            firstTraceEmitted = true;
+        }
+        if (traceLevel >= TRACELEVEL_STATE) {
+            sb.append(indent).append(frameState).append(nl);
+        }
+        sb.append(indent);
         sb.append(blockStart ? '+' : '|');
         if (bci < 10) {
             sb.append("  ");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/BytecodeParserOptions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,8 +35,10 @@
 public class BytecodeParserOptions {
     // @formatter:off
     @Option(help = "The trace level for the bytecode parser. A value of 1 enables instruction tracing " +
-                   "and any greater value emits a frame state trace just prior to an instruction trace. " +
-                   "This option requires assertions to be enabled.", type = OptionType.Debug)
+                   "and any greater value emits a frame state trace just prior to each instruction trace." +
+                   "Instruction tracing output from multiple compiler threads will be interleaved so " +
+                   "use of this option make most sense for single threaded compilation. " +
+                   "The MethodFilter option can be used to refine tracing to selected methods.", type = OptionType.Debug)
     public static final OptionKey<Integer> TraceBytecodeParserLevel = new OptionKey<>(0);
 
     @Option(help = "Inlines trivial methods during bytecode parsing.", type = OptionType.Expert)
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/ComputeLoopFrequenciesClosure.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractMergeNode;
 import org.graalvm.compiler.nodes.ControlSplitNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/FrameStateBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -46,7 +46,6 @@
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.StampPair;
 import org.graalvm.compiler.debug.DebugContext;
-import org.graalvm.compiler.debug.TTY;
 import org.graalvm.compiler.graph.NodeSourcePosition;
 import org.graalvm.compiler.java.BciBlockMapping.BciBlock;
 import org.graalvm.compiler.nodeinfo.Verbosity;
@@ -982,16 +981,4 @@
         }
         sideEffects.add(sideEffect);
     }
-
-    public void traceState() {
-        TTY.println("|   state [nr locals = %d, stack depth = %d, method = %s]", localsSize(), stackSize(), getMethod());
-        for (int i = 0; i < localsSize(); ++i) {
-            ValueNode value = locals[i];
-            TTY.println("|   local[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
-        }
-        for (int i = 0; i < stackSize(); ++i) {
-            ValueNode value = stack[i];
-            TTY.println("|   stack[%d] = %-8s : %s", i, value == null ? "bogus" : value == TWO_SLOT_MARKER ? "second" : value.getStackKind().getJavaName(), value);
-        }
-    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.java/src/org/graalvm/compiler/java/LocalLiveness.java	Thu Apr 26 17:59:02 2018 +0200
@@ -220,7 +220,7 @@
     protected abstract void storeOne(int blockID, int local);
 
     private void computeLocalLiveness(BytecodeStream stream, BciBlock block) {
-        if (block.startBci < 0 || block.endBci < 0) {
+        if (block.isExceptionDispatch()) {
             return;
         }
         int blockID = block.getId();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64ArrayCompareToOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.lir.aarch64;
+
+import static jdk.vm.ci.aarch64.AArch64.zr;
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+import static org.graalvm.compiler.lir.LIRInstruction.OperandFlag.REG;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.aarch64.AArch64Address;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler.ConditionFlag;
+import org.graalvm.compiler.core.common.LIRKind;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+import org.graalvm.compiler.lir.gen.LIRGeneratorTool;
+
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.JavaKind;
+import jdk.vm.ci.meta.Value;
+import sun.misc.Unsafe;
+
+/**
+ * Emits code which compares two arrays lexicographically. If the CPU supports any vector
+ * instructions specialized code is emitted to leverage these instructions.
+ */
+@Opcode("ARRAY_COMPARE_TO")
+public final class AArch64ArrayCompareToOp extends AArch64LIRInstruction {
+    public static final LIRInstructionClass<AArch64ArrayCompareToOp> TYPE = LIRInstructionClass.create(AArch64ArrayCompareToOp.class);
+
+    private final JavaKind kind1;
+    private final JavaKind kind2;
+
+    private final int array1BaseOffset;
+    private final int array2BaseOffset;
+
+    @Def({REG}) protected Value resultValue;
+
+    @Alive({REG}) protected Value array1Value;
+    @Alive({REG}) protected Value array2Value;
+    @Use({REG}) protected Value length1Value;
+    @Use({REG}) protected Value length2Value;
+    @Temp({REG}) protected Value length1ValueTemp;
+    @Temp({REG}) protected Value length2ValueTemp;
+
+    @Temp({REG}) protected Value temp1;
+    @Temp({REG}) protected Value temp2;
+    @Temp({REG}) protected Value temp3;
+    @Temp({REG}) protected Value temp4;
+    @Temp({REG}) protected Value temp5;
+    @Temp({REG}) protected Value temp6;
+
+    public AArch64ArrayCompareToOp(LIRGeneratorTool tool, JavaKind kind1, JavaKind kind2, Value result, Value array1, Value array2, Value length1, Value length2) {
+        super(TYPE);
+        this.kind1 = kind1;
+        this.kind2 = kind2;
+
+        // Both offsets should be the same but better be safe than sorry.
+        Class<?> array1Class = Array.newInstance(kind1.toJavaClass(), 0).getClass();
+        Class<?> array2Class = Array.newInstance(kind2.toJavaClass(), 0).getClass();
+        this.array1BaseOffset = UNSAFE.arrayBaseOffset(array1Class);
+        this.array2BaseOffset = UNSAFE.arrayBaseOffset(array2Class);
+
+        this.resultValue = result;
+
+        this.array1Value = array1;
+        this.array2Value = array2;
+
+        /*
+         * The length values are inputs but are also killed like temporaries so need both Use and
+         * Temp annotations, which will only work with fixed registers.
+         */
+
+        this.length1Value = length1;
+        this.length2Value = length2;
+        this.length1ValueTemp = length1;
+        this.length2ValueTemp = length2;
+
+        // Allocate some temporaries.
+        this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+        this.temp2 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+        this.temp3 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+        this.temp4 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+        this.temp5 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+        this.temp6 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
+    }
+
+    private static final Unsafe UNSAFE = initUnsafe();
+
+    private static Unsafe initUnsafe() {
+        try {
+            return Unsafe.getUnsafe();
+        } catch (SecurityException se) {
+            try {
+                Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+                theUnsafe.setAccessible(true);
+                return (Unsafe) theUnsafe.get(Unsafe.class);
+            } catch (Exception e) {
+                throw new RuntimeException("exception while trying to get Unsafe", e);
+            }
+        }
+    }
+
+    @Override
+    protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+
+        Register result = asRegister(resultValue);
+        Register length1 = asRegister(length1Value);
+        Register length2 = asRegister(length2Value);
+
+        Register array1 = asRegister(temp1);
+        Register array2 = asRegister(temp2);
+        Register length = asRegister(temp3);
+        Register temp = asRegister(temp4);
+        Register tailCount = asRegister(temp5);
+        Register vecCount = asRegister(temp6);
+
+        // Checkstyle: stop
+        final Label BREAK_LABEL = new Label();
+        final Label STRING_DIFFER_LABEL = new Label();
+        final Label LENGTH_DIFFER_LABEL = new Label();
+        final Label MAIN_LOOP_LABEL = new Label();
+        final Label COMPARE_SHORT_LABEL = new Label();
+        // Checkstyle: resume
+
+        // Checkstyle: stop
+        int CHAR_SIZE_BYTES = 1;
+        int VECTOR_SIZE_BYTES = 8;
+        int VECTOR_COUNT_BYTES = 8;
+        // Checkstyle: resume
+
+        // Byte is expanded to short if we compare strings with different encoding
+        if (kind1 != kind2 || kind1 == JavaKind.Char) {
+            CHAR_SIZE_BYTES = 2;
+        }
+
+        if (kind1 != kind2) {
+            VECTOR_COUNT_BYTES = 4;
+        }
+
+        // Load array base addresses.
+        masm.lea(array1, AArch64Address.createUnscaledImmediateAddress(asRegister(array1Value), array1BaseOffset));
+        masm.lea(array2, AArch64Address.createUnscaledImmediateAddress(asRegister(array2Value), array2BaseOffset));
+
+        // Calculate minimal length in chars for different kind case
+        // Conditions could be squashed but lets keep it readable
+        if (kind1 != kind2) {
+            masm.lshr(64, length2, length2, 1);
+        }
+
+        if (kind1 == kind2 && kind1 == JavaKind.Char) {
+            masm.lshr(64, length1, length1, 1);
+            masm.lshr(64, length2, length2, 1);
+        }
+
+        masm.cmp(64, length1, length2);
+        masm.cmov(64, length, length1, length2, ConditionFlag.LT);
+
+        // One of strings is empty
+        masm.cbz(64, length, LENGTH_DIFFER_LABEL);
+
+        // Go back to bytes if necessary
+        if (kind1 != kind2 || kind1 == JavaKind.Char) {
+            masm.shl(64, length, length, 1);
+        }
+
+        masm.mov(64, vecCount, zr);
+        masm.and(64, tailCount, length, VECTOR_SIZE_BYTES - 1); // tail count (in bytes)
+        masm.ands(64, length, length, ~(VECTOR_SIZE_BYTES - 1));  // vector count (in bytes)
+
+        // Length of string is less than VECTOR_SIZE, go to simple compare
+        masm.branchConditionally(ConditionFlag.EQ, COMPARE_SHORT_LABEL);
+
+        // MAIN_LOOP - read strings by 8 byte.
+        masm.bind(MAIN_LOOP_LABEL);
+        if (kind1 != kind2) {
+            // Load 32 bits ad unpack it to entire 64bit register
+            masm.ldr(32, result, AArch64Address.createRegisterOffsetAddress(array1, vecCount, false));
+            masm.ubfm(64, temp, result, 0, 7);
+            masm.lshr(64, result, result, 8);
+            masm.bfm(64, temp, result, 48, 7);
+            masm.lshr(64, result, result, 8);
+            masm.bfm(64, temp, result, 32, 7);
+            masm.lshr(64, result, result, 8);
+            masm.bfm(64, temp, result, 16, 7);
+            // Unpacked value placed in temp now
+
+            masm.shl(64, result, vecCount, 1);
+            masm.ldr(64, result, AArch64Address.createRegisterOffsetAddress(array2, result, false));
+        } else {
+            masm.ldr(64, temp, AArch64Address.createRegisterOffsetAddress(array1, vecCount, false));
+            masm.ldr(64, result, AArch64Address.createRegisterOffsetAddress(array2, vecCount, false));
+        }
+        masm.eor(64, result, temp, result);
+        masm.cbnz(64, result, STRING_DIFFER_LABEL);
+        masm.add(64, vecCount, vecCount, VECTOR_COUNT_BYTES);
+        masm.cmp(64, vecCount, length);
+        masm.branchConditionally(ConditionFlag.LT, MAIN_LOOP_LABEL);
+        // End of MAIN_LOOP
+
+        // Strings are equal and no TAIL go to END
+        masm.cbz(64, tailCount, LENGTH_DIFFER_LABEL);
+
+        // Compaire tail of long string ...
+        masm.lea(array1, AArch64Address.createRegisterOffsetAddress(array1, length, false));
+        masm.lea(array2, AArch64Address.createRegisterOffsetAddress(array2, length, false));
+
+        // ... or string less than vector length
+        masm.bind(COMPARE_SHORT_LABEL);
+        for (int i = 0; i < VECTOR_COUNT_BYTES; i += CHAR_SIZE_BYTES) {
+            if (kind1 != kind2) {
+                masm.ldr(8, temp, AArch64Address.createUnscaledImmediateAddress(array1, i / 2));
+            } else {
+                masm.ldr(8 * CHAR_SIZE_BYTES, temp, AArch64Address.createUnscaledImmediateAddress(array1, i));
+            }
+
+            masm.ldr(8 * CHAR_SIZE_BYTES, result, AArch64Address.createUnscaledImmediateAddress(array2, i));
+
+            if (kind1 != kind2 && kind1 == JavaKind.Char) {
+                // Weird swap of substraction order
+                masm.subs(64, result, result, temp);
+            } else {
+                masm.subs(64, result, temp, result);
+            }
+
+            masm.branchConditionally(ConditionFlag.NE, BREAK_LABEL);
+            masm.subs(64, tailCount, tailCount, CHAR_SIZE_BYTES);
+            masm.branchConditionally(ConditionFlag.EQ, LENGTH_DIFFER_LABEL);
+        }
+
+        // STRING_DIFFER extract exact value of a difference
+        masm.bind(STRING_DIFFER_LABEL);
+        masm.rbit(64, tailCount, result);
+        masm.clz(64, vecCount, tailCount);
+        masm.and(64, vecCount, vecCount, ~((8 * CHAR_SIZE_BYTES) - 1)); // Round to byte or short
+
+        masm.eor(64, result, temp, result);
+        masm.ashr(64, result, result, vecCount);
+        masm.ashr(64, temp, temp, vecCount);
+
+        masm.and(64, result, result, 0xFFFF >>> (16 - (8 * CHAR_SIZE_BYTES))); // 0xFF or 0xFFFF
+        masm.and(64, temp, temp, 0xFFFF >>> (16 - (8 * CHAR_SIZE_BYTES)));
+
+        masm.sub(64, result, temp, result);
+        masm.branchConditionally(ConditionFlag.AL, BREAK_LABEL);
+        // End of STRING_DIFFER
+
+        // Strings are equials up to length,
+        // return length difference in chars
+        masm.bind(LENGTH_DIFFER_LABEL);
+        if (kind1 != kind2 && kind1 == JavaKind.Char) {
+            // Weird swap of substraction order
+            masm.sub(64, result, length2, length1);
+        } else {
+            masm.sub(64, result, length1, length2);
+        }
+
+        // We are done
+        masm.bind(BREAK_LABEL);
+    }
+
+} // class
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64AtomicMove.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.lir.aarch64;
+
+import static jdk.vm.ci.code.ValueUtil.asRegister;
+
+import org.graalvm.compiler.asm.Label;
+import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
+import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
+import org.graalvm.compiler.lir.LIRInstructionClass;
+import org.graalvm.compiler.lir.Opcode;
+import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
+
+import jdk.vm.ci.aarch64.AArch64.CPUFeature;
+import jdk.vm.ci.aarch64.AArch64.Flag;
+import jdk.vm.ci.aarch64.AArch64Kind;
+import jdk.vm.ci.code.Register;
+import jdk.vm.ci.meta.AllocatableValue;
+import jdk.vm.ci.meta.Value;
+
+public class AArch64AtomicMove {
+    /**
+     * Compare and swap instruction. Does the following atomically: <code>
+     *  CAS(newVal, expected, address):
+     *    oldVal = *address
+     *    if oldVal == expected:
+     *        *address = newVal
+     *    return oldVal
+     * </code>
+     */
+    @Opcode("CAS")
+    public static class CompareAndSwapOp extends AArch64LIRInstruction {
+        public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
+
+        @Def protected AllocatableValue resultValue;
+        @Alive protected Value expectedValue;
+        @Alive protected AllocatableValue newValue;
+        @Alive protected AllocatableValue addressValue;
+        @Temp protected AllocatableValue scratchValue;
+
+        public CompareAndSwapOp(AllocatableValue result, Value expectedValue, AllocatableValue newValue, AllocatableValue addressValue, AllocatableValue scratch) {
+            super(TYPE);
+            this.resultValue = result;
+            this.expectedValue = expectedValue;
+            this.newValue = newValue;
+            this.addressValue = addressValue;
+            this.scratchValue = scratch;
+        }
+
+        @Override
+        public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
+            AArch64Kind kind = (AArch64Kind) expectedValue.getPlatformKind();
+            assert kind.isInteger();
+            final int size = kind.getSizeInBytes() * Byte.SIZE;
+
+            Register address = asRegister(addressValue);
+            Register result = asRegister(resultValue);
+            Register newVal = asRegister(newValue);
+             if (masm.supports(CPUFeature.LSE) || masm.isFlagSet(Flag.UseLSE)) {
+                Register expected = asRegister(expectedValue);
+                masm.mov(size, result, expected);
+                masm.cas(size, expected, newVal, address, true /*acquire*/, true /*release*/);
+                AArch64Compare.gpCompare(masm, resultValue, expectedValue);
+            } else {
+                // We could avoid using a scratch register here, by reusing resultValue for the stlxr
+                // success flag and issue a mov resultValue, expectedValue in case of success before
+                // returning.
+                Register scratch = asRegister(scratchValue);
+                Label retry = new Label();
+                Label fail = new Label();
+                masm.bind(retry);
+                masm.ldaxr(size, result, address);
+                AArch64Compare.gpCompare(masm, resultValue, expectedValue);
+                masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, fail);
+                masm.stlxr(size, scratch, newVal, address);
+                // if scratch == 0 then write successful, else retry.
+                masm.cbnz(32, scratch, retry);
+                masm.bind(fail);
+            }
+        }
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.aarch64/src/org/graalvm/compiler/lir/aarch64/AArch64Move.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,9 +37,7 @@
 import static jdk.vm.ci.code.ValueUtil.isRegister;
 import static jdk.vm.ci.code.ValueUtil.isStackSlot;
 
-import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.asm.aarch64.AArch64Address;
-import org.graalvm.compiler.asm.aarch64.AArch64Assembler;
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler;
 import org.graalvm.compiler.asm.aarch64.AArch64MacroAssembler.ScratchRegister;
 import org.graalvm.compiler.core.common.LIRKind;
@@ -339,60 +337,6 @@
         }
     }
 
-    /**
-     * Compare and swap instruction. Does the following atomically: <code>
-     *  CAS(newVal, expected, address):
-     *    oldVal = *address
-     *    if oldVal == expected:
-     *        *address = newVal
-     *    return oldVal
-     * </code>
-     */
-    @Opcode("CAS")
-    public static class CompareAndSwapOp extends AArch64LIRInstruction {
-        public static final LIRInstructionClass<CompareAndSwapOp> TYPE = LIRInstructionClass.create(CompareAndSwapOp.class);
-
-        @Def protected AllocatableValue resultValue;
-        @Alive protected Value expectedValue;
-        @Alive protected AllocatableValue newValue;
-        @Alive protected AllocatableValue addressValue;
-        @Temp protected AllocatableValue scratchValue;
-
-        public CompareAndSwapOp(AllocatableValue result, Value expectedValue, AllocatableValue newValue, AllocatableValue addressValue, AllocatableValue scratch) {
-            super(TYPE);
-            this.resultValue = result;
-            this.expectedValue = expectedValue;
-            this.newValue = newValue;
-            this.addressValue = addressValue;
-            this.scratchValue = scratch;
-        }
-
-        @Override
-        public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
-            AArch64Kind kind = (AArch64Kind) expectedValue.getPlatformKind();
-            assert kind.isInteger();
-            final int size = kind.getSizeInBytes() * Byte.SIZE;
-
-            Register address = asRegister(addressValue);
-            Register result = asRegister(resultValue);
-            Register newVal = asRegister(newValue);
-            Register scratch = asRegister(scratchValue);
-            // We could avoid using a scratch register here, by reusing resultValue for the stlxr
-            // success flag and issue a mov resultValue, expectedValue in case of success before
-            // returning.
-            Label retry = new Label();
-            Label fail = new Label();
-            masm.bind(retry);
-            masm.ldaxr(size, result, address);
-            AArch64Compare.gpCompare(masm, resultValue, expectedValue);
-            masm.branchConditionally(AArch64Assembler.ConditionFlag.NE, fail);
-            masm.stlxr(size, scratch, newVal, address);
-            // if scratch == 0 then write successful, else retry.
-            masm.cbnz(32, scratch, retry);
-            masm.bind(fail);
-        }
-    }
-
     private static void emitStore(@SuppressWarnings("unused") CompilationResultBuilder crb, AArch64MacroAssembler masm, AArch64Kind kind, AArch64Address dst, Value src) {
         int destSize = kind.getSizeInBytes() * Byte.SIZE;
         if (kind.isInteger()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ArrayCompareToOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -71,8 +71,10 @@
     @Def({REG}) protected Value resultValue;
     @Alive({REG}) protected Value array1Value;
     @Alive({REG}) protected Value array2Value;
-    @Alive({REG}) protected Value length1Value;
-    @Alive({REG}) protected Value length2Value;
+    @Use({REG}) protected Value length1Value;
+    @Use({REG}) protected Value length2Value;
+    @Temp({REG}) protected Value length1ValueTemp;
+    @Temp({REG}) protected Value length2ValueTemp;
     @Temp({REG}) protected Value temp1;
     @Temp({REG}) protected Value temp2;
 
@@ -92,8 +94,14 @@
         this.resultValue = result;
         this.array1Value = array1;
         this.array2Value = array2;
+        /*
+         * The length values are inputs but are also killed like temporaries so need both Use and
+         * Temp annotations, which will only work with fixed registers.
+         */
         this.length1Value = length1;
         this.length2Value = length2;
+        this.length1ValueTemp = length1;
+        this.length2ValueTemp = length2;
 
         // Allocate some temporaries.
         this.temp1 = tool.newVariable(LIRKind.unknownReference(tool.target().arch.getWordKind()));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64SaveRegistersOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
 
 import java.util.Arrays;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.LIRValueUtil;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.amd64/src/org/graalvm/compiler/lir/amd64/AMD64ZapRegistersOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.lir.amd64.AMD64SaveRegistersOp.prune;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.amd64.AMD64MacroAssembler;
 import org.graalvm.compiler.lir.LIRInstructionClass;
 import org.graalvm.compiler.lir.Opcode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCControlFlow.java	Thu Apr 26 17:59:02 2018 +0200
@@ -78,8 +78,8 @@
 import java.util.EnumSet;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.asm.Assembler.LabelHint;
 import org.graalvm.compiler.asm.Label;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.sparc/src/org/graalvm/compiler/lir/sparc/SPARCSaveRegistersOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 
 import java.util.Arrays;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.sparc.SPARCAddress;
 import org.graalvm.compiler.asm.sparc.SPARCMacroAssembler;
 import org.graalvm.compiler.lir.LIRInstructionClass;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir.test/src/org/graalvm/compiler/lir/test/alloc/trace/TraceGlobalMoveResolutionMappingTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
 
 import java.util.HashSet;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.lir.alloc.trace.ShadowedRegisterValue;
 import org.graalvm.compiler.lir.alloc.trace.TraceGlobalMoveResolutionPhase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/LIRIntrospection.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,9 +33,9 @@
 import java.util.Arrays;
 import java.util.EnumSet;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.core.common.FieldIntrospection;
 import org.graalvm.compiler.core.common.Fields;
 import org.graalvm.compiler.core.common.FieldsScanner;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/RedundantMoveElimination.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,8 +30,8 @@
 import java.util.Collections;
 import java.util.EnumSet;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.debug.CounterKey;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/StandardOp.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
 import java.util.ArrayList;
 import java.util.EnumSet;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.asm.Label;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.debug.GraalError;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/RegisterAllocationPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.lir.alloc;
+
+import org.graalvm.compiler.lir.phases.AllocationPhase;
+
+/**
+ * Marker class for register allocation phases.
+ */
+public abstract class RegisterAllocationPhase extends AllocationPhase {
+    private boolean neverSpillConstants;
+
+    public void setNeverSpillConstants(boolean neverSpillConstants) {
+        this.neverSpillConstants = neverSpillConstants;
+    }
+
+    public boolean getNeverSpillConstants() {
+        return neverSpillConstants;
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScan.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
 import java.util.BitSet;
 import java.util.EnumSet;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanLifetimeAnalysisPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,8 +35,8 @@
 import java.util.BitSet;
 import java.util.EnumSet;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.core.common.alloc.ComputeBlockOrder;
@@ -160,12 +160,14 @@
         intervalInLoop = new BitMap2D(allocator.operandSize(), allocator.numLoops());
 
         try {
+            final BitSet liveGenScratch = new BitSet(liveSize);
+            final BitSet liveKillScratch = new BitSet(liveSize);
             // iterate all blocks
             for (final AbstractBlockBase<?> block : allocator.sortedBlocks()) {
                 try (Indent indent = debug.logAndIndent("compute local live sets for block %s", block)) {
 
-                    final BitSet liveGen = new BitSet(liveSize);
-                    final BitSet liveKill = new BitSet(liveSize);
+                    liveGenScratch.clear();
+                    liveKillScratch.clear();
 
                     ArrayList<LIRInstruction> instructions = allocator.getLIR().getLIRforBlock(block);
                     int numInst = instructions.size();
@@ -173,8 +175,8 @@
                     ValueConsumer useConsumer = (operand, mode, flags) -> {
                         if (isVariable(operand)) {
                             int operandNum = allocator.operandNumber(operand);
-                            if (!liveKill.get(operandNum)) {
-                                liveGen.set(operandNum);
+                            if (!liveKillScratch.get(operandNum)) {
+                                liveGenScratch.set(operandNum);
                                 if (debug.isLogEnabled()) {
                                     debug.log("liveGen for operand %d(%s)", operandNum, operand);
                                 }
@@ -185,14 +187,14 @@
                         }
 
                         if (allocator.detailedAsserts) {
-                            verifyInput(block, liveKill, operand);
+                            verifyInput(block, liveKillScratch, operand);
                         }
                     };
                     ValueConsumer stateConsumer = (operand, mode, flags) -> {
                         if (LinearScan.isVariableOrRegister(operand)) {
                             int operandNum = allocator.operandNumber(operand);
-                            if (!liveKill.get(operandNum)) {
-                                liveGen.set(operandNum);
+                            if (!liveKillScratch.get(operandNum)) {
+                                liveGenScratch.set(operandNum);
                                 if (debug.isLogEnabled()) {
                                     debug.log("liveGen in state for operand %d(%s)", operandNum, operand);
                                 }
@@ -202,7 +204,7 @@
                     ValueConsumer defConsumer = (operand, mode, flags) -> {
                         if (isVariable(operand)) {
                             int varNum = allocator.operandNumber(operand);
-                            liveKill.set(varNum);
+                            liveKillScratch.set(varNum);
                             if (debug.isLogEnabled()) {
                                 debug.log("liveKill for operand %d(%s)", varNum, operand);
                             }
@@ -217,7 +219,7 @@
                              * be processed in live sets. Process them only in debug mode so that
                              * this can be checked
                              */
-                            verifyTemp(liveKill, operand);
+                            verifyTemp(liveKillScratch, operand);
                         }
                     };
 
@@ -239,10 +241,11 @@
                     } // end of instruction iteration
 
                     BlockData blockSets = allocator.getBlockData(block);
-                    blockSets.liveGen = liveGen;
-                    blockSets.liveKill = liveKill;
-                    blockSets.liveIn = new BitSet(liveSize);
-                    blockSets.liveOut = new BitSet(liveSize);
+                    blockSets.liveGen = trimClone(liveGenScratch);
+                    blockSets.liveKill = trimClone(liveKillScratch);
+                    // sticky size, will get non-sticky in computeGlobalLiveSets
+                    blockSets.liveIn = new BitSet(0);
+                    blockSets.liveOut = new BitSet(0);
 
                     if (debug.isLogEnabled()) {
                         debug.log("liveGen  B%d %s", block.getId(), blockSets.liveGen);
@@ -292,7 +295,7 @@
             boolean changeOccurred;
             boolean changeOccurredInBlock;
             int iterationCount = 0;
-            BitSet liveOut = new BitSet(allocator.liveSetSize()); // scratch set for calculations
+            BitSet scratch = new BitSet(allocator.liveSetSize()); // scratch set for calculations
 
             /*
              * Perform a backward dataflow analysis to compute liveOut and liveIn for each block.
@@ -315,22 +318,16 @@
                          */
                         int n = block.getSuccessorCount();
                         if (n > 0) {
-                            liveOut.clear();
+                            scratch.clear();
                             // block has successors
                             if (n > 0) {
                                 for (AbstractBlockBase<?> successor : block.getSuccessors()) {
-                                    liveOut.or(allocator.getBlockData(successor).liveIn);
+                                    scratch.or(allocator.getBlockData(successor).liveIn);
                                 }
                             }
 
-                            if (!blockSets.liveOut.equals(liveOut)) {
-                                /*
-                                 * A change occurred. Swap the old and new live out sets to avoid
-                                 * copying.
-                                 */
-                                BitSet temp = blockSets.liveOut;
-                                blockSets.liveOut = liveOut;
-                                liveOut = temp;
+                            if (!blockSets.liveOut.equals(scratch)) {
+                                blockSets.liveOut = trimClone(scratch);
 
                                 changeOccurred = true;
                                 changeOccurredInBlock = true;
@@ -344,13 +341,20 @@
                              *
                              * Note: liveIn has to be computed only in first iteration or if liveOut
                              * has changed!
+                             *
+                             * Note: liveIn set can only grow, never shrink. No need to clear it.
                              */
                             BitSet liveIn = blockSets.liveIn;
-                            liveIn.clear();
+                            /*
+                             * BitSet#or will call BitSet#ensureSize (since the bit set is of length
+                             * 0 initially) and set sticky to false
+                             */
                             liveIn.or(blockSets.liveOut);
                             liveIn.andNot(blockSets.liveKill);
                             liveIn.or(blockSets.liveGen);
 
+                            liveIn.clone(); // trimToSize()
+
                             if (debug.isLogEnabled()) {
                                 debug.log("block %d: livein = %s,  liveout = %s", block.getId(), liveIn, blockSets.liveOut);
                             }
@@ -384,6 +388,20 @@
         }
     }
 
+    /**
+     * Creates a trimmed copy a bit set.
+     *
+     * {@link BitSet#clone()} cannot be used since it will not {@linkplain BitSet#trimToSize trim}
+     * the array if the bit set is {@linkplain BitSet#sizeIsSticky sticky}.
+     */
+    @SuppressWarnings("javadoc")
+    private static BitSet trimClone(BitSet set) {
+        BitSet trimmedSet = new BitSet(0); // zero-length words array, sticky
+        trimmedSet.or(set); // words size ensured to be words-in-use of set,
+                            // also makes it non-sticky
+        return trimmedSet;
+    }
+
     @SuppressWarnings("try")
     protected void reportFailure(int numBlocks) {
         try (DebugContext.Scope s = debug.forceLog()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,26 +23,20 @@
 package org.graalvm.compiler.lir.alloc.lsra;
 
 import org.graalvm.compiler.core.common.alloc.RegisterAllocationConfig;
+import org.graalvm.compiler.lir.alloc.RegisterAllocationPhase;
 import org.graalvm.compiler.lir.alloc.lsra.ssa.SSALinearScan;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
-import org.graalvm.compiler.lir.phases.AllocationPhase;
 
 import jdk.vm.ci.code.TargetDescription;
 
-public final class LinearScanPhase extends AllocationPhase {
-
-    private boolean neverSpillConstants;
-
-    public void setNeverSpillConstants(boolean neverSpillConstants) {
-        this.neverSpillConstants = neverSpillConstants;
-    }
+public final class LinearScanPhase extends RegisterAllocationPhase {
 
     @Override
     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
         MoveFactory spillMoveFactory = context.spillMoveFactory;
         RegisterAllocationConfig registerAllocationConfig = context.registerAllocationConfig;
-        final LinearScan allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig, lirGenRes.getLIR().linearScanOrder(), neverSpillConstants);
+        final LinearScan allocator = new SSALinearScan(target, lirGenRes, spillMoveFactory, registerAllocationConfig, lirGenRes.getLIR().linearScanOrder(), getNeverSpillConstants());
         allocator.allocate(target, lirGenRes, context);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/LinearScanRegisterAllocationPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.lir.alloc.lsra;
 
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.debug.Indent;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/lsra/MoveResolver.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
 
 import java.util.ArrayList;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.LIRKind;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/alloc/trace/TraceRegisterAllocationPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.Indent;
 import org.graalvm.compiler.lir.LIR;
+import org.graalvm.compiler.lir.alloc.RegisterAllocationPhase;
 import org.graalvm.compiler.lir.alloc.trace.TraceAllocationPhase.TraceAllocationContext;
 import org.graalvm.compiler.lir.gen.LIRGenerationResult;
 import org.graalvm.compiler.lir.gen.LIRGeneratorTool.MoveFactory;
-import org.graalvm.compiler.lir.phases.AllocationPhase;
 import org.graalvm.compiler.lir.ssa.SSAUtil;
 import org.graalvm.compiler.options.Option;
 import org.graalvm.compiler.options.OptionKey;
@@ -47,7 +47,7 @@
  * <a href="http://dx.doi.org/10.1145/2972206.2972211">"Trace-based Register Allocation in a JIT
  * Compiler"</a> by Josef Eisl et al.
  */
-public final class TraceRegisterAllocationPhase extends AllocationPhase {
+public final class TraceRegisterAllocationPhase extends RegisterAllocationPhase {
 
     public static class Options {
         // @formatter:off
@@ -67,9 +67,20 @@
     public static final CounterKey globalStackSlots = DebugContext.counter("TraceRA[GlobalStackSlots]");
     public static final CounterKey allocatedStackSlots = DebugContext.counter("TraceRA[AllocatedStackSlots]");
 
+    private final TraceBuilderPhase traceBuilder;
+    private final GlobalLivenessAnalysisPhase livenessAnalysis;
+
+    public TraceRegisterAllocationPhase() {
+        this.traceBuilder = new TraceBuilderPhase();
+        this.livenessAnalysis = new GlobalLivenessAnalysisPhase();
+    }
+
     @Override
     @SuppressWarnings("try")
     protected void run(TargetDescription target, LIRGenerationResult lirGenRes, AllocationContext context) {
+        traceBuilder.apply(target, lirGenRes, context);
+        livenessAnalysis.apply(target, lirGenRes, context);
+
         MoveFactory spillMoveFactory = context.spillMoveFactory;
         RegisterAllocationConfig registerAllocationConfig = context.registerAllocationConfig;
         LIR lir = lirGenRes.getLIR();
@@ -80,8 +91,8 @@
         TraceAllocationContext traceContext = new TraceAllocationContext(spillMoveFactory, registerAllocationConfig, resultTraces, livenessInfo);
         AllocatableValue[] cachedStackSlots = Options.TraceRACacheStackSlots.getValue(lir.getOptions()) ? new AllocatableValue[lir.numVariables()] : null;
 
-        // currently this is not supported
-        boolean neverSpillConstant = false;
+        boolean neverSpillConstant = getNeverSpillConstants();
+        assert !neverSpillConstant : "currently this is not supported";
 
         final TraceRegisterAllocationPolicy plan = DefaultTraceRegisterAllocationPolicy.allocationPolicy(target, lirGenRes, spillMoveFactory, registerAllocationConfig, cachedStackSlots, resultTraces,
                         neverSpillConstant, livenessInfo, lir.getOptions());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/asm/CompilationResultBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
 import java.util.List;
 import java.util.function.Consumer;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.asm.AbstractAddress;
 import org.graalvm.compiler.asm.Assembler;
 import org.graalvm.compiler.code.CompilationResult;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/LIRGenerationResult.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
  */
 package org.graalvm.compiler.lir.gen;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.CompilationIdentifier.Verbosity;
 import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/gen/PhiResolver.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,8 +30,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.lir.LIRInsertionBuffer;
 import org.graalvm.compiler.lir.LIRInstruction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/AllocationStage.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/AllocationStage.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,6 @@
 import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.lir.alloc.AllocationStageVerifier;
 import org.graalvm.compiler.lir.alloc.lsra.LinearScanPhase;
-import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase;
-import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase;
 import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase;
 import org.graalvm.compiler.lir.dfa.LocationMarkerPhase;
 import org.graalvm.compiler.lir.dfa.MarkBasePointersPhase;
@@ -42,8 +40,6 @@
     public AllocationStage(OptionValues options) {
         appendPhase(new MarkBasePointersPhase());
         if (TraceRA.getValue(options)) {
-            appendPhase(new TraceBuilderPhase());
-            appendPhase(new GlobalLivenessAnalysisPhase());
             appendPhase(new TraceRegisterAllocationPhase());
         } else {
             appendPhase(new LinearScanPhase());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyAllocationStage.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/phases/EconomyAllocationStage.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,6 @@
 import static org.graalvm.compiler.core.common.GraalOptions.TraceRA;
 
 import org.graalvm.compiler.lir.alloc.lsra.LinearScanPhase;
-import org.graalvm.compiler.lir.alloc.trace.GlobalLivenessAnalysisPhase;
-import org.graalvm.compiler.lir.alloc.trace.TraceBuilderPhase;
 import org.graalvm.compiler.lir.alloc.trace.TraceRegisterAllocationPhase;
 import org.graalvm.compiler.lir.dfa.LocationMarkerPhase;
 import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
@@ -36,8 +34,6 @@
 public class EconomyAllocationStage extends LIRPhaseSuite<AllocationContext> {
     public EconomyAllocationStage(OptionValues options) {
         if (TraceRA.getValue(options)) {
-            appendPhase(new TraceBuilderPhase());
-            appendPhase(new GlobalLivenessAnalysisPhase());
             appendPhase(new TraceRegisterAllocationPhase());
         } else {
             appendPhase(new LinearScanPhase());
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/FixPointIntervalBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,8 +31,8 @@
 import java.util.Deque;
 import java.util.EnumSet;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.debug.CounterKey;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/stackslotalloc/LSStackSlotAllocator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
 import java.util.EnumSet;
 import java.util.PriorityQueue;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.cfg.AbstractBlockBase;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.lir/src/org/graalvm/compiler/lir/util/GenericValueMap.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
  */
 package org.graalvm.compiler.lir.util;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 
 import jdk.vm.ci.meta.Value;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/CountedLoopInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,7 @@
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.util.UnsignedLong;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.loop.InductionVariable.Direction;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.ConstantNode;
@@ -223,34 +224,37 @@
         return loop.loopBegin().getOverflowGuard();
     }
 
+    @SuppressWarnings("try")
     public GuardingNode createOverFlowGuard() {
         GuardingNode overflowGuard = getOverFlowGuard();
         if (overflowGuard != null) {
             return overflowGuard;
         }
-        IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT);
-        StructuredGraph graph = iv.valueNode().graph();
-        CompareNode cond; // we use a negated guard with a < condition to achieve a >=
-        ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
-        if (iv.direction() == Direction.Up) {
-            ValueNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
-            if (oneOff) {
-                v1 = sub(graph, v1, one);
+        try (DebugCloseable position = loop.loopBegin().withNodeSourcePosition()) {
+            IntegerStamp stamp = (IntegerStamp) iv.valueNode().stamp(NodeView.DEFAULT);
+            StructuredGraph graph = iv.valueNode().graph();
+            CompareNode cond; // we use a negated guard with a < condition to achieve a >=
+            ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph);
+            if (iv.direction() == Direction.Up) {
+                ValueNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one));
+                if (oneOff) {
+                    v1 = sub(graph, v1, one);
+                }
+                cond = graph.unique(new IntegerLessThanNode(v1, end));
+            } else {
+                assert iv.direction() == Direction.Down;
+                ValueNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
+                if (oneOff) {
+                    v1 = add(graph, v1, one);
+                }
+                cond = graph.unique(new IntegerLessThanNode(end, v1));
             }
-            cond = graph.unique(new IntegerLessThanNode(v1, end));
-        } else {
-            assert iv.direction() == Direction.Down;
-            ValueNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode()));
-            if (oneOff) {
-                v1 = add(graph, v1, one);
-            }
-            cond = graph.unique(new IntegerLessThanNode(end, v1));
+            assert graph.getGuardsStage().allowsFloatingGuards();
+            overflowGuard = graph.unique(new GuardNode(cond, AbstractBeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
+                            JavaConstant.NULL_POINTER)); // TODO gd: use speculation
+            loop.loopBegin().setOverflowGuard(overflowGuard);
+            return overflowGuard;
         }
-        assert graph.getGuardsStage().allowsFloatingGuards();
-        overflowGuard = graph.unique(new GuardNode(cond, AbstractBeginNode.prevBegin(loop.entryPoint()), DeoptimizationReason.LoopLimitCheck, DeoptimizationAction.InvalidateRecompile, true,
-                        JavaConstant.NULL_POINTER)); // TODO gd: use speculation
-        loop.loopBegin().setOverflowGuard(overflowGuard);
-        return overflowGuard;
     }
 
     public IntegerStamp getStamp() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopEx.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,9 +26,9 @@
 import java.util.LinkedList;
 import java.util.Queue;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragment.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
 import java.util.Deque;
 import java.util.Iterator;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Graph.DuplicationReplacement;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentInside.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import java.util.LinkedList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopFragmentWhole.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.loop;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.Graph;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.loop/src/org/graalvm/compiler/loop/LoopsData.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,9 +27,9 @@
 import java.util.LinkedList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.nodes.LoopBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/EncodedGraph.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.NodeClass;
 
 import jdk.vm.ci.meta.Assumptions;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FieldLocationIdentity.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/FieldLocationIdentity.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import jdk.vm.ci.meta.JavaKind.FormatWithToString;
 
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ResolvedJavaField;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphDecoder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,9 +37,9 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.Fields;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.core.common.util.TypeReader;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphEncoder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
 import java.util.Iterator;
 import java.util.Objects;
 
-import org.graalvm.collections.Pair;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.core.common.Fields;
 import org.graalvm.compiler.core.common.util.FrequencyEncoder;
 import org.graalvm.compiler.core.common.util.TypeConversion;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/GraphSpeculationLog.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2018, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package org.graalvm.compiler.nodes;
+
+import jdk.internal.vm.compiler.collections.EconomicMap;
+
+import jdk.vm.ci.meta.JavaConstant;
+import jdk.vm.ci.meta.SpeculationLog;
+
+/**
+ * A wrapper around a {@link SpeculationLog} instance.
+ *
+ * This should be used when the wrapped instance may be accessed by multiple threads. Due to races,
+ * such an instance can return true for a call to {@link SpeculationLog#maySpeculate} but still fail
+ * (i.e. raise an {@link IllegalArgumentException}) when {@link SpeculationLog#speculate} is called.
+ *
+ * A {@link GraphSpeculationLog} must only be used by a single thread and is typically closely
+ * coupled with a {@link StructuredGraph} (hence the name).
+ */
+public final class GraphSpeculationLog implements SpeculationLog {
+
+    private final SpeculationLog log;
+    private final EconomicMap<SpeculationReason, JavaConstant> speculations;
+
+    public GraphSpeculationLog(SpeculationLog log) {
+        this.log = log;
+        this.speculations = EconomicMap.create();
+    }
+
+    /**
+     * Unwraps {@code log} if it is a {@link GraphSpeculationLog}.
+     */
+    public static SpeculationLog unwrap(SpeculationLog log) {
+        if (log instanceof GraphSpeculationLog) {
+            return ((GraphSpeculationLog) log).log;
+        }
+        return log;
+    }
+
+    /**
+     * Determines if the compiler is allowed to speculate with {@code reason}. Note that a
+     * {@code true} return value guarantees that a subsequent call to
+     * {@link #speculate(SpeculationReason)} with an argument {@linkplain Object#equals(Object)
+     * equal} to {@code reason} will succeed.
+     */
+    @Override
+    public boolean maySpeculate(SpeculationReason reason) {
+        JavaConstant speculation = speculations.get(reason);
+        if (speculation == null) {
+            if (log.maySpeculate(reason)) {
+                try {
+                    speculation = log.speculate(reason);
+                    speculations.put(reason, speculation);
+                } catch (IllegalArgumentException e) {
+                    // The speculation was disabled by another thread in between
+                    // the call to log.maySpeculate and log.speculate
+                    speculation = null;
+                }
+            }
+        }
+        return speculation != null;
+    }
+
+    @Override
+    public JavaConstant speculate(SpeculationReason reason) {
+        if (maySpeculate(reason)) {
+            JavaConstant speculation = speculations.get(reason);
+            assert speculation != null;
+            return speculation;
+        }
+        throw new IllegalArgumentException("Cannot make speculation with reason " + reason + " as it is known to fail");
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj instanceof GraphSpeculationLog) {
+            GraphSpeculationLog that = (GraphSpeculationLog) obj;
+            return this.log == that.log;
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return log.hashCode();
+    }
+
+    @Override
+    public void collectFailedSpeculations() {
+        log.collectFailedSpeculations();
+    }
+
+    /**
+     * Returns if this log has speculations.
+     *
+     * @return true if {@link #maySpeculate(SpeculationReason)} has ever returned {@code true} for
+     *         this object
+     */
+    @Override
+    public boolean hasSpeculations() {
+        return !speculations.isEmpty();
+    }
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/IfNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,8 +30,8 @@
 import java.util.Iterator;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.calc.Condition;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InliningLog.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,14 +24,12 @@
 
 import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.compiler.core.common.GraalOptions;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.options.OptionValues;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -56,6 +54,8 @@
  * {@link #addDecision} to log negative decisions.
  */
 public class InliningLog {
+    private static final String TREE_NODE = "\u251c\u2500\u2500";
+    private static final String LAST_TREE_NODE = "\u2514\u2500\u2500";
 
     public static final class Decision {
         private final boolean positive;
@@ -88,7 +88,8 @@
 
         @Override
         public String toString() {
-            return String.format("<%s> %s: %s", phase, target != null ? target.format("%H.%n(%p)") : "", reason);
+            return String.format("<%s> %s: %s, %s", phase, target != null ? target.format("%H.%n(%p)") : "", positive ? "yes" : "no",
+                            reason);
         }
     }
 
@@ -114,9 +115,9 @@
 
         public String positionString() {
             if (parent == null) {
-                return "<root>";
+                return "compilation of " + target.format("%H.%n(%p)");
             }
-            return MetaUtil.appendLocation(new StringBuilder(100), parent.target, getBci()).toString();
+            return "at " + MetaUtil.appendLocation(new StringBuilder(100), parent.target, getBci()).toString();
         }
 
         public int getBci() {
@@ -126,13 +127,13 @@
 
     private final Callsite root;
     private final EconomicMap<Invokable, Callsite> leaves;
-    private final OptionValues options;
+    private final boolean enabled;
 
-    public InliningLog(ResolvedJavaMethod rootMethod, OptionValues options) {
+    public InliningLog(ResolvedJavaMethod rootMethod, boolean enabled) {
         this.root = new Callsite(null, null);
         this.root.target = rootMethod;
         this.leaves = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE);
-        this.options = options;
+        this.enabled = enabled;
     }
 
     /**
@@ -142,15 +143,22 @@
      * logged after replacing an {@link Invoke} with a graph. In this case, the node replacement map
      * and the {@link InliningLog} of the inlined graph must be provided.
      */
-    public void addDecision(Invokable invoke, boolean positive, String reason, String phase, EconomicMap<Node, Node> replacements, InliningLog calleeLog) {
+    public void addDecision(Invokable invoke, boolean positive, String phase, EconomicMap<Node, Node> replacements, InliningLog calleeLog, String reason, Object... args) {
+        if (!enabled) {
+            return;
+        }
         assert leaves.containsKey(invoke);
-        assert (!positive && replacements == null && calleeLog == null) || (positive && replacements != null && calleeLog != null);
+        assert (!positive && replacements == null && calleeLog == null) || (positive && replacements != null && calleeLog != null) ||
+                        (positive && replacements == null && calleeLog == null);
         Callsite callsite = leaves.get(invoke);
         callsite.target = callsite.invoke.getTargetMethod();
-        Decision decision = new Decision(positive, reason, phase, invoke.getTargetMethod());
+        Decision decision = new Decision(positive, String.format(reason, args), phase, invoke.getTargetMethod());
         callsite.decisions.add(decision);
         if (positive) {
             leaves.removeKey(invoke);
+            if (calleeLog == null) {
+                return;
+            }
             EconomicMap<Callsite, Callsite> mapping = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE);
             for (Callsite calleeChild : calleeLog.root.children) {
                 Callsite child = callsite.addChild(calleeChild.invoke);
@@ -227,7 +235,7 @@
         mapping.put(replacementSite, site);
         site.target = replacementSite.target;
         site.decisions.addAll(replacementSite.decisions);
-        site.invoke = replacementSite.invoke != null && replacementSite.invoke.asFixedNode().isAlive() ? (Invokable) replacements.get(replacementSite.invoke.asFixedNode()) : null;
+        site.invoke = replacementSite.invoke != null && replacementSite.invoke.isAlive() ? (Invokable) replacements.get(replacementSite.invoke.asFixedNode()) : null;
         for (Callsite replacementChild : replacementSite.children) {
             Callsite child = new Callsite(site, null);
             site.children.add(child);
@@ -253,7 +261,7 @@
     private UpdateScope noUpdates = new UpdateScope((oldNode, newNode) -> {
     });
 
-    private UpdateScope activated = null;
+    private UpdateScope currentUpdateScope = null;
 
     /**
      * Used to designate scopes in which {@link Invokable} registration or cloning should be handled
@@ -267,17 +275,17 @@
         }
 
         public void activate() {
-            if (activated != null) {
+            if (currentUpdateScope != null) {
                 throw GraalError.shouldNotReachHere("InliningLog updating already set.");
             }
-            activated = this;
+            currentUpdateScope = this;
         }
 
         @Override
         public void close() {
-            if (GraalOptions.TraceInlining.getValue(options)) {
-                assert activated != null;
-                activated = null;
+            if (enabled) {
+                assert currentUpdateScope != null;
+                currentUpdateScope = null;
             }
         }
 
@@ -287,10 +295,10 @@
     }
 
     public BiConsumer<Invokable, Invokable> getUpdateScope() {
-        if (activated == null) {
+        if (currentUpdateScope == null) {
             return null;
         }
-        return activated.getUpdater();
+        return currentUpdateScope.getUpdater();
     }
 
     /**
@@ -305,7 +313,7 @@
      * @return a bound {@link UpdateScope} object, or a {@code null} if tracing is disabled
      */
     public UpdateScope openUpdateScope(BiConsumer<Invokable, Invokable> updater) {
-        if (GraalOptions.TraceInlining.getValue(options)) {
+        if (enabled) {
             UpdateScope scope = new UpdateScope(updater);
             scope.activate();
             return scope;
@@ -324,7 +332,7 @@
      * @see #openUpdateScope
      */
     public UpdateScope openDefaultUpdateScope() {
-        if (GraalOptions.TraceInlining.getValue(options)) {
+        if (enabled) {
             noUpdates.activate();
             return noUpdates;
         } else {
@@ -332,6 +340,97 @@
         }
     }
 
+    private RootScope currentRootScope = null;
+
+    /**
+     * Used to change the current effective root of the method being compiled.
+     *
+     * This root scope is used in situations in which a phase does its own ad-hoc inlining, in which
+     * it replaces an Invoke with other nodes, some of which may be other Invokes. The prime example
+     * for this is the bytecode parser, which does not create separate graphs with their own
+     * inlining logs when inlining an Invoke, but instead continues recursively parsing the graph
+     * corresponding to the Invoke.
+     *
+     * Root scopes can be nested.
+     *
+     * @see #openRootScope
+     */
+    public final class RootScope implements AutoCloseable {
+        private final RootScope parent;
+        private Callsite replacementRoot;
+
+        public RootScope(RootScope parent, Callsite replacementRoot) {
+            this.parent = parent;
+            this.replacementRoot = replacementRoot;
+        }
+
+        void activate() {
+            currentRootScope = this;
+        }
+
+        public Invokable getInvoke() {
+            return replacementRoot.invoke;
+        }
+
+        @Override
+        public void close() {
+            if (enabled) {
+                assert currentRootScope != null;
+                removeLeafCallsite(replacementRoot.invoke);
+                currentRootScope = parent;
+            }
+        }
+    }
+
+    public final class PlaceholderInvokable implements Invokable {
+        private int bci;
+        private ResolvedJavaMethod method;
+
+        public PlaceholderInvokable(ResolvedJavaMethod method, int bci) {
+            this.method = method;
+            this.bci = bci;
+        }
+
+        @Override
+        public ResolvedJavaMethod getTargetMethod() {
+            return method;
+        }
+
+        @Override
+        public int bci() {
+            return bci;
+        }
+
+        @Override
+        public boolean isAlive() {
+            return false;
+        }
+
+        @Override
+        public FixedNode asFixedNode() {
+            throw new UnsupportedOperationException("Parsed invokable is a placeholder, not a concrete node.");
+        }
+    }
+
+    public RootScope openRootScope(ResolvedJavaMethod target, int bci) {
+        return openRootScope(new PlaceholderInvokable(target, bci));
+    }
+
+    public RootScope openRootScope(Invokable invoke) {
+        if (enabled) {
+            if (!leaves.containsKey(invoke)) {
+                // Create the invoke if it was not added to the graph yet.
+                trackNewCallsite(invoke);
+            }
+            RootScope scope = new RootScope(currentRootScope, leaves.get(invoke));
+            scope.replacementRoot.target = invoke.getTargetMethod();
+            scope.activate();
+            return scope;
+        } else {
+            return null;
+        }
+    }
+
     public boolean containsLeafCallsite(Invokable invokable) {
         return leaves.containsKey(invokable);
     }
@@ -342,11 +441,16 @@
 
     public void trackNewCallsite(Invokable invoke) {
         assert !leaves.containsKey(invoke);
-        Callsite callsite = new Callsite(root, invoke);
-        root.children.add(callsite);
+        Callsite currentRoot = findCurrentRoot();
+        Callsite callsite = new Callsite(currentRoot, invoke);
+        currentRoot.children.add(callsite);
         leaves.put(invoke, callsite);
     }
 
+    private Callsite findCurrentRoot() {
+        return currentRootScope != null ? currentRootScope.replacementRoot : root;
+    }
+
     public void trackDuplicatedCallsite(Invokable sibling, Invokable newInvoke) {
         Callsite siblingCallsite = leaves.get(sibling);
         Callsite parentCallsite = siblingCallsite.parent;
@@ -361,7 +465,19 @@
         callsite.invoke = newInvoke;
     }
 
-    public String formatAsTree() {
+    /**
+     * Formats the inlining log as a hierarchical tree.
+     *
+     * @param nullIfEmpty specifies whether null should be returned if there are no inlining
+     *            decisions
+     * @return the tree representation of the inlining log
+     */
+    public String formatAsTree(boolean nullIfEmpty) {
+        assert root.decisions.isEmpty();
+        assert !root.children.isEmpty() || leaves.isEmpty();
+        if (nullIfEmpty && root.children.isEmpty()) {
+            return null;
+        }
         StringBuilder builder = new StringBuilder(512);
         formatAsTree(root, "", builder);
         return builder.toString();
@@ -369,12 +485,20 @@
 
     private void formatAsTree(Callsite site, String indent, StringBuilder builder) {
         String position = site.positionString();
-        builder.append(indent).append("at ").append(position).append(": ");
+        builder.append(indent).append(position).append(": ");
         if (site.decisions.isEmpty()) {
+            if (site.parent != null) {
+                builder.append("(no decisions made about ").append(site.target != null ? site.target.format("%H.%n(%p)") : "").append(")");
+            }
+            builder.append(System.lineSeparator());
+        } else if (site.decisions.size() == 1) {
+            builder.append(site.decisions.get(0).toString());
             builder.append(System.lineSeparator());
         } else {
+            builder.append(System.lineSeparator());
             for (Decision decision : site.decisions) {
-                builder.append(decision.toString());
+                String node = (decision == site.decisions.get(site.decisions.size() - 1)) ? LAST_TREE_NODE : TREE_NODE;
+                builder.append(indent + "   " + node).append(decision.toString());
                 builder.append(System.lineSeparator());
             }
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/Invokable.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,10 @@
 
     int bci();
 
+    default boolean isAlive() {
+        return asFixedNode().isAlive();
+    }
+
     FixedNode asFixedNode();
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -41,7 +41,7 @@
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
 import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import java.util.Map;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/InvokeWithExceptionNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
 import org.graalvm.compiler.nodes.spi.UncheckedInterfaceProvider;
 import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import java.util.Map;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/KillingBeginNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 @NodeInfo(allowedUsageTypes = {Memory}, cycles = CYCLES_0, size = SIZE_0)
 public final class KillingBeginNode extends AbstractBeginNode implements MemoryCheckpoint.Single {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopExitNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/LoopExitNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -105,9 +105,7 @@
         Node prev = this.predecessor();
         while (tool.allUsagesAvailable() && prev instanceof BeginNode && prev.hasNoUsages()) {
             AbstractBeginNode begin = (AbstractBeginNode) prev;
-            if (begin.getNodeSourcePosition() != null || this.getNodeSourcePosition() == null || this.getNodeSourcePosition().isPlaceholder()) {
-                this.setNodeSourcePosition(begin.getNodeSourcePosition());
-            }
+            this.setNodeSourcePosition(begin.getNodeSourcePosition());
             prev = prev.predecessor();
             graph().removeFixed(begin);
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/NamedLocationIdentity.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,9 +24,9 @@
 
 import java.util.EnumMap;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaKind.FormatWithToString;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StartNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * The start node of a graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/StructuredGraph.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.function.Consumer;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.core.common.CancellationBailoutException;
 import org.graalvm.compiler.core.common.CompilationIdentifier;
 import org.graalvm.compiler.core.common.GraalOptions;
@@ -359,12 +359,16 @@
         this.compilationId = compilationId;
         this.entryBCI = entryBCI;
         this.assumptions = assumptions;
-        this.speculationLog = speculationLog;
+        if (speculationLog != null && !(speculationLog instanceof GraphSpeculationLog)) {
+            this.speculationLog = new GraphSpeculationLog(speculationLog);
+        } else {
+            this.speculationLog = speculationLog;
+        }
         this.useProfilingInfo = useProfilingInfo;
         this.trackNodeSourcePosition = trackNodeSourcePosition;
         assert trackNodeSourcePosition != null;
         this.cancellable = cancellable;
-        this.inliningLog = new InliningLog(rootMethod, options);
+        this.inliningLog = new InliningLog(rootMethod, GraalOptions.TraceInlining.getValue(options));
         this.callerContext = context;
     }
 
@@ -480,7 +484,10 @@
 
     public void logInliningTree() {
         if (GraalOptions.TraceInlining.getValue(getOptions())) {
-            TTY.println(getInliningLog().formatAsTree());
+            String formattedTree = getInliningLog().formatAsTree(true);
+            if (formattedTree != null) {
+                TTY.println(formattedTree);
+            }
         }
     }
 
@@ -518,6 +525,7 @@
         copy.isAfterFloatingReadPhase = isAfterFloatingReadPhase;
         copy.hasValueProxies = hasValueProxies;
         copy.isAfterExpandLogic = isAfterExpandLogic;
+        copy.trackNodeSourcePosition = trackNodeSourcePosition;
         EconomicMap<Node, Node> replacements = EconomicMap.create(Equivalence.IDENTITY);
         replacements.put(start, copy.start);
         UnmodifiableEconomicMap<Node, Node> duplicates;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/Block.java	Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
 import org.graalvm.compiler.nodes.LoopEndNode;
 import org.graalvm.compiler.nodes.LoopExitNode;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public final class Block extends AbstractBlockBase<Block> {
     public static final Block[] EMPTY_ARRAY = new Block[0];
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/HIRLoop.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.nodes.LoopBeginNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public final class HIRLoop extends Loop<Block> {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/LocationSet.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/cfg/LocationSet.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 import java.util.Arrays;
 import java.util.List;
 
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public class LocationSet {
     private LocationIdentity firstLocation;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/debug/StringToBytesNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/BytecodeExceptionNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.MetaAccessProvider;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/ForeignCallNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -46,7 +46,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/GuardedUnsafeLoadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,7 +27,7 @@
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.nodeinfo.NodeInfo;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaReadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/JavaWriteNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/MembarNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Creates a memory barrier.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawLoadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -44,7 +44,7 @@
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Assumptions;
 import jdk.vm.ci.meta.Constant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/RawStoreNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Assumptions;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeAccessNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,7 +35,7 @@
 import org.graalvm.compiler.nodes.NamedLocationIdentity;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.type.StampTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Assumptions;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeCopyNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,7 @@
 import org.graalvm.compiler.graph.Node.NodeIntrinsic;
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryLoadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryLoadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/extended/UnsafeMemoryStoreNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/graphbuilderconf/InvocationPlugins.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,15 +35,16 @@
 import java.util.List;
 import java.util.Map;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.MethodSubstitutionRegistry;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
+import org.graalvm.compiler.core.common.SuppressFBWarnings;
 import org.graalvm.compiler.debug.Assertions;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
@@ -862,6 +863,7 @@
         lateRegistrations = lateClassPlugins;
     }
 
+    @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "string literal object identity used as sentinel")
     private synchronized boolean closeLateRegistrations() {
         if (lateRegistrations == null || lateRegistrations.className != CLOSED_LATE_CLASS_PLUGIN) {
             lateRegistrations = new LateClassPlugins(lateRegistrations, CLOSED_LATE_CLASS_PLUGIN);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AbstractCompareAndSwapNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
 import org.graalvm.compiler.nodes.memory.LIRLowerableAccess;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Low-level atomic compare-and-swap operation.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndAddNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Value;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/AtomicReadAndWriteNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ExceptionObjectNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_8;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LogicCompareAndSwapNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,7 +34,7 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/LoweredAtomicReadAndWriteNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -39,7 +39,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Value;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorEnterNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * The {@code MonitorEnterNode} represents the acquisition of a monitor.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/MonitorExitNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * The {@code MonitorExitNode} represents a monitor release. If it is the release of the monitor of
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/RawMonitorEnterNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,7 +38,7 @@
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * The {@code RawMonitorEnterNode} represents the acquisition of a monitor. The object needs to
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/UnsafeCompareAndSwapNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
@@ -53,8 +53,8 @@
     @Input ValueNode expected;
     @Input ValueNode newValue;
 
-    protected final JavaKind valueKind;
-    protected final LocationIdentity locationIdentity;
+    private final JavaKind valueKind;
+    private final LocationIdentity locationIdentity;
 
     public UnsafeCompareAndSwapNode(ValueNode object, ValueNode offset, ValueNode expected, ValueNode newValue, JavaKind valueKind, LocationIdentity locationIdentity) {
         super(TYPE, StampFactory.forKind(JavaKind.Boolean.getStackKind()));
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/java/ValueCompareAndSwapNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * A special purpose store node that differs from {@link LogicCompareAndSwapNode} in that it returns
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/AbstractWriteNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.ValueNodeUtil;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 @NodeInfo(allowedUsageTypes = {InputType.Memory, InputType.Guard}, cycles = CYCLES_2, size = SIZE_1)
 public abstract class AbstractWriteNode extends FixedAccessNode implements StateSplit, MemoryCheckpoint.Single, MemoryAccess, GuardingNode {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/Access.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import org.graalvm.compiler.nodes.extended.GuardedNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public interface Access extends GuardedNode, HeapAccess {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FixedAccessNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -31,7 +31,7 @@
 import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Accesses a value at an memory address specified by an {@linkplain #address address}. The access
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatableAccessNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,7 +28,7 @@
 import org.graalvm.compiler.nodes.FrameState;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * An {@link FixedAccessNode} that can be converted to a {@link FloatingAccessNode}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingAccessNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,7 +29,7 @@
 import org.graalvm.compiler.nodes.FloatingGuardedNode;
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 @NodeInfo
 public abstract class FloatingAccessNode extends FloatingGuardedNode implements Access, MemoryAccess {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/FloatingReadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -41,7 +41,7 @@
 import org.graalvm.compiler.nodes.extended.GuardingNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * A floating read of a value from memory specified in terms of an object base and an object
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryAccess.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.nodes.memory;
 
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * This interface marks nodes that access some memory location, and that have an edge to the last
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryCheckpoint.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.FixedNode;
 import org.graalvm.compiler.nodes.FixedNodeInterface;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * This interface marks subclasses of {@link FixedNode} that kill a set of memory locations
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMap.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMap.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.nodes.memory;
 
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Maps a {@linkplain LocationIdentity location} to the last node that (potentially) wrote to the
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryMapNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,15 +26,15 @@
 import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_0;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_0;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.graph.NodeClass;
 import org.graalvm.compiler.graph.NodeInputList;
@@ -44,7 +44,7 @@
 import org.graalvm.compiler.nodes.calc.FloatingNode;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 @NodeInfo(allowedUsageTypes = {Extension, Memory}, cycles = CYCLES_0, size = SIZE_0)
 public final class MemoryMapNode extends FloatingNode implements MemoryMap, MemoryNode, LIRLowerable {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryPhiNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/MemoryPhiNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
 import org.graalvm.compiler.nodes.AbstractMergeNode;
 import org.graalvm.compiler.nodes.PhiNode;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Memory {@code PhiNode}s merge memory dependencies at control flow merges.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/ReadNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -48,7 +48,7 @@
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.Constant;
 import jdk.vm.ci.meta.MetaAccessProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/memory/WriteNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.memory.address.AddressNode;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * Writes a given {@linkplain #value() value} a {@linkplain FixedAccessNode memory location}.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/MemoryProxy.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/spi/MemoryProxy.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,7 +23,7 @@
 package org.graalvm.compiler.nodes.spi;
 
 import org.graalvm.compiler.nodes.memory.MemoryNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public interface MemoryProxy extends Proxy, MemoryNode {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/util/GraphUtil.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
 import java.util.List;
 import java.util.function.BiFunction;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.code.SourceStackTraceBailoutException;
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.nodes/src/org/graalvm/compiler/nodes/virtual/CommitAllocationNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -54,7 +54,7 @@
 import org.graalvm.compiler.nodes.spi.LoweringTool;
 import org.graalvm.compiler.nodes.spi.VirtualizableAllocation;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 // @formatter:off
 @NodeInfo(nameTemplate = "Alloc {i#virtualObjects}",
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.processor/src/org/graalvm/compiler/options/processor/OptionProcessor.java	Thu Apr 26 17:59:02 2018 +0200
@@ -61,6 +61,7 @@
 import org.graalvm.compiler.options.OptionDescriptor;
 import org.graalvm.compiler.options.OptionDescriptors;
 import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
 
 /**
  * Processes static fields annotated with {@link Option}. An {@link OptionDescriptors}
@@ -218,7 +219,7 @@
             }
         }
 
-        info.options.add(new OptionInfo(optionName, help, extraHelp, optionType, declaringClass, field));
+        info.options.add(new OptionInfo(optionName, annotation.type(), help, extraHelp, optionType, declaringClass, field));
     }
 
     private void createFiles(OptionsInfo info) {
@@ -243,6 +244,7 @@
             out.println("");
             out.println("import java.util.*;");
             out.println("import " + OptionDescriptors.class.getPackage().getName() + ".*;");
+            out.println("import " + OptionType.class.getName() + ";");
             out.println("");
             out.println("public class " + optionsClassName + " implements " + OptionDescriptors.class.getSimpleName() + " {");
 
@@ -263,6 +265,7 @@
                     optionField = option.declaringClass + "." + option.field.getSimpleName();
                 }
                 out.println("        case \"" + name + "\": {");
+                OptionType optionType = option.optionType;
                 String type = option.type;
                 String help = option.help;
                 String[] extraHelp = option.extraHelp;
@@ -270,7 +273,8 @@
                 Name fieldName = option.field.getSimpleName();
                 out.printf("            return " + desc + ".create(\n");
                 out.printf("                /*name*/ \"%s\",\n", name);
-                out.printf("                /*type*/ %s.class,\n", type);
+                out.printf("                /*optionType*/ %s.%s,\n", optionType.getDeclaringClass().getSimpleName(), optionType.name());
+                out.printf("                /*optionValueType*/ %s.class,\n", type);
                 out.printf("                /*help*/ \"%s\",\n", help);
                 if (extraHelp.length != 0) {
                     out.printf("                /*extraHelp*/ new String[] {\n");
@@ -332,14 +336,16 @@
     static class OptionInfo implements Comparable<OptionInfo> {
 
         final String name;
+        final OptionType optionType;
         final String help;
         final String[] extraHelp;
         final String type;
         final String declaringClass;
         final VariableElement field;
 
-        OptionInfo(String name, String help, String[] extraHelp, String type, String declaringClass, VariableElement field) {
+        OptionInfo(String name, OptionType optionType, String help, String[] extraHelp, String type, String declaringClass, VariableElement field) {
             this.name = name;
+            this.optionType = optionType;
             this.help = help;
             this.extraHelp = extraHelp;
             this.type = type;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionKeyTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/NestedBooleanOptionKeyTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,6 +40,7 @@
 import org.graalvm.compiler.options.NestedBooleanOptionKey;
 import org.graalvm.compiler.options.OptionDescriptor;
 import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 import org.junit.Test;
 
@@ -54,12 +55,12 @@
         public static final OptionKey<Boolean> NestedOption2 = new NestedBooleanOptionKey(Master2, false);
     }
 
-    static final OptionDescriptor master0 = OptionDescriptor.create("Master0", Boolean.class, "", Options.class, "Master0", Master0);
-    static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
-    static final OptionDescriptor master1 = OptionDescriptor.create("Master1", Boolean.class, "", Options.class, "Master1", Master1);
-    static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
-    static final OptionDescriptor master2 = OptionDescriptor.create("Master2", Boolean.class, "", Options.class, "Master2", Master2);
-    static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
+    static final OptionDescriptor master0 = OptionDescriptor.create("Master0", OptionType.Debug, Boolean.class, "", Options.class, "Master0", Master0);
+    static final OptionDescriptor nestedOption0 = OptionDescriptor.create("NestedOption0", OptionType.Debug, Boolean.class, "", Options.class, "NestedOption0", NestedOption0);
+    static final OptionDescriptor master1 = OptionDescriptor.create("Master1", OptionType.Debug, Boolean.class, "", Options.class, "Master1", Master1);
+    static final OptionDescriptor nestedOption1 = OptionDescriptor.create("NestedOption1", OptionType.Debug, Boolean.class, "", Options.class, "NestedOption1", NestedOption1);
+    static final OptionDescriptor master2 = OptionDescriptor.create("Master2", OptionType.Debug, Boolean.class, "", Options.class, "Master2", Master2);
+    static final OptionDescriptor nestedOption2 = OptionDescriptor.create("NestedOption2", OptionType.Debug, Boolean.class, "", Options.class, "NestedOption2", NestedOption2);
 
     @Test
     public void runDefaultTrue() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionKey.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options.test/src/org/graalvm/compiler/options/test/TestOptionKey.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,6 +36,7 @@
 import org.graalvm.compiler.options.ModifiableOptionValues;
 import org.graalvm.compiler.options.OptionDescriptor;
 import org.graalvm.compiler.options.OptionKey;
+import org.graalvm.compiler.options.OptionType;
 import org.graalvm.compiler.options.OptionValues;
 import org.junit.Assert;
 import org.junit.Assume;
@@ -51,7 +52,7 @@
 
     @Test
     public void toStringTest() {
-        OptionDescriptor.create("MyOption", String.class, "", Options.class, "MyOption", MyOption);
+        OptionDescriptor.create("MyOption", OptionType.Debug, String.class, "", Options.class, "MyOption", MyOption);
         assertEquals("MyOption", MyOption.toString());
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/EnumOptionKey.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.EnumSet;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 
 public class EnumOptionKey<T extends Enum<T>> extends OptionKey<T> {
     final Class<T> enumClass;
@@ -45,11 +45,11 @@
         return EnumSet.allOf(enumClass);
     }
 
-    Object valueOf(String name) {
+    public Object valueOf(String name) {
         try {
             return Enum.valueOf(enumClass, name);
         } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException("\"" + name + "\" is not a valid option for " + getName() + ". Valid values are " + EnumSet.allOf(enumClass));
+            throw new IllegalArgumentException("\"" + name + "\" is not a valid option for " + getName() + ". Valid values are " + getAllValues());
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/ModifiableOptionValues.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,10 +24,10 @@
 
 import java.util.concurrent.atomic.AtomicReference;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 
 /**
  * A context for obtaining values for {@link OptionKey}s that allows for key/value pairs to be
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionDescriptor.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionDescriptor.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,8 @@
 public final class OptionDescriptor {
 
     protected final String name;
-    protected final Class<?> type;
+    protected final OptionType optionType;
+    protected final Class<?> optionValueType;
     protected final String help;
     protected final List<String> extraHelp;
     protected final OptionKey<?> optionKey;
@@ -42,39 +43,41 @@
 
     private static final String[] NO_EXTRA_HELP = {};
 
-    public static OptionDescriptor create(String name, Class<?> type, String help, Class<?> declaringClass, String fieldName, OptionKey<?> option) {
-        return create(name, type, help, NO_EXTRA_HELP, declaringClass, fieldName, option);
+    public static OptionDescriptor create(String name, OptionType optionType, Class<?> optionValueType, String help, Class<?> declaringClass, String fieldName, OptionKey<?> option) {
+        return create(name, optionType, optionValueType, help, NO_EXTRA_HELP, declaringClass, fieldName, option);
     }
 
-    public static OptionDescriptor create(String name, Class<?> type, String help, String[] extraHelp, Class<?> declaringClass, String fieldName, OptionKey<?> option) {
+    public static OptionDescriptor create(String name, OptionType optionType, Class<?> optionValueType, String help, String[] extraHelp, Class<?> declaringClass, String fieldName,
+                    OptionKey<?> option) {
         assert option != null : declaringClass + "." + fieldName;
         OptionDescriptor result = option.getDescriptor();
         if (result == null) {
             List<String> extraHelpList = extraHelp == null || extraHelp.length == 0 ? Collections.emptyList() : Collections.unmodifiableList(Arrays.asList(extraHelp));
-            result = new OptionDescriptor(name, type, help, extraHelpList, declaringClass, fieldName, option);
+            result = new OptionDescriptor(name, optionType, optionValueType, help, extraHelpList, declaringClass, fieldName, option);
             option.setDescriptor(result);
         }
-        assert result.name.equals(name) && result.type == type && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.optionKey == option;
+        assert result.name.equals(name) && result.optionValueType == optionValueType && result.declaringClass == declaringClass && result.fieldName.equals(fieldName) && result.optionKey == option;
         return result;
     }
 
-    private OptionDescriptor(String name, Class<?> type, String help, List<String> extraHelp, Class<?> declaringClass, String fieldName, OptionKey<?> optionKey) {
+    private OptionDescriptor(String name, OptionType optionType, Class<?> optionValueType, String help, List<String> extraHelp, Class<?> declaringClass, String fieldName, OptionKey<?> optionKey) {
         this.name = name;
-        this.type = type;
+        this.optionType = optionType;
+        this.optionValueType = optionValueType;
         this.help = help;
         this.extraHelp = extraHelp;
         this.optionKey = optionKey;
         this.declaringClass = declaringClass;
         this.fieldName = fieldName;
-        assert !type.isPrimitive() : "must used boxed type instead of " + type;
+        assert !optionValueType.isPrimitive() : "must used boxed optionValueType instead of " + optionValueType;
     }
 
     /**
      * Gets the type of values stored in the option. This will be the boxed type for a primitive
      * option.
      */
-    public Class<?> getType() {
-        return type;
+    public Class<?> getOptionValueType() {
+        return optionValueType;
     }
 
     /**
@@ -104,6 +107,13 @@
     }
 
     /**
+     * Gets the type of the option.
+     */
+    public OptionType getOptionType() {
+        return optionType;
+    }
+
+    /**
      * Gets the boxed option value.
      */
     public OptionKey<?> getOptionKey() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionKey.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.Formatter;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 
 /**
  * A key for an option. The value for an option is obtained from an {@link OptionValues} object.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValues.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,10 +30,10 @@
 import java.util.SortedMap;
 import java.util.TreeMap;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 
 /**
  * A context for obtaining values for {@link OptionKey}s.
@@ -126,7 +126,7 @@
     /**
      * Decodes a value that may be the sentinel value for {@code null} in a map.
      */
-    protected static Object decodeNull(Object value) {
+    public static Object decodeNull(Object value) {
         return value == NULL ? null : value;
     }
 
@@ -212,7 +212,7 @@
 
             String name = namePrefix + e.getKey();
             String assign = containsKey(desc.optionKey) ? ":=" : "=";
-            String typeName = desc.getOptionKey() instanceof EnumOptionKey ? "String" : desc.getType().getSimpleName();
+            String typeName = desc.getOptionKey() instanceof EnumOptionKey ? "String" : desc.getOptionValueType().getSimpleName();
             String linePrefix = String.format("%s %s %s ", name, assign, value);
             int typeStartPos = PROPERTY_LINE_WIDTH - typeName.length();
             int linePad = typeStartPos - linePrefix.length();
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionValuesAccess.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +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.options;
-
-/**
- * Defines a service that supplies values for options. The values supplied may come from a source
- * such as system properties or a command line.
- *
- * This mechanism for obtaining option values must only be used if there is no other more local
- * context from which option values can be obtained.
- */
-public interface OptionValuesAccess {
-
-    /**
-     * Gets the option values available via this service.
-     */
-    OptionValues getOptions();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.options/src/org/graalvm/compiler/options/OptionsParser.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
 import java.util.List;
 import java.util.ServiceLoader;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.util.CollectionsUtil;
 
 /**
@@ -116,7 +116,7 @@
      * @param loader source of the available {@link OptionDescriptors}
      * @throws IllegalArgumentException if there's a problem parsing {@code option}
      */
-    static void parseOption(String name, Object uncheckedValue, EconomicMap<OptionKey<?>, Object> values, Iterable<OptionDescriptors> loader) {
+    public static void parseOption(String name, Object uncheckedValue, EconomicMap<OptionKey<?>, Object> values, Iterable<OptionDescriptors> loader) {
 
         OptionDescriptor desc = lookup(loader, name);
         if (desc == null) {
@@ -132,7 +132,7 @@
             throw new IllegalArgumentException(msg.toString());
         }
 
-        Class<?> optionType = desc.getType();
+        Class<?> optionType = desc.getOptionValueType();
         Object value;
         if (!(uncheckedValue instanceof String)) {
             if (optionType != uncheckedValue.getClass()) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/AddressLoweringByUsePhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -93,7 +93,7 @@
             } else {
                 continue;
             }
-            // the lowered address amy already be a replacement
+            // the lowered address may already be a replacement
             // in which case we want to use it not delete it!
             if (lowered != address) {
                 // replace original with lowered at this usage only
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/CanonicalizerPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -314,7 +314,7 @@
 
         @SuppressWarnings("try")
         public boolean tryCanonicalize(final Node node, NodeClass<?> nodeClass) {
-            try (DebugCloseable position = node.withNodeSourcePosition()) {
+            try (DebugCloseable position = node.withNodeSourcePosition(); DebugContext.Scope scope = debug.scope("tryCanonicalize", node)) {
                 if (customCanonicalizer != null) {
                     Node canonical = customCanonicalizer.canonicalize(node);
                     if (performReplacement(node, canonical)) {
@@ -349,6 +349,8 @@
                     return node.isDeleted();
                 }
                 return false;
+            } catch (Throwable throwable) {
+                throw debug.handle(throwable);
             }
         }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ConditionalEliminationPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,10 +28,10 @@
 import java.util.Deque;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/ExpandLogicPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,7 @@
 
 import org.graalvm.compiler.core.common.type.FloatStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node;
@@ -51,6 +52,7 @@
     private static final double EPSILON = 1E-6;
 
     @Override
+    @SuppressWarnings("try")
     protected void run(StructuredGraph graph) {
         for (ShortCircuitOrNode logic : graph.getNodes(ShortCircuitOrNode.TYPE)) {
             processBinary(logic);
@@ -58,7 +60,9 @@
         assert graph.getNodes(ShortCircuitOrNode.TYPE).isEmpty();
 
         for (NormalizeCompareNode logic : graph.getNodes(NormalizeCompareNode.TYPE)) {
-            processNormalizeCompareNode(logic);
+            try (DebugCloseable context = logic.withNodeSourcePosition()) {
+                processNormalizeCompareNode(logic);
+            }
         }
         graph.setAfterExpandLogic();
     }
@@ -84,76 +88,83 @@
         normalize.replaceAtUsagesAndDelete(value);
     }
 
+    @SuppressWarnings("try")
     private static void processBinary(ShortCircuitOrNode binary) {
         while (binary.usages().isNotEmpty()) {
             Node usage = binary.usages().first();
-            if (usage instanceof ShortCircuitOrNode) {
-                processBinary((ShortCircuitOrNode) usage);
-            } else if (usage instanceof IfNode) {
-                processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, binary.getShortCircuitProbability());
-            } else if (usage instanceof ConditionalNode) {
-                processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage);
-            } else {
-                throw GraalError.shouldNotReachHere();
+            try (DebugCloseable nsp = usage.withNodeSourcePosition()) {
+                if (usage instanceof ShortCircuitOrNode) {
+                    processBinary((ShortCircuitOrNode) usage);
+                } else if (usage instanceof IfNode) {
+                    processIf(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (IfNode) usage, binary.getShortCircuitProbability());
+                } else if (usage instanceof ConditionalNode) {
+                    processConditional(binary.getX(), binary.isXNegated(), binary.getY(), binary.isYNegated(), (ConditionalNode) usage);
+                } else {
+                    throw GraalError.shouldNotReachHere();
+                }
             }
         }
         binary.safeDelete();
     }
 
+    @SuppressWarnings("try")
     private static void processIf(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, IfNode ifNode, double shortCircuitProbability) {
-        /*
-         * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into two
-         * separate IfNodes: if(X) and if(Y)
-         *
-         * for computing the probabilities P(X) and P(Y), we use two different approaches. The first
-         * one assumes that the shortCircuitProbability and the probability on the IfNode were
-         * created with each other in mind. If this assumption does not hold, we fall back to
-         * another mechanism for computing the probabilities.
-         */
-        AbstractBeginNode trueTarget = ifNode.trueSuccessor();
-        AbstractBeginNode falseTarget = ifNode.falseSuccessor();
-
-        // 1st approach
-        // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
-        double firstIfTrueProbability = shortCircuitProbability;
-        double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
-        double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
-
-        if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
+        try (DebugCloseable context = ifNode.withNodeSourcePosition()) {
             /*
-             * 2nd approach
-             *
-             * the assumption above did not hold, so we either used an artificial probability as
-             * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
+             * this method splits an IfNode, which has a ShortCircuitOrNode as its condition, into
+             * two separate IfNodes: if(X) and if(Y)
              *
-             * so, we distribute the if's trueSuccessorProbability between the newly generated if
-             * nodes according to the shortCircuitProbability. the following invariant is always
-             * true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
+             * for computing the probabilities P(X) and P(Y), we use two different approaches. The
+             * first one assumes that the shortCircuitProbability and the probability on the IfNode
+             * were created with each other in mind. If this assumption does not hold, we fall back
+             * to another mechanism for computing the probabilities.
              */
-            firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
-            secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
-        }
+            AbstractBeginNode trueTarget = ifNode.trueSuccessor();
+            AbstractBeginNode falseTarget = ifNode.falseSuccessor();
+
+            // 1st approach
+            // assumption: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) * P(Y))
+            double firstIfTrueProbability = shortCircuitProbability;
+            double secondIfTrueProbability = sanitizeProbability((ifNode.getTrueSuccessorProbability() - shortCircuitProbability) / (1 - shortCircuitProbability));
+            double expectedOriginalIfTrueProbability = firstIfTrueProbability + (1 - firstIfTrueProbability) * secondIfTrueProbability;
 
-        ifNode.clearSuccessors();
-        Graph graph = ifNode.graph();
-        AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
-        trueTargetMerge.setNext(trueTarget);
-        EndNode firstTrueEnd = graph.add(new EndNode());
-        EndNode secondTrueEnd = graph.add(new EndNode());
-        trueTargetMerge.addForwardEnd(firstTrueEnd);
-        trueTargetMerge.addForwardEnd(secondTrueEnd);
-        AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
-        AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
-        if (yNegated) {
-            secondIfTrueProbability = 1.0 - secondIfTrueProbability;
+            if (!doubleEquals(ifNode.getTrueSuccessorProbability(), expectedOriginalIfTrueProbability)) {
+                /*
+                 * 2nd approach
+                 *
+                 * the assumption above did not hold, so we either used an artificial probability as
+                 * shortCircuitProbability or the ShortCircuitOrNode was moved to some other IfNode.
+                 *
+                 * so, we distribute the if's trueSuccessorProbability between the newly generated
+                 * if nodes according to the shortCircuitProbability. the following invariant is
+                 * always true in this case: P(originalIf.trueSuccessor) == P(X) + ((1 - P(X)) *
+                 * P(Y))
+                 */
+                firstIfTrueProbability = ifNode.getTrueSuccessorProbability() * shortCircuitProbability;
+                secondIfTrueProbability = sanitizeProbability(1 - (ifNode.probability(falseTarget) / (1 - firstIfTrueProbability)));
+            }
+
+            ifNode.clearSuccessors();
+            Graph graph = ifNode.graph();
+            AbstractMergeNode trueTargetMerge = graph.add(new MergeNode());
+            trueTargetMerge.setNext(trueTarget);
+            EndNode firstTrueEnd = graph.add(new EndNode());
+            EndNode secondTrueEnd = graph.add(new EndNode());
+            trueTargetMerge.addForwardEnd(firstTrueEnd);
+            trueTargetMerge.addForwardEnd(secondTrueEnd);
+            AbstractBeginNode firstTrueTarget = BeginNode.begin(firstTrueEnd);
+            AbstractBeginNode secondTrueTarget = BeginNode.begin(secondTrueEnd);
+            if (yNegated) {
+                secondIfTrueProbability = 1.0 - secondIfTrueProbability;
+            }
+            if (xNegated) {
+                firstIfTrueProbability = 1.0 - firstIfTrueProbability;
+            }
+            AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
+            IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
+            ifNode.replaceAtPredecessor(firstIf);
+            ifNode.safeDelete();
         }
-        if (xNegated) {
-            firstIfTrueProbability = 1.0 - firstIfTrueProbability;
-        }
-        AbstractBeginNode secondIf = BeginNode.begin(graph.add(new IfNode(y, yNegated ? falseTarget : secondTrueTarget, yNegated ? secondTrueTarget : falseTarget, secondIfTrueProbability)));
-        IfNode firstIf = graph.add(new IfNode(x, xNegated ? secondIf : firstTrueTarget, xNegated ? firstTrueTarget : secondIf, firstIfTrueProbability));
-        ifNode.replaceAtPredecessor(firstIf);
-        ifNode.safeDelete();
     }
 
     private static boolean doubleEquals(double a, double b) {
@@ -169,13 +180,16 @@
         return newValue;
     }
 
+    @SuppressWarnings("try")
     private static void processConditional(LogicNode x, boolean xNegated, LogicNode y, boolean yNegated, ConditionalNode conditional) {
-        ValueNode trueTarget = conditional.trueValue();
-        ValueNode falseTarget = conditional.falseValue();
-        Graph graph = conditional.graph();
-        ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
-        ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
-        conditional.replaceAndDelete(firstConditional);
+        try (DebugCloseable context = conditional.withNodeSourcePosition()) {
+            ValueNode trueTarget = conditional.trueValue();
+            ValueNode falseTarget = conditional.falseValue();
+            Graph graph = conditional.graph();
+            ConditionalNode secondConditional = graph.unique(new ConditionalNode(y, yNegated ? falseTarget : trueTarget, yNegated ? trueTarget : falseTarget));
+            ConditionalNode firstConditional = graph.unique(new ConditionalNode(x, xNegated ? secondConditional : trueTarget, xNegated ? trueTarget : secondConditional));
+            conditional.replaceAndDelete(firstConditional);
+        }
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FixReadsPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,8 @@
  */
 package org.graalvm.compiler.phases.common;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.core.common.type.FloatStamp;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FloatingReadPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,16 +24,16 @@
 
 import static org.graalvm.compiler.graph.Graph.NodeEvent.NODE_ADDED;
 import static org.graalvm.compiler.graph.Graph.NodeEvent.ZERO_USAGES;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.graph.Graph.NodeEventScope;
@@ -71,7 +71,7 @@
 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator;
 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.LoopInfo;
 import org.graalvm.compiler.phases.graph.ReentrantNodeIterator.NodeIteratorClosure;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public class FloatingReadPhase extends Phase {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/FrameStateAssignmentPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/LoweringPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -75,7 +75,7 @@
 import org.graalvm.compiler.phases.Phase;
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.DeoptimizationAction;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/PropagateDeoptimizeProbabilityPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,9 +22,9 @@
  */
 package org.graalvm.compiler.phases.common;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.graph.NodeStack;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractDeoptimizeNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/InliningUtil.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,11 +33,11 @@
 import java.util.Objects;
 import java.util.function.Consumer;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.core.common.GraalOptions;
@@ -45,6 +45,7 @@
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.TypeReference;
 import org.graalvm.compiler.core.common.util.Util;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.GraalGraphError;
@@ -340,7 +341,13 @@
      */
     @SuppressWarnings("try")
     public static UnmodifiableEconomicMap<Node, Node> inline(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod) {
-        return inline(invoke, inlineGraph, receiverNullCheck, inlineeMethod, "", "");
+        try {
+            return inline(invoke, inlineGraph, receiverNullCheck, inlineeMethod, "reason not specified", "phase not specified");
+        } catch (GraalError ex) {
+            ex.addContext("inlining into", invoke.asNode().graph().method());
+            ex.addContext("inlinee", inlineGraph.method());
+            throw ex;
+        }
     }
 
     /**
@@ -423,7 +430,7 @@
         try (InliningLog.UpdateScope scope = graph.getInliningLog().openDefaultUpdateScope()) {
             duplicates = graph.addDuplicates(nodes, inlineGraph, inlineGraph.getNodeCount(), localReplacement);
             if (scope != null) {
-                graph.getInliningLog().addDecision(invoke, true, reason, phase, duplicates, inlineGraph.getInliningLog());
+                graph.getInliningLog().addDecision(invoke, true, phase, duplicates, inlineGraph.getInliningLog(), reason);
             }
         }
 
@@ -491,13 +498,8 @@
      * @return the set of nodes to canonicalize
      */
     @SuppressWarnings("try")
-    public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod) {
-        return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, null);
-    }
-
-    public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod,
-                    Consumer<UnmodifiableEconomicMap<Node, Node>> duplicatesConsumer) {
-        return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, duplicatesConsumer, "", "");
+    public static EconomicSet<Node> inlineForCanonicalization(Invoke invoke, StructuredGraph inlineGraph, boolean receiverNullCheck, ResolvedJavaMethod inlineeMethod, String reason, String phase) {
+        return inlineForCanonicalization(invoke, inlineGraph, receiverNullCheck, inlineeMethod, null, reason, phase);
     }
 
     @SuppressWarnings("try")
@@ -684,28 +686,42 @@
         newNodes.addAll(invokeGraph.getNewNodes(mark));
         EconomicMap<NodeSourcePosition, NodeSourcePosition> posMap = EconomicMap.create(Equivalence.DEFAULT);
         UnmodifiableMapCursor<Node, Node> cursor = duplicates.getEntries();
+        ResolvedJavaMethod inlineeRoot = null;
         while (cursor.advance()) {
-            if (!newNodes.contains(cursor.getValue())) {
+            Node value = cursor.getValue();
+            if (!newNodes.contains(value)) {
                 continue;
             }
-            NodeSourcePosition pos = cursor.getKey().getNodeSourcePosition();
-            if (pos != null) {
-                NodeSourcePosition callerPos = posMap.get(pos);
-                if (callerPos == null) {
-                    callerPos = pos.addCaller(invokePos, isSubstitution);
-                    posMap.put(pos, callerPos);
-                }
-                cursor.getValue().setNodeSourcePosition(callerPos);
+            if (isSubstitution && invokePos == null) {
+                // There's no caller information so the source position for this node will be
+                // invalid, so it should be cleared.
+                value.clearNodeSourcePosition();
             } else {
-                if (isSubstitution) {
-                    /*
-                     * If no other position is provided at least attribute the substituted node to
-                     * the original invoke.
-                     */
-                    cursor.getValue().setNodeSourcePosition(invokePos);
+                NodeSourcePosition pos = cursor.getKey().getNodeSourcePosition();
+                if (pos != null) {
+                    if (inlineeRoot == null) {
+                        assert (inlineeRoot = pos.getRootMethod()) != null;
+                    } else {
+                        assert pos.verifyRootMethod(inlineeRoot);
+                    }
+                    NodeSourcePosition callerPos = posMap.get(pos);
+                    if (callerPos == null) {
+                        callerPos = pos.addCaller(invokePos, isSubstitution);
+                        posMap.put(pos, callerPos);
+                    }
+                    value.setNodeSourcePosition(callerPos);
+                } else {
+                    if (isSubstitution) {
+                        /*
+                         * If no other position is provided at least attribute the substituted node
+                         * to the original invoke.
+                         */
+                        value.setNodeSourcePosition(invokePos);
+                    }
                 }
             }
         }
+        assert invokeGraph.verifySourcePositions();
     }
 
     public static void processMonitorId(FrameState stateAfter, MonitorIdNode monitorIdNode) {
@@ -942,37 +958,42 @@
      * Gets the receiver for an invoke, adding a guard if necessary to ensure it is non-null, and
      * ensuring that the resulting type is compatible with the method being invoked.
      */
+    @SuppressWarnings("try")
     public static ValueNode nonNullReceiver(Invoke invoke) {
-        MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
-        assert !callTarget.isStatic() : callTarget.targetMethod();
-        StructuredGraph graph = callTarget.graph();
-        ValueNode oldReceiver = callTarget.arguments().get(0);
-        ValueNode newReceiver = oldReceiver;
-        if (newReceiver.getStackKind() == JavaKind.Object) {
+        try (DebugCloseable position = invoke.asNode().withNodeSourcePosition()) {
+            MethodCallTargetNode callTarget = (MethodCallTargetNode) invoke.callTarget();
+            assert !callTarget.isStatic() : callTarget.targetMethod();
+            StructuredGraph graph = callTarget.graph();
+            ValueNode oldReceiver = callTarget.arguments().get(0);
+            ValueNode newReceiver = oldReceiver;
+            if (newReceiver.getStackKind() == JavaKind.Object) {
 
-            if (invoke.getInvokeKind() == InvokeKind.Special) {
-                Stamp paramStamp = newReceiver.stamp(NodeView.DEFAULT);
-                Stamp stamp = paramStamp.join(StampFactory.object(TypeReference.create(graph.getAssumptions(), callTarget.targetMethod().getDeclaringClass())));
-                if (!stamp.equals(paramStamp)) {
-                    // The verifier and previous optimizations guarantee unconditionally that the
-                    // receiver is at least of the type of the method holder for a special invoke.
-                    newReceiver = graph.unique(new PiNode(newReceiver, stamp));
+                if (invoke.getInvokeKind() == InvokeKind.Special) {
+                    Stamp paramStamp = newReceiver.stamp(NodeView.DEFAULT);
+                    Stamp stamp = paramStamp.join(StampFactory.object(TypeReference.create(graph.getAssumptions(), callTarget.targetMethod().getDeclaringClass())));
+                    if (!stamp.equals(paramStamp)) {
+                        // The verifier and previous optimizations guarantee unconditionally that
+                        // the
+                        // receiver is at least of the type of the method holder for a special
+                        // invoke.
+                        newReceiver = graph.unique(new PiNode(newReceiver, stamp));
+                    }
+                }
+
+                if (!StampTool.isPointerNonNull(newReceiver)) {
+                    LogicNode condition = graph.unique(IsNullNode.create(newReceiver));
+                    FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true));
+                    PiNode nonNullReceiver = graph.unique(new PiNode(newReceiver, StampFactory.objectNonNull(), fixedGuard));
+                    graph.addBeforeFixed(invoke.asNode(), fixedGuard);
+                    newReceiver = nonNullReceiver;
                 }
             }
 
-            if (!StampTool.isPointerNonNull(newReceiver)) {
-                LogicNode condition = graph.unique(IsNullNode.create(newReceiver));
-                FixedGuardNode fixedGuard = graph.add(new FixedGuardNode(condition, NullCheckException, InvalidateReprofile, true));
-                PiNode nonNullReceiver = graph.unique(new PiNode(newReceiver, StampFactory.objectNonNull(), fixedGuard));
-                graph.addBeforeFixed(invoke.asNode(), fixedGuard);
-                newReceiver = nonNullReceiver;
+            if (newReceiver != oldReceiver) {
+                callTarget.replaceFirstInput(oldReceiver, newReceiver);
             }
+            return newReceiver;
         }
-
-        if (newReceiver != oldReceiver) {
-            callTarget.replaceFirstInput(oldReceiver, newReceiver);
-        }
-        return newReceiver;
     }
 
     public static boolean canIntrinsify(Replacements replacements, ResolvedJavaMethod target, int invokeBci) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AbstractInlineInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.phases.common.inlining.info;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -54,10 +54,10 @@
     }
 
     @SuppressWarnings("try")
-    protected static EconomicSet<Node> inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, boolean receiverNullCheck) {
+    protected static EconomicSet<Node> inline(Invoke invoke, ResolvedJavaMethod concrete, Inlineable inlineable, boolean receiverNullCheck, String reason) {
         assert inlineable instanceof InlineableGraph;
         StructuredGraph calleeGraph = ((InlineableGraph) inlineable).getGraph();
-        return InliningUtil.inlineForCanonicalization(invoke, calleeGraph, receiverNullCheck, concrete);
+        return InliningUtil.inlineForCanonicalization(invoke, calleeGraph, receiverNullCheck, concrete, reason, "InliningPhase");
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/AssumptionInlineInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.phases.common.inlining.info;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.graalvm.compiler.nodes.Invoke;
@@ -46,9 +46,9 @@
     }
 
     @Override
-    public EconomicSet<Node> inline(Providers providers) {
+    public EconomicSet<Node> inline(Providers providers, String reason) {
         takenAssumption.recordTo(invoke.asNode().graph().getAssumptions());
-        return super.inline(providers);
+        return super.inline(providers, reason);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/ExactInlineInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.phases.common.inlining.info;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.phases.common.inlining.info.elem.Inlineable;
@@ -51,8 +51,8 @@
     }
 
     @Override
-    public EconomicSet<Node> inline(Providers providers) {
-        return inline(invoke, concrete, inlineableElement, !suppressNullCheck);
+    public EconomicSet<Node> inline(Providers providers, String reason) {
+        return inline(invoke, concrete, inlineableElement, !suppressNullCheck, reason);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/InlineInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.phases.common.inlining.info;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.StructuredGraph;
@@ -75,7 +75,7 @@
      *
      * @return a collection of nodes that need to be canonicalized after the inlining
      */
-    EconomicSet<Node> inline(Providers providers);
+    EconomicSet<Node> inline(Providers providers, String reason);
 
     /**
      * Try to make the call static bindable to avoid interface and virtual method calls.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/MultiTypeGuardInlineInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
@@ -156,11 +156,11 @@
     }
 
     @Override
-    public EconomicSet<Node> inline(Providers providers) {
+    public EconomicSet<Node> inline(Providers providers, String reason) {
         if (hasSingleMethod()) {
-            return inlineSingleMethod(graph(), providers.getStampProvider(), providers.getConstantReflection());
+            return inlineSingleMethod(graph(), providers.getStampProvider(), providers.getConstantReflection(), reason);
         } else {
-            return inlineMultipleMethods(graph(), providers);
+            return inlineMultipleMethods(graph(), providers, reason);
         }
     }
 
@@ -182,7 +182,7 @@
         return notRecordedTypeProbability > 0;
     }
 
-    private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers) {
+    private EconomicSet<Node> inlineMultipleMethods(StructuredGraph graph, Providers providers, String reason) {
         int numberOfMethods = concretes.size();
         FixedNode continuation = invoke.next();
 
@@ -277,7 +277,7 @@
         // do the actual inlining for every invoke
         for (int i = 0; i < numberOfMethods; i++) {
             Invoke invokeForInlining = (Invoke) successors[i].next();
-            canonicalizeNodes.addAll(doInline(i, invokeForInlining));
+            canonicalizeNodes.addAll(doInline(i, invokeForInlining, reason));
         }
         if (returnValuePhi != null) {
             canonicalizeNodes.add(returnValuePhi);
@@ -285,8 +285,8 @@
         return canonicalizeNodes;
     }
 
-    protected EconomicSet<Node> doInline(int index, Invoke invokeForInlining) {
-        return inline(invokeForInlining, methodAt(index), inlineableElementAt(index), false);
+    protected EconomicSet<Node> doInline(int index, Invoke invokeForInlining, String reason) {
+        return inline(invokeForInlining, methodAt(index), inlineableElementAt(index), false, reason);
     }
 
     private int getTypeCount(int concreteMethodIndex) {
@@ -322,7 +322,7 @@
         return result;
     }
 
-    private EconomicSet<Node> inlineSingleMethod(StructuredGraph graph, StampProvider stampProvider, ConstantReflectionProvider constantReflection) {
+    private EconomicSet<Node> inlineSingleMethod(StructuredGraph graph, StampProvider stampProvider, ConstantReflectionProvider constantReflection, String reason) {
         assert concretes.size() == 1 && inlineableElements.length == 1 && ptypes.size() > 1 && !shouldFallbackToInvoke() && notRecordedTypeProbability == 0;
 
         AbstractBeginNode calleeEntryNode = graph.add(new BeginNode());
@@ -333,7 +333,7 @@
 
         calleeEntryNode.setNext(invoke.asNode());
 
-        return inline(invoke, methodAt(0), inlineableElementAt(0), false);
+        return inline(invoke, methodAt(0), inlineableElementAt(0), false, reason);
     }
 
     private boolean createDispatchOnTypeBeforeInvoke(StructuredGraph graph, AbstractBeginNode[] successors, boolean invokeIsOnlySuccessor, StampProvider stampProvider,
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/info/TypeGuardInlineInfo.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,8 +22,9 @@
  */
 package org.graalvm.compiler.phases.common.inlining.info;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
 import org.graalvm.compiler.nodes.ConstantNode;
@@ -98,9 +99,9 @@
     }
 
     @Override
-    public EconomicSet<Node> inline(Providers providers) {
+    public EconomicSet<Node> inline(Providers providers, String reason) {
         createGuard(graph(), providers);
-        return inline(invoke, concrete, inlineableElement, false);
+        return inline(invoke, concrete, inlineableElement, false, reason);
     }
 
     @Override
@@ -109,19 +110,22 @@
         InliningUtil.replaceInvokeCallTarget(invoke, graph(), InvokeKind.Special, concrete);
     }
 
+    @SuppressWarnings("try")
     private void createGuard(StructuredGraph graph, Providers providers) {
-        ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
-        LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
-        ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph);
+        try (DebugCloseable context = invoke.asNode().withNodeSourcePosition()) {
+            ValueNode nonNullReceiver = InliningUtil.nonNullReceiver(invoke);
+            LoadHubNode receiverHub = graph.unique(new LoadHubNode(providers.getStampProvider(), nonNullReceiver));
+            ConstantNode typeHub = ConstantNode.forConstant(receiverHub.stamp(NodeView.DEFAULT), providers.getConstantReflection().asObjectHub(type), providers.getMetaAccess(), graph);
 
-        LogicNode typeCheck = CompareNode.createCompareNode(graph, CanonicalCondition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT);
-        FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
-        assert invoke.predecessor() != null;
+            LogicNode typeCheck = CompareNode.createCompareNode(graph, CanonicalCondition.EQ, receiverHub, typeHub, providers.getConstantReflection(), NodeView.DEFAULT);
+            FixedGuardNode guard = graph.add(new FixedGuardNode(typeCheck, DeoptimizationReason.TypeCheckedInliningViolated, DeoptimizationAction.InvalidateReprofile));
+            assert invoke.predecessor() != null;
 
-        ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true);
-        invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver);
+            ValueNode anchoredReceiver = InliningUtil.createAnchoredReceiver(graph, guard, type, nonNullReceiver, true);
+            invoke.callTarget().replaceFirstInput(nonNullReceiver, anchoredReceiver);
 
-        graph.addBeforeFixed(invoke.asNode(), guard);
+            graph.addBeforeFixed(invoke.asNode(), guard);
+        }
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/GreedyInliningPolicy.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,6 +27,7 @@
 import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
 import static org.graalvm.compiler.core.common.GraalOptions.MaximumInliningSize;
 import static org.graalvm.compiler.core.common.GraalOptions.SmallCompiledLowLevelGraphSize;
+import static org.graalvm.compiler.core.common.GraalOptions.TraceInlining;
 import static org.graalvm.compiler.core.common.GraalOptions.TrivialInliningSize;
 
 import java.util.Map;
@@ -61,8 +62,8 @@
     }
 
     @Override
-    public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+        final boolean isTracing = TraceInlining.getValue(replacements.getOptions());
         final InlineInfo info = invocation.callee();
         OptionValues options = info.graph().getOptions();
         final double probability = invocation.probability();
@@ -70,17 +71,17 @@
 
         if (InlineEverything.getValue(options)) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "inline everything");
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "inline everything");
         }
 
         if (isIntrinsic(replacements, info)) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "intrinsic");
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "intrinsic");
         }
 
         if (info.shouldInline()) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "forced inlining");
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "forced inlining");
         }
 
         double inliningBonus = getInliningBonus(info);
@@ -90,12 +91,13 @@
         if (SmallCompiledLowLevelGraphSize.getValue(options) > 0 && lowLevelGraphSize > SmallCompiledLowLevelGraphSize.getValue(options) * inliningBonus) {
             InliningUtil.traceNotInlinedMethod(info, inliningDepth, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)", lowLevelGraphSize,
                             relevance, probability, inliningBonus, nodes);
-            return false;
+            return InliningPolicy.Decision.NO.withReason(isTracing, "too large previous low-level graph (low-level-nodes: %d, relevance=%f, probability=%f, bonus=%f, nodes=%d)", lowLevelGraphSize,
+                            relevance, probability, inliningBonus, nodes);
         }
 
         if (nodes < TrivialInliningSize.getValue(options) * inliningBonus) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "trivial (relevance=%f, probability=%f, bonus=%f, nodes=%d)", relevance, probability, inliningBonus, nodes);
         }
 
         /*
@@ -108,17 +110,19 @@
         if (LimitInlinedInvokes.getValue(options) > 0 && fullyProcessed && invokes > LimitInlinedInvokes.getValue(options) * inliningBonus) {
             InliningUtil.traceNotInlinedMethod(info, inliningDepth, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, relevance,
                             probability, inliningBonus, nodes);
-            return false;
+            return InliningPolicy.Decision.NO.withReason(isTracing, "callee invoke probability is too high (invokeP=%f, relevance=%f, probability=%f, bonus=%f, nodes=%d)", invokes, relevance,
+                            probability, inliningBonus, nodes);
         }
 
         double maximumNodes = computeMaximumSize(relevance, (int) (MaximumInliningSize.getValue(options) * inliningBonus));
         if (nodes <= maximumNodes) {
             InliningUtil.traceInlinedMethod(info, inliningDepth, fullyProcessed, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
                             nodes, maximumNodes);
-            return true;
+            return InliningPolicy.Decision.YES.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d <= %f)", relevance, probability, inliningBonus,
+                            nodes, maximumNodes);
         }
 
         InliningUtil.traceNotInlinedMethod(info, inliningDepth, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
-        return false;
+        return InliningPolicy.Decision.NO.withReason(isTracing, "relevance-based (relevance=%f, probability=%f, bonus=%f, nodes=%d > %f)", relevance, probability, inliningBonus, nodes, maximumNodes);
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineEverythingPolicy.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,6 +24,7 @@
 
 import static org.graalvm.compiler.core.common.GraalOptions.MaximumDesiredSize;
 
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.spi.Replacements;
@@ -41,7 +42,7 @@
     }
 
     @Override
-    public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
-        return true;
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+        return Decision.YES.withReason(GraalOptions.TraceInlining.getValue(replacements.getOptions()), "inline everything");
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InlineMethodSubstitutionsPolicy.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,7 @@
  */
 package org.graalvm.compiler.phases.common.inlining.policy;
 
+import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.nodes.CallTargetNode;
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 import org.graalvm.compiler.nodes.spi.Replacements;
@@ -35,14 +36,15 @@
 public final class InlineMethodSubstitutionsPolicy extends InlineEverythingPolicy {
 
     @Override
-    public boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+    public Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed) {
+        final boolean isTracing = GraalOptions.TraceInlining.getValue(replacements.getOptions());
         CallTargetNode callTarget = invocation.callee().invoke().callTarget();
         if (callTarget instanceof MethodCallTargetNode) {
             ResolvedJavaMethod calleeMethod = ((MethodCallTargetNode) callTarget).targetMethod();
             if (replacements.hasSubstitution(calleeMethod, invocation.callee().invoke().bci())) {
-                return true;
+                return Decision.YES.withReason(isTracing, "has a method subtitution");
             }
         }
-        return false;
+        return Decision.NO.withReason(isTracing, "does not have a method substitution");
     }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/policy/InliningPolicy.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,36 @@
 import org.graalvm.compiler.phases.common.inlining.walker.MethodInvocation;
 
 public interface InliningPolicy {
+    class Decision {
+        public static final Decision YES = new Decision(true, "(unknown reason)");
+        public static final Decision NO = new Decision(false, "(unknown reason)");
+
+        private final boolean shouldInline;
+        private final String reason;
+
+        private Decision(boolean shouldInline, String reason) {
+            this.shouldInline = shouldInline;
+            this.reason = reason;
+        }
+
+        public boolean shouldInline() {
+            return shouldInline;
+        }
+
+        public String getReason() {
+            return reason;
+        }
+
+        public Decision withReason(boolean isTracing, String newReason, Object... args) {
+            if (isTracing) {
+                return new Decision(shouldInline, String.format(newReason, args));
+            } else {
+                return this;
+            }
+        }
+    }
 
     boolean continueInlining(StructuredGraph graph);
 
-    boolean isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
+    Decision isWorthInlining(Replacements replacements, MethodInvocation invocation, int inliningDepth, boolean fullyProcessed);
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/CallsiteHolderExplorable.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import java.util.LinkedList;
 import java.util.function.ToDoubleFunction;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.nodes.FixedNode;
 import org.graalvm.compiler.nodes.Invoke;
 import org.graalvm.compiler.nodes.ParameterNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/ComputeInliningRelevance.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
 import java.util.ArrayList;
 import java.util.function.ToDoubleFunction;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.SuppressFBWarnings;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeWorkList;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/inlining/walker/InliningData.java	Thu Apr 26 17:59:02 2018 +0200
@@ -34,8 +34,8 @@
 import java.util.LinkedList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.type.ObjectStamp;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
@@ -167,6 +167,7 @@
             return true;
         } else {
             InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), method, failureMessage);
+            invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, failureMessage);
             return false;
         }
     }
@@ -258,12 +259,14 @@
         JavaTypeProfile typeProfile = ((MethodCallTargetNode) invoke.callTarget()).getProfile();
         if (typeProfile == null) {
             InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no type profile exists");
+            invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "no type profile exists");
             return null;
         }
 
         JavaTypeProfile.ProfiledType[] ptypes = typeProfile.getTypes();
         if (ptypes == null || ptypes.length <= 0) {
             InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no types in profile");
+            invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "no types in profile");
             return null;
         }
         ResolvedJavaType contextType = invoke.getContextType();
@@ -273,6 +276,7 @@
         if (ptypes.length == 1 && notRecordedTypeProbability == 0) {
             if (!optimisticOpts.inlineMonomorphicCalls(options)) {
                 InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining monomorphic calls is disabled");
+                invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "inlining monomorphic calls is disabled");
                 return null;
             }
 
@@ -288,6 +292,7 @@
 
             if (!optimisticOpts.inlinePolymorphicCalls(options) && notRecordedTypeProbability == 0) {
                 InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining polymorphic calls is disabled (%d types)", ptypes.length);
+                invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "inlining polymorphic calls is disabled (%d types)", ptypes.length);
                 return null;
             }
             if (!optimisticOpts.inlineMegamorphicCalls(options) && notRecordedTypeProbability > 0) {
@@ -295,6 +300,8 @@
                 // the number of types is lower than what can be recorded in a type profile
                 InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.length,
                                 notRecordedTypeProbability * 100);
+                invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null,
+                                "inlining megamorphic calls is disabled (%d types, %f %% not recorded types)", ptypes.length, notRecordedTypeProbability);
                 return null;
             }
 
@@ -305,6 +312,7 @@
                 ResolvedJavaMethod concrete = ptypes[i].getType().resolveConcreteMethod(targetMethod, contextType);
                 if (concrete == null) {
                     InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "could not resolve method");
+                    invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "could not resolve method");
                     return null;
                 }
                 int index = concreteMethods.indexOf(concrete);
@@ -333,6 +341,8 @@
                     // No method left that is worth inlining.
                     InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no methods remaining after filtering less frequent methods (%d methods previously)",
                                     concreteMethods.size());
+                    invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null,
+                                    "no methods remaining after filtering less frequent methods (%d methods previously)", concreteMethods.size());
                     return null;
                 }
 
@@ -342,6 +352,7 @@
 
             if (concreteMethods.size() > maxMethodPerInlining) {
                 InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "polymorphic call with more than %d target methods", maxMethodPerInlining);
+                invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "polymorphic call with more than %d target methods", maxMethodPerInlining);
                 return null;
             }
 
@@ -363,12 +374,16 @@
             if (usedTypes.isEmpty()) {
                 // No type left that is worth checking for.
                 InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "no types remaining after filtering less frequent types (%d types previously)", ptypes.length);
+                invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null, "no types remaining after filtering less frequent types (%d types previously)",
+                                ptypes.length);
                 return null;
             }
 
             for (ResolvedJavaMethod concrete : concreteMethods) {
                 if (!checkTargetConditions(invoke, concrete)) {
                     InliningUtil.traceNotInlinedMethod(invoke, inliningDepth(), targetMethod, "it is a polymorphic method call and at least one invoked method cannot be inlined");
+                    invoke.asNode().graph().getInliningLog().addDecision(invoke, false, "InliningPhase", null, null,
+                                    "it is a polymorphic method call and at least one invoked method cannot be inlined");
                     return null;
                 }
             }
@@ -393,14 +408,14 @@
     }
 
     @SuppressWarnings("try")
-    private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation) {
+    private void doInline(CallsiteHolderExplorable callerCallsiteHolder, MethodInvocation calleeInvocation, String reason) {
         StructuredGraph callerGraph = callerCallsiteHolder.graph();
         InlineInfo calleeInfo = calleeInvocation.callee();
         try {
             try (DebugContext.Scope scope = debug.scope("doInline", callerGraph)) {
                 EconomicSet<Node> canonicalizedNodes = EconomicSet.create(Equivalence.IDENTITY);
                 canonicalizedNodes.addAll(calleeInfo.invoke().asNode().usages());
-                EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context));
+                EconomicSet<Node> parameterUsages = calleeInfo.inline(new Providers(context), reason);
                 canonicalizedNodes.addAll(parameterUsages);
                 counterInliningRuns.increment(debug);
                 debug.dump(DebugContext.DETAILED_LEVEL, callerGraph, "after %s", calleeInfo);
@@ -449,8 +464,9 @@
         assert callerCallsiteHolder.containsInvoke(calleeInfo.invoke());
         counterInliningConsidered.increment(debug);
 
-        if (inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true)) {
-            doInline(callerCallsiteHolder, calleeInvocation);
+        InliningPolicy.Decision decision = inliningPolicy.isWorthInlining(context.getReplacements(), calleeInvocation, inliningDepth, true);
+        if (decision.shouldInline()) {
+            doInline(callerCallsiteHolder, calleeInvocation, decision.getReason());
             return true;
         }
 
@@ -483,7 +499,7 @@
      * <p>
      * The {@link InlineInfo} used to get things rolling is kept around in the
      * {@link MethodInvocation}, it will be needed in case of inlining, see
-     * {@link InlineInfo#inline(Providers)}
+     * {@link InlineInfo#inline(Providers, String)}
      * </p>
      */
     private void processNextInvoke() {
@@ -709,7 +725,7 @@
 
         final MethodInvocation currentInvocation = currentInvocation();
 
-        final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false));
+        final boolean backtrack = (!currentInvocation.isRoot() && !inliningPolicy.isWorthInlining(context.getReplacements(), currentInvocation, inliningDepth(), false).shouldInline());
         if (backtrack) {
             int remainingGraphs = currentInvocation.totalGraphs() - currentInvocation.processedGraphs();
             assert remainingGraphs > 0;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases.common/src/org/graalvm/compiler/phases/common/util/HashSetNodeEventListener.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import java.util.HashSet;
 import java.util.Set;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.graph.Graph.NodeEvent;
 import org.graalvm.compiler.graph.Graph.NodeEventListener;
 import org.graalvm.compiler.graph.Node;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/FixedNodeProbabilityCache.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 
 import java.util.function.ToDoubleFunction;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.debug.CounterKey;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.Node;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/PostOrderNodeIterator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
 import java.util.Deque;
 import java.util.Set;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeBitMap;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantBlockIterator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,8 +28,8 @@
 import java.util.List;
 import java.util.function.Predicate;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
 import org.graalvm.compiler.core.common.RetryableBailoutException;
 import org.graalvm.compiler.core.common.cfg.Loop;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/ReentrantNodeIterator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,9 +28,9 @@
 import java.util.Iterator;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
 import org.graalvm.compiler.nodes.AbstractEndNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/graph/SinglePassNodeIterator.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
 import java.util.Deque;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.graph.NodeBitMap;
 import org.graalvm.compiler.nodes.AbstractBeginNode;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/MemoryScheduleVerification.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,8 +24,8 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.debug.DebugContext;
@@ -42,7 +42,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryPhiNode;
 import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
 import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public final class MemoryScheduleVerification extends BlockIteratorClosure<EconomicSet<FloatingReadNode>> {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/schedule/SchedulePhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.phases.schedule;
 
-import static org.graalvm.collections.Equivalence.IDENTITY;
+import static jdk.internal.vm.compiler.collections.Equivalence.IDENTITY;
 import static org.graalvm.compiler.core.common.GraalOptions.GuardPriorities;
 import static org.graalvm.compiler.core.common.GraalOptions.OptScheduleOutOfLoops;
 import static org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph.strictlyDominates;
@@ -38,7 +38,7 @@
 import java.util.TreeSet;
 import java.util.function.Function;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.SuppressFBWarnings;
 import org.graalvm.compiler.core.common.cfg.AbstractControlFlowGraph;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
@@ -83,7 +83,7 @@
 import org.graalvm.compiler.nodes.spi.ValueProxy;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.Phase;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public final class SchedulePhase extends Phase {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/Suites.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/tiers/Suites.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,10 @@
  */
 package org.graalvm.compiler.phases.tiers;
 
+import org.graalvm.compiler.lir.alloc.RegisterAllocationPhase;
+import org.graalvm.compiler.lir.phases.AllocationPhase.AllocationContext;
+import org.graalvm.compiler.lir.phases.LIRPhase;
+import org.graalvm.compiler.lir.phases.LIRPhaseSuite;
 import org.graalvm.compiler.lir.phases.LIRSuites;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.PhaseSuite;
@@ -56,7 +60,25 @@
     }
 
     public static LIRSuites createLIRSuites(CompilerConfiguration config, OptionValues options) {
-        return new LIRSuites(config.createPreAllocationOptimizationStage(options), config.createAllocationStage(options), config.createPostAllocationOptimizationStage(options));
+        LIRPhaseSuite<AllocationContext> allocationStage = config.createAllocationStage(options);
+        assert verifyAllocationStage(allocationStage);
+        return new LIRSuites(config.createPreAllocationOptimizationStage(options), allocationStage, config.createPostAllocationOptimizationStage(options));
+    }
+
+    private static boolean verifyAllocationStage(LIRPhaseSuite<AllocationContext> allocationStage) {
+        boolean allocationPhase = false;
+        for (LIRPhase<?> phase : allocationStage.getPhases()) {
+            if (phase instanceof RegisterAllocationPhase) {
+                if (allocationPhase) {
+                    assert false : "More than one register allocation phase";
+                    return false;
+                }
+                allocationPhase = true;
+            }
+
+        }
+        assert allocationPhase : "No register allocation phase";
+        return allocationPhase;
     }
 
     public boolean isImmutable() {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/util/GraphOrder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.GraalGraphError;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyCallerSensitiveMethods.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyCallerSensitiveMethods.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,7 +22,7 @@
  */
 package org.graalvm.compiler.phases.verify;
 
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import java.lang.annotation.Annotation;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.phases/src/org/graalvm/compiler/phases/verify/VerifyGraphAddUsage.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/BinaryGraphPrinter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,9 @@
 import static org.graalvm.compiler.graph.Edges.Type.Successors;
 
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -72,17 +75,26 @@
 import jdk.vm.ci.meta.ResolvedJavaField;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 import jdk.vm.ci.meta.Signature;
+import org.graalvm.graphio.GraphLocations;
 
 public class BinaryGraphPrinter implements
                 GraphStructure<BinaryGraphPrinter.GraphInfo, Node, NodeClass<?>, Edges>,
                 GraphBlocks<BinaryGraphPrinter.GraphInfo, Block, Node>,
                 GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition>,
+                GraphLocations<ResolvedJavaMethod, NodeSourcePosition, SourceLanguagePosition>,
                 GraphTypes, GraphPrinter {
     private final SnippetReflectionProvider snippetReflection;
     private final GraphOutput<BinaryGraphPrinter.GraphInfo, ResolvedJavaMethod> output;
 
     public BinaryGraphPrinter(DebugContext ctx, SnippetReflectionProvider snippetReflection) throws IOException {
-        this.output = ctx.buildOutput(GraphOutput.newBuilder(this).protocolVersion(5, 0).blocks(this).elements(this).types(this));
+        // @formatter:off
+        this.output = ctx.buildOutput(GraphOutput.newBuilder(this).
+                        protocolVersion(6, 0).
+                        blocks(this).
+                        elementsAndLocations(this, this).
+                        types(this)
+        );
+        // @formatter:on
         this.snippetReflection = snippetReflection;
     }
 
@@ -266,17 +278,6 @@
             }
             props.put("category", "floating");
         }
-        if (node.getNodeSourcePosition() != null) {
-            NodeSourcePosition pos = node.getNodeSourcePosition();
-            while (pos != null) {
-                SourceLanguagePosition cur = pos.getSourceLanauage();
-                if (cur != null) {
-                    cur.addSourceInformation(props);
-                    break;
-                }
-                pos = pos.getCaller();
-            }
-        }
         if (getSnippetReflectionProvider() != null) {
             for (Map.Entry<String, Object> prop : props.entrySet()) {
                 if (prop.getValue() instanceof JavaConstantFormattable) {
@@ -502,6 +503,85 @@
         return method.asStackTraceElement(bci);
     }
 
+    @Override
+    public Iterable<SourceLanguagePosition> methodLocation(ResolvedJavaMethod method, int bci, NodeSourcePosition pos) {
+        StackTraceElement e = methodStackTraceElement(method, bci, pos);
+        class JavaSourcePosition implements SourceLanguagePosition {
+
+            @Override
+            public String toShortString() {
+                return e.toString();
+            }
+
+            @Override
+            public int getOffsetEnd() {
+                return -1;
+            }
+
+            @Override
+            public int getOffsetStart() {
+                return -1;
+            }
+
+            @Override
+            public int getLineNumber() {
+                return e.getLineNumber();
+            }
+
+            @Override
+            public URI getURI() {
+                String path = e.getFileName();
+                try {
+                    return path == null ? null : new URI(null, null, path, null);
+                } catch (URISyntaxException ex) {
+                    throw new IllegalArgumentException(ex);
+                }
+            }
+
+            @Override
+            public String getLanguage() {
+                return "Java";
+            }
+        }
+
+        List<SourceLanguagePosition> arr = new ArrayList<>();
+        arr.add(new JavaSourcePosition());
+        NodeSourcePosition at = pos;
+        while (at != null) {
+            SourceLanguagePosition cur = at.getSourceLanguage();
+            if (cur != null) {
+                arr.add(cur);
+            }
+            at = at.getCaller();
+        }
+        return arr;
+    }
+
+    @Override
+    public String locationLanguage(SourceLanguagePosition location) {
+        return location.getLanguage();
+    }
+
+    @Override
+    public URI locationURI(SourceLanguagePosition location) {
+        return location.getURI();
+    }
+
+    @Override
+    public int locationLineNumber(SourceLanguagePosition location) {
+        return location.getLineNumber();
+    }
+
+    @Override
+    public int locationOffsetStart(SourceLanguagePosition location) {
+        return location.getOffsetStart();
+    }
+
+    @Override
+    public int locationOffsetEnd(SourceLanguagePosition location) {
+        return location.getOffsetEnd();
+    }
+
     static final class GraphInfo {
         final DebugContext debug;
         final Graph graph;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/CFGPrinter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,7 +33,7 @@
 import java.util.Map;
 import java.util.TreeMap;
 
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeDisassembler;
 import org.graalvm.compiler.core.common.alloc.Trace;
@@ -116,38 +116,38 @@
     }
 
     private void printBlock(BciBlockMapping.BciBlock block) {
-        out.print("name \"B").print(block.startBci).println('"');
-        out.print("from_bci ").println(block.startBci);
-        out.print("to_bci ").println(block.endBci);
+        out.print("name \"B").print(block.getStartBci()).println('"');
+        out.print("from_bci ").println(block.getStartBci());
+        out.print("to_bci ").println(block.getEndBci());
 
         out.println("predecessors ");
 
         out.print("successors ");
         for (BciBlockMapping.BciBlock succ : block.getSuccessors()) {
-            if (!succ.isExceptionEntry) {
-                out.print("\"B").print(succ.startBci).print("\" ");
+            if (!succ.isExceptionEntry()) {
+                out.print("\"B").print(succ.getStartBci()).print("\" ");
             }
         }
         out.println();
 
         out.print("xhandlers");
         for (BciBlockMapping.BciBlock succ : block.getSuccessors()) {
-            if (succ.isExceptionEntry) {
-                out.print("\"B").print(succ.startBci).print("\" ");
+            if (succ.isExceptionEntry()) {
+                out.print("\"B").print(succ.getStartBci()).print("\" ");
             }
         }
         out.println();
 
         out.print("flags ");
-        if (block.isExceptionEntry) {
+        if (block.isExceptionEntry()) {
             out.print("\"ex\" ");
         }
-        if (block.isLoopHeader) {
+        if (block.isLoopHeader()) {
             out.print("\"plh\" ");
         }
         out.println();
 
-        out.print("loop_depth ").println(Long.bitCount(block.loops));
+        out.print("loop_depth ").println(Long.bitCount(block.getLoops()));
     }
 
     private NodeMap<Block> latestScheduling;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,15 +37,13 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.util.JavaConstantFormatter;
 import org.graalvm.compiler.phases.schedule.SchedulePhase;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
 import jdk.vm.ci.meta.MetaUtil;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
-import jdk.vm.ci.runtime.JVMCI;
-import jdk.vm.ci.services.Services;
 
 interface GraphPrinter extends Closeable, JavaConstantFormatter {
 
@@ -72,16 +70,6 @@
     void close();
 
     /**
-     * A JVMCI package dynamically exported to trusted modules.
-     */
-    String JVMCI_RUNTIME_PACKAGE = JVMCI.class.getPackage().getName();
-
-    /**
-     * {@code jdk.vm.ci} module.
-     */
-    Object JVMCI_MODULE = JDK9Method.JAVA_SPECIFICATION_VERSION < 9 ? null : JDK9Method.getModule(Services.class);
-
-    /**
      * Classes whose {@link #toString()} method does not run any untrusted code.
      */
     List<Class<?>> TRUSTED_CLASSES = Arrays.asList(
@@ -105,17 +93,8 @@
         if (TRUSTED_CLASSES.contains(c)) {
             return true;
         }
-        if (JDK9Method.JAVA_SPECIFICATION_VERSION < 9) {
-            if (c.getClassLoader() == Services.class.getClassLoader()) {
-                // Loaded by the JVMCI class loader
-                return true;
-            }
-        } else {
-            Object module = JDK9Method.getModule(c);
-            if (JVMCI_MODULE == module || JDK9Method.isOpenTo(JVMCI_MODULE, JVMCI_RUNTIME_PACKAGE, module)) {
-                // Can access non-statically-exported package in JVMCI
-                return true;
-            }
+        if (GraalServices.isToStringTrusted(c)) {
+            return true;
         }
         if (c.getClassLoader() == GraphPrinter.class.getClassLoader()) {
             return true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.printer/src/org/graalvm/compiler/printer/GraphPrinterDumpHandler.java	Thu Apr 26 17:59:02 2018 +0200
@@ -45,6 +45,7 @@
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.phases.contract.NodeCostUtil;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.meta.JavaMethod;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
@@ -86,11 +87,11 @@
     }
 
     private static String jvmArguments() {
-        try {
-            return String.join(" ", java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments());
-        } catch (LinkageError err) {
-            return "unknown";
+        List<String> inputArguments = GraalServices.getInputArguments();
+        if (inputArguments != null) {
+            return String.join(" ", inputArguments);
         }
+        return "unknown";
     }
 
     private void ensureInitialized(DebugContext ctx, Graph graph) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64GraphBuilderPlugins.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,6 +28,7 @@
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
+import static org.graalvm.compiler.serviceprovider.GraalServices.JAVA_SPECIFICATION_VERSION;
 
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.nodes.ValueNode;
@@ -53,6 +54,9 @@
                 registerIntegerLongPlugins(invocationPlugins, AArch64IntegerSubstitutions.class, JavaKind.Int, bytecodeProvider);
                 registerIntegerLongPlugins(invocationPlugins, AArch64LongSubstitutions.class, JavaKind.Long, bytecodeProvider);
                 registerMathPlugins(invocationPlugins);
+                registerStringLatin1Plugins(invocationPlugins, bytecodeProvider);
+                registerStringUTF16Plugins(invocationPlugins, bytecodeProvider);
+
             }
         });
     }
@@ -114,4 +118,23 @@
             }
         });
     }
+
+    private static void registerStringLatin1Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
+        if (JAVA_SPECIFICATION_VERSION >= 9) {
+            Registration r = new Registration(plugins, "java.lang.StringLatin1", replacementsBytecodeProvider);
+            r.setAllowOverwrite(true);
+            r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareTo", byte[].class, byte[].class);
+            r.registerMethodSubstitution(AArch64StringLatin1Substitutions.class, "compareToUTF16", byte[].class, byte[].class);
+        }
+    }
+
+    private static void registerStringUTF16Plugins(InvocationPlugins plugins, BytecodeProvider replacementsBytecodeProvider) {
+        if (JAVA_SPECIFICATION_VERSION >= 9) {
+            Registration r = new Registration(plugins, "java.lang.StringUTF16", replacementsBytecodeProvider);
+            r.setAllowOverwrite(true);
+            r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareTo", byte[].class, byte[].class);
+            r.registerMethodSubstitution(AArch64StringUTF16Substitutions.class, "compareToLatin1", byte[].class, byte[].class);
+        }
+    }
+
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * 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.replacements.aarch64;
-
-import jdk.vm.ci.aarch64.AArch64Kind;
-import org.graalvm.compiler.core.aarch64.AArch64ArithmeticLIRGenerator;
-import org.graalvm.compiler.core.aarch64.AArch64LIRGenerator;
-import org.graalvm.compiler.core.common.type.IntegerStamp;
-import org.graalvm.compiler.core.common.type.Stamp;
-import org.graalvm.compiler.graph.NodeClass;
-import org.graalvm.compiler.lir.aarch64.AArch64AddressValue;
-import org.graalvm.compiler.nodeinfo.NodeInfo;
-import org.graalvm.compiler.nodes.FrameState;
-import org.graalvm.compiler.nodes.NodeView;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.compiler.nodes.calc.SignExtendNode;
-import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
-import org.graalvm.compiler.nodes.extended.GuardingNode;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.nodes.memory.address.AddressNode;
-import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
-
-/**
- * AArch64-specific subclass of ReadNode that knows how to merge ZeroExtend and SignExtend into the
- * read.
- */
-
-@NodeInfo
-public class AArch64ReadNode extends ReadNode {
-    public static final NodeClass<AArch64ReadNode> TYPE = NodeClass.create(AArch64ReadNode.class);
-    private final IntegerStamp accessStamp;
-    private final boolean isSigned;
-
-    public AArch64ReadNode(AddressNode address, LocationIdentity location, Stamp stamp, GuardingNode guard, BarrierType barrierType, boolean nullCheck,
-                    FrameState stateBefore, IntegerStamp accessStamp, boolean isSigned) {
-        super(TYPE, address, location, stamp, guard, barrierType, nullCheck, stateBefore);
-        this.accessStamp = accessStamp;
-        this.isSigned = isSigned;
-    }
-
-    @Override
-    public void generate(NodeLIRBuilderTool gen) {
-        AArch64LIRGenerator lirgen = (AArch64LIRGenerator) gen.getLIRGeneratorTool();
-        AArch64ArithmeticLIRGenerator arithgen = (AArch64ArithmeticLIRGenerator) lirgen.getArithmetic();
-        AArch64Kind readKind = (AArch64Kind) lirgen.getLIRKind(accessStamp).getPlatformKind();
-        int resultBits = ((IntegerStamp) stamp(NodeView.DEFAULT)).getBits();
-        gen.setResult(this, arithgen.emitExtendMemory(isSigned, readKind, resultBits, (AArch64AddressValue) gen.operand(getAddress()), gen.state(this)));
-    }
-
-    /**
-     * replace a ReadNode with an AArch64-specific variant which knows how to merge a downstream
-     * zero or sign extend into the read operation.
-     *
-     * @param readNode
-     */
-    public static void replace(ReadNode readNode) {
-        assert readNode.getUsageCount() == 1;
-        assert readNode.getUsageAt(0) instanceof ZeroExtendNode || readNode.getUsageAt(0) instanceof SignExtendNode;
-
-        ValueNode usage = (ValueNode) readNode.getUsageAt(0);
-        boolean isSigned = usage instanceof SignExtendNode;
-        IntegerStamp accessStamp = ((IntegerStamp) readNode.getAccessStamp());
-
-        AddressNode address = readNode.getAddress();
-        LocationIdentity location = readNode.getLocationIdentity();
-        Stamp stamp = usage.stamp(NodeView.DEFAULT);
-        GuardingNode guard = readNode.getGuard();
-        BarrierType barrierType = readNode.getBarrierType();
-        boolean nullCheck = readNode.getNullCheck();
-        FrameState stateBefore = readNode.stateBefore();
-        AArch64ReadNode clone = new AArch64ReadNode(address, location, stamp, guard, barrierType, nullCheck, stateBefore, accessStamp, isSigned);
-        StructuredGraph graph = readNode.graph();
-        graph.add(clone);
-        // splice out the extend node
-        usage.replaceAtUsagesAndDelete(readNode);
-        // swap the clone for the read
-        graph.replaceFixedWithFixed(readNode, clone);
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64ReadReplacementPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,58 +0,0 @@
-/*
- * 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.replacements.aarch64;
-
-import org.graalvm.compiler.graph.Node;
-import org.graalvm.compiler.nodes.StructuredGraph;
-import org.graalvm.compiler.nodes.calc.SignExtendNode;
-import org.graalvm.compiler.nodes.calc.ZeroExtendNode;
-import org.graalvm.compiler.nodes.memory.ReadNode;
-import org.graalvm.compiler.phases.Phase;
-
-/**
- * AArch64-specific phase which substitutes certain read nodes with arch-specific variants in order
- * to allow merging of zero and sign extension into the read operation.
- */
-
-public class AArch64ReadReplacementPhase extends Phase {
-    @Override
-    protected void run(StructuredGraph graph) {
-        for (Node node : graph.getNodes()) {
-            // don't process nodes we just added
-            if (node instanceof AArch64ReadNode) {
-                continue;
-            }
-            if (node instanceof ReadNode) {
-                ReadNode readNode = (ReadNode) node;
-                if (readNode.getUsageCount() == 1) {
-                    Node usage = readNode.getUsageAt(0);
-                    if (usage instanceof ZeroExtendNode || usage instanceof SignExtendNode) {
-                        AArch64ReadNode.replace(readNode);
-                    }
-                }
-            }
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64StringLatin1Substitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,59 @@
+/*
+ * 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.replacements.aarch64;
+
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
+
+import jdk.vm.ci.meta.JavaKind;
+
+// JaCoCo Exclude
+
+/**
+ * Substitutions for {@code java.lang.StringLatin1} methods.
+ *
+ * Since JDK 9.
+ */
+@ClassSubstitution(className = "java.lang.StringLatin1", optional = true)
+public class AArch64StringLatin1Substitutions {
+
+    /**
+     * @param value is byte[]
+     * @param other is char[]
+     */
+    @MethodSubstitution
+    public static int compareTo(byte[] value, byte[] other) {
+        return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Byte, JavaKind.Byte);
+    }
+
+    /**
+     * @param value is byte[]
+     * @param other is char[]
+     */
+    @MethodSubstitution
+    public static int compareToUTF16(byte[] value, byte[] other) {
+        return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Byte, JavaKind.Char);
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.aarch64/src/org/graalvm/compiler/replacements/aarch64/AArch64StringUTF16Substitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,63 @@
+/*
+ * 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.replacements.aarch64;
+
+import org.graalvm.compiler.api.replacements.ClassSubstitution;
+import org.graalvm.compiler.api.replacements.MethodSubstitution;
+import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
+
+import jdk.vm.ci.meta.JavaKind;
+
+// JaCoCo Exclude
+
+/**
+ * Substitutions for {@code java.lang.StringUTF16} methods.
+ *
+ * Since JDK 9.
+ */
+@ClassSubstitution(className = "java.lang.StringUTF16", optional = true)
+public class AArch64StringUTF16Substitutions {
+
+    /**
+     * @param value is char[]
+     * @param other is char[]
+     */
+    @MethodSubstitution
+    public static int compareTo(byte[] value, byte[] other) {
+        return ArrayCompareToNode.compareTo(value, other, value.length, other.length, JavaKind.Char, JavaKind.Char);
+    }
+
+    /**
+     * @param value is char[]
+     * @param other is byte[]
+     */
+    @MethodSubstitution
+    public static int compareToLatin1(byte[] value, byte[] other) {
+        /*
+         * Swapping array arguments because intrinsic expects order to be byte[]/char[] but kind
+         * arguments stay in original order.
+         */
+        return ArrayCompareToNode.compareTo(other, value, other.length, value.length, JavaKind.Char, JavaKind.Byte);
+    }
+
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,8 +29,8 @@
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN;
 import static org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.JAVA_SPECIFICATION_VERSION;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.JAVA_SPECIFICATION_VERSION;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import java.util.Arrays;
 
@@ -57,7 +57,7 @@
 import org.graalvm.compiler.replacements.nodes.BitCountNode;
 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.amd64.AMD64;
 import jdk.vm.ci.amd64.AMD64.CPUFeature;
@@ -194,8 +194,7 @@
                 r.registerMethodSubstitution(AMD64StringSubstitutions.class, "indexOf", char[].class, int.class,
                                 int.class, char[].class, int.class, int.class, int.class);
             }
-            // r.registerMethodSubstitution(AMD64StringSubstitutions.class, "compareTo",
-            // Receiver.class, String.class);
+            r.registerMethodSubstitution(AMD64StringSubstitutions.class, "compareTo", Receiver.class, String.class);
         }
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringIndexOfNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,8 +38,8 @@
 import org.graalvm.compiler.nodes.memory.MemoryNode;
 import org.graalvm.compiler.nodes.spi.LIRLowerable;
 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.amd64/src/org/graalvm/compiler/replacements/amd64/AMD64StringSubstitutions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
 import org.graalvm.compiler.replacements.StringSubstitutions;
 import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
+import jdk.internal.vm.compiler.word.Pointer;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/NestedExceptionHandlerTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,12 +22,20 @@
  */
 package org.graalvm.compiler.replacements.test;
 
+import static org.graalvm.compiler.core.common.GraalOptions.RemoveNeverExecutedCode;
+import static org.graalvm.compiler.core.common.GraalOptions.UseExceptionProbability;
+import static org.graalvm.compiler.core.common.GraalOptions.UseTypeCheckHints;
+
 import org.graalvm.compiler.api.directives.GraalDirectives;
 import org.graalvm.compiler.core.phases.HighTier;
 import org.graalvm.compiler.core.test.GraalCompilerTest;
+import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
 import org.graalvm.compiler.options.OptionValues;
+import org.junit.Ignore;
 import org.junit.Test;
 
+import jdk.vm.ci.meta.ResolvedJavaMethod;
+
 public class NestedExceptionHandlerTest extends GraalCompilerTest {
 
     @BytecodeParserNeverInline(invokeWithException = true)
@@ -63,4 +71,67 @@
         test(new OptionValues(getInitialOptions(), HighTier.Options.Inline, false), "nestedExceptionHandler");
     }
 
+    @SuppressWarnings("try")
+    public static String snippet1() {
+        try {
+            synchronized (String.class) {
+                try (AutoCloseable scope = null) {
+                    return "RETURN";
+                } catch (Throwable t) {
+                    return t.toString();
+                }
+            }
+        } finally {
+            raise();
+        }
+    }
+
+    public static void raise() {
+        throw new RuntimeException();
+    }
+
+    @SuppressWarnings("try")
+    public static String snippet2() {
+        try {
+            synchronized (String.class) {
+                try (AutoCloseable scope = null) {
+                    return performCompilation();
+                } catch (Throwable t) {
+                    return t.toString();
+                }
+            }
+        } finally {
+            synchronized (String.class) {
+                String.class.toString();
+            }
+        }
+    }
+
+    private static String performCompilation() {
+        return "passed";
+    }
+
+    @Ignore("https://bugs.eclipse.org/bugs/show_bug.cgi?id=533187")
+    @Test
+    public void testSnippet1() {
+        OptionValues options = parseAllCodeWithoutInlining();
+        ResolvedJavaMethod method = getResolvedJavaMethod("snippet1");
+        parseEager(method, AllowAssumptions.YES, options);
+    }
+
+    @Ignore("https://bugs.eclipse.org/bugs/show_bug.cgi?id=533187")
+    @Test
+    public void testSnippet2() {
+        OptionValues options = parseAllCodeWithoutInlining();
+        ResolvedJavaMethod method = getResolvedJavaMethod("snippet2");
+        parseEager(method, AllowAssumptions.YES, options);
+    }
+
+    private static OptionValues parseAllCodeWithoutInlining() {
+        OptionValues options = new OptionValues(getInitialOptions(),
+                        UseTypeCheckHints, false,
+                        UseExceptionProbability, false,
+                        RemoveNeverExecutedCode, false);
+        return options;
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ObjectAccessTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -33,9 +33,9 @@
 import org.graalvm.compiler.nodes.extended.JavaWriteNode;
 import org.graalvm.compiler.nodes.memory.address.OffsetAddressNode;
 import org.graalvm.compiler.word.ObjectAccess;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
 import org.junit.Assert;
 import org.junit.Test;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PEGraphDecoderTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -45,7 +45,7 @@
 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 import org.graalvm.compiler.phases.tiers.PhaseContext;
 import org.graalvm.compiler.replacements.CachingPEGraphDecoder;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 import org.junit.Test;
 
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/PointerTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,9 +37,9 @@
 import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.word.Word;
 import org.graalvm.compiler.word.WordCastNode;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.WordFactory;
 import org.junit.Assert;
 import org.junit.Test;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/ReplacementsParseTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -62,7 +62,7 @@
 import org.graalvm.compiler.phases.common.GuardLoweringPhase;
 import org.graalvm.compiler.phases.common.LoweringPhase;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 import org.junit.Assert;
 import org.junit.BeforeClass;
 import org.junit.Test;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/StringCompareToTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,10 +26,10 @@
 import org.graalvm.compiler.replacements.nodes.ArrayCompareToNode;
 import org.junit.Assert;
 import org.junit.Assume;
-import org.junit.Ignore;
 import org.junit.Test;
 
 import jdk.vm.ci.amd64.AMD64;
+import jdk.vm.ci.aarch64.AArch64;
 import jdk.vm.ci.code.InstalledCode;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
 
@@ -49,6 +49,7 @@
                     "\uFF21\uFF21",
                     "\u043c\u0430\u043c\u0430\u0020\u043c\u044b\u043b\u0430\u0020\u0440\u0430\u043c\u0443\u002c\u0020\u0440\u0430\u043c\u0430\u0020\u0441\u044a\u0435\u043b\u0430\u0020\u043c\u0430\u043c\u0443",
                     "crazy dog jumps over laszy fox",
+                    "some-string\0xff",
                     "XMM-XMM-YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
                     "XMM-XMM+YMM-YMM-ZMM-ZMM-ZMM-ZMM-",
                     "XMM-XMM-YMM-YMM+ZMM-ZMM-ZMM-ZMM-",
@@ -61,7 +62,7 @@
     };
 
     public StringCompareToTest() {
-        Assume.assumeTrue(getTarget().arch instanceof AMD64);
+        Assume.assumeTrue((getTarget().arch instanceof AMD64) || (getTarget().arch instanceof AArch64));
 
         realMethod = getResolvedJavaMethod(String.class, "compareTo", String.class);
         testMethod = getResolvedJavaMethod("stringCompareTo");
@@ -91,24 +92,35 @@
     }
 
     @Test
-    @Ignore("GR-8748")
     public void testEqualString() {
         String s = "equal-string";
         executeStringCompareTo(s, new String(s.toCharArray()));
     }
 
     @Test
-    @Ignore("GR-8748")
     public void testDifferentString() {
-        executeStringCompareTo("some-string", "different-string");
+        // Smoke test for primary cases
+        executeStringCompareTo("AAAAAAAA", "");
+        // LL
+        executeStringCompareTo("some-stringA", "some-string\0xff");
+        // UU
+        executeStringCompareTo("\u2241AAAAAAAB", "\u2241\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
+        // LU
+        executeStringCompareTo("AAAAAAAAB", "\u0041\u0041\u0041\u0041\u0041\u0041\u0041\u0041\uFF41");
     }
 
     @Test
-    @Ignore("GR-8748")
     public void testAllStrings() {
         for (String s0 : testData) {
             for (String s1 : testData) {
-                executeStringCompareTo(s0, s1);
+                try {
+                    executeStringCompareTo(s0, s1);
+                } catch (AssertionError ex) {
+                    System.out.println("FAIL: '" + ex + "'");
+                    System.out.println(" ***: s0 '" + s0 + "'");
+                    System.out.println(" ***: s1 '" + s1 + "'");
+                    throw ex;
+                }
             }
         }
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/WordTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,10 +29,10 @@
 import org.graalvm.compiler.phases.PhaseSuite;
 import org.graalvm.compiler.phases.tiers.HighTierContext;
 import org.graalvm.compiler.word.Word;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
 import org.junit.Test;
 
 /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements.test/src/org/graalvm/compiler/replacements/test/classfile/ClassfileBytecodeProviderTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -149,7 +149,7 @@
                     for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
                         final ZipEntry zipEntry = entry.nextElement();
                         String name = zipEntry.getName();
-                        if (name.endsWith(".class") && !name.equals("module-info.class")) {
+                        if (name.endsWith(".class") && !name.equals("module-info.class") && !name.startsWith("META-INF/versions/")) {
                             String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
                             if (isInNativeImage(className)) {
                                 /*
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/CachingPEGraphDecoder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING;
 
-import org.graalvm.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.SourceLanguagePositionProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/DefaultJavaLoweringProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -48,6 +48,7 @@
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.core.common.type.TypeReference;
+import org.graalvm.compiler.debug.DebugCloseable;
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Node;
@@ -131,7 +132,7 @@
 import org.graalvm.compiler.replacements.nodes.BinaryMathIntrinsicNode.BinaryOperation;
 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode;
 import org.graalvm.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.CodeUtil;
 import jdk.vm.ci.code.MemoryBarriers;
@@ -526,7 +527,8 @@
         ValueNode newValue = implicitStoreConvert(graph, valueKind, cas.newValue());
 
         AddressNode address = graph.unique(new OffsetAddressNode(cas.object(), cas.offset()));
-        LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, compareAndSwapBarrierType(cas)));
+        BarrierType barrierType = storeBarrierType(cas.object(), expectedValue);
+        LogicCompareAndSwapNode atomicNode = graph.add(new LogicCompareAndSwapNode(address, cas.getLocationIdentity(), expectedValue, newValue, barrierType));
         atomicNode.setStateAfter(cas.stateAfter());
         graph.replaceFixedWithFixed(cas, atomicNode);
     }
@@ -538,7 +540,8 @@
         ValueNode newValue = implicitStoreConvert(graph, valueKind, n.newValue());
 
         AddressNode address = graph.unique(new OffsetAddressNode(n.object(), n.offset()));
-        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, atomicReadAndWriteBarrierType(n)));
+        BarrierType barrierType = storeBarrierType(n.object(), n.newValue());
+        LoweredAtomicReadAndWriteNode memoryRead = graph.add(new LoweredAtomicReadAndWriteNode(address, n.getLocationIdentity(), newValue, barrierType));
         memoryRead.setStateAfter(n.stateAfter());
 
         ValueNode readValue = implicitLoadConvert(graph, valueKind, memoryRead);
@@ -673,6 +676,7 @@
         memoryWrite.setGuard(write.getGuard());
     }
 
+    @SuppressWarnings("try")
     protected void lowerCommitAllocationNode(CommitAllocationNode commit, LoweringTool tool) {
         StructuredGraph graph = commit.graph();
         if (graph.getGuardsStage() == StructuredGraph.GuardsStage.FIXED_DEOPTS) {
@@ -685,10 +689,12 @@
                 VirtualObjectNode virtual = commit.getVirtualObjects().get(objIndex);
                 int entryCount = virtual.entryCount();
                 AbstractNewObjectNode newObject;
-                if (virtual instanceof VirtualInstanceNode) {
-                    newObject = graph.add(createNewInstanceFromVirtual(virtual));
-                } else {
-                    newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
+                try (DebugCloseable nsp = virtual.withNodeSourcePosition()) {
+                    if (virtual instanceof VirtualInstanceNode) {
+                        newObject = graph.add(createNewInstanceFromVirtual(virtual));
+                    } else {
+                        newObject = graph.add(createNewArrayFromVirtual(virtual, ConstantNode.forInt(entryCount, graph)));
+                    }
                 }
                 recursiveLowerings.add(newObject);
                 graph.addBeforeFixed(commit, newObject);
@@ -884,23 +890,15 @@
         return entryKind == JavaKind.Object ? BarrierType.PRECISE : BarrierType.NONE;
     }
 
-    protected BarrierType unsafeStoreBarrierType(RawStoreNode store) {
+    private static BarrierType unsafeStoreBarrierType(RawStoreNode store) {
         if (!store.needsBarrier()) {
             return BarrierType.NONE;
         }
         return storeBarrierType(store.object(), store.value());
     }
 
-    protected BarrierType compareAndSwapBarrierType(UnsafeCompareAndSwapNode cas) {
-        return storeBarrierType(cas.object(), cas.expected());
-    }
-
-    protected BarrierType atomicReadAndWriteBarrierType(AtomicReadAndWriteNode n) {
-        return storeBarrierType(n.object(), n.newValue());
-    }
-
-    protected BarrierType storeBarrierType(ValueNode object, ValueNode value) {
-        if (value.getStackKind() == JavaKind.Object) {
+    private static BarrierType storeBarrierType(ValueNode object, ValueNode value) {
+        if (value.getStackKind() == JavaKind.Object && object.getStackKind() == JavaKind.Object) {
             ResolvedJavaType type = StampTool.typeOrNull(object);
             if (type != null && !type.isArray()) {
                 return BarrierType.IMPRECISE;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/GraphKit.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,10 +29,12 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.graalvm.compiler.core.common.CompilationIdentifier;
 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.DebugCloseable;
+import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.graph.Graph;
 import org.graalvm.compiler.graph.Node.ValueNumberable;
@@ -71,7 +73,7 @@
 import org.graalvm.compiler.phases.common.inlining.InliningUtil;
 import org.graalvm.compiler.phases.util.Providers;
 import org.graalvm.compiler.word.WordTypes;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
@@ -99,9 +101,20 @@
     protected abstract static class Structure {
     }
 
-    public GraphKit(StructuredGraph graph, Providers providers, WordTypes wordTypes, GraphBuilderConfiguration.Plugins graphBuilderPlugins) {
+    public GraphKit(DebugContext debug, ResolvedJavaMethod stubMethod, Providers providers, WordTypes wordTypes, Plugins graphBuilderPlugins, CompilationIdentifier compilationId, String name) {
         this.providers = providers;
-        this.graph = graph;
+        StructuredGraph.Builder builder = new StructuredGraph.Builder(debug.getOptions(), debug).compilationId(compilationId);
+        if (name != null) {
+            builder.name(name);
+        } else {
+            builder.method(stubMethod);
+        }
+        this.graph = builder.build();
+        graph.disableUnsafeAccessTracking();
+        if (graph.trackNodeSourcePosition()) {
+            // Set up a default value that everything constructed by GraphKit will use.
+            graph.withNodeSourcePosition(NodeSourcePosition.substitution(stubMethod));
+        }
         this.wordTypes = wordTypes;
         this.graphBuilderPlugins = graphBuilderPlugins;
         this.lastFixedNode = graph.start();
@@ -229,7 +242,7 @@
      */
     @SuppressWarnings("try")
     public InvokeNode createInvoke(ResolvedJavaMethod method, InvokeKind invokeKind, FrameStateBuilder frameStateBuilder, int bci, ValueNode... args) {
-        try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.placeholder(method))) {
+        try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), method))) {
             assert method.isStatic() == (invokeKind == InvokeKind.Static);
             Signature signature = method.getSignature();
             JavaType returnType = signature.getReturnType(null);
@@ -254,15 +267,29 @@
         }
     }
 
+    @SuppressWarnings("try")
     public InvokeWithExceptionNode createInvokeWithExceptionAndUnwind(ResolvedJavaMethod method, InvokeKind invokeKind,
                     FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci, ValueNode... args) {
+        try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), method))) {
+            InvokeWithExceptionNode result = startInvokeWithException(method, invokeKind, frameStateBuilder, invokeBci, exceptionEdgeBci, args);
+            exceptionPart();
+            ExceptionObjectNode exception = exceptionObject();
+            append(new UnwindNode(exception));
+            endInvokeWithException();
+            return result;
+        }
+    }
 
-        InvokeWithExceptionNode result = startInvokeWithException(method, invokeKind, frameStateBuilder, invokeBci, exceptionEdgeBci, args);
-        exceptionPart();
-        ExceptionObjectNode exception = exceptionObject();
-        append(new UnwindNode(exception));
-        endInvokeWithException();
-        return result;
+    @SuppressWarnings("try")
+    public InvokeWithExceptionNode createInvokeWithExceptionAndUnwind(MethodCallTargetNode callTarget, FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci) {
+        try (DebugCloseable context = graph.withNodeSourcePosition(NodeSourcePosition.substitution(graph.currentNodeSourcePosition(), callTarget.targetMethod()))) {
+            InvokeWithExceptionNode result = startInvokeWithException(callTarget, frameStateBuilder, invokeBci, exceptionEdgeBci);
+            exceptionPart();
+            ExceptionObjectNode exception = exceptionObject();
+            append(new UnwindNode(exception));
+            endInvokeWithException();
+            return result;
+        }
     }
 
     protected MethodCallTargetNode createMethodCallTarget(InvokeKind invokeKind, ResolvedJavaMethod targetMethod, ValueNode[] args, StampPair returnStamp, @SuppressWarnings("unused") int bci) {
@@ -305,10 +332,10 @@
     /**
      * Recursively {@linkplain #inline inlines} all invocations currently in the graph.
      */
-    public void inlineInvokes() {
+    public void inlineInvokes(String reason, String phase) {
         while (!graph.getNodes().filter(InvokeNode.class).isEmpty()) {
             for (InvokeNode invoke : graph.getNodes().filter(InvokeNode.class).snapshot()) {
-                inline(invoke);
+                inline(invoke, reason, phase);
             }
         }
 
@@ -320,7 +347,7 @@
      * Inlines a given invocation to a method. The graph of the inlined method is processed in the
      * same manner as for snippets and method substitutions.
      */
-    public void inline(InvokeNode invoke) {
+    public void inline(InvokeNode invoke, String reason, String phase) {
         ResolvedJavaMethod method = ((MethodCallTargetNode) invoke.callTarget()).targetMethod();
 
         MetaAccessProvider metaAccess = providers.getMetaAccess();
@@ -341,7 +368,7 @@
         calleeGraph.clearAllStateAfter();
         new DeadCodeEliminationPhase(Optionality.Required).apply(calleeGraph);
 
-        InliningUtil.inline(invoke, calleeGraph, false, method);
+        InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase);
     }
 
     protected void pushStructure(Structure structure) {
@@ -493,6 +520,11 @@
         if (returnStamp == null) {
             returnStamp = StampFactory.forDeclaredType(graph.getAssumptions(), returnType, false);
         }
+        MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnStamp, invokeBci));
+        return startInvokeWithException(callTarget, frameStateBuilder, invokeBci, exceptionEdgeBci);
+    }
+
+    public InvokeWithExceptionNode startInvokeWithException(MethodCallTargetNode callTarget, FrameStateBuilder frameStateBuilder, int invokeBci, int exceptionEdgeBci) {
         ExceptionObjectNode exceptionObject = add(new ExceptionObjectNode(getMetaAccess()));
         if (frameStateBuilder != null) {
             FrameStateBuilder exceptionState = frameStateBuilder.copy();
@@ -501,7 +533,6 @@
             exceptionState.setRethrowException(false);
             exceptionObject.setStateAfter(exceptionState.create(exceptionEdgeBci, exceptionObject));
         }
-        MethodCallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, method, args, returnStamp, invokeBci));
         InvokeWithExceptionNode invoke = append(new InvokeWithExceptionNode(callTarget, exceptionObject, invokeBci));
         AbstractBeginNode noExceptionEdge = graph.add(KillingBeginNode.create(LocationIdentity.any()));
         invoke.setNext(noExceptionEdge);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/MethodHandlePlugin.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,6 +22,8 @@
  */
 package org.graalvm.compiler.replacements;
 
+import static org.graalvm.compiler.core.common.GraalOptions.MaximumRecursiveInlining;
+
 import org.graalvm.compiler.core.common.type.StampPair;
 import org.graalvm.compiler.graph.NodeInputList;
 import org.graalvm.compiler.nodes.CallTargetNode;
@@ -46,6 +48,16 @@
         this.safeForDeoptimization = safeForDeoptimization;
     }
 
+    private static int countRecursiveInlining(GraphBuilderContext b, ResolvedJavaMethod method) {
+        int count = 0;
+        for (GraphBuilderContext c = b.getParent(); c != null; c = c.getParent()) {
+            if (method.equals(c.getMethod())) {
+                count++;
+            }
+        }
+        return count;
+    }
+
     @Override
     public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod method, ValueNode[] args) {
         IntrinsicMethod intrinsicMethod = methodHandleAccess.lookupMethodHandleIntrinsic(method);
@@ -83,11 +95,19 @@
                     // As such, it needs to recursively inline everything.
                     inlineEverything = args.length != argumentsList.size();
                 }
-                if (inlineEverything && !callTarget.targetMethod().hasBytecodes()) {
+                ResolvedJavaMethod targetMethod = callTarget.targetMethod();
+                if (inlineEverything && !targetMethod.hasBytecodes()) {
                     // we need to force-inline but we can not, leave the invoke as-is
                     return false;
                 }
-                b.handleReplacedInvoke(invoke.getInvokeKind(), callTarget.targetMethod(), argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything);
+
+                int recursionDepth = countRecursiveInlining(b, targetMethod);
+                int maxRecursionDepth = MaximumRecursiveInlining.getValue(b.getOptions());
+                if (recursionDepth > maxRecursionDepth) {
+                    return false;
+                }
+
+                b.handleReplacedInvoke(invoke.getInvokeKind(), targetMethod, argumentsList.toArray(new ValueNode[argumentsList.size()]), inlineEverything);
             }
             return true;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/PEGraphDecoder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,8 +32,8 @@
 import java.util.List;
 import java.util.Map;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
 import org.graalvm.compiler.core.common.PermanentBailoutException;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/ReplacementsImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,8 +36,8 @@
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.api.replacements.Fold;
 import org.graalvm.compiler.api.replacements.MethodSubstitution;
 import org.graalvm.compiler.api.replacements.Snippet;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetCounterNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -50,7 +50,7 @@
 import org.graalvm.compiler.replacements.SnippetTemplate.Arguments;
 import org.graalvm.compiler.replacements.SnippetTemplate.SnippetInfo;
 import org.graalvm.compiler.word.ObjectAccess;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.TargetDescription;
 import sun.misc.Unsafe;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetLowerableMemoryNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetLowerableMemoryNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,7 +37,7 @@
 import org.graalvm.compiler.nodes.memory.MemoryNode;
 import org.graalvm.compiler.nodes.spi.Lowerable;
 import org.graalvm.compiler.nodes.spi.LoweringTool;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 @NodeInfo(cycles = CYCLES_IGNORED, size = SIZE_IGNORED)
 public class SnippetLowerableMemoryNode extends FixedWithNextNode implements Lowerable, MemoryAccess {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/SnippetTemplate.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,7 +30,7 @@
 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_IGNORED;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_IGNORED;
 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Method;
@@ -47,10 +47,10 @@
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Predicate;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.UnmodifiableEconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.UnmodifiableEconomicMap;
 import org.graalvm.compiler.api.replacements.Snippet;
 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
 import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
@@ -131,8 +131,8 @@
 import org.graalvm.compiler.replacements.nodes.ExplodeLoopNode;
 import org.graalvm.compiler.replacements.nodes.LoadSnippetVarargParameterNode;
 import org.graalvm.util.CollectionsUtil;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.WordBase;
 
 import jdk.vm.ci.code.TargetDescription;
 import jdk.vm.ci.meta.Constant;
@@ -651,8 +651,9 @@
                 try (DebugContext debug = openDebugContext(outer, args)) {
                     try (DebugCloseable a = SnippetTemplateCreationTime.start(debug); DebugContext.Scope s = debug.scope("SnippetSpecialization", args.info.method)) {
                         SnippetTemplates.increment(debug);
-                        template = new SnippetTemplate(options, debug, providers, snippetReflection, args, graph.trackNodeSourcePosition(), replacee);
-                        if (Options.UseSnippetTemplateCache.getValue(options) && args.cacheable) {
+                        OptionValues snippetOptions = new OptionValues(options, GraalOptions.TraceInlining, GraalOptions.TraceInliningForStubsAndSnippets.getValue(options));
+                        template = new SnippetTemplate(snippetOptions, debug, providers, snippetReflection, args, graph.trackNodeSourcePosition(), replacee);
+                        if (Options.UseSnippetTemplateCache.getValue(snippetOptions) && args.cacheable) {
                             templates.put(args.cacheKey, template);
                         }
                     } catch (Throwable e) {
@@ -1516,9 +1517,7 @@
                 replaceeGraph.getInliningLog().addLog(duplicates, snippet.getInliningLog());
             }
             NodeSourcePosition position = replacee.getNodeSourcePosition();
-            if (position != null) {
-                InliningUtil.updateSourcePosition(replaceeGraph, duplicates, mark, position, true);
-            }
+            InliningUtil.updateSourcePosition(replaceeGraph, duplicates, mark, position, true);
             debug.dump(DebugContext.DETAILED_LEVEL, replaceeGraph, "After inlining snippet %s", snippet.method());
             return duplicates;
         }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/StandardGraphBuilderPlugins.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -31,7 +31,7 @@
 import static jdk.vm.ci.code.MemoryBarriers.STORE_LOAD;
 import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
 import static org.graalvm.compiler.nodes.NamedLocationIdentity.OFF_HEAP_LOCATION;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
+import static org.graalvm.compiler.serviceprovider.GraalServices.Java8OrEarlier;
 
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
@@ -105,7 +105,7 @@
 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerAddExactNode;
 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerMulExactNode;
 import org.graalvm.compiler.replacements.nodes.arithmetic.IntegerSubExactNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.DeoptimizationAction;
 import jdk.vm.ci.meta.DeoptimizationReason;
@@ -233,10 +233,10 @@
                 // Ordered object-based accesses
                 if (Java8OrEarlier) {
                     if (kind == JavaKind.Int || kind == JavaKind.Long || kind == JavaKind.Object) {
-                        r.register4("putOrdered" + kindName, Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, true));
+                        r.register4("putOrdered" + kindName, Receiver.class, Object.class, long.class, javaClass, UnsafePutPlugin.putOrdered(kind));
                     }
                 } else {
-                    r.register4("put" + kindName + "Release", Receiver.class, Object.class, long.class, javaClass, new UnsafePutPlugin(kind, true));
+                    r.register4("put" + kindName + "Release", Receiver.class, Object.class, long.class, javaClass, UnsafePutPlugin.putOrdered(kind));
                 }
                 if (kind != JavaKind.Boolean && kind != JavaKind.Object) {
                     // Raw accesses to memory addresses
@@ -693,15 +693,29 @@
     public static class UnsafePutPlugin implements InvocationPlugin {
 
         private final JavaKind kind;
-        private final boolean isVolatile;
+        private final boolean hasBarrier;
+        private final int preWrite;
+        private final int postWrite;
 
         public UnsafePutPlugin(JavaKind kind, boolean isVolatile) {
+            this(kind, isVolatile, JMM_PRE_VOLATILE_WRITE, JMM_POST_VOLATILE_WRITE);
+        }
+
+        private UnsafePutPlugin(JavaKind kind, boolean hasBarrier, int preWrite, int postWrite) {
+            super();
             this.kind = kind;
-            this.isVolatile = isVolatile;
+            this.hasBarrier = hasBarrier;
+            this.preWrite = preWrite;
+            this.postWrite = postWrite;
+        }
+
+        public static UnsafePutPlugin putOrdered(JavaKind kind) {
+            return new UnsafePutPlugin(kind, true, LOAD_STORE | STORE_STORE, 0);
         }
 
         @Override
         public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode address, ValueNode value) {
+            assert !hasBarrier : "Barriers for address based Unsafe put is not supported.";
             // Emits a null-check for the otherwise unused receiver
             unsafe.get();
             b.add(new UnsafeMemoryStoreNode(address, value, kind, OFF_HEAP_LOCATION));
@@ -713,13 +727,13 @@
         public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unsafe, ValueNode object, ValueNode offset, ValueNode value) {
             // Emits a null-check for the otherwise unused receiver
             unsafe.get();
-            if (isVolatile) {
-                b.add(new MembarNode(JMM_PRE_VOLATILE_WRITE));
+            if (hasBarrier) {
+                b.add(new MembarNode(preWrite));
             }
             LocationIdentity locationIdentity = object.isNullConstant() ? OFF_HEAP_LOCATION : LocationIdentity.any();
             b.add(new RawStoreNode(object, offset, value, kind, locationIdentity));
-            if (isVolatile) {
-                b.add(new MembarNode(JMM_POST_VOLATILE_WRITE));
+            if (hasBarrier) {
+                b.add(new MembarNode(postWrite));
             }
             b.getGraph().markUnsafeAccess();
             return true;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,19 +22,16 @@
  */
 package org.graalvm.compiler.replacements.classfile;
 
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getModule;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getResourceAsStream;
-
 import java.io.DataInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
 import org.graalvm.compiler.bytecode.Bytecode;
 import org.graalvm.compiler.bytecode.BytecodeProvider;
-import org.graalvm.compiler.serviceprovider.JDK9Method;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.MetaAccessProvider;
@@ -98,20 +95,6 @@
         return false;
     }
 
-    private static InputStream getClassfileAsStream(Class<?> c) {
-        String classfilePath = c.getName().replace('.', '/') + ".class";
-        if (JDK9Method.JAVA_SPECIFICATION_VERSION >= 9) {
-            Object module = getModule(c);
-            return getResourceAsStream(module, classfilePath);
-        } else {
-            ClassLoader cl = c.getClassLoader();
-            if (cl == null) {
-                return ClassLoader.getSystemResourceAsStream(classfilePath);
-            }
-            return cl.getResourceAsStream(classfilePath);
-        }
-    }
-
     /**
      * Gets a {@link Classfile} created by parsing the class file bytes for {@code c}.
      *
@@ -123,7 +106,7 @@
         if (classfile == null) {
             try {
                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
-                InputStream in = getClassfileAsStream(c);
+                InputStream in = GraalServices.getClassfileAsStream(c);
                 if (in != null) {
                     DataInputStream stream = new DataInputStream(in);
                     classfile = new Classfile(type, stream, this);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/D	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,102 @@
+diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
+index 88403c3..728297d 100644
+--- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
++++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileBytecodeProvider.java
+@@ -138,7 +138,11 @@ public final class ClassfileBytecodeProvider implements BytecodeProvider {
+         return classfile;
+     }
+ 
+-    synchronized Class<?> resolveToClass(String descriptor) {
++    Class<?> resolveToClass(String descriptor) {
++        return resolveToClass(descriptor, false);
++    }
++
++    synchronized Class<?> resolveToClass(String descriptor, boolean initialize) {
+         Class<?> c = classes.get(descriptor);
+         if (c == null) {
+             if (descriptor.length() == 1) {
+@@ -155,7 +159,7 @@ public final class ClassfileBytecodeProvider implements BytecodeProvider {
+                     name = descriptor.replace('/', '.');
+                 }
+                 try {
+-                    c = Class.forName(name, true, loader);
++                    c = Class.forName(name, initialize, loader);
+                     classes.put(descriptor, c);
+                 } catch (ClassNotFoundException e) {
+                     throw new NoClassDefFoundError(descriptor);
+diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java
+index 087f78b..bde2dd4 100644
+--- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java
++++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstant.java
+@@ -70,8 +70,9 @@ abstract class ClassfileConstant {
+      * @param cp
+      * @param index
+      * @param opcode
++     * @param initialize
+      */
+-    public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
++    public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
+     }
+ 
+     @Override
+@@ -90,15 +91,19 @@ abstract class ClassfileConstant {
+         }
+ 
+         @Override
+-        public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
+-            resolve(cp);
++        public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
++            resolve(cp, initialize);
+         }
+ 
+         public ResolvedJavaType resolve(ClassfileConstantPool cp) throws GraalError {
++            return resolve(cp, false /* initialize */);
++        }
++
++        public ResolvedJavaType resolve(ClassfileConstantPool cp, boolean initialize) throws GraalError {
+             if (type == null) {
+                 String typeDescriptor = cp.get(Utf8.class, nameIndex).value;
+                 ClassfileBytecodeProvider context = cp.context;
+-                type = context.metaAccess.lookupJavaType(context.resolveToClass(typeDescriptor));
++                type = context.metaAccess.lookupJavaType(context.resolveToClass(typeDescriptor, initialize));
+             }
+             return type;
+         }
+@@ -116,8 +121,8 @@ abstract class ClassfileConstant {
+         }
+ 
+         @Override
+-        public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
+-            cp.get(ClassRef.class, classIndex).loadReferencedType(cp, classIndex, opcode);
++        public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
++            cp.get(ClassRef.class, classIndex).loadReferencedType(cp, classIndex, opcode, initialize);
+         }
+     }
+ 
+@@ -269,7 +274,7 @@ abstract class ClassfileConstant {
+         }
+ 
+         @Override
+-        public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode) {
++        public void loadReferencedType(ClassfileConstantPool cp, int index, int opcode, boolean initialize) {
+             throw new GraalError("Resolution of " + name + " constant pool entries not supported by " + ClassfileBytecodeProvider.class.getSimpleName());
+         }
+     }
+diff --git a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java
+index 218df10..a54779b 100644
+--- a/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java
++++ b/compiler/src/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/classfile/ClassfileConstantPool.java
+@@ -133,11 +133,11 @@ class ClassfileConstantPool implements ConstantPool {
+     }
+ 
+     @Override
+-    public void loadReferencedType(int index, int opcode) {
++    public void loadReferencedType(int index, int opcode, boolean initialize) {
+         if (opcode == Bytecodes.INVOKEDYNAMIC) {
+             throw new GraalError("INVOKEDYNAMIC not supported by " + ClassfileBytecodeProvider.class.getSimpleName());
+         }
+-        entries[index].loadReferencedType(this, index, opcode);
++        entries[index].loadReferencedType(this, index, opcode, initialize);
+     }
+ 
+     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayCompareToNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -44,7 +44,7 @@
 import org.graalvm.compiler.nodes.spi.Virtualizable;
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.Value;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/ArrayEqualsNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -46,7 +46,7 @@
 import org.graalvm.compiler.nodes.spi.VirtualizerTool;
 import org.graalvm.compiler.nodes.util.GraphUtil;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/BasicArrayCopyNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import static org.graalvm.compiler.nodeinfo.InputType.Memory;
 import static org.graalvm.compiler.nodeinfo.InputType.State;
 import static org.graalvm.compiler.nodeinfo.NodeSize.SIZE_64;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import org.graalvm.compiler.core.common.type.StampFactory;
 import org.graalvm.compiler.debug.DebugContext;
@@ -51,7 +51,7 @@
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.meta.JavaKind;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -189,7 +189,7 @@
                     ((Lowerable) nonNullReceiver).lower(tool);
                 }
             }
-            InliningUtil.inline(invoke, replacementGraph, false, targetMethod);
+            InliningUtil.inline(invoke, replacementGraph, false, targetMethod, "Replace with graph.", "LoweringPhase");
             replacementGraph.getDebug().dump(DebugContext.DETAILED_LEVEL, graph(), "After inlining replacement %s", replacementGraph);
         } else {
             if (isPlaceholderBci(invoke.bci())) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.replacements/src/org/graalvm/compiler/replacements/nodes/MacroStateSplitNode.java	Thu Apr 26 17:59:02 2018 +0200
@@ -36,7 +36,7 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
 import org.graalvm.compiler.nodes.memory.MemoryCheckpoint;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.code.BytecodeFrame;
 import jdk.vm.ci.meta.ResolvedJavaMethod;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/GraalServices.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,53 +22,44 @@
  */
 package org.graalvm.compiler.serviceprovider;
 
-import static org.graalvm.compiler.serviceprovider.JDK9Method.Java8OrEarlier;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.addOpens;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getModule;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.getPackages;
-import static org.graalvm.compiler.serviceprovider.JDK9Method.isOpenTo;
+import static java.lang.Thread.currentThread;
 
-import java.lang.reflect.Method;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Iterator;
+import java.util.List;
 import java.util.ServiceConfigurationError;
 import java.util.ServiceLoader;
-import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
 
 import jdk.vm.ci.services.JVMCIPermission;
 import jdk.vm.ci.services.Services;
 
 /**
- * A mechanism for accessing service providers that abstracts over whether Graal is running on
- * JVMCI-8 or JVMCI-9. In JVMCI-8, a JVMCI specific mechanism is used to lookup services via the
- * hidden JVMCI class loader. In JVMCI-9, the standard {@link ServiceLoader} mechanism is used.
+ * Interface to functionality that abstracts over which JDK version Graal is running on.
  */
 public final class GraalServices {
 
-    private GraalServices() {
+    private static int getJavaSpecificationVersion() {
+        String value = System.getProperty("java.specification.version");
+        if (value.startsWith("1.")) {
+            value = value.substring(2);
+        }
+        return Integer.parseInt(value);
     }
 
     /**
-     * Opens all JVMCI packages to the module of a given class. This relies on JVMCI already having
-     * opened all its packages to the module defining {@link GraalServices}.
-     *
-     * @param other all JVMCI packages will be opened to the module defining this class
+     * The integer value corresponding to the value of the {@code java.specification.version} system
+     * property after any leading {@code "1."} has been stripped.
      */
-    public static void openJVMCITo(Class<?> other) {
-        Object jvmci = getModule(Services.class);
-        Object otherModule = getModule(other);
-        if (jvmci != otherModule) {
-            Set<String> packages = getPackages(jvmci);
-            for (String pkg : packages) {
-                boolean opened = isOpenTo(jvmci, pkg, otherModule);
-                if (!opened) {
-                    try {
-                        addOpens.invoke(jvmci, pkg, otherModule);
-                    } catch (Throwable throwable) {
-                        throw new InternalError(throwable);
-                    }
-                }
-            }
-        }
+    public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();
+
+    /**
+     * Determines if the Java runtime is version 8 or earlier.
+     */
+    public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8;
+
+    private GraalServices() {
     }
 
     /**
@@ -79,15 +70,12 @@
      */
     public static <S> Iterable<S> load(Class<S> service) {
         assert !service.getName().startsWith("jdk.vm.ci") : "JVMCI services must be loaded via " + Services.class.getName();
-        if (Java8OrEarlier) {
-            return load8(service);
-        }
         Iterable<S> iterable = ServiceLoader.load(service);
-        return new Iterable<S>() {
+        return new Iterable<>() {
             @Override
             public Iterator<S> iterator() {
                 Iterator<S> iterator = iterable.iterator();
-                return new Iterator<S>() {
+                return new Iterator<>() {
                     @Override
                     public boolean hasNext() {
                         return iterator.hasNext();
@@ -111,19 +99,20 @@
     }
 
     /**
-     * {@code Services.load(Class)} is only defined in JVMCI-8.
+     * Opens all JVMCI packages to the module of a given class. This relies on JVMCI already having
+     * opened all its packages to the module defining {@link GraalServices}.
+     *
+     * @param other all JVMCI packages will be opened to the module defining this class
      */
-    private static volatile Method loadMethod;
-
-    @SuppressWarnings("unchecked")
-    private static <S> Iterable<S> load8(Class<S> service) throws InternalError {
-        try {
-            if (loadMethod == null) {
-                loadMethod = Services.class.getMethod("load", Class.class);
+    static void openJVMCITo(Class<?> other) {
+        Module jvmciModule = JVMCI_MODULE;
+        Module otherModule = other.getModule();
+        if (jvmciModule != otherModule) {
+            for (String pkg : jvmciModule.getPackages()) {
+                if (!jvmciModule.isOpen(pkg, otherModule)) {
+                    jvmciModule.addOpens(pkg, otherModule);
+                }
             }
-            return (Iterable<S>) loadMethod.invoke(null, service);
-        } catch (Exception e) {
-            throw new InternalError(e);
         }
     }
 
@@ -159,4 +148,185 @@
         }
         return singleProvider;
     }
+
+    /**
+     * Gets the class file bytes for {@code c}.
+     */
+    public static InputStream getClassfileAsStream(Class<?> c) throws IOException {
+        String classfilePath = c.getName().replace('.', '/') + ".class";
+        return c.getModule().getResourceAsStream(classfilePath);
+    }
+
+    private static final Module JVMCI_MODULE = Services.class.getModule();
+
+    /**
+     * A JVMCI package dynamically exported to trusted modules.
+     */
+    private static final String JVMCI_RUNTIME_PACKAGE = "jdk.vm.ci.runtime";
+    static {
+        assert JVMCI_MODULE.getPackages().contains(JVMCI_RUNTIME_PACKAGE);
+    }
+
+    /**
+     * Determines if invoking {@link Object#toString()} on an instance of {@code c} will only run
+     * trusted code.
+     */
+    public static boolean isToStringTrusted(Class<?> c) {
+        Module module = c.getModule();
+        Module jvmciModule = JVMCI_MODULE;
+        assert jvmciModule.getPackages().contains("jdk.vm.ci.runtime");
+        if (module == jvmciModule || jvmciModule.isOpen(JVMCI_RUNTIME_PACKAGE, module)) {
+            // Can access non-statically-exported package in JVMCI
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Gets a unique identifier for this execution such as a process ID or a
+     * {@linkplain #getGlobalTimeStamp() fixed timestamp}.
+     */
+    public static String getExecutionID() {
+        return Long.toString(ProcessHandle.current().pid());
+    }
+
+    private static final AtomicLong globalTimeStamp = new AtomicLong();
+
+    /**
+     * 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();
+    }
+
+    /**
+     * Access to thread specific information made available via Java Management Extensions (JMX).
+     * Using this abstraction enables avoiding a dependency to the {@code java.management} and
+     * {@code jdk.management} modules on JDK 9 and later.
+     */
+    public abstract static class JMXService {
+        protected abstract long getThreadAllocatedBytes(long id);
+
+        protected abstract long getCurrentThreadCpuTime();
+
+        protected abstract boolean isThreadAllocatedMemorySupported();
+
+        protected abstract boolean isCurrentThreadCpuTimeSupported();
+
+        protected abstract List<String> getInputArguments();
+
+        // Placing this static field in JMXService (instead of GraalServices)
+        // allows for lazy initialization.
+        static final JMXService instance = loadSingle(JMXService.class, false);
+    }
+
+    /**
+     * Returns an approximation of the total amount of memory, in bytes, allocated in heap memory
+     * for the thread of the specified ID. The returned value is an approximation because some Java
+     * virtual machine implementations may use object allocation mechanisms that result in a delay
+     * between the time an object is allocated and the time its size is recorded.
+     * <p>
+     * If the thread of the specified ID is not alive or does not exist, this method returns
+     * {@code -1}. If thread memory allocation measurement is disabled, this method returns
+     * {@code -1}. A thread is alive if it has been started and has not yet died.
+     * <p>
+     * If thread memory allocation measurement is enabled after the thread has started, the Java
+     * virtual machine implementation may choose any time up to and including the time that the
+     * capability is enabled as the point where thread memory allocation measurement starts.
+     *
+     * @param id the thread ID of a thread
+     * @return an approximation of the total memory allocated, in bytes, in heap memory for a thread
+     *         of the specified ID if the thread of the specified ID exists, the thread is alive,
+     *         and thread memory allocation measurement is enabled; {@code -1} otherwise.
+     *
+     * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}.
+     * @throws UnsupportedOperationException if the Java virtual machine implementation does not
+     *             {@linkplain #isThreadAllocatedMemorySupported() support} thread memory allocation
+     *             measurement.
+     */
+    public static long getThreadAllocatedBytes(long id) {
+        JMXService jmx = JMXService.instance;
+        if (jmx == null) {
+            throw new UnsupportedOperationException();
+        }
+        return jmx.getThreadAllocatedBytes(id);
+    }
+
+    /**
+     * Convenience method for calling {@link #getThreadAllocatedBytes(long)} with the id of the
+     * current thread.
+     */
+    public static long getCurrentThreadAllocatedBytes() {
+        return getThreadAllocatedBytes(currentThread().getId());
+    }
+
+    /**
+     * Returns the total CPU time for the current thread in nanoseconds. The returned value is of
+     * nanoseconds precision but not necessarily nanoseconds accuracy. If the implementation
+     * distinguishes between user mode time and system mode time, the returned CPU time is the
+     * amount of time that the current thread has executed in user mode or system mode.
+     *
+     * @return the total CPU time for the current thread if CPU time measurement is enabled;
+     *         {@code -1} otherwise.
+     *
+     * @throws UnsupportedOperationException if the Java virtual machine does not
+     *             {@linkplain #isCurrentThreadCpuTimeSupported() support} CPU time measurement for
+     *             the current thread
+     */
+    public static long getCurrentThreadCpuTime() {
+        JMXService jmx = JMXService.instance;
+        if (jmx == null) {
+            throw new UnsupportedOperationException();
+        }
+        return jmx.getCurrentThreadCpuTime();
+    }
+
+    /**
+     * Determines if the Java virtual machine implementation supports thread memory allocation
+     * measurement.
+     */
+    public static boolean isThreadAllocatedMemorySupported() {
+        JMXService jmx = JMXService.instance;
+        if (jmx == null) {
+            return false;
+        }
+        return jmx.isThreadAllocatedMemorySupported();
+    }
+
+    /**
+     * Determines if the Java virtual machine supports CPU time measurement for the current thread.
+     */
+    public static boolean isCurrentThreadCpuTimeSupported() {
+        JMXService jmx = JMXService.instance;
+        if (jmx == null) {
+            return false;
+        }
+        return jmx.isCurrentThreadCpuTimeSupported();
+    }
+
+    /**
+     * Gets the input arguments passed to the Java virtual machine which does not include the
+     * arguments to the {@code main} method. This method returns an empty list if there is no input
+     * argument to the Java virtual machine.
+     * <p>
+     * Some Java virtual machine implementations may take input arguments from multiple different
+     * sources: for examples, arguments passed from the application that launches the Java virtual
+     * machine such as the 'java' command, environment variables, configuration files, etc.
+     * <p>
+     * Typically, not all command-line options to the 'java' command are passed to the Java virtual
+     * machine. Thus, the returned input arguments may not include all command-line options.
+     *
+     * @return the input arguments to the JVM or {@code null} if they are unavailable
+     */
+    public static List<String> getInputArguments() {
+        JMXService jmx = JMXService.instance;
+        if (jmx == null) {
+            return null;
+        }
+        return jmx.getInputArguments();
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.serviceprovider/src/org/graalvm/compiler/serviceprovider/JDK9Method.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +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.serviceprovider;
-
-import java.io.InputStream;
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodHandles;
-import java.lang.reflect.Method;
-import java.util.Set;
-
-/**
- * Reflection based access to API introduced by JDK 9. This allows the API to be used in code that
- * must be compiled on a JDK prior to 9.
- */
-public final class JDK9Method {
-
-    private static int getJavaSpecificationVersion() {
-        String value = System.getProperty("java.specification.version");
-        if (value.startsWith("1.")) {
-            value = value.substring(2);
-        }
-        return Integer.parseInt(value);
-    }
-
-    /**
-     * The integer value corresponding to the value of the {@code java.specification.version} system
-     * property after any leading {@code "1."} has been stripped.
-     */
-    public static final int JAVA_SPECIFICATION_VERSION = getJavaSpecificationVersion();
-
-    public static MethodHandle lookupMethodHandle(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
-        try {
-            return MethodHandles.lookup().unreflect(declaringClass.getMethod(name, parameterTypes));
-        } catch (Exception e) {
-            throw new InternalError(e);
-        }
-    }
-
-    private static Method lookupMethod(Class<?> declaringClass, String name, Class<?>... parameterTypes) {
-        try {
-            return declaringClass.getMethod(name, parameterTypes);
-        } catch (Exception e) {
-            throw new InternalError(e);
-        }
-    }
-
-    /**
-     * Determines if the Java runtime is version 8 or earlier.
-     */
-    public static final boolean Java8OrEarlier = JAVA_SPECIFICATION_VERSION <= 8;
-
-    /**
-     * {@code Class.getModule()}.
-     */
-    private static final MethodHandle getModuleHandle;
-
-    public static Object getModule(Class<?> clazz) {
-        try {
-            return getModuleHandle.invoke(clazz);
-        } catch (Throwable throwable) {
-            throw new InternalError(throwable);
-        }
-    }
-
-    /**
-     * {@code java.lang.Module.getPackages()}.
-     */
-    private static final MethodHandle getPackages;
-
-    public static Set<String> getPackages(Object module) {
-        try {
-            return (Set<String>) getPackages.invoke(module);
-        } catch (Throwable throwable) {
-            throw new InternalError(throwable);
-        }
-    }
-
-    /**
-     * {@code java.lang.Module.getResourceAsStream(String)}.
-     */
-    private static final MethodHandle getResourceAsStream;
-
-    public static InputStream getResourceAsStream(Object module, String resource) {
-        try {
-            return (InputStream) getResourceAsStream.invoke(module, resource);
-        } catch (Throwable throwable) {
-            throw new InternalError(throwable);
-        }
-    }
-
-    /**
-     * {@code java.lang.Module.addOpens(String, Module)}. This only seems to work correctly when
-     * invoked through reflection.
-     */
-    public static final Method addOpens;
-
-    /**
-     * {@code java.lang.Module.isOpen(String, Module)}.
-     */
-    private static final MethodHandle isOpenTo;
-
-    public static boolean isOpenTo(Object module1, String pkg, Object module2) {
-        try {
-            return (boolean) isOpenTo.invoke(module1, pkg, module2);
-        } catch (Throwable throwable) {
-            throw new InternalError(throwable);
-        }
-    }
-
-    public static final Class<?> MODULE_CLASS;
-
-    static {
-        if (JAVA_SPECIFICATION_VERSION >= 9) {
-            try {
-                MODULE_CLASS = Class.class.getMethod("getModule").getReturnType();
-                getModuleHandle = lookupMethodHandle(Class.class, "getModule");
-                getPackages = lookupMethodHandle(MODULE_CLASS, "getPackages");
-                addOpens = lookupMethod(MODULE_CLASS, "addOpens", String.class, MODULE_CLASS);
-                getResourceAsStream = lookupMethodHandle(MODULE_CLASS, "getResourceAsStream", String.class);
-                isOpenTo = lookupMethodHandle(MODULE_CLASS, "isOpen", String.class, MODULE_CLASS);
-            } catch (NoSuchMethodException e) {
-                throw new InternalError(e);
-            }
-        } else {
-            MODULE_CLASS = null;
-            getModuleHandle = null;
-            getPackages = null;
-            addOpens = null;
-            getResourceAsStream = null;
-            isOpenTo = null;
-        }
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/GraalTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,6 +40,7 @@
 import org.graalvm.compiler.debug.DebugHandlersFactory;
 import org.graalvm.compiler.debug.GlobalMetrics;
 import org.graalvm.compiler.options.OptionValues;
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.internal.ComparisonCriteria;
@@ -64,7 +65,7 @@
         }
     }
 
-    public static final boolean Java8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+    public static final boolean Java8OrEarlier = GraalServices.Java8OrEarlier;
 
     protected Method getMethod(String methodName) {
         return getMethod(getClass(), methodName);
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.test/src/org/graalvm/compiler/test/SubprocessUtil.java	Thu Apr 26 17:59:02 2018 +0200
@@ -35,6 +35,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import org.graalvm.compiler.serviceprovider.GraalServices;
 import org.graalvm.util.CollectionsUtil;
 
 /**
@@ -236,7 +237,7 @@
         return new Subprocess(command, process.waitFor(), output);
     }
 
-    private static final boolean isJava8OrEarlier = System.getProperty("java.specification.version").compareTo("1.9") < 0;
+    private static final boolean isJava8OrEarlier = GraalServices.Java8OrEarlier;
 
     private static boolean hasArg(String optionName) {
         if (optionName.equals("-cp") || optionName.equals("-classpath")) {
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual.bench/.checkstyle.exclude	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-src_gen
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsBlockState.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
 import java.util.Iterator;
 import java.util.Map;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.UnmodifiableMapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.UnmodifiableMapCursor;
 
 public abstract class EffectsBlockState<T extends EffectsBlockState<T>> {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsClosure.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,9 +25,9 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.cfg.BlockMap;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.type.Stamp;
@@ -62,7 +62,7 @@
 import org.graalvm.compiler.phases.graph.ReentrantBlockIterator;
 import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.BlockIteratorClosure;
 import org.graalvm.compiler.phases.graph.ReentrantBlockIterator.LoopInfo;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 public abstract class EffectsClosure<BlockT extends EffectsBlockState<BlockT>> extends EffectsPhase.Closure<BlockT> {
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/EffectsPhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.core.common.util.CompilationAlarm;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.graph.Graph.NodeEventScope;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationBlockState.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,8 +25,8 @@
 import java.util.Iterator;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.type.IntegerStamp;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.debug.DebugContext;
@@ -37,7 +37,7 @@
 import org.graalvm.compiler.nodes.virtual.VirtualInstanceNode;
 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 import org.graalvm.compiler.options.OptionValues;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PEReadEliminationClosure.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,11 +29,11 @@
 import java.util.Iterator;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
-import org.graalvm.collections.Pair;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.Pair;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
 import org.graalvm.compiler.graph.Node;
@@ -66,7 +66,7 @@
 import org.graalvm.compiler.nodes.virtual.VirtualArrayNode;
 import org.graalvm.compiler.options.OptionValues;
 import org.graalvm.compiler.virtual.phases.ea.PEReadEliminationBlockState.ReadCacheEntry;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapeClosure.java	Thu Apr 26 17:59:02 2018 +0200
@@ -28,9 +28,9 @@
 import java.util.List;
 import java.util.function.IntUnaryOperator;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.core.common.GraalOptions;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.spi.ConstantFieldProvider;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/PartialEscapePhase.java	Thu Apr 26 17:59:02 2018 +0200
@@ -25,7 +25,7 @@
 import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalysisIterations;
 import static org.graalvm.compiler.core.common.GraalOptions.EscapeAnalyzeOnly;
 
-import org.graalvm.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.EconomicSet;
 import org.graalvm.compiler.graph.Node;
 import org.graalvm.compiler.nodes.StructuredGraph;
 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationBlockState.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,10 +24,10 @@
 
 import java.util.Iterator;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.nodes.ValueNode;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 /**
  * This class maintains a set of known values, identified by base object, locations and offset.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/ReadEliminationClosure.java	Thu Apr 26 17:59:02 2018 +0200
@@ -23,15 +23,15 @@
 package org.graalvm.compiler.virtual.phases.ea;
 
 import static org.graalvm.compiler.core.common.GraalOptions.ReadEliminationMaxLoopVisits;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.util.Iterator;
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.EconomicSet;
-import org.graalvm.collections.Equivalence;
-import org.graalvm.collections.MapCursor;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.EconomicSet;
+import jdk.internal.vm.compiler.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.MapCursor;
 import org.graalvm.compiler.core.common.cfg.Loop;
 import org.graalvm.compiler.core.common.type.Stamp;
 import org.graalvm.compiler.graph.Node;
@@ -63,7 +63,7 @@
 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.CacheEntry;
 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.LoadCacheEntry;
 import org.graalvm.compiler.virtual.phases.ea.ReadEliminationBlockState.UnsafeLoadCacheEntry;
-import org.graalvm.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.LocationIdentity;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.ResolvedJavaType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.virtual/src/org/graalvm/compiler/virtual/phases/ea/VirtualUtil.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 
 import java.util.List;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.debug.DebugContext;
 import org.graalvm.compiler.debug.GraalError;
 import org.graalvm.compiler.debug.TTY;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/BarrieredAccess.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,11 +24,11 @@
 
 import org.graalvm.compiler.word.Word.Opcode;
 import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
 
 /**
  * Medium-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/ObjectAccess.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,11 +24,11 @@
 
 import org.graalvm.compiler.word.Word.Opcode;
 import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
 
 /**
  * Low-level memory access for Objects. Similarly to the readXxx and writeXxx methods defined for
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/Word.java	Thu Apr 26 17:59:02 2018 +0200
@@ -48,19 +48,19 @@
 import org.graalvm.compiler.nodes.calc.XorNode;
 import org.graalvm.compiler.nodes.memory.HeapAccess.BarrierType;
 import org.graalvm.compiler.nodes.memory.address.AddressNode.Address;
-import org.graalvm.word.ComparableWord;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.Pointer;
-import org.graalvm.word.SignedWord;
-import org.graalvm.word.UnsignedWord;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.ComparableWord;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.Pointer;
+import jdk.internal.vm.compiler.word.SignedWord;
+import jdk.internal.vm.compiler.word.UnsignedWord;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
+import jdk.internal.vm.compiler.word.impl.WordBoxFactory;
 
-public abstract class Word extends WordFactory implements SignedWord, UnsignedWord, Pointer {
+public abstract class Word implements SignedWord, UnsignedWord, Pointer {
 
     static {
-        assert WordFactory.boxFactory == null : "BoxFactory must be initialized only once.";
-        WordFactory.boxFactory = new BoxFactoryImpl();
+        BoxFactoryImpl.initialize();
     }
 
     public static void ensureInitialized() {
@@ -109,10 +109,15 @@
         TO_RAW_VALUE,
     }
 
-    public static class BoxFactoryImpl implements BoxFactory {
+    static class BoxFactoryImpl extends WordBoxFactory {
+        static void initialize() {
+            assert boxFactory == null : "BoxFactory must be initialized only once.";
+            boxFactory = new BoxFactoryImpl();
+        }
+
         @SuppressWarnings("unchecked")
         @Override
-        public <T extends WordBase> T box(long val) {
+        public <T extends WordBase> T boxImpl(long val) {
             return (T) HostedWord.boxLong(val);
         }
     }
@@ -697,55 +702,55 @@
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public byte readByte(int offset, LocationIdentity locationIdentity) {
-        return readByte(signed(offset), locationIdentity);
+        return readByte(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public char readChar(int offset, LocationIdentity locationIdentity) {
-        return readChar(signed(offset), locationIdentity);
+        return readChar(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public short readShort(int offset, LocationIdentity locationIdentity) {
-        return readShort(signed(offset), locationIdentity);
+        return readShort(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public int readInt(int offset, LocationIdentity locationIdentity) {
-        return readInt(signed(offset), locationIdentity);
+        return readInt(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public long readLong(int offset, LocationIdentity locationIdentity) {
-        return readLong(signed(offset), locationIdentity);
+        return readLong(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public float readFloat(int offset, LocationIdentity locationIdentity) {
-        return readFloat(signed(offset), locationIdentity);
+        return readFloat(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public double readDouble(int offset, LocationIdentity locationIdentity) {
-        return readDouble(signed(offset), locationIdentity);
+        return readDouble(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity) {
-        return readWord(signed(offset), locationIdentity);
+        return readWord(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public Object readObject(int offset, LocationIdentity locationIdentity) {
-        return readObject(signed(offset), locationIdentity);
+        return readObject(WordFactory.signed(offset), locationIdentity);
     }
 
     @Override
@@ -809,61 +814,61 @@
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeByte(int offset, byte val, LocationIdentity locationIdentity) {
-        writeByte(signed(offset), val, locationIdentity);
+        writeByte(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeChar(int offset, char val, LocationIdentity locationIdentity) {
-        writeChar(signed(offset), val, locationIdentity);
+        writeChar(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeShort(int offset, short val, LocationIdentity locationIdentity) {
-        writeShort(signed(offset), val, locationIdentity);
+        writeShort(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeInt(int offset, int val, LocationIdentity locationIdentity) {
-        writeInt(signed(offset), val, locationIdentity);
+        writeInt(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeLong(int offset, long val, LocationIdentity locationIdentity) {
-        writeLong(signed(offset), val, locationIdentity);
+        writeLong(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeFloat(int offset, float val, LocationIdentity locationIdentity) {
-        writeFloat(signed(offset), val, locationIdentity);
+        writeFloat(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeDouble(int offset, double val, LocationIdentity locationIdentity) {
-        writeDouble(signed(offset), val, locationIdentity);
+        writeDouble(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeWord(int offset, WordBase val, LocationIdentity locationIdentity) {
-        writeWord(signed(offset), val, locationIdentity);
+        writeWord(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.INITIALIZE)
     public void initializeLong(int offset, long val, LocationIdentity locationIdentity) {
-        initializeLong(signed(offset), val, locationIdentity);
+        initializeLong(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeObject(int offset, Object val, LocationIdentity locationIdentity) {
-        writeObject(signed(offset), val, locationIdentity);
+        writeObject(WordFactory.signed(offset), val, locationIdentity);
     }
 
     @Override
@@ -924,60 +929,60 @@
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public byte readByte(int offset) {
-        return readByte(signed(offset));
+        return readByte(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public char readChar(int offset) {
-        return readChar(signed(offset));
+        return readChar(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public short readShort(int offset) {
-        return readShort(signed(offset));
+        return readShort(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public int readInt(int offset) {
-        return readInt(signed(offset));
+        return readInt(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public long readLong(int offset) {
-        return readLong(signed(offset));
+        return readLong(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public float readFloat(int offset) {
-        return readFloat(signed(offset));
+        return readFloat(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public double readDouble(int offset) {
-        return readDouble(signed(offset));
+        return readDouble(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public <T extends WordBase> T readWord(int offset) {
-        return readWord(signed(offset));
+        return readWord(WordFactory.signed(offset));
     }
 
     @Override
     @Operation(opcode = Opcode.READ_POINTER)
     public Object readObject(int offset) {
-        return readObject(signed(offset));
+        return readObject(WordFactory.signed(offset));
     }
 
     @Operation(opcode = Opcode.READ_HEAP)
     public Object readObject(int offset, BarrierType barrierType) {
-        return readObject(signed(offset), barrierType);
+        return readObject(WordFactory.signed(offset), barrierType);
     }
 
     @Override
@@ -1073,103 +1078,103 @@
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeByte(int offset, byte val) {
-        writeByte(signed(offset), val);
+        writeByte(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeChar(int offset, char val) {
-        writeChar(signed(offset), val);
+        writeChar(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeShort(int offset, short val) {
-        writeShort(signed(offset), val);
+        writeShort(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeInt(int offset, int val) {
-        writeInt(signed(offset), val);
+        writeInt(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeLong(int offset, long val) {
-        writeLong(signed(offset), val);
+        writeLong(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeFloat(int offset, float val) {
-        writeFloat(signed(offset), val);
+        writeFloat(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeDouble(int offset, double val) {
-        writeDouble(signed(offset), val);
+        writeDouble(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeWord(int offset, WordBase val) {
-        writeWord(signed(offset), val);
+        writeWord(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.WRITE_POINTER)
     public void writeObject(int offset, Object val) {
-        writeObject(signed(offset), val);
+        writeObject(WordFactory.signed(offset), val);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity) {
-        return compareAndSwapInt(signed(offset), expectedValue, newValue, locationIdentity);
+        return compareAndSwapInt(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity) {
-        return compareAndSwapLong(signed(offset), expectedValue, newValue, locationIdentity);
+        return compareAndSwapLong(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity) {
-        return compareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity);
+        return compareAndSwapWord(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity) {
-        return compareAndSwapObject(signed(offset), expectedValue, newValue, locationIdentity);
+        return compareAndSwapObject(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity) {
-        return logicCompareAndSwapInt(signed(offset), expectedValue, newValue, locationIdentity);
+        return logicCompareAndSwapInt(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity) {
-        return logicCompareAndSwapLong(signed(offset), expectedValue, newValue, locationIdentity);
+        return logicCompareAndSwapLong(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity) {
-        return logicCompareAndSwapWord(signed(offset), expectedValue, newValue, locationIdentity);
+        return logicCompareAndSwapWord(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     @Override
     @Operation(opcode = Opcode.CAS_POINTER)
     public boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity) {
-        return logicCompareAndSwapObject(signed(offset), expectedValue, newValue, locationIdentity);
+        return logicCompareAndSwapObject(WordFactory.signed(offset), expectedValue, newValue, locationIdentity);
     }
 
     /**
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordOperationPlugin.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 
 import static org.graalvm.compiler.nodes.ConstantNode.forInt;
 import static org.graalvm.compiler.nodes.ConstantNode.forIntegerKind;
-import static org.graalvm.word.LocationIdentity.any;
+import static jdk.internal.vm.compiler.word.LocationIdentity.any;
 
 import java.lang.reflect.Constructor;
 import java.util.Arrays;
@@ -70,8 +70,8 @@
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.word.Word.Opcode;
 import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.LocationIdentity;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.LocationIdentity;
+import jdk.internal.vm.compiler.word.impl.WordFactoryOperation;
 
 import jdk.vm.ci.code.BailoutException;
 import jdk.vm.ci.meta.JavaKind;
@@ -85,7 +85,7 @@
  * A plugin for calls to {@linkplain Operation word operations}, as well as all other nodes that
  * need special handling for {@link Word} types.
  */
-public class WordOperationPlugin extends WordFactory implements NodePlugin, TypePlugin, InlineInvokePlugin {
+public class WordOperationPlugin implements NodePlugin, TypePlugin, InlineInvokePlugin {
     protected final WordTypes wordTypes;
     protected final JavaKind wordKind;
     protected final SnippetReflectionProvider snippetReflection;
@@ -175,14 +175,14 @@
     }
 
     protected LoadIndexedNode createLoadIndexedNode(ValueNode array, ValueNode index) {
-        return new LoadIndexedNode(null, array, index, wordTypes.getWordKind());
+        return new LoadIndexedNode(null, array, index, wordKind);
     }
 
     @Override
     public boolean handleStoreField(GraphBuilderContext b, ValueNode object, ResolvedJavaField field, ValueNode value) {
         if (field.getJavaKind() == JavaKind.Object) {
             boolean isWordField = wordTypes.isWord(field.getType());
-            boolean isWordValue = value.getStackKind() == wordTypes.getWordKind();
+            boolean isWordValue = value.getStackKind() == wordKind;
 
             if (isWordField && !isWordValue) {
                 throw bailout(b, "Cannot store a non-word value into a word field: " + field.format("%H.%n"));
@@ -205,20 +205,20 @@
         ResolvedJavaType arrayType = StampTool.typeOrNull(array);
         if (arrayType != null && wordTypes.isWord(arrayType.getComponentType())) {
             assert elementKind == JavaKind.Object;
-            if (value.getStackKind() != wordTypes.getWordKind()) {
+            if (value.getStackKind() != wordKind) {
                 throw bailout(b, "Cannot store a non-word value into a word array: " + arrayType.toJavaName(true));
             }
             b.add(createStoreIndexedNode(array, index, value));
             return true;
         }
-        if (elementKind == JavaKind.Object && value.getStackKind() == wordTypes.getWordKind()) {
+        if (elementKind == JavaKind.Object && value.getStackKind() == wordKind) {
             throw bailout(b, "Cannot store a word value into a non-word array: " + arrayType.toJavaName(true));
         }
         return false;
     }
 
     protected StoreIndexedNode createStoreIndexedNode(ValueNode array, ValueNode index, ValueNode value) {
-        return new StoreIndexedNode(array, index, wordTypes.getWordKind(), value);
+        return new StoreIndexedNode(array, index, wordKind, value);
     }
 
     @Override
@@ -230,7 +230,7 @@
             return false;
         }
 
-        if (object.getStackKind() != wordTypes.getWordKind()) {
+        if (object.getStackKind() != wordKind) {
             throw bailout(b, "Cannot cast a non-word value to a word type: " + type.toJavaName(true));
         }
         b.push(JavaKind.Object, object);
@@ -249,7 +249,7 @@
 
     protected void processWordOperation(GraphBuilderContext b, ValueNode[] args, ResolvedJavaMethod wordMethod) throws GraalError {
         JavaKind returnKind = wordMethod.getSignature().getReturnKind();
-        WordFactory.FactoryOperation factoryOperation = BridgeMethodUtils.getAnnotation(WordFactory.FactoryOperation.class, wordMethod);
+        WordFactoryOperation factoryOperation = BridgeMethodUtils.getAnnotation(WordFactoryOperation.class, wordMethod);
         if (factoryOperation != null) {
             switch (factoryOperation.opcode()) {
                 case ZERO:
@@ -510,10 +510,6 @@
         }
     }
 
-    public WordTypes getWordTypes() {
-        return wordTypes;
-    }
-
     private static BailoutException bailout(GraphBuilderContext b, String msg) {
         throw b.bailout(msg + "\nat " + b.getCode().asStackTraceElement(b.bci()));
     }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.word/src/org/graalvm/compiler/word/WordTypes.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,8 +27,8 @@
 import org.graalvm.compiler.nodes.ValueNode;
 import org.graalvm.compiler.nodes.type.StampTool;
 import org.graalvm.compiler.word.Word.Operation;
-import org.graalvm.word.WordBase;
-import org.graalvm.word.WordFactory;
+import jdk.internal.vm.compiler.word.WordBase;
+import jdk.internal.vm.compiler.word.WordFactory;
 
 import jdk.vm.ci.meta.JavaKind;
 import jdk.vm.ci.meta.JavaType;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphElements.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphElements.java	Thu Apr 26 17:59:02 2018 +0200
@@ -187,7 +187,10 @@
     int nodeSourcePositionBCI(P pos);
 
     /**
-     * Stack trace element for a method, index and position.
+     * Stack trace element for a method, index and position. This is the basic version of the method
+     * that works with {@link StackTraceElement} and is suitable for Java-like languages. Should you
+     * need to provide more details about the location of multiple strata, see
+     * {@link GraphLocations} interface that gives more control over the provided location data.
      *
      * @param method the method
      * @param bci the index
@@ -195,4 +198,5 @@
      * @return stack trace element for the method, index and position
      */
     StackTraceElement methodStackTraceElement(M method, int bci, P pos);
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphLocations.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2011, 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.graphio;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+
+/**
+ * Provides source location information about compiled code. This interface is an extension of
+ * {@link GraphElements} - by default the elements work with classical {@link StackTraceElement}.
+ * Should the default behavior not be sufficient, feel free to implement the additional operations
+ * available in this interface and register your implementation when {@link GraphOutput.Builder
+ * building} the {@link GraphOutput} instance.
+ *
+ * @param <M> type representing methods
+ * @param <P> type representing source code location
+ * @param <L> represeting {@link StackTraceElement stack element} location
+ *
+ * @since 0.33 part of GraalVM 0.33
+ */
+public interface GraphLocations<M, P, L> {
+    /**
+     * Stack trace element for a method, index and position. Returns all applicable source locations
+     * for given code position. Each provided location is expected to represent location in a
+     * different {@link #locationLanguage(java.lang.Object) language}.
+     *
+     * @param method the method
+     * @param bci the index
+     * @param pos the position
+     * @return elements representing location for all language strata
+     */
+    Iterable<L> methodLocation(M method, int bci, P pos);
+
+    /**
+     * Identification of the language. Each location can point to a source in a different language -
+     * e.g. each location can have multiple <em>strata</em>.
+     *
+     * @param location the location
+     * @return id of the language/strata
+     */
+    String locationLanguage(L location);
+
+    /**
+     * The universal resource identification that contains the location.If the location can be found
+     * in an assummably accessible resource, then use such resource identification. It is up to the
+     * side processing the URI to load the content from the location. Protocols scheme {@code file},
+     * {@code http}, or {@code https} are assumed to be accessible.
+     * <p>
+     * If the location is inside of a virtual source, or source which is unlikely to be accessible
+     * outside of running program, then it may be better to encode the whole source into the
+     * resource identifier. This can be done by using
+     * <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs">data
+     * URIs</a> like:
+     *
+     * <pre>
+     * data:text/javascript,alert('Vivat graphs!')
+     * </pre>
+     *
+     * @param location the location
+     * @return the file name for the given location or {@code null} if it is not known
+     * @throws URISyntaxException yielding this exception aborts the graph dumping
+     */
+    URI locationURI(L location) throws URISyntaxException;
+
+    /**
+     * Line number of a location. The first line in the source file is one. Negative value means the
+     * line location isn't available. In such situation one can provide an offset driven location
+     * co-ordinates via {@link #locationOffsetStart(java.lang.Object)} and
+     * {@link #locationOffsetEnd(java.lang.Object)} methods.
+     *
+     * @param location the location
+     * @return the line number for given location, negative value means no line
+     */
+    int locationLineNumber(L location);
+
+    /**
+     * Offset of the location. In certain situations it is preferrable to specify offset rather than
+     * {@link #locationLineNumber(java.lang.Object) line number} of a location in source. In such
+     * case return the start offset from this method and end offset via
+     * {@link #locationOffsetEnd(java.lang.Object)} method. Offsets are counted from {@code 0}.
+     *
+     * @param location the location
+     * @return the starting offset of the location, negative value means no offset
+     */
+    int locationOffsetStart(L location);
+
+    /**
+     * Offset of the location. In certain situations it is preferrable to specify offset rather than
+     * {@link #locationLineNumber(java.lang.Object) line number} of a location in source. In such
+     * case return the start offset via {@link #locationOffsetStart(java.lang.Object)} method and
+     * end from this method. Offsets are counted from {@code 0}.
+     *
+     * @param location the location
+     * @return the end offset (exclusive) of the location, negative value means no offset
+     */
+    int locationOffsetEnd(L location);
+}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphOutput.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,10 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.channels.WritableByteChannel;
+import java.util.Collections;
 import java.util.Map;
 
 /**
@@ -34,9 +37,9 @@
  * @param <M> the type of methods this instance handles
  */
 public final class GraphOutput<G, M> implements Closeable {
-    private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?> printer;
+    private final GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> printer;
 
-    private GraphOutput(GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?> p) {
+    private GraphOutput(GraphProtocol<G, ?, ?, ?, ?, M, ?, ?, ?, ?> p) {
         this.printer = p;
     }
 
@@ -110,7 +113,8 @@
      */
     public static final class Builder<G, N, M> {
         private final GraphStructure<G, N, ?, ?> structure;
-        private GraphElements<M, ?, ?, ?> elements = null;
+        private ElementsAndLocations<M, ?, ?> elementsAndLocations;
+
         private GraphTypes types = DefaultGraphTypes.DEFAULT;
         private GraphBlocks<G, ?, N> blocks = DefaultGraphBlocks.empty();
         private int major = 4;
@@ -164,9 +168,24 @@
          * @param graphElements the elements implementation
          * @return this builder
          */
+        public <E, P> Builder<G, N, E> elements(GraphElements<E, ?, ?, P> graphElements) {
+            StackLocations<E, P> loc = new StackLocations<>(graphElements);
+            return elementsAndLocations(graphElements, loc);
+        }
+
+        /**
+         * Associates implementation of graph elements and an advanced way to interpret their
+         * locations.
+         *
+         * @param graphElements the elements implementation
+         * @param graphLocations the locations for the elements
+         * @return this builder
+         * @since 0.33 GraalVM 0.33
+         */
         @SuppressWarnings({"unchecked", "rawtypes"})
-        public <E> Builder<G, N, E> elements(GraphElements<E, ?, ?, ?> graphElements) {
-            this.elements = (GraphElements) graphElements;
+        public <E, P> Builder<G, N, E> elementsAndLocations(GraphElements<E, ?, ?, P> graphElements, GraphLocations<E, P, ?> graphLocations) {
+            ElementsAndLocations both = new ElementsAndLocations<>(graphElements, graphLocations);
+            this.elementsAndLocations = both;
             return (Builder<G, N, E>) this;
         }
 
@@ -179,8 +198,7 @@
          * @throws IOException if something goes wrong when writing to the channel
          */
         public GraphOutput<G, M> build(WritableByteChannel channel) throws IOException {
-            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(major, minor, structure, types, blocks, elements, channel);
-            return new GraphOutput<>(p);
+            return buildImpl(elementsAndLocations, channel);
         }
 
         /**
@@ -200,8 +218,85 @@
          * @return new output sharing {@code channel} and other internals with {@code parent}
          */
         public GraphOutput<G, M> build(GraphOutput<?, ?> parent) {
-            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?> p = new ProtocolImpl<>(parent.printer, structure, types, blocks, elements);
+            return buildImpl(elementsAndLocations, parent);
+        }
+
+        private <L, P> GraphOutput<G, M> buildImpl(ElementsAndLocations<M, L, P> e, WritableByteChannel channel) throws IOException {
+            // @formatter:off
+            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?, ?> p = new ProtocolImpl<>(
+                major, minor, structure, types, blocks,
+                e == null ? null : e.elements,
+                e == null ? null : e.locations, channel
+            );
+            // @formatter:on
+            return new GraphOutput<>(p);
+        }
+
+        private <L, P> GraphOutput<G, M> buildImpl(ElementsAndLocations<M, L, P> e, GraphOutput<?, ?> parent) {
+            // @formatter:off
+            ProtocolImpl<G, N, ?, ?, ?, M, ?, ?, ?, ?> p = new ProtocolImpl<>(
+                parent.printer, structure, types, blocks,
+                e == null ? null : e.elements,
+                e == null ? null : e.locations
+            );
+            // @formatter:on
             return new GraphOutput<>(p);
         }
     }
+
+    private static final class ElementsAndLocations<M, P, L> {
+        final GraphElements<M, ?, ?, P> elements;
+        final GraphLocations<M, P, L> locations;
+
+        ElementsAndLocations(GraphElements<M, ?, ?, P> elements, GraphLocations<M, P, L> locations) {
+            elements.getClass();
+            locations.getClass();
+            this.elements = elements;
+            this.locations = locations;
+        }
+    }
+
+    private static final class StackLocations<M, P> implements GraphLocations<M, P, StackTraceElement> {
+        private final GraphElements<M, ?, ?, P> graphElements;
+
+        StackLocations(GraphElements<M, ?, ?, P> graphElements) {
+            this.graphElements = graphElements;
+        }
+
+        @Override
+        public Iterable<StackTraceElement> methodLocation(M method, int bci, P pos) {
+            StackTraceElement ste = this.graphElements.methodStackTraceElement(method, bci, pos);
+            return Collections.singleton(ste);
+        }
+
+        @Override
+        public URI locationURI(StackTraceElement location) {
+            String path = location.getFileName();
+            try {
+                return path == null ? null : new URI(null, null, path, null);
+            } catch (URISyntaxException ex) {
+                throw new IllegalArgumentException(ex);
+            }
+        }
+
+        @Override
+        public int locationLineNumber(StackTraceElement location) {
+            return location.getLineNumber();
+        }
+
+        @Override
+        public String locationLanguage(StackTraceElement location) {
+            return "Java";
+        }
+
+        @Override
+        public int locationOffsetStart(StackTraceElement location) {
+            return -1;
+        }
+
+        @Override
+        public int locationOffsetEnd(StackTraceElement location) {
+            return -1;
+        }
+    }
 }
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/GraphProtocol.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,16 +24,20 @@
 
 import java.io.Closeable;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.ByteBuffer;
 import java.nio.channels.WritableByteChannel;
 import java.nio.charset.Charset;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.Map;
+import java.util.Objects;
 
-abstract class GraphProtocol<Graph, Node, NodeClass, Edges, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> implements Closeable {
+abstract class GraphProtocol<Graph, Node, NodeClass, Edges, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition, Location> implements Closeable {
     private static final Charset UTF8 = Charset.forName("UTF-8");
 
     private static final int CONSTANT_POOL_MAX_SIZE = 8000;
@@ -76,7 +80,7 @@
     final int versionMinor;
 
     GraphProtocol(WritableByteChannel channel, int major, int minor) throws IOException {
-        if (major > 5 || (major == 5 && minor > 0)) {
+        if (major > 6 || (major == 6 && minor > 0)) {
             throw new IllegalArgumentException("Unrecognized version " + major + "." + minor);
         }
         this.versionMajor = major;
@@ -87,7 +91,7 @@
         writeVersion();
     }
 
-    GraphProtocol(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent) {
+    GraphProtocol(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?, ?> parent) {
         this.versionMajor = parent.versionMajor;
         this.versionMinor = parent.versionMinor;
         this.constantPool = parent.constantPool;
@@ -254,7 +258,19 @@
 
     protected abstract int findNodeSourcePositionBCI(NodeSourcePosition pos);
 
-    protected abstract StackTraceElement findMethodStackTraceElement(ResolvedJavaMethod method, int bci, NodeSourcePosition pos);
+    protected abstract Iterable<Location> findLocation(ResolvedJavaMethod method, int bci, NodeSourcePosition pos);
+
+    protected abstract String findLocationFile(Location loc) throws IOException;
+
+    protected abstract int findLocationLine(Location loc);
+
+    protected abstract URI findLocationURI(Location loc) throws URISyntaxException;
+
+    protected abstract String findLocationLanguage(Location loc);
+
+    protected abstract int findLocationStart(Location loc);
+
+    protected abstract int findLocationEnd(Location loc);
 
     private void writeVersion() throws IOException {
         writeBytesRaw(MAGIC_BYTES);
@@ -374,34 +390,57 @@
         if (id == null) {
             addPoolEntry(object);
         } else {
-            if (findJavaField(object) != null) {
-                writeByte(POOL_FIELD);
-            } else if (findSignature(object) != null) {
-                writeByte(POOL_SIGNATURE);
-            } else if (versionMajor >= 4 && findNodeSourcePosition(object) != null) {
-                writeByte(POOL_NODE_SOURCE_POSITION);
-            } else {
-                final Node node = findNode(object);
-                if (versionMajor == 4 && node != null) {
-                    object = classForNode(node);
+            int type = findPoolType(object, null);
+            writeByte(type);
+            writeShort(id.charValue());
+        }
+    }
+
+    private int findPoolType(Object obj, Object[] found) throws IOException {
+        Object object = obj;
+        if (object == null) {
+            return POOL_NULL;
+        }
+        if (isFound(findJavaField(object), found)) {
+            return POOL_FIELD;
+        } else if (isFound(findSignature(object), found)) {
+            return POOL_SIGNATURE;
+        } else if (versionMajor >= 4 && isFound(findNodeSourcePosition(object), found)) {
+            return POOL_NODE_SOURCE_POSITION;
+        } else {
+            final Node node = findNode(object);
+            if (versionMajor == 4 && node != null) {
+                object = classForNode(node);
+            }
+            if (isFound(findNodeClass(object), found)) {
+                return POOL_NODE_CLASS;
+            } else if (versionMajor >= 5 && isFound(node, found)) {
+                return POOL_NODE;
+            } else if (isFound(findMethod(object), found)) {
+                return POOL_METHOD;
+            } else if (object instanceof Enum<?>) {
+                if (found != null) {
+                    found[0] = ((Enum<?>) object).ordinal();
                 }
-                if (findNodeClass(object) != null) {
-                    writeByte(POOL_NODE_CLASS);
-                } else if (versionMajor >= 5 && node != null) {
-                    writeByte(POOL_NODE);
-                } else if (findMethod(object) != null) {
-                    writeByte(POOL_METHOD);
+                return POOL_ENUM;
+            } else {
+                int val = findEnumOrdinal(object);
+                if (val >= 0) {
+                    if (found != null) {
+                        found[0] = val;
+                    }
+                    return POOL_ENUM;
+                } else if (object instanceof Class<?>) {
+                    if (found != null) {
+                        found[0] = ((Class<?>) object).getName();
+                    }
+                    return POOL_CLASS;
+                } else if (isFound(findJavaTypeName(object), found)) {
+                    return POOL_CLASS;
                 } else {
-                    if (object instanceof Enum<?> || findEnumOrdinal(object) >= 0) {
-                        writeByte(POOL_ENUM);
-                    } else if (object instanceof Class<?> || findJavaTypeName(object) != null) {
-                        writeByte(POOL_CLASS);
-                    } else {
-                        writeByte(POOL_STRING);
-                    }
+                    return POOL_STRING;
                 }
             }
-            writeShort(id.charValue());
         }
     }
 
@@ -519,61 +558,89 @@
         }
     }
 
-    @SuppressWarnings("all")
+    @SuppressWarnings("unchecked")
     private void addPoolEntry(Object obj) throws IOException {
         Object object = obj;
-        ResolvedJavaField field;
-        String typeName;
-        Signature signature;
-        NodeSourcePosition pos;
-        int enumOrdinal;
         char index = constantPool.add(object);
         writeByte(POOL_NEW);
         writeShort(index);
-        if ((field = findJavaField(object)) != null) {
-            writeByte(POOL_FIELD);
-            writePoolObject(findFieldDeclaringClass(field));
-            writePoolObject(findFieldName(field));
-            writePoolObject(findFieldTypeName(field));
-            writeInt(findFieldModifiers(field));
-        } else if ((signature = findSignature(object)) != null) {
-            writeByte(POOL_SIGNATURE);
-            int args = findSignatureParameterCount(signature);
-            writeShort((char) args);
-            for (int i = 0; i < args; i++) {
-                writePoolObject(findSignatureParameterTypeName(signature, i));
+
+        Object[] found = {null};
+        int type = findPoolType(object, found);
+        writeByte(type);
+        switch (type) {
+            case POOL_FIELD: {
+                ResolvedJavaField field = (ResolvedJavaField) found[0];
+                Objects.nonNull(field);
+                writePoolObject(findFieldDeclaringClass(field));
+                writePoolObject(findFieldName(field));
+                writePoolObject(findFieldTypeName(field));
+                writeInt(findFieldModifiers(field));
+                break;
+            }
+            case POOL_SIGNATURE: {
+                Signature signature = (Signature) found[0];
+                int args = findSignatureParameterCount(signature);
+                writeShort((char) args);
+                for (int i = 0; i < args; i++) {
+                    writePoolObject(findSignatureParameterTypeName(signature, i));
+                }
+                writePoolObject(findSignatureReturnTypeName(signature));
+                break;
             }
-            writePoolObject(findSignatureReturnTypeName(signature));
-        } else if (versionMajor >= 4 && (pos = findNodeSourcePosition(object)) != null) {
-            writeByte(POOL_NODE_SOURCE_POSITION);
-            ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
-            writePoolObject(method);
-            final int bci = findNodeSourcePositionBCI(pos);
-            writeInt(bci);
-            StackTraceElement ste = findMethodStackTraceElement(method, bci, pos);
-            if (ste != null && ste.getFileName() != null) {
-                writePoolObject(ste.getFileName());
-                writeInt(ste.getLineNumber());
-            } else {
-                writePoolObject(null);
+            case POOL_NODE_SOURCE_POSITION: {
+                NodeSourcePosition pos = (NodeSourcePosition) found[0];
+                Objects.nonNull(pos);
+                ResolvedJavaMethod method = findNodeSourcePositionMethod(pos);
+                writePoolObject(method);
+                final int bci = findNodeSourcePositionBCI(pos);
+                writeInt(bci);
+                Iterator<Location> ste = findLocation(method, bci, pos).iterator();
+                if (versionMajor >= 6) {
+                    while (ste.hasNext()) {
+                        Location loc = ste.next();
+                        URI uri;
+                        try {
+                            uri = findLocationURI(loc);
+                        } catch (URISyntaxException ex) {
+                            throw new IOException(ex);
+                        }
+                        if (uri == null) {
+                            throw new IOException("No URI for " + loc);
+                        }
+                        String l = findLocationLanguage(loc);
+                        if (l == null) {
+                            continue;
+                        }
+                        writePoolObject(uri.toString());
+                        writeString(l);
+                        writeInt(findLocationLine(loc));
+                        writeInt(findLocationStart(loc));
+                        writeInt(findLocationEnd(loc));
+                    }
+                    writePoolObject(null);
+                } else {
+                    Location first = ste.hasNext() ? ste.next() : null;
+                    String fileName = first != null ? findLocationFile(first) : null;
+                    if (fileName != null) {
+                        writePoolObject(fileName);
+                        writeInt(findLocationLine(first));
+                    } else {
+                        writePoolObject(null);
+                    }
+                }
+                writePoolObject(findNodeSourcePositionCaller(pos));
+                break;
             }
-            writePoolObject(findNodeSourcePositionCaller(pos));
-        } else {
-            Node node = findNode(object);
-            if (node != null) {
-                if (versionMajor >= 5) {
-                    writeByte(POOL_NODE);
-                    writeInt(findNodeId(node));
-                    writePoolObject(classForNode(node));
-                    return;
-                }
-                if (versionMajor == 4) {
-                    object = classForNode(node);
-                }
+            case POOL_NODE: {
+                Node node = (Node) found[0];
+                Objects.nonNull(node);
+                writeInt(findNodeId(node));
+                writePoolObject(classForNode(node));
+                break;
             }
-            NodeClass nodeClass = findNodeClass(object);
-            if (nodeClass != null) {
-                writeByte(POOL_NODE_CLASS);
+            case POOL_NODE_CLASS: {
+                NodeClass nodeClass = (NodeClass) found[0];
                 final Object clazz = findJavaClass(nodeClass);
                 if (versionMajor >= 3) {
                     writePoolObject(clazz);
@@ -585,39 +652,50 @@
                 }
                 writeEdgesInfo(nodeClass, true);
                 writeEdgesInfo(nodeClass, false);
-                return;
+                break;
             }
-            ResolvedJavaMethod method = findMethod(object);
-            if (method == null) {
-                if ((typeName = findJavaTypeName(object)) != null) {
-                    writeByte(POOL_CLASS);
-                    writeString(typeName);
-                    String[] enumValueNames = findEnumTypeValues(object);
-                    if (enumValueNames != null) {
-                        writeByte(ENUM_KLASS);
-                        writeInt(enumValueNames.length);
-                        for (String o : enumValueNames) {
-                            writePoolObject(o);
-                        }
-                    } else {
-                        writeByte(KLASS);
+            case POOL_CLASS: {
+                String typeName = (String) found[0];
+                Objects.nonNull(typeName);
+                writeString(typeName);
+                String[] enumValueNames = findEnumTypeValues(object);
+                if (enumValueNames != null) {
+                    writeByte(ENUM_KLASS);
+                    writeInt(enumValueNames.length);
+                    for (String o : enumValueNames) {
+                        writePoolObject(o);
                     }
-                } else if ((enumOrdinal = findEnumOrdinal(object)) >= 0) {
-                    writeByte(POOL_ENUM);
-                    writePoolObject(findEnumClass(object));
-                    writeInt(enumOrdinal);
                 } else {
-                    writeByte(POOL_STRING);
-                    writeString(object.toString());
+                    writeByte(KLASS);
+                }
+                break;
+            }
+            case POOL_METHOD: {
+                ResolvedJavaMethod method = (ResolvedJavaMethod) found[0];
+                Objects.nonNull(method);
+                writePoolObject(findMethodDeclaringClass(method));
+                writePoolObject(findMethodName(method));
+                final Signature methodSignature = findMethodSignature(method);
+                if (findSignature(methodSignature) == null) {
+                    throw new IOException("Should be recognized as signature: " + methodSignature + " for " + method);
                 }
-                return;
+                writePoolObject(methodSignature);
+                writeInt(findMethodModifiers(method));
+                writeBytes(findMethodCode(method));
+                break;
             }
-            writeByte(POOL_METHOD);
-            writePoolObject(findMethodDeclaringClass(method));
-            writePoolObject(findMethodName(method));
-            writePoolObject(findMethodSignature(method));
-            writeInt(findMethodModifiers(method));
-            writeBytes(findMethodCode(method));
+            case POOL_ENUM: {
+                int enumOrdinal = (int) found[0];
+                writePoolObject(findEnumClass(object));
+                writeInt(enumOrdinal);
+                break;
+            }
+            case POOL_STRING: {
+                writeString(object.toString());
+                break;
+            }
+            default:
+                throw new IllegalStateException();
         }
     }
 
@@ -696,6 +774,16 @@
         }
     }
 
+    private static boolean isFound(Object obj, Object[] found) {
+        if (obj == null) {
+            return false;
+        }
+        if (found != null) {
+            found[0] = obj;
+        }
+        return true;
+    }
+
     private static final class ConstantPool extends LinkedHashMap<Object, Character> {
 
         private final LinkedList<Character> availableIds;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.graphio/src/org/graalvm/graphio/ProtocolImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -22,34 +22,43 @@
  */
 package org.graalvm.graphio;
 
+import java.io.File;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.channels.WritableByteChannel;
 import java.util.Collection;
 import java.util.Map;
 
-final class ProtocolImpl<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition>
-                extends GraphProtocol<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> {
+final class ProtocolImpl<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition, Location>
+                extends GraphProtocol<Graph, Node, NodeClass, Port, Block, ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition, Location> {
     private final GraphStructure<Graph, Node, NodeClass, Port> structure;
     private final GraphTypes types;
     private final GraphBlocks<Graph, Block, Node> blocks;
     private final GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements;
+    private final GraphLocations<ResolvedJavaMethod, NodeSourcePosition, Location> locations;
 
     ProtocolImpl(int major, int minor, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
-                    GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements, WritableByteChannel channel) throws IOException {
+                    GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements,
+                    GraphLocations<ResolvedJavaMethod, NodeSourcePosition, Location> locs,
+                    WritableByteChannel channel) throws IOException {
         super(channel, major, minor);
         this.structure = structure;
         this.types = enums;
         this.blocks = blocks;
         this.elements = elements;
+        this.locations = locs;
     }
 
-    ProtocolImpl(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?> parent, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
-                    GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements) {
+    ProtocolImpl(GraphProtocol<?, ?, ?, ?, ?, ?, ?, ?, ?, ?> parent, GraphStructure<Graph, Node, NodeClass, Port> structure, GraphTypes enums, GraphBlocks<Graph, Block, Node> blocks,
+                    GraphElements<ResolvedJavaMethod, ResolvedJavaField, Signature, NodeSourcePosition> elements,
+                    GraphLocations<ResolvedJavaMethod, NodeSourcePosition, Location> locs) {
         super(parent);
         this.structure = structure;
         this.types = enums;
         this.blocks = blocks;
         this.elements = elements;
+        this.locations = locs;
     }
 
     @Override
@@ -285,8 +294,56 @@
     }
 
     @Override
-    protected StackTraceElement findMethodStackTraceElement(ResolvedJavaMethod method, int bci, NodeSourcePosition pos) {
-        return elements.methodStackTraceElement(method, bci, pos);
+    protected Iterable<Location> findLocation(ResolvedJavaMethod method, int bci, NodeSourcePosition pos) {
+        return locations.methodLocation(method, bci, pos);
+    }
+
+    @Override
+    protected String findLocationFile(Location loc) throws IOException {
+        if (loc == null) {
+            return null;
+        }
+        URI u;
+        try {
+            u = locations.locationURI(loc);
+        } catch (URISyntaxException ex) {
+            throw new IOException(ex);
+        }
+        if (u == null) {
+            return null;
+        }
+        if (u.getScheme() == null) {
+            return u.getPath();
+        }
+        if ("file".equals(u.getScheme())) {
+            return new File(u).getPath();
+        }
+        return null;
+    }
+
+    @Override
+    protected int findLocationLine(Location loc) {
+        return locations.locationLineNumber(loc);
+    }
+
+    @Override
+    protected URI findLocationURI(Location loc) throws URISyntaxException {
+        return locations.locationURI(loc);
+    }
+
+    @Override
+    protected String findLocationLanguage(Location loc) {
+        return locations.locationLanguage(loc);
+    }
+
+    @Override
+    protected int findLocationStart(Location loc) {
+        return locations.locationOffsetStart(loc);
+    }
+
+    @Override
+    protected int findLocationEnd(Location loc) {
+        return locations.locationOffsetEnd(loc);
     }
 
     @Override
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util.test/src/org/graalvm/util/test/CollectionSizeTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,8 +24,8 @@
 
 import static org.junit.Assert.assertEquals;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 import org.graalvm.compiler.test.GraalTest;
 import org.graalvm.util.ObjectSizeEstimate;
 import org.junit.Assume;
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.util/src/org/graalvm/util/ObjectSizeEstimate.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,8 +26,8 @@
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 
-import org.graalvm.collections.EconomicMap;
-import org.graalvm.collections.Equivalence;
+import jdk.internal.vm.compiler.collections.EconomicMap;
+import jdk.internal.vm.compiler.collections.Equivalence;
 
 /**
  * Calculates approximate estimates of the size of an object graph.
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/.checkstyle_checks.xml	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,240 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
-
-<!--
-    This configuration file was written by the eclipse-cs plugin configuration editor
--->
-<!--
-    Checkstyle-Configuration: Checks
-    Description: none
--->
-<module name="Checker">
-  <property name="severity" value="error"/>
-  <module name="TreeWalker">
-    <module name="AvoidStarImport">
-      <property name="allowClassImports" value="false"/>
-      <property name="allowStaticMemberImports" value="false"/>
-    </module>
-    <property name="tabWidth" value="4"/>
-    <module name="FileContentsHolder"/>
-    <module name="JavadocStyle">
-      <property name="checkHtml" value="false"/>
-    </module>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName">
-      <property name="format" value="^(([a-z][a-zA-Z0-9]*$)|(_[A-Z][a-zA-Z0-9]*_[a-z][a-zA-Z0-9]*$))"/>
-    </module>
-    <module name="MethodName"/>
-    <module name="PackageName"/>
-    <module name="ParameterName"/>
-    <module name="TypeName">
-      <property name="format" value="^[A-Z][_a-zA-Z0-9]*$"/>
-    </module>
-    <module name="RedundantImport"/>
-    <module name="LineLength">
-      <property name="max" value="250"/>
-    </module>
-    <module name="MethodParamPad"/>
-    <module name="NoWhitespaceAfter">
-      <property name="tokens" value="ARRAY_INIT,BNOT,DEC,DOT,INC,LNOT,UNARY_MINUS,UNARY_PLUS"/>
-    </module>
-    <module name="NoWhitespaceBefore">
-      <property name="tokens" value="SEMI,POST_DEC,POST_INC"/>
-    </module>
-    <module name="ParenPad"/>
-    <module name="TypecastParenPad">
-      <property name="tokens" value="RPAREN,TYPECAST"/>
-    </module>
-    <module name="WhitespaceAfter"/>
-    <module name="WhitespaceAround">
-      <property name="tokens" value="ASSIGN,BAND,BAND_ASSIGN,BOR,BOR_ASSIGN,BSR,BSR_ASSIGN,BXOR,BXOR_ASSIGN,COLON,DIV,DIV_ASSIGN,EQUAL,GE,GT,LAND,LE,LITERAL_ASSERT,LITERAL_CATCH,LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_FOR,LITERAL_IF,LITERAL_RETURN,LITERAL_SYNCHRONIZED,LITERAL_TRY,LITERAL_WHILE,LOR,LT,MINUS,MINUS_ASSIGN,MOD,MOD_ASSIGN,NOT_EQUAL,PLUS,PLUS_ASSIGN,QUESTION,SL,SLIST,SL_ASSIGN,SR,SR_ASSIGN,STAR,STAR_ASSIGN,LITERAL_ASSERT,TYPE_EXTENSION_AND"/>
-    </module>
-    <module name="RedundantModifier"/>
-    <module name="AvoidNestedBlocks">
-      <property name="allowInSwitchCase" value="true"/>
-    </module>
-    <module name="EmptyBlock">
-      <property name="option" value="text"/>
-      <property name="tokens" value="LITERAL_DO,LITERAL_ELSE,LITERAL_FINALLY,LITERAL_IF,LITERAL_TRY,LITERAL_WHILE,STATIC_INIT"/>
-    </module>
-    <module name="LeftCurly"/>
-    <module name="NeedBraces"/>
-    <module name="RightCurly"/>
-    <module name="EmptyStatement"/>
-    <module name="HiddenField">
-      <property name="severity" value="ignore"/>
-      <property name="ignoreConstructorParameter" value="true"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="FinalClass"/>
-    <module name="HideUtilityClassConstructor">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ArrayTypeStyle"/>
-    <module name="UpperEll"/>
-    <module name="FallThrough"/>
-    <module name="FinalLocalVariable">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="MultipleVariableDeclarations"/>
-    <module name="StringLiteralEquality">
-      <property name="severity" value="error"/>
-    </module>
-    <module name="SuperFinalize"/>
-    <module name="UnnecessaryParentheses">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="Indentation">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="StaticVariableName">
-      <property name="format" value="^[A-Za-z][a-zA-Z0-9]*$"/>
-    </module>
-    <module name="EmptyForInitializerPad"/>
-    <module name="EmptyForIteratorPad"/>
-    <module name="ModifierOrder"/>
-    <module name="DefaultComesLast"/>
-    <module name="InnerAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ModifiedControlVariable"/>
-    <module name="MutableException">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="ParameterAssignment">
-      <property name="severity" value="ignore"/>
-      <metadata name="net.sf.eclipsecs.core.lastEnabledSeverity" value="inherit"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="format" value="\s$"/>
-      <property name="message" value="Illegal trailing whitespace(s) at the end of the line."/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for trailing spaces at the end of a line"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <metadata name="net.sf.eclipsecs.core.comment" value="illegal space before a comma"/>
-      <property name="format" value=" ,"/>
-      <property name="message" value="illegal space before a comma"/>
-      <property name="ignoreComments" value="true"/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Checks for whitespace before a comma."/>
-      <metadata name="com.atlassw.tools.eclipse.checkstyle.customMessage" value="Illegal whitespace before a comma."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="[^\x00-\x7F]"/>
-      <property name="message" value="Only use ASCII characters."/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="new (Hashtable|Vector|Stack|StringBuffer)[^\w]"/>
-      <property name="message" value="Don't use old synchronized collection classes"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="instanceof MoveOp"/>
-      <property name="message" value="Do not use `op instanceof MoveOp`. Use `MoveOp.isMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="instanceof ValueMoveOp"/>
-      <property name="message" value="Do not use `op instanceof ValueMoveOp`. Use `ValueMoveOp.isValueMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="instanceof LoadConstantOp"/>
-      <property name="message" value="Do not use `op instanceof LoadConstantOp`. Use `LoadConstantOp.isLoadConstantOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="\(MoveOp\)"/>
-      <property name="message" value="Do not cast directly to `MoveOp`. Use `MoveOp.asMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="\(ValueMoveOp\)"/>
-      <property name="message" value="Do not cast directly to `ValueMoveOp`. Use `ValueMoveOp.asValueMoveOp(op)` instead!"/>
-    </module>
-    <module name="RegexpSinglelineJava">
-      <property name="format" value="\(LoadConstantOp\)"/>
-      <property name="message" value="Do not cast directly to `LoadConstantOp`. Use `LoadConstantOp.asLoadConstantOp(op)` instead!"/>
-    </module>
-  </module>
-  <module name="RegexpHeader">
-    <property name="header" value="/\*\n \* Copyright \(c\) (20[0-9][0-9], )?20[0-9][0-9], Oracle and/or its affiliates. All rights reserved.\n \* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.\n \*\n \* This code is free software; you can redistribute it and/or modify it\n \* under the terms of the GNU General Public License version 2 only, as\n \* published by the Free Software Foundation.  Oracle designates this\n \* particular file as subject to the &quot;Classpath&quot; exception as provided\n \* by Oracle in the LICENSE file that accompanied this code.\n \*\n \* This code is distributed in the hope that it will be useful, but WITHOUT\n \* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or\n \* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\n \* version 2 for more details \(a copy is included in the LICENSE file that\n \* accompanied this code\).\n \*\n \* You should have received a copy of the GNU General Public License version\n \* 2 along with this work; if not, write to the Free Software Foundation,\n \* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.\n \*\n \* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA\n \* or visit www.oracle.com if you need additional information or have any\n \* questions.\n \*/\n"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="FileTabCharacter">
-    <property name="severity" value="error"/>
-    <property name="fileExtensions" value="java"/>
-  </module>
-  <module name="NewlineAtEndOfFile">
-    <property name="lineSeparator" value="lf"/>
-  </module>
-  <module name="Translation"/>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop constant name check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume constant name check"/>
-    <property name="checkFormat" value="ConstantNameCheck"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Allow non-conforming constant names"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop method name check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume method name check"/>
-    <property name="checkFormat" value="MethodName"/>
-    <property name="checkC" value="false"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable method name checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop parameter assignment check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume parameter assignment check"/>
-    <property name="checkFormat" value="ParameterAssignment"/>
-    <property name="checkC" value="false"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable Parameter Assignment"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop final variable check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume final variable check"/>
-    <property name="checkFormat" value="FinalLocalVariable"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable final variable checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop"/>
-    <property name="onCommentFormat" value="Checkstyle: resume"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable all checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop inner assignment check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume inner assignment check"/>
-    <property name="checkFormat" value="InnerAssignment"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable inner assignment checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="Checkstyle: stop field name check"/>
-    <property name="onCommentFormat" value="Checkstyle: resume field name check"/>
-    <property name="checkFormat" value="MemberName"/>
-    <property name="checkC" value="false"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable field name checks"/>
-  </module>
-  <module name="RegexpMultiline">
-    <metadata name="net.sf.eclipsecs.core.comment" value="illegal Windows line ending"/>
-    <property name="format" value="\r\n"/>
-    <property name="message" value="illegal Windows line ending"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop header check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume header check"/>
-    <property name="checkFormat" value=".*Header"/>
-    <metadata name="com.atlassw.tools.eclipse.checkstyle.comment" value="Disable header checks"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: stop line length check"/>
-    <property name="onCommentFormat" value="CheckStyle: resume line length check"/>
-    <property name="checkFormat" value="LineLength"/>
-  </module>
-  <module name="SuppressionCommentFilter">
-    <property name="offCommentFormat" value="CheckStyle: start generated"/>
-    <property name="onCommentFormat" value="CheckStyle: stop generated"/>
-    <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/>
-  </module>
-</module>
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/ComparableWord.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,44 +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 ComparableWord extends WordBase {
-
-    /**
-     * Compares this word with the specified value.
-     *
-     * @param val value to which this word is to be compared.
-     * @return {@code this == val}
-     */
-    boolean equal(ComparableWord val);
-
-    /**
-     * Compares this word with the specified value.
-     *
-     * @param val value to which this word is to be compared.
-     * @return {@code this != val}
-     */
-    boolean notEqual(ComparableWord val);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/LocationIdentity.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 2011, 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.  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;
-
-// JaCoCo Exclude
-
-/**
- * Marker interface for location identities. A different location identity of two memory accesses
- * guarantees that the two accesses do not interfere.
- *
- * Clients of {@link LocationIdentity} must use {@link #equals(Object)}, not {@code ==}, when
- * comparing two {@link LocationIdentity} values for equality. Likewise, they must not use
- * {@link java.util.IdentityHashMap}s with {@link LocationIdentity} values as keys.
- */
-public abstract class LocationIdentity {
-
-    private static final class AnyLocationIdentity extends LocationIdentity {
-        @Override
-        public boolean isImmutable() {
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            return "ANY_LOCATION";
-        }
-    }
-
-    private static final class InitLocationIdentity extends LocationIdentity {
-        @Override
-        public boolean isImmutable() {
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            return "INIT_LOCATION";
-        }
-    }
-
-    public static final LocationIdentity ANY_LOCATION = new AnyLocationIdentity();
-    public static final LocationIdentity INIT_LOCATION = new InitLocationIdentity();
-
-    /**
-     * Indicates that the given location is the union of all possible mutable locations. A write to
-     * such a location kill all reads from mutable locations and a read from this location is killed
-     * by any write (except for initialization writes).
-     */
-    public static LocationIdentity any() {
-        return ANY_LOCATION;
-    }
-
-    /**
-     * Location only allowed to be used for writes. Indicates that a completely new memory location
-     * is written. Kills no read. The previous value at the given location must be either
-     * uninitialized or null. Writes to this location do not need a GC pre-barrier.
-     */
-    public static LocationIdentity init() {
-        return INIT_LOCATION;
-    }
-
-    /**
-     * Denotes a location is unchanging in all cases. Not that this is different than the Java
-     * notion of final which only requires definite assignment.
-     */
-    public abstract boolean isImmutable();
-
-    public final boolean isMutable() {
-        return !isImmutable();
-    }
-
-    public final boolean isAny() {
-        return this == ANY_LOCATION;
-    }
-
-    public final boolean isInit() {
-        return this == INIT_LOCATION;
-    }
-
-    public final boolean isSingle() {
-        return this != ANY_LOCATION;
-    }
-
-    public final boolean overlaps(LocationIdentity other) {
-        return isAny() || other.isAny() || this.equals(other);
-    }
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/Pointer.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,965 +0,0 @@
-/*
- * Copyright (c) 2012, 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.  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;
-
-/**
- * Lowest-level memory access of native C memory.
- * <p>
- * Do not use these methods to access Java objects. These methods access the raw memory without any
- * 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 UnsignedWord, PointerBase {
-
-    /**
-     * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
-     * checks are performed. The caller must ensure that the Pointer contains a valid Java object
-     * that can i.e., processed by the garbage collector.
-     *
-     * @return this Pointer cast to Object.
-     */
-    Object toObject();
-
-    /**
-     * Unsafe conversion of this Pointer to a Java language object. No correctness checks or type
-     * checks are performed. The caller must ensure that the Pointer contains a valid Java object
-     * that can i.e., processed by the garbage collector and the Pointer does not contain 0.
-     *
-     * @return this Pointer cast to non-null Object.
-     */
-    Object toObjectNonNull();
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    byte readByte(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    char readChar(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    short readShort(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    int readInt(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    long readLong(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    float readFloat(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    double readDouble(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    <T extends WordBase> T readWord(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    Object readObject(WordBase offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    byte readByte(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    char readChar(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    short readShort(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    int readInt(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    long readLong(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    float readFloat(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    double readDouble(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    <T extends WordBase> T readWord(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the read
-     * @return the result of the memory access
-     */
-    Object readObject(int offset, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeByte(WordBase offset, byte val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeChar(WordBase offset, char val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeShort(WordBase offset, short val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeInt(WordBase offset, int val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeLong(WordBase offset, long val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeFloat(WordBase offset, float val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeDouble(WordBase offset, double val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeWord(WordBase offset, WordBase val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void initializeLong(WordBase offset, long val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeObject(WordBase offset, Object val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeByte(int offset, byte val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeChar(int offset, char val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeShort(int offset, short val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeInt(int offset, int val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeLong(int offset, long val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeFloat(int offset, float val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeDouble(int offset, double val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeWord(int offset, WordBase val, LocationIdentity locationIdentity);
-
-    /**
-     * 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.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void initializeLong(int offset, long val, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param locationIdentity the identity of the write
-     * @param val the value to be written to memory
-     */
-    void writeObject(int offset, Object val, LocationIdentity locationIdentity);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    byte readByte(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    char readChar(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    short readShort(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    int readInt(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    long readLong(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    float readFloat(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    double readDouble(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    <T extends WordBase> T readWord(WordBase offset);
-
-    /**
-     * 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 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
-     * @return the result of the memory access
-     */
-    Object readObject(WordBase offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    byte readByte(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    char readChar(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    short readShort(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    int readInt(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    long readLong(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    float readFloat(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    double readDouble(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    <T extends WordBase> T readWord(int offset);
-
-    /**
-     * Reads the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @return the result of the memory access
-     */
-    Object readObject(int offset);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeByte(WordBase offset, byte val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeChar(WordBase offset, char val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeShort(WordBase offset, short val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeInt(WordBase offset, int val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeLong(WordBase offset, long val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeFloat(WordBase offset, float val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeDouble(WordBase offset, double val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeWord(WordBase offset, WordBase val);
-
-    /**
-     * 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 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
-     * @param val the value to be written to memory
-     */
-    void writeObject(WordBase offset, Object val);
-
-    int compareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
-    long compareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
-    <T extends WordBase> T compareAndSwapWord(WordBase offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
-
-    Object compareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapInt(WordBase offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapLong(WordBase offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapWord(WordBase offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapObject(WordBase offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeByte(int offset, byte val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeChar(int offset, char val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeShort(int offset, short val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeInt(int offset, int val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeLong(int offset, long val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeFloat(int offset, float val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeDouble(int offset, double val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeWord(int offset, WordBase val);
-
-    /**
-     * Writes the memory at address {@code (this + offset)}. Both the base address and offset are in
-     * bytes.
-     *
-     * @param offset the signed offset for the memory access
-     * @param val the value to be written to memory
-     */
-    void writeObject(int offset, Object val);
-
-    int compareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
-    long compareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
-    <T extends WordBase> T compareAndSwapWord(int offset, T expectedValue, T newValue, LocationIdentity locationIdentity);
-
-    Object compareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapInt(int offset, int expectedValue, int newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapLong(int offset, long expectedValue, long newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapWord(int offset, WordBase expectedValue, WordBase newValue, LocationIdentity locationIdentity);
-
-    boolean logicCompareAndSwapObject(int offset, Object expectedValue, Object newValue, LocationIdentity locationIdentity);
-
-    // Math functions that are defined in Unsigned, but known to preserve the
-    // pointer-characteristics.
-    // It is therefore safe that they return a static type of Pointer instead of Unsigned.
-
-    @Override
-    Pointer add(UnsignedWord val);
-
-    @Override
-    Pointer add(int val);
-
-    @Override
-    Pointer subtract(UnsignedWord val);
-
-    @Override
-    Pointer subtract(int val);
-
-    @Override
-    Pointer and(UnsignedWord val);
-
-    @Override
-    Pointer and(int val);
-
-    @Override
-    Pointer or(UnsignedWord val);
-
-    @Override
-    Pointer or(int val);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/PointerBase.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2013, 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  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;
-
-/**
- * Marker interface for all {@link WordBase word types} that have the semantic of a pointer (but not
- * necessarily all the memory access methods defined in {@link Pointer}).
- */
-public interface PointerBase extends ComparableWord {
-
-    /**
-     * Returns true if this pointer is the {@link WordFactory#nullPointer null pointer}.
-     */
-    boolean isNull();
-
-    /**
-     * Returns true if this pointer is not the {@link WordFactory#nullPointer null pointer}.
-     */
-    boolean isNonNull();
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/SignedWord.java	Mon Apr 23 12:53:43 2018 +0200
+++ /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 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/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/UnsignedWord.java	Mon Apr 23 12:53:43 2018 +0200
+++ /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 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/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordBase.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,39 +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 WordBase {
-
-    long rawValue();
-
-    /**
-     * This is deprecated because of the easy to mistype name collision between {@link #equals} and
-     * the other word based equality routines. In general you should never be statically calling
-     * this method anyway.
-     */
-    @Override
-    @Deprecated
-    boolean equals(Object o);
-}
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.word/src/org/graalvm/word/WordFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,146 +0,0 @@
-/*
- * Copyright (c) 2012, 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.  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.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-public abstract class WordFactory {
-
-    /**
-     * Links a method to a canonical operation represented by an {@link FactoryOpcode} val.
-     */
-    @Retention(RetentionPolicy.RUNTIME)
-    @Target(ElementType.METHOD)
-    protected @interface FactoryOperation {
-        FactoryOpcode opcode();
-    }
-
-    /**
-     * The canonical {@link FactoryOperation} represented by a method in a word type.
-     */
-    protected enum FactoryOpcode {
-        ZERO,
-        FROM_UNSIGNED,
-        FROM_SIGNED,
-    }
-
-    protected interface BoxFactory {
-        <T extends WordBase> T box(long val);
-    }
-
-    protected static BoxFactory boxFactory;
-
-    /**
-     * We allow subclassing, because only subclasses can access the protected inner classes that we
-     * use to mark the operations.
-     */
-    protected WordFactory() {
-    }
-
-    /**
-     * The constant 0, i.e., the word with no bits set. There is no difference between a signed and
-     * unsigned zero.
-     *
-     * @return the constant 0.
-     */
-    @FactoryOperation(opcode = FactoryOpcode.ZERO)
-    public static <T extends WordBase> T zero() {
-        return boxFactory.box(0L);
-    }
-
-    /**
-     * The null pointer, i.e., the pointer with no bits set. There is no difference to a signed or
-     * unsigned {@link #zero}.
-     *
-     * @return the null pointer.
-     */
-    @FactoryOperation(opcode = FactoryOpcode.ZERO)
-    public static <T extends PointerBase> T nullPointer() {
-        return boxFactory.box(0L);
-    }
-
-    /**
-     * Unsafe conversion from a Java long value to a Word. The parameter is treated as an unsigned
-     * 64-bit value (in contrast to the semantics of a Java long).
-     *
-     * @param val a 64 bit unsigned value
-     * @return the value cast to Word
-     */
-    @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
-    public static <T extends UnsignedWord> T unsigned(long val) {
-        return boxFactory.box(val);
-    }
-
-    /**
-     * Unsafe conversion from a Java long value to a {@link PointerBase pointer}. The parameter is
-     * treated as an unsigned 64-bit value (in contrast to the semantics of a Java long).
-     *
-     * @param val a 64 bit unsigned value
-     * @return the value cast to PointerBase
-     */
-    @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
-    public static <T extends PointerBase> T pointer(long val) {
-        return boxFactory.box(val);
-    }
-
-    /**
-     * Unsafe conversion from a Java int value to a Word. The parameter is treated as an unsigned
-     * 32-bit value (in contrast to the semantics of a Java int).
-     *
-     * @param val a 32 bit unsigned value
-     * @return the value cast to Word
-     */
-    @FactoryOperation(opcode = FactoryOpcode.FROM_UNSIGNED)
-    public static <T extends UnsignedWord> T unsigned(int val) {
-        return boxFactory.box(val & 0xffffffffL);
-    }
-
-    /**
-     * Unsafe conversion from a Java long value to a Word. The parameter is treated as a signed
-     * 64-bit value (unchanged semantics of a Java long).
-     *
-     * @param val a 64 bit signed value
-     * @return the value cast to Word
-     */
-    @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
-    public static <T extends SignedWord> T signed(long val) {
-        return boxFactory.box(val);
-    }
-
-    /**
-     * Unsafe conversion from a Java int value to a Word. The parameter is treated as a signed
-     * 32-bit value (unchanged semantics of a Java int).
-     *
-     * @param val a 32 bit signed value
-     * @return the value cast to Word
-     */
-    @FactoryOperation(opcode = FactoryOpcode.FROM_SIGNED)
-    public static <T extends SignedWord> T signed(int val) {
-        return boxFactory.box(val);
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -45,14 +45,12 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.taglets.DeprecatedTaglet;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 import static javax.lang.model.element.Modifier.*;
 
@@ -134,7 +132,7 @@
     /**
      * Create the summary table for this element.
      * The table should be created and initialized if needed, and configured
-     * so that it is ready to add content with {@link Table#addRows(Content[])}
+     * so that it is ready to add content with {@link Table#addRow(Content[])}
      * and similar methods.
      *
      * @return the summary table
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeFieldWriterImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -37,13 +37,11 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 
-
 /**
  * Writes annotation type field documentation in HTML format.
  *
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -41,10 +41,8 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 /**
  * Generate the Class Information Page.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -45,14 +45,11 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ClassWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
-import jdk.javadoc.internal.doclets.toolkit.builders.MemberSummaryBuilder;
 import jdk.javadoc.internal.doclets.toolkit.taglets.ParamTaglet;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFileIOException;
-import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 /**
  * Generate the Class Information Page.
@@ -122,7 +119,7 @@
             Content moduleNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classModuleLabel);
             moduleNameDiv.addContent(Contents.SPACE);
             moduleNameDiv.addContent(getModuleLink(mdle,
-                    new StringContent(mdle.getQualifiedName().toString())));
+                    new StringContent(mdle.getQualifiedName())));
             div.addContent(moduleNameDiv);
         }
         PackageElement pkg = utils.containingPackage(typeElement);
@@ -373,8 +370,8 @@
     @Override
     public void addSubClassInfo(Content classInfoTree) {
         if (utils.isClass(typeElement)) {
-            if (typeElement.getQualifiedName().toString().equals("java.lang.Object") ||
-                    typeElement.getQualifiedName().toString().equals("org.omg.CORBA.Object")) {
+            if (typeElement.getQualifiedName().contentEquals("java.lang.Object") ||
+                    typeElement.getQualifiedName().contentEquals("org.omg.CORBA.Object")) {
                 return;    // Don't generate the list, too huge
             }
             Set<TypeElement> subclasses = classtree.directSubClasses(typeElement, false);
@@ -415,8 +412,8 @@
         if (!utils.isInterface(typeElement)) {
             return;
         }
-        if (typeElement.getQualifiedName().toString().equals("java.lang.Cloneable") ||
-                typeElement.getQualifiedName().toString().equals("java.io.Serializable")) {
+        if (typeElement.getQualifiedName().contentEquals("java.lang.Cloneable") ||
+                typeElement.getQualifiedName().contentEquals("java.io.Serializable")) {
             return;   // Don't generate the list, too big
         }
         Set<TypeElement> implcl = classtree.implementingClasses(typeElement);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstructorWriterImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,12 +38,13 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 
 /**
@@ -72,10 +73,9 @@
     public ConstructorWriterImpl(SubWriterHolderWriter writer, TypeElement typeElement) {
         super(writer, typeElement);
 
-        VisibleMemberMap visibleMemberMap = configuration.getVisibleMemberMap(
-                typeElement,
-                VisibleMemberMap.Kind.CONSTRUCTORS);
-        List<Element> constructors = visibleMemberMap.getMembers(typeElement);
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+        List<? extends Element> constructors = vmt.getVisibleMembers(CONSTRUCTORS);
+
         for (Element constructor : constructors) {
             if (utils.isProtected(constructor) || utils.isPrivate(constructor)) {
                 setFoundNonPubConstructor(true);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Contents.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,8 @@
 
 package jdk.javadoc.internal.doclets.formats.html;
 
+import java.util.EnumMap;
+import java.util.Objects;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -36,6 +38,8 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.Resources;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
 
 /**
  * Constants and factory methods for common fragments of content
@@ -165,6 +169,8 @@
     public final Content useLabel;
     public final Content valueLabel;
 
+    private final EnumMap<VisibleMemberTable.Kind, Content> navLinkLabels;
+
     private final Resources resources;
 
     /**
@@ -289,6 +295,13 @@
         typeLabel = getContent("doclet.Type");
         useLabel = getContent("doclet.navClassUse");
         valueLabel = getContent("doclet.Value");
+
+        navLinkLabels = new EnumMap<>(VisibleMemberTable.Kind.class);
+        navLinkLabels.put(VisibleMemberTable.Kind.INNER_CLASSES, getContent("doclet.navNested"));
+        navLinkLabels.put(VisibleMemberTable.Kind.ENUM_CONSTANTS, getContent("doclet.navEnum"));
+        navLinkLabels.put(VisibleMemberTable.Kind.FIELDS, getContent("doclet.navField"));
+        navLinkLabels.put(VisibleMemberTable.Kind.CONSTRUCTORS, getContent("doclet.navConstructor"));
+        navLinkLabels.put(VisibleMemberTable.Kind.METHODS, getContent("doclet.navMethod"));
     }
 
     /**
@@ -393,4 +406,13 @@
         c.addContent(text.substring(start));
         return c; // TODO: should be made immutable
     }
+
+    /**
+     * Returns a content for a visible member kind.
+     * @param kind the visible member table kind.
+     * @return the string content
+     */
+    public Content getNavLinkLabelContent(VisibleMemberTable.Kind kind) {
+        return Objects.requireNonNull(navLinkLabels.get(kind));
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -107,7 +107,6 @@
      * For new format.
      *
      * @throws DocletException if there is a problem while writing the other files
-     * @see jdk.doclet.DocletEnvironment
      */
     @Override // defined by AbstractDoclet
     protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree)
@@ -242,7 +241,7 @@
         List<TypeElement> list = new ArrayList<>(arr);
         ListIterator<TypeElement> iterator = list.listIterator();
         for (TypeElement klass : list) {
-            if (utils.isHidden(klass) ||
+            if (utils.hasHiddenTag(klass) ||
                     !(configuration.isGeneratedDoc(klass) && utils.isIncluded(klass))) {
                 continue;
             }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -69,13 +69,11 @@
 
 import jdk.javadoc.internal.doclets.formats.html.markup.ContentBuilder;
 import jdk.javadoc.internal.doclets.formats.html.markup.DocType;
-import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlDocument;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.Links;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
 import jdk.javadoc.internal.doclets.formats.html.markup.Script;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
@@ -94,9 +92,8 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
 import jdk.javadoc.internal.doclets.toolkit.util.DocletConstants;
-import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 import static com.sun.source.doctree.DocTree.Kind.*;
 import static jdk.javadoc.internal.doclets.toolkit.util.CommentHelper.SPACER;
@@ -302,11 +299,12 @@
         TypeElement enclosing = utils.getEnclosingTypeElement(method);
         List<? extends TypeMirror> intfacs = enclosing.getInterfaces();
         ExecutableElement overriddenMethod = utils.overriddenMethod(method);
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(enclosing);
         // Check whether there is any implementation or overridden info to be
         // printed. If no overridden or implementation info needs to be
         // printed, do not print this section.
         if ((!intfacs.isEmpty()
-                && new ImplementedMethods(method, this.configuration).build().isEmpty() == false)
+                && vmt.getImplementedMethods(method).isEmpty() == false)
                 || overriddenMethod != null) {
             MethodWriterImpl.addImplementsInfo(this, method, dl);
             if (overriddenMethod != null) {
@@ -1078,10 +1076,11 @@
 
             // Find the enclosing type where the method is actually visible
             // in the inheritance hierarchy.
+            ExecutableElement overriddenMethod = null;
             if (refMem.getKind() == ElementKind.METHOD) {
-                VisibleMemberMap vmm = configuration.getVisibleMemberMap(containing,
-                        VisibleMemberMap.Kind.METHODS);
-                ExecutableElement overriddenMethod = vmm.getVisibleMethod((ExecutableElement)refMem);
+                VisibleMemberTable vmt = configuration.getVisibleMemberTable(containing);
+                overriddenMethod = vmt.getOverriddenMethod((ExecutableElement)refMem);
+
                 if (overriddenMethod != null)
                     containing = utils.getEnclosingTypeElement(overriddenMethod);
             }
@@ -1112,6 +1111,10 @@
                 if (refMemName.indexOf('(') < 0) {
                     refMemName += utils.makeSignature((ExecutableElement)refMem, true);
                 }
+                if (overriddenMethod != null) {
+                    // The method to actually link.
+                    refMem = overriddenMethod;
+                }
             }
 
             text = plainOrCode(kind == LINK_PLAIN, new StringContent(refMemName));
@@ -1596,7 +1599,7 @@
      * {@literal <a href="./com/sun/javadoc/package-summary.html">The package Page</a>}
      *
      * @param element the Element object whose documentation is being written.
-     * @param text the text being written.
+     * @param tt the text being written.
      *
      * @return the text, with all the relative links redirected to work.
      */
@@ -1671,7 +1674,7 @@
      * Add the annotation types of the executable receiver.
      *
      * @param method the executable to write the receiver annotations for.
-     * @param descList list of annotation description.
+     * @param descList a list of annotation mirrors.
      * @param htmltree the documentation tree to which the annotation info will be
      *        added
      */
@@ -1718,7 +1721,7 @@
      * Adds the annotatation types for the given Element.
      *
      * @param element the element to write annotations for.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param htmltree the documentation tree to which the annotation info will be
      *        added
      */
@@ -1732,7 +1735,7 @@
      *
      * @param indent the number of extra spaces to indent the annotations.
      * @param element the element to write annotations for.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param htmltree the documentation tree to which the annotation info will be
      *        added
      */
@@ -1758,9 +1761,9 @@
      * the given doc.
      *
      * @param indent the number of extra spaces to indent the annotations.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param linkBreak if true, add new line between each member value.
-     * @return an array of strings representing the annotations being
+     * @return a list of strings representing the annotations being
      *         documented.
      */
     private List<Content> getAnnotations(int indent, List<? extends AnnotationMirror> descList, boolean linkBreak) {
@@ -1781,10 +1784,10 @@
      * annotations should be returned without any filtering.
      *
      * @param indent the number of extra spaces to indent the annotations.
-     * @param descList the array of {@link AnnotationDesc}.
+     * @param descList a list of annotation mirrors.
      * @param linkBreak if true, add new line between each member value.
      * @param isJava5DeclarationLocation
-     * @return an array of strings representing the annotations being
+     * @return a list of strings representing the annotations being
      *         documented.
      */
     public List<Content> getAnnotations(int indent, List<? extends AnnotationMirror> descList,
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -40,13 +40,12 @@
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
-import jdk.javadoc.internal.doclets.formats.html.markup.Navigation;
 import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.MemberSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.ImplementedMethods;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 /**
  * Writes method documentation in HTML format.
@@ -383,13 +382,13 @@
             return;
         }
         Contents contents = writer.contents;
-        ImplementedMethods implementedMethodsFinder =
-                new ImplementedMethods(method, writer.configuration);
+        VisibleMemberTable vmt = writer.configuration
+                .getVisibleMemberTable(utils.getEnclosingTypeElement(method));
         SortedSet<ExecutableElement> implementedMethods =
                 new TreeSet<>(utils.makeOverrideUseComparator());
-        implementedMethods.addAll(implementedMethodsFinder.build());
+        implementedMethods.addAll(vmt.getImplementedMethods(method));
         for (ExecutableElement implementedMeth : implementedMethods) {
-            TypeMirror intfac = implementedMethodsFinder.getMethodHolder(implementedMeth);
+            TypeMirror intfac = vmt.getImplementedMethodHolder(method, implementedMeth);
             intfac = utils.getDeclaredType(utils.getEnclosingTypeElement(method), intfac);
             Content intfaclink = writer.getLink(new LinkInfoImpl(
                     writer.configuration, LinkInfoImpl.Kind.METHOD_SPECIFIED_BY, intfac));
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/WriterFactoryImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -30,7 +30,6 @@
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
 
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeFieldWriter;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeOptionalMemberWriter;
@@ -45,7 +44,7 @@
 import jdk.javadoc.internal.doclets.toolkit.SerializedFormWriter;
 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 /**
  * The factory that returns HTML writers.
@@ -184,7 +183,7 @@
      */
     @Override
     public MemberSummaryWriter getMemberSummaryWriter(ClassWriter classWriter,
-            VisibleMemberMap.Kind memberType) {
+            VisibleMemberTable.Kind memberType) {
         switch (memberType) {
             case CONSTRUCTORS:
                 return getConstructorWriter(classWriter);
@@ -209,7 +208,7 @@
      */
     @Override
     public MemberSummaryWriter getMemberSummaryWriter(AnnotationTypeWriter annotationTypeWriter,
-            VisibleMemberMap.Kind memberType) {
+            VisibleMemberTable.Kind memberType) {
         switch (memberType) {
             case ANNOTATION_TYPE_FIELDS:
                 return (AnnotationTypeFieldWriterImpl)
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Navigation.java	Thu Apr 26 17:59:02 2018 +0200
@@ -30,6 +30,7 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.SortedSet;
 
 import javax.lang.model.element.Element;
@@ -48,7 +49,9 @@
 import jdk.javadoc.internal.doclets.toolkit.util.DocLink;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPath;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Factory for navigation bar.
@@ -414,28 +417,28 @@
             case CLASS:
                 if (element.getKind() == ElementKind.ANNOTATION_TYPE) {
                     addAnnotationTypeSummaryLink("doclet.navField",
-                            VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS, listContents);
+                            ANNOTATION_TYPE_FIELDS, listContents);
                     addAnnotationTypeSummaryLink("doclet.navAnnotationTypeRequiredMember",
-                            VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
+                            ANNOTATION_TYPE_MEMBER_REQUIRED, listContents);
                     addAnnotationTypeSummaryLink("doclet.navAnnotationTypeOptionalMember",
-                            VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
+                            ANNOTATION_TYPE_MEMBER_OPTIONAL, listContents);
                 } else {
                     TypeElement typeElement = (TypeElement) element;
-                    for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.summarySet) {
-                        if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+                    for (VisibleMemberTable.Kind kind : summarySet) {
+                        if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
-                        if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+                        if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
                         AbstractMemberWriter writer
                                 = ((AbstractMemberWriter) memberSummaryBuilder.getMemberSummaryWriter(kind));
                         if (writer == null) {
-                            addContentToList(listContents,
-                                    contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+                            addContentToList(listContents, contents.getNavLinkLabelContent(kind));
                         } else {
                             addTypeSummaryLink(memberSummaryBuilder.members(kind),
-                                    memberSummaryBuilder.getVisibleMemberMap(kind), listContents);
+                                    memberSummaryBuilder.getVisibleMemberTable(),
+                                    kind, listContents);
                         }
                     }
                 }
@@ -487,24 +490,25 @@
      * Add the navigation summary link.
      *
      * @param members members to be linked
-     * @param visibleMemberMap the visible inherited members map
+     * @param vmt the visible member table
+     * @param kind the visible member kind
      * @param listContents the list of contents
      */
     private void addTypeSummaryLink(SortedSet<? extends Element> members,
-            VisibleMemberMap visibleMemberMap, List<Content> listContents) {
+            VisibleMemberTable vmt,
+            VisibleMemberTable.Kind kind, List<Content> listContents) {
         if (!members.isEmpty()) {
-            addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+            addTypeSummaryLink(null, kind, true, listContents);
             return;
         }
-
-        SortedSet<TypeElement> visibleClasses = visibleMemberMap.getVisibleClasses();
+        Set<TypeElement> visibleClasses = vmt.getVisibleTypeElements();
         for (TypeElement t : visibleClasses) {
-            if (!configuration.getVisibleMemberMap(t, visibleMemberMap.kind).getLeafMembers().isEmpty()) {
-                addTypeSummaryLink(null, visibleMemberMap.kind, true, listContents);
+            if (configuration.getVisibleMemberTable(t).hasVisibleMembers(kind)) {
+                addTypeSummaryLink(null, kind, true, listContents);
                 return;
             }
         }
-        addTypeSummaryLink(null, visibleMemberMap.kind, false, listContents);
+        addTypeSummaryLink(null, kind, false, listContents);
     }
 
     /**
@@ -515,7 +519,7 @@
      * @param link true if the members are listed and need to be linked
      * @param listContents the list of contents to which the summary will be added
      */
-    private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberMap.Kind kind, boolean link,
+    private void addTypeSummaryLink(TypeElement typeElement, VisibleMemberTable.Kind kind, boolean link,
             List<Content> listContents) {
         switch (kind) {
             case CONSTRUCTORS:
@@ -601,17 +605,17 @@
      * Add the navigation Type summary link.
      *
      * @param label the label to be added
-     * @param type the kind of member being documented
+     * @param kind the kind of member being documented
      * @param listContents the list of contents to which the summary will be added
      */
-    private void addAnnotationTypeSummaryLink(String label, VisibleMemberMap.Kind type, List<Content> listContents) {
+    private void addAnnotationTypeSummaryLink(String label, VisibleMemberTable.Kind kind, List<Content> listContents) {
         AbstractMemberWriter writer = ((AbstractMemberWriter) memberSummaryBuilder.
-                getMemberSummaryWriter(type));
+                getMemberSummaryWriter(kind));
         if (writer == null) {
             addContentToList(listContents, contents.getContent(label));
         } else {
-            boolean link = !memberSummaryBuilder.getVisibleMemberMap(type).noVisibleMembers();
-            switch (type) {
+            boolean link = memberSummaryBuilder.getVisibleMemberTable().hasVisibleMembers(kind);
+            switch (kind) {
                 case ANNOTATION_TYPE_FIELDS:
                     if (link) {
                         addContentToList(listContents, links.createLink(SectionName.ANNOTATION_TYPE_FIELD_SUMMARY,
@@ -657,20 +661,20 @@
                     addAnnotationTypeDetailLink(listContents);
                 } else {
                     TypeElement typeElement = (TypeElement) element;
-                    for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.detailSet) {
+                    for (VisibleMemberTable.Kind kind : detailSet) {
                         AbstractMemberWriter writer
                                 = ((AbstractMemberWriter) memberSummaryBuilder.
                                         getMemberSummaryWriter(kind));
-                        if (kind == VisibleMemberMap.Kind.ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
+                        if (kind == ENUM_CONSTANTS && !configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
-                        if (kind == VisibleMemberMap.Kind.CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
+                        if (kind == CONSTRUCTORS && configuration.utils.isEnum(typeElement)) {
                             continue;
                         }
                         if (writer == null) {
-                            addContentToList(listContents, contents.getContent(VisibleMemberMap.Kind.getNavLinkLabels(kind)));
+                            addContentToList(listContents, contents.getNavLinkLabelContent(kind));
                         } else {
-                            addTypeDetailLink(kind, !memberSummaryBuilder.members(kind).isEmpty(), listContents);
+                            addTypeDetailLink(kind, memberSummaryBuilder.hasMembers(kind), listContents);
                         }
                     }
                 }
@@ -693,7 +697,7 @@
      * @param link true if the members are listed and need to be linked
      * @param listContents the list of contents to which the detail will be added.
      */
-    protected void addTypeDetailLink(VisibleMemberMap.Kind kind, boolean link, List<Content> listContents) {
+    protected void addTypeDetailLink(VisibleMemberTable.Kind kind, boolean link, List<Content> listContents) {
         switch (kind) {
             case CONSTRUCTORS:
                 if (link) {
@@ -744,25 +748,25 @@
         TypeElement annotationType = (TypeElement) element;
         AbstractMemberWriter writerField
                 = ((AbstractMemberWriter) memberSummaryBuilder.
-                        getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS));
+                        getMemberSummaryWriter(ANNOTATION_TYPE_FIELDS));
         AbstractMemberWriter writerOptional
                 = ((AbstractMemberWriter) memberSummaryBuilder.
-                        getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL));
+                        getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_OPTIONAL));
         AbstractMemberWriter writerRequired
                 = ((AbstractMemberWriter) memberSummaryBuilder.
-                        getMemberSummaryWriter(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED));
+                        getMemberSummaryWriter(ANNOTATION_TYPE_MEMBER_REQUIRED));
         if (writerField != null) {
-            addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS,
+            addAnnotationTypeDetailLink(ANNOTATION_TYPE_FIELDS,
                     !configuration.utils.getAnnotationFields(annotationType).isEmpty(),
                     listContents);
         } else {
             addContentToList(listContents, contents.navField);
         }
         if (writerOptional != null) {
-            addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL,
+            addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_OPTIONAL,
                     !annotationType.getAnnotationMirrors().isEmpty(), listContents);
         } else if (writerRequired != null) {
-            addAnnotationTypeDetailLink(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED,
+            addAnnotationTypeDetailLink(ANNOTATION_TYPE_MEMBER_REQUIRED,
                     !annotationType.getAnnotationMirrors().isEmpty(), listContents);
         } else {
             addContentToList(listContents, contents.navAnnotationTypeMember);
@@ -776,7 +780,7 @@
      * @param link true if the member details need to be linked
      * @param listContents the list of contents to which the annotation detail will be added.
      */
-    protected void addAnnotationTypeDetailLink(VisibleMemberMap.Kind type, boolean link, List<Content> listContents) {
+    protected void addAnnotationTypeDetailLink(VisibleMemberTable.Kind type, boolean link, List<Content> listContents) {
         switch (type) {
             case ANNOTATION_TYPE_FIELDS:
                 if (link) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/AbstractDoclet.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -81,7 +81,7 @@
 
     /**
      * Verify that the only doclet that is using this toolkit is
-     * {@value #TOOLKIT_DOCLET_NAME}.
+     * #TOOLKIT_DOCLET_NAME.
      */
     private boolean isValidDoclet() {
         if (!getClass().getName().equals(TOOLKIT_DOCLET_NAME)) {
@@ -102,10 +102,7 @@
     public boolean run(DocletEnvironment docEnv) {
         configuration = getConfiguration();
         configuration.initConfiguration(docEnv);
-        configuration.cmtUtils = new CommentUtils(configuration);
-        configuration.utils = new Utils(configuration);
         utils = configuration.utils;
-        configuration.workArounds = new WorkArounds(configuration);
         messages = configuration.getMessages();
 
         if (!isValidDoclet()) {
@@ -189,7 +186,6 @@
      * TreeWriter generation first to ensure the Class Hierarchy is built
      * first and then can be used in the later generation.
      *
-     * @see jdk.doclet.DocletEnvironment
      * @throws DocletException if there is a problem while generating the documentation
      */
     private void startGeneration(DocletEnvironment docEnv) throws DocletException {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/BaseConfiguration.java	Thu Apr 26 17:59:02 2018 +0200
@@ -26,7 +26,6 @@
 package jdk.javadoc.internal.doclets.toolkit;
 
 import java.io.*;
-import java.lang.ref.*;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -56,9 +55,8 @@
 import jdk.javadoc.internal.doclets.toolkit.util.TypeElementCatalog;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils;
 import jdk.javadoc.internal.doclets.toolkit.util.Utils.Pair;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.GetterSetter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberCache;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 import static javax.tools.Diagnostic.Kind.*;
 
@@ -299,8 +297,6 @@
 
     private List<Pair<String, String>> groupPairs;
 
-    private final Map<TypeElement, EnumMap<Kind, Reference<VisibleMemberMap>>> typeElementMemberCache;
-
     public abstract Messages getMessages();
 
     public abstract Resources getResources();
@@ -331,11 +327,6 @@
 
     public OverviewElement overviewElement;
 
-    // The following three fields provide caches for use by all instances of VisibleMemberMap.
-    public final Map<TypeElement, List<Element>> propertiesCache = new HashMap<>();
-    public final Map<Element, Element> classPropertiesMap = new HashMap<>();
-    public final Map<Element, GetterSetter> getterSetterMap = new HashMap<>();
-
     public DocFileFactory docFileFactory;
 
     /**
@@ -352,6 +343,17 @@
             "jdk.javadoc.internal.doclets.toolkit.resources.doclets";
 
     /**
+     * Primarily used to disable strict checks in the regression
+     * tests allowing those tests to be executed successfully, for
+     * instance, with OpenJDK builds which may not contain FX libraries.
+     */
+    public boolean disableJavaFxStrictChecks = false;
+
+    VisibleMemberCache visibleMemberCache = null;
+
+    public PropertyUtils propertyUtils = null;
+
+    /**
      * Constructs the configurations needed by the doclet.
      *
      * @param doclet the doclet that created this configuration
@@ -363,7 +365,6 @@
         setTabWidth(DocletConstants.DEFAULT_TAB_STOP_LENGTH);
         metakeywords = new MetaKeywords(this);
         groupPairs = new ArrayList<>(0);
-        typeElementMemberCache = new HashMap<>();
     }
 
     private boolean initialized = false;
@@ -374,6 +375,15 @@
         }
         initialized = true;
         this.docEnv = docEnv;
+        // Utils needs docEnv, safe to init now.
+        utils = new Utils(this);
+
+        // Once docEnv and Utils have been initialized, others should be safe.
+        cmtUtils = new CommentUtils(this);
+        workArounds = new WorkArounds(this);
+        visibleMemberCache = new VisibleMemberCache(this);
+        propertyUtils = new PropertyUtils(this);
+
         Splitter specifiedSplitter = new Splitter(docEnv, false);
         specifiedModuleElements = Collections.unmodifiableSet(specifiedSplitter.mset);
         specifiedPackageElements = Collections.unmodifiableSet(specifiedSplitter.pset);
@@ -699,6 +709,13 @@
                         allowScriptInComments = true;
                         return true;
                     }
+                },
+                new Hidden(resources, "--disable-javafx-strict-checks") {
+                    @Override
+                    public boolean process(String opt, List<String> args) {
+                        disableJavaFxStrictChecks = true;
+                        return true;
+                    }
                 }
         };
         Set<Doclet.Option> set = new TreeSet<>();
@@ -1285,17 +1302,7 @@
         return allowScriptInComments;
     }
 
-    public VisibleMemberMap getVisibleMemberMap(TypeElement te, VisibleMemberMap.Kind kind) {
-        EnumMap<Kind, Reference<VisibleMemberMap>> cacheMap = typeElementMemberCache
-                .computeIfAbsent(te, k -> new EnumMap<>(VisibleMemberMap.Kind.class));
-
-        Reference<VisibleMemberMap> vmapRef = cacheMap.get(kind);
-        // recompute, if referent has been garbage collected
-        VisibleMemberMap vMap = vmapRef == null ? null : vmapRef.get();
-        if (vMap == null) {
-            vMap = new VisibleMemberMap(te, kind, this);
-            cacheMap.put(kind, new SoftReference<>(vMap));
-        }
-        return vMap;
+    public synchronized VisibleMemberTable getVisibleMemberTable(TypeElement te) {
+        return visibleMemberCache.getVisibleMemberTable(te);
     }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/MemberSummaryWriter.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -31,7 +31,6 @@
 import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
 /**
  * The interface for writing member summary output.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/PropertyUtils.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.toolkit;
+
+import java.util.regex.Pattern;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+
+/**
+ * This class provides basic JavaFX property related utility methods.
+ * Refer to the JavaFX conventions in the VisibleMemberTable comments.
+ */
+public class PropertyUtils {
+
+    final TypeMirror jbObservableType;
+
+    final Pattern fxMethodPatterns;
+
+    final boolean javafx;
+
+    final Types typeUtils;
+
+    PropertyUtils(BaseConfiguration configuration) {
+
+        javafx = configuration.javafx;
+
+        typeUtils = configuration.docEnv.getTypeUtils();
+
+        // Disable strict check for JDK's without FX.
+        TypeMirror jboType = configuration.disableJavaFxStrictChecks
+                ? null
+                : configuration.utils.getSymbol("javafx.beans.Observable");
+
+        jbObservableType = jboType != null
+                ? configuration.docEnv.getTypeUtils().erasure(jboType)
+                : null;
+
+        fxMethodPatterns = javafx
+                ? Pattern.compile("[sg]et\\p{Upper}.*||is\\p{Upper}.*")
+                : null;
+    }
+
+    /**
+     * Returns a base name for a property method. Supposing we
+     * have {@code BooleanProperty acmeProperty()}, then "acme"
+     * will be returned.
+     * @param propertyMethod
+     * @return the base name of a property method.
+     */
+    public String getBaseName(ExecutableElement propertyMethod) {
+        String name = propertyMethod.getSimpleName().toString();
+        String baseName = name.substring(0, name.indexOf("Property"));
+        return baseName;
+    }
+
+    /**
+     * Returns a property getter's name. Supposing we have a property
+     * method {@code DoubleProperty acmeProperty()}, then "getAcme"
+     * will be returned.
+     * @param propertyMethod
+     * @return the property getter's name.
+     */
+    public String getGetName(ExecutableElement propertyMethod) {
+        String baseName = getBaseName(propertyMethod);
+        String fnUppercased = "" +
+                Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+        return "get" + fnUppercased;
+    }
+
+    /**
+     * Returns an "is" method's name for a property method. Supposing
+     * we have a property method {@code BooleanProperty acmeProperty()},
+     * then "isAcme" will be returned.
+     * @param propertyMethod
+     * @return the property is getter's name.
+     */
+    public String getIsName(ExecutableElement propertyMethod) {
+        String baseName = getBaseName(propertyMethod);
+        String fnUppercased = "" +
+                Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+        return "is" + fnUppercased;
+    }
+
+    /**
+     * Returns true if a property method could have an "is" method, meaning
+     * {@code isAcme} could exist for a property method.
+     * @param propertyMethod
+     * @return true if the property could have an "is" method, false otherwise.
+     */
+    public boolean hasIsMethod(ExecutableElement propertyMethod) {
+        String propertyTypeName = propertyMethod.getReturnType().toString();
+        return "boolean".equals(propertyTypeName) ||
+                propertyTypeName.endsWith("BooleanProperty");
+    }
+
+    /**
+     * Returns a property setter's name. Supposing we have a property
+     * method {@code DoubleProperty acmeProperty()}, then "setAcme"
+     * will be returned.
+     * @param propertyMethod
+     * @return the property setter's method name.
+     */
+    public String getSetName(ExecutableElement propertyMethod) {
+        String baseName = getBaseName(propertyMethod);
+        String fnUppercased = "" +
+                Character.toUpperCase(baseName.charAt(0)) + baseName.substring(1);
+        return "set" + fnUppercased;
+    }
+
+    /**
+     * Returns true if the given setter method is a valid property setter
+     * method.
+     * @param setterMethod
+     * @return true if setter method, false otherwise.
+     */
+    public boolean isValidSetterMethod(ExecutableElement setterMethod) {
+        return setterMethod.getReturnType().getKind() == TypeKind.VOID;
+    }
+
+    /**
+     * Returns true if the method is a property method.
+     * @param propertyMethod
+     * @return true if the method is a property method, false otherwise.
+     */
+    public boolean isPropertyMethod(ExecutableElement propertyMethod) {
+        if (!javafx ||
+                !propertyMethod.getParameters().isEmpty() ||
+                !propertyMethod.getTypeParameters().isEmpty()) {
+            return false;
+        }
+        String methodName = propertyMethod.getSimpleName().toString();
+        if (!methodName.endsWith("Property") ||
+                fxMethodPatterns.matcher(methodName).matches()) {
+            return false;
+        }
+
+        TypeMirror returnType = propertyMethod.getReturnType();
+        if (jbObservableType == null) {
+            // JavaFX references missing, make a lazy backward compatible check.
+            return returnType.getKind() != TypeKind.VOID;
+        } else {
+            // Apply strict checks since JavaFX references are available
+            returnType = typeUtils.erasure(propertyMethod.getReturnType());
+            return typeUtils.isAssignable(returnType, jbObservableType);
+        }
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/WriterFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -29,10 +29,9 @@
 import javax.lang.model.element.ModuleElement;
 import javax.lang.model.element.PackageElement;
 import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
 
 import jdk.javadoc.internal.doclets.toolkit.util.ClassTree;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 /**
  * The interface for a factory creates writers.
@@ -180,30 +179,30 @@
      * Return the specified member summary writer for a given class.
      *
      * @param classWriter the writer for the class being documented.
-     * @param memberType  the {@link VisibleMemberMap} member type indicating
+     * @param memberType  the {@link VisibleMemberTable} member type indicating
      *                    the type of member summary that should be returned.
      * @return the summary writer for the give class.  Return null if this
      * writer is not supported by the doclet.
      *
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
     public abstract MemberSummaryWriter getMemberSummaryWriter(
-        ClassWriter classWriter, VisibleMemberMap.Kind memberType);
+        ClassWriter classWriter, VisibleMemberTable.Kind memberType);
 
     /**
      * Return the specified member summary writer for a given annotation type.
      *
      * @param annotationTypeWriter the writer for the annotation type being
      *                             documented.
-     * @param memberType  the {@link VisibleMemberMap} member type indicating
+     * @param memberType  the {@link VisibleMemberTable} member type indicating
      *                    the type of member summary that should be returned.
      * @return the summary writer for the give class.  Return null if this
      * writer is not supported by the doclet.
      *
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
     public abstract MemberSummaryWriter getMemberSummaryWriter(
-        AnnotationTypeWriter annotationTypeWriter, VisibleMemberMap.Kind memberType);
+        AnnotationTypeWriter annotationTypeWriter, VisibleMemberTable.Kind memberType);
 
     /**
      * Return the writer for the serialized form.
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AbstractMemberBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,14 @@
 
 package jdk.javadoc.internal.doclets.toolkit.builders;
 
+import java.util.List;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind;
 
 /**
  * The superclass for all member builders.  Member builders are only executed
@@ -42,13 +48,19 @@
  */
 public abstract class AbstractMemberBuilder extends AbstractBuilder {
 
+    final protected TypeElement typeElement;
+
+    final protected VisibleMemberTable visibleMemberTable;
+
     /**
      * Construct a SubBuilder.
      * @param context a context object, providing information used in this run
      *        of the doclet.
      */
-    public AbstractMemberBuilder(Context context) {
+    public AbstractMemberBuilder(Context context, TypeElement typeElement) {
         super(context);
+        this.typeElement = typeElement;
+        visibleMemberTable = configuration.getVisibleMemberTable(typeElement);
     }
 
     /**
@@ -77,4 +89,14 @@
      * @return true if this subbuilder has anything to document
      */
     public abstract boolean hasMembersToDocument();
+
+    /**
+     * Returns a list of visible elements of the specified kind in this
+     * type element.
+     * @param kind of members
+     * @return a list of members
+     */
+    protected List<? extends Element> getVisibleMembers(Kind kind) {
+        return visibleMemberTable.getVisibleMembers(kind);
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeFieldBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -34,7 +34,7 @@
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
 
 /**
@@ -50,16 +50,6 @@
 public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder {
 
     /**
-     * The annotation type whose members are being documented.
-     */
-    protected TypeElement typeElement;
-
-    /**
-     * The visible members for the given class.
-     */
-    protected VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the member documentation.
      */
     protected AnnotationTypeFieldWriter writer;
@@ -67,7 +57,7 @@
     /**
      * The list of members being documented.
      */
-    protected List<Element> members;
+    protected List<? extends Element> members;
 
     /**
      * The index of the current member that is being documented at this point
@@ -86,12 +76,10 @@
     protected AnnotationTypeFieldBuilder(Context context,
             TypeElement typeElement,
             AnnotationTypeFieldWriter writer,
-            VisibleMemberMap.Kind memberType) {
-        super(context);
-        this.typeElement = typeElement;
+            VisibleMemberTable.Kind memberType) {
+        super(context, typeElement);
         this.writer = writer;
-        this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
-        this.members = this.visibleMemberMap.getMembers(typeElement);
+        this.members = getVisibleMembers(memberType);
     }
 
 
@@ -107,7 +95,7 @@
             Context context, TypeElement typeElement,
             AnnotationTypeFieldWriter writer) {
         return new AnnotationTypeFieldBuilder(context, typeElement,
-                    writer, VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
+                    writer, VisibleMemberTable.Kind.ANNOTATION_TYPE_FIELDS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeOptionalMemberBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -31,8 +31,8 @@
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeRequiredMemberWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for optional annotation type members.
@@ -57,8 +57,7 @@
     private AnnotationTypeOptionalMemberBuilder(Context context,
             TypeElement typeElement,
             AnnotationTypeOptionalMemberWriter writer) {
-        super(context, typeElement, writer,
-                VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+        super(context, typeElement, writer, ANNOTATION_TYPE_MEMBER_OPTIONAL);
     }
 
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -34,8 +34,9 @@
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for required annotation type members.
@@ -50,15 +51,6 @@
  */
 public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder {
 
-    /**
-     * The annotation type whose members are being documented.
-     */
-    protected TypeElement typeElement;
-
-    /**
-     * The visible members for the given class.
-     */
-    protected VisibleMemberMap visibleMemberMap;
 
     /**
      * The writer to output the member documentation.
@@ -68,7 +60,7 @@
     /**
      * The list of members being documented.
      */
-    protected List<Element> members;
+    protected List<? extends Element> members;
 
     /**
      * The index of the current member that is being documented at this point
@@ -87,12 +79,10 @@
     protected AnnotationTypeRequiredMemberBuilder(Context context,
             TypeElement typeElement,
             AnnotationTypeRequiredMemberWriter writer,
-            VisibleMemberMap.Kind memberType) {
-        super(context);
-        this.typeElement = typeElement;
+            VisibleMemberTable.Kind memberType) {
+        super(context, typeElement);
         this.writer = writer;
-        this.visibleMemberMap = configuration.getVisibleMemberMap(typeElement, memberType);
-        this.members = this.visibleMemberMap.getMembers(typeElement);
+        this.members = getVisibleMembers(memberType);
     }
 
 
@@ -108,8 +98,7 @@
             Context context, TypeElement typeElement,
             AnnotationTypeRequiredMemberWriter writer) {
         return new AnnotationTypeRequiredMemberBuilder(context, typeElement,
-                    writer,
-                    VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
+                writer, ANNOTATION_TYPE_MEMBER_REQUIRED);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstantsSummaryBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,9 @@
 import jdk.javadoc.internal.doclets.toolkit.ConstantsSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds the Constants Summary Page.
@@ -262,9 +263,8 @@
      * @return true if the given package has constant fields to document.
      */
     private boolean hasConstantField (TypeElement typeElement) {
-        VisibleMemberMap visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
-            VisibleMemberMap.Kind.FIELDS);
-        List<Element> fields = visibleMemberMapFields.getLeafMembers();
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+        List<? extends Element> fields = vmt.getVisibleMembers(FIELDS);
         for (Element f : fields) {
             VariableElement field = (VariableElement)f;
             if (field.getConstantValue() != null) {
@@ -279,7 +279,7 @@
      * Return true if the given package name has been printed.  Also
      * return true if the root of this package has been printed.
      *
-     * @param pkgname the name of the package to check.
+     * @param pkg the name of the package to check.
      */
     private boolean hasPrintedPackageIndex(PackageElement pkg) {
         for (PackageElement printedPkg : printedPackageHeaders) {
@@ -298,16 +298,6 @@
     private class ConstantFieldBuilder {
 
         /**
-         * The map used to get the visible variables.
-         */
-        protected VisibleMemberMap visibleMemberMapFields = null;
-
-        /**
-         * The map used to get the visible variables.
-         */
-        protected VisibleMemberMap visibleMemberMapEnumConst = null;
-
-        /**
          * The typeElement that we are examining constants for.
          */
         protected TypeElement typeElement;
@@ -318,10 +308,6 @@
          */
         public ConstantFieldBuilder(TypeElement typeElement) {
             this.typeElement = typeElement;
-            visibleMemberMapFields = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.FIELDS);
-            visibleMemberMapEnumConst = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.ENUM_CONSTANTS);
         }
 
         /**
@@ -342,8 +328,10 @@
          * @return the set of visible constant fields for the given type.
          */
         protected SortedSet<VariableElement> members() {
-            List<Element> members = visibleMemberMapFields.getLeafMembers();
-            members.addAll(visibleMemberMapEnumConst.getLeafMembers());
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(typeElement);
+            List<Element> members = new ArrayList<>();
+            members.addAll(vmt.getVisibleMembers(FIELDS));
+            members.addAll(vmt.getVisibleMembers(ENUM_CONSTANTS));
             SortedSet<VariableElement> includes =
                     new TreeSet<>(utils.makeGeneralPurposeComparator());
             for (Element element : members) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ConstructorBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,8 @@
 import jdk.javadoc.internal.doclets.toolkit.ConstructorWriter;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a constructor.
@@ -57,16 +57,6 @@
     private ExecutableElement currentConstructor;
 
     /**
-     * The class whose constructors are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible constructors for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the constructor documentation.
      */
     private final ConstructorWriter writer;
@@ -74,7 +64,7 @@
     /**
      * The constructors being documented.
      */
-    private final List<Element> constructors;
+    private final List<? extends Element> constructors;
 
     /**
      * Construct a new ConstructorBuilder.
@@ -86,12 +76,9 @@
     private ConstructorBuilder(Context context,
             TypeElement typeElement,
             ConstructorWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.CONSTRUCTORS);
-        constructors = visibleMemberMap.getMembers(typeElement);
+        constructors = getVisibleMembers(CONSTRUCTORS);
         for (Element ctor : constructors) {
             if (utils.isProtected(ctor) || utils.isPrivate(ctor)) {
                 writer.setFoundNonPubConstructor(true);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/EnumConstantBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,8 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.EnumConstantWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a enum constants.
@@ -52,16 +52,6 @@
 public class EnumConstantBuilder extends AbstractMemberBuilder {
 
     /**
-     * The class whose enum constants are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible enum constantss for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the enum constants documentation.
      */
     private final EnumConstantWriter writer;
@@ -69,7 +59,7 @@
     /**
      * The set of enum constants being documented.
      */
-    private final List<Element> enumConstants;
+    private final List<? extends Element> enumConstants;
 
     /**
      * The current enum constant that is being documented at this point
@@ -86,12 +76,9 @@
      */
     private EnumConstantBuilder(Context context,
             TypeElement typeElement, EnumConstantWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.ENUM_CONSTANTS);
-        enumConstants = visibleMemberMap.getMembers(typeElement);
+        enumConstants = getVisibleMembers(ENUM_CONSTANTS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/FieldBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,8 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.FieldWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a field.
@@ -52,16 +52,6 @@
 public class FieldBuilder extends AbstractMemberBuilder {
 
     /**
-     * The class whose fields are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible fields for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the field documentation.
      */
     private final FieldWriter writer;
@@ -69,7 +59,7 @@
     /**
      * The list of fields being documented.
      */
-    private final List<Element> fields;
+    private final List<? extends Element> fields;
 
     /**
      * The index of the current field that is being documented at this point
@@ -85,14 +75,11 @@
      * @param writer the doclet specific writer.
      */
     private FieldBuilder(Context context,
-            TypeElement typeElement,
-            FieldWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+                         TypeElement typeElement,
+                         FieldWriter writer) {
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.FIELDS);
-        fields = visibleMemberMap.getLeafMembers();
+        fields = getVisibleMembers(FIELDS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MemberSummaryBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -27,12 +27,15 @@
 
 import java.text.MessageFormat;
 import java.util.*;
+import java.util.stream.Collectors;
 
 import javax.lang.model.element.Element;
 import javax.lang.model.element.ExecutableElement;
 import javax.lang.model.element.TypeElement;
 import javax.lang.model.element.VariableElement;
+import javax.lang.model.util.ElementFilter;
 
+import com.sun.source.doctree.DocCommentTree;
 import com.sun.source.doctree.DocTree;
 import com.sun.source.doctree.DocTree.Kind;
 import jdk.javadoc.internal.doclets.toolkit.AnnotationTypeWriter;
@@ -42,9 +45,11 @@
 import jdk.javadoc.internal.doclets.toolkit.WriterFactory;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 import jdk.javadoc.internal.doclets.toolkit.CommentUtils;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
+
 /**
  * Builds the member summary.
  * There are two anonymous subtype variants of this builder, created
@@ -69,12 +74,9 @@
     /**
      * The member summary writers for the given class.
      */
-    private final EnumMap<VisibleMemberMap.Kind, MemberSummaryWriter> memberSummaryWriters;
+    private final EnumMap<VisibleMemberTable.Kind, MemberSummaryWriter> memberSummaryWriters;
 
-    /**
-     * The type being documented.
-     */
-    protected final TypeElement typeElement;
+    final PropertyHelper pHelper;
 
     /**
      * Construct a new MemberSummaryBuilder.
@@ -83,11 +85,10 @@
      * @param typeElement   the type element.
      */
     private MemberSummaryBuilder(Context context, TypeElement typeElement) {
-        super(context);
-        this.typeElement = typeElement;
-        memberSummaryWriters = new EnumMap<>(VisibleMemberMap.Kind.class);
-
-        comparator = utils.makeGeneralPurposeComparator();
+        super(context, typeElement);
+        memberSummaryWriters = new EnumMap<>(VisibleMemberTable.Kind.class);
+        comparator = utils.makeIndexUseComparator();
+        pHelper = new PropertyHelper(this);
     }
 
     /**
@@ -113,20 +114,14 @@
 
             @Override
             public boolean hasMembersToDocument() {
-                for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-                    VisibleMemberMap members = getVisibleMemberMap(kind);
-                    if (!members.noVisibleMembers()) {
-                        return true;
-                    }
-                }
-                return false;
+                return visibleMemberTable.hasVisibleMembers();
             }
         };
         WriterFactory wf = context.configuration.getWriterFactory();
-        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
-                    ? null
-                    : wf.getMemberSummaryWriter(classWriter, kind);
+        for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
+            MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
+                    ? wf.getMemberSummaryWriter(classWriter, kind)
+                    : null;
             builder.memberSummaryWriters.put(kind, msw);
         }
         return builder;
@@ -157,10 +152,10 @@
             }
         };
         WriterFactory wf = context.configuration.getWriterFactory();
-        for (VisibleMemberMap.Kind kind : VisibleMemberMap.Kind.values()) {
-            MemberSummaryWriter msw = builder.getVisibleMemberMap(kind).noVisibleMembers()
-                    ? null
-                    : wf.getMemberSummaryWriter(annotationTypeWriter, kind);
+        for (VisibleMemberTable.Kind kind : VisibleMemberTable.Kind.values()) {
+            MemberSummaryWriter msw = builder.getVisibleMemberTable().hasVisibleMembers(kind)
+                    ? wf.getMemberSummaryWriter(annotationTypeWriter, kind)
+                    : null;
             builder.memberSummaryWriters.put(kind, msw);
         }
         return builder;
@@ -169,13 +164,12 @@
     /**
      * Return the specified visible member map.
      *
-     * @param kind the kind of visible member map to return.
      * @return the specified visible member map.
      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
-    public VisibleMemberMap getVisibleMemberMap(VisibleMemberMap.Kind kind) {
-        return configuration.getVisibleMemberMap(typeElement, kind);
+    public VisibleMemberTable getVisibleMemberTable() {
+        return visibleMemberTable;
     }
 
     /**.
@@ -184,9 +178,9 @@
      * @param kind the kind of member summary writer to return.
      * @return the specified member summary writer.
      * @throws ArrayIndexOutOfBoundsException when the type is invalid.
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
-    public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberMap.Kind kind) {
+    public MemberSummaryWriter getMemberSummaryWriter(VisibleMemberTable.Kind kind) {
         return memberSummaryWriters.get(kind);
     }
 
@@ -197,25 +191,31 @@
      *
      * @param kind the kind of elements to return.
      * @return a list of methods that will be documented.
-     * @see VisibleMemberMap
+     * @see VisibleMemberTable
      */
-    public SortedSet<Element> members(VisibleMemberMap.Kind kind) {
+    public SortedSet<Element> members(VisibleMemberTable.Kind kind) {
         TreeSet<Element> out = new TreeSet<>(comparator);
-        out.addAll(getVisibleMemberMap(kind).getLeafMembers());
+        out.addAll(getVisibleMembers(kind));
         return out;
     }
 
     /**
+     * Returns true if there are members of the given kind, false otherwise.
+     * @param kind
+     * @return true if there are members of the given kind, false otherwise
+     */
+    public boolean hasMembers(VisibleMemberTable.Kind kind) {
+        return !getVisibleMembers(kind).isEmpty();
+    }
+
+    /**
      * Build the summary for the enum constants.
      *
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildEnumConstantsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ENUM_CONSTANTS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ENUM_CONSTANTS);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ENUM_CONSTANTS);
+        addSummary(writer, ENUM_CONSTANTS, false, memberSummaryTree);
     }
 
     /**
@@ -224,11 +224,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildAnnotationTypeFieldsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_FIELDS);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_FIELDS);
+        addSummary(writer, ANNOTATION_TYPE_FIELDS, false, memberSummaryTree);
     }
 
     /**
@@ -237,11 +234,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildAnnotationTypeOptionalMemberSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_OPTIONAL);
+        addSummary(writer, ANNOTATION_TYPE_MEMBER_OPTIONAL, false, memberSummaryTree);
     }
 
     /**
@@ -250,11 +244,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildAnnotationTypeRequiredMemberSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.ANNOTATION_TYPE_MEMBER_REQUIRED);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(ANNOTATION_TYPE_MEMBER_REQUIRED);
+        addSummary(writer, ANNOTATION_TYPE_MEMBER_REQUIRED, false, memberSummaryTree);
     }
 
     /**
@@ -263,11 +254,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildFieldsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.FIELDS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.FIELDS);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(FIELDS);
+        addSummary(writer, FIELDS, true, memberSummaryTree);
     }
 
     /**
@@ -276,11 +264,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildPropertiesSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.PROPERTIES);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.PROPERTIES);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(PROPERTIES);
+        addSummary(writer, PROPERTIES, true, memberSummaryTree);
     }
 
     /**
@@ -289,11 +274,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildNestedClassesSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.INNER_CLASSES);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.INNER_CLASSES);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(INNER_CLASSES);
+        addSummary(writer, INNER_CLASSES, true, memberSummaryTree);
     }
 
     /**
@@ -302,11 +284,8 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildMethodsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.METHODS);
-        VisibleMemberMap visibleMemberMap =
-               getVisibleMemberMap(VisibleMemberMap.Kind.METHODS);
-        addSummary(writer, visibleMemberMap, true, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(METHODS);
+        addSummary(writer, METHODS, true, memberSummaryTree);
     }
 
     /**
@@ -315,28 +294,25 @@
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     protected void buildConstructorsSummary(Content memberSummaryTree) {
-        MemberSummaryWriter writer =
-                memberSummaryWriters.get(VisibleMemberMap.Kind.CONSTRUCTORS);
-        VisibleMemberMap visibleMemberMap =
-                getVisibleMemberMap(VisibleMemberMap.Kind.CONSTRUCTORS);
-        addSummary(writer, visibleMemberMap, false, memberSummaryTree);
+        MemberSummaryWriter writer = memberSummaryWriters.get(CONSTRUCTORS);
+        addSummary(writer, CONSTRUCTORS, false, memberSummaryTree);
     }
 
     /**
      * Build the member summary for the given members.
      *
      * @param writer the summary writer to write the output.
-     * @param visibleMemberMap the given members to summarize.
+     * @param kind the kind of  members to summarize.
      * @param summaryTreeList list of content trees to which the documentation will be added
      */
     private void buildSummary(MemberSummaryWriter writer,
-            VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
-        SortedSet<Element> members = asSortedSet(visibleMemberMap.getLeafMembers());
+            VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
+        SortedSet<? extends Element> members = asSortedSet(getVisibleMembers(kind));
         if (!members.isEmpty()) {
             for (Element member : members) {
-                final Element property = visibleMemberMap.getPropertyElement(member);
+                final Element property = pHelper.getPropertyElement(member);
                 if (property != null) {
-                    processProperty(visibleMemberMap, member, property);
+                    processProperty(member, property);
                 }
                 List<? extends DocTree> firstSentenceTags = utils.getFirstSentenceTrees(member);
                 if (utils.isExecutableElement(member) && firstSentenceTags.isEmpty()) {
@@ -367,12 +343,10 @@
      * the see tags if the appropriate property getter and setter are
      * available.
      *
-     * @param visibleMemberMap the members information.
      * @param member the member which is to be augmented.
      * @param property the original property documentation.
      */
-    private void processProperty(VisibleMemberMap visibleMemberMap,
-                                 Element member,
+    private void processProperty(Element member,
                                  Element property) {
         CommentUtils cmtutils = configuration.cmtUtils;
         final boolean isSetter = isSetter(member);
@@ -418,8 +392,8 @@
 
         //add @see tags
         if (!isGetter && !isSetter) {
-            ExecutableElement getter = (ExecutableElement) visibleMemberMap.getGetterForProperty(member);
-            ExecutableElement setter = (ExecutableElement) visibleMemberMap.getSetterForProperty(member);
+            ExecutableElement getter = pHelper.getGetterForProperty((ExecutableElement)member);
+            ExecutableElement setter = pHelper.getSetterForProperty((ExecutableElement)member);
 
             if (null != getter) {
                 StringBuilder sb = new StringBuilder("#");
@@ -465,47 +439,28 @@
      * Build the inherited member summary for the given methods.
      *
      * @param writer the writer for this member summary.
-     * @param visibleMemberMap the map for the members to document.
+     * @param kind the kind of members to document.
      * @param summaryTreeList list of content trees to which the documentation will be added
      */
     private void buildInheritedSummary(MemberSummaryWriter writer,
-            VisibleMemberMap visibleMemberMap, LinkedList<Content> summaryTreeList) {
-        for (TypeElement inheritedClass : visibleMemberMap.getVisibleClasses()) {
+            VisibleMemberTable.Kind kind, LinkedList<Content> summaryTreeList) {
+        VisibleMemberTable visibleMemberTable = getVisibleMemberTable();
+        SortedSet<? extends Element> inheritedMembersFromMap = asSortedSet(visibleMemberTable.getAllVisibleMembers(kind));
+
+        for (TypeElement inheritedClass : visibleMemberTable.getVisibleTypeElements()) {
             if (!(utils.isPublic(inheritedClass) || utils.isLinkable(inheritedClass))) {
                 continue;
             }
             if (inheritedClass == typeElement) {
                 continue;
             }
-            SortedSet<Element> inheritedMembersFromMap = asSortedSet(
-                    visibleMemberMap.getMembers(inheritedClass));
 
-            if (!inheritedMembersFromMap.isEmpty()) {
+            List<Element> members = inheritedMembersFromMap.stream()
+                    .filter(e -> utils.getEnclosingTypeElement(e) == inheritedClass)
+                    .collect(Collectors.toList());
+            if (!members.isEmpty()) {
                 SortedSet<Element> inheritedMembers = new TreeSet<>(comparator);
-                List<ExecutableElement> enclosedSuperMethods = utils.getMethods(inheritedClass);
-                for (Element inheritedMember : inheritedMembersFromMap) {
-                    if (visibleMemberMap.kind != VisibleMemberMap.Kind.METHODS) {
-                        inheritedMembers.add(inheritedMember);
-                        continue;
-                    }
-
-                    // Skip static methods in interfaces they are not inherited
-                    if (utils.isInterface(inheritedClass) && utils.isStatic(inheritedMember))
-                        continue;
-
-                    // If applicable, filter those overridden methods that
-                    // should not be documented in the summary/detail sections,
-                    // and instead document them in the footnote. Care must be taken
-                    // to handle JavaFX property methods, which have no source comments,
-                    // but comments for these are synthesized on the output.
-                    ExecutableElement inheritedMethod = (ExecutableElement)inheritedMember;
-                    if (enclosedSuperMethods.stream()
-                            .anyMatch(e -> utils.executableMembersEqual(inheritedMethod, e) &&
-                                    (!utils.isSimpleOverride(e) || visibleMemberMap.getPropertyElement(e) != null))) {
-                        inheritedMembers.add(inheritedMember);
-                    }
-                }
-
+                inheritedMembers.addAll(members);
                 Content inheritedTree = writer.getInheritedSummaryHeader(inheritedClass);
                 Content linksTree = writer.getInheritedSummaryLinksTree();
                 addSummaryFootNote(inheritedClass, inheritedMembers, linksTree, writer);
@@ -529,17 +484,17 @@
      * Add the summary for the documentation.
      *
      * @param writer the writer for this member summary.
-     * @param visibleMemberMap the map for the members to document.
+     * @param kind the kind of members to document.
      * @param showInheritedSummary true if inherited summary should be documented
      * @param memberSummaryTree the content tree to which the documentation will be added
      */
     private void addSummary(MemberSummaryWriter writer,
-            VisibleMemberMap visibleMemberMap, boolean showInheritedSummary,
+            VisibleMemberTable.Kind kind, boolean showInheritedSummary,
             Content memberSummaryTree) {
         LinkedList<Content> summaryTreeList = new LinkedList<>();
-        buildSummary(writer, visibleMemberMap, summaryTreeList);
+        buildSummary(writer, kind, summaryTreeList);
         if (showInheritedSummary)
-            buildInheritedSummary(writer, visibleMemberMap, summaryTreeList);
+            buildInheritedSummary(writer, kind, summaryTreeList);
         if (!summaryTreeList.isEmpty()) {
             Content memberTree = writer.getMemberSummaryHeader(typeElement, memberSummaryTree);
             summaryTreeList.stream().forEach(memberTree::addContent);
@@ -547,9 +502,91 @@
         }
     }
 
-    private SortedSet<Element> asSortedSet(Collection<Element> members) {
+    private SortedSet<? extends Element> asSortedSet(Collection<? extends Element> members) {
         SortedSet<Element> out = new TreeSet<>(comparator);
         out.addAll(members);
         return out;
     }
+
+    static class PropertyHelper {
+
+        private final Map<Element, Element> classPropertiesMap = new HashMap<>();
+
+        private final MemberSummaryBuilder  builder;
+
+        PropertyHelper(MemberSummaryBuilder builder) {
+            this.builder = builder;
+            computeProperties();
+        }
+
+        private void computeProperties() {
+            VisibleMemberTable vmt = builder.getVisibleMemberTable();
+            List<ExecutableElement> props = ElementFilter.methodsIn(vmt.getVisibleMembers(PROPERTIES));
+            for (ExecutableElement propertyMethod : props) {
+                ExecutableElement getter = vmt.getPropertyGetter(propertyMethod);
+                ExecutableElement setter = vmt.getPropertySetter(propertyMethod);
+                VariableElement field = vmt.getPropertyField(propertyMethod);
+
+                addToPropertiesMap(propertyMethod, field, getter, setter);
+            }
+        }
+
+        private void addToPropertiesMap(ExecutableElement propertyMethod,
+                                        VariableElement field,
+                                        ExecutableElement getter,
+                                        ExecutableElement setter) {
+            if (field == null || builder.utils.getDocCommentTree(field) == null) {
+                addToPropertiesMap(propertyMethod, propertyMethod);
+                addToPropertiesMap(getter, propertyMethod);
+                addToPropertiesMap(setter, propertyMethod);
+            } else {
+                addToPropertiesMap(propertyMethod, field);
+                addToPropertiesMap(getter, field);
+                addToPropertiesMap(setter, field);
+            }
+        }
+
+        private void addToPropertiesMap(Element propertyMethod,
+                                        Element commentSource) {
+            if (null == propertyMethod || null == commentSource) {
+                return;
+            }
+            DocCommentTree docTree = builder.utils.getDocCommentTree(propertyMethod);
+
+            /* The second condition is required for the property buckets. In
+             * this case the comment is at the property method (not at the field)
+             * and it needs to be listed in the map.
+             */
+            if ((docTree == null) || propertyMethod.equals(commentSource)) {
+                classPropertiesMap.put(propertyMethod, commentSource);
+            }
+        }
+
+        /**
+         * Returns the property field documentation belonging to the given member.
+         * @param element the member for which the property documentation is needed.
+         * @return the property field documentation, null if there is none.
+         */
+        public Element getPropertyElement(Element element) {
+            return classPropertiesMap.get(element);
+        }
+
+        /**
+         * Returns the getter documentation belonging to the given property method.
+         * @param propertyMethod the method for which the getter is needed.
+         * @return the getter documentation, null if there is none.
+         */
+        public ExecutableElement getGetterForProperty(ExecutableElement propertyMethod) {
+            return builder.getVisibleMemberTable().getPropertyGetter(propertyMethod);
+        }
+
+        /**
+         * Returns the setter documentation belonging to the given property method.
+         * @param propertyMethod the method for which the setter is needed.
+         * @return the setter documentation, null if there is none.
+         */
+        public ExecutableElement getSetterForProperty(ExecutableElement propertyMethod) {
+            return builder.getVisibleMemberTable().getPropertySetter(propertyMethod);
+        }
+    }
 }
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/MethodBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -37,8 +37,8 @@
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.MethodWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.DocFinder;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a method.
@@ -60,16 +60,6 @@
     private ExecutableElement currentMethod;
 
     /**
-     * The class whose methods are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible methods for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the method documentation.
      */
     private final MethodWriter writer;
@@ -77,7 +67,7 @@
     /**
      * The methods being documented.
      */
-    private final List<Element> methods;
+    private final List<? extends Element> methods;
 
 
     /**
@@ -90,12 +80,9 @@
     private MethodBuilder(Context context,
             TypeElement typeElement,
             MethodWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.METHODS);
-        methods = visibleMemberMap.getLeafMembers();
+        methods = getVisibleMembers(METHODS);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/PropertyBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,8 +35,9 @@
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.DocletException;
 import jdk.javadoc.internal.doclets.toolkit.PropertyWriter;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap;
+import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable;
 
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Builds documentation for a property.
@@ -52,16 +53,6 @@
 public class PropertyBuilder extends AbstractMemberBuilder {
 
     /**
-     * The class whose properties are being documented.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * The visible properties for the given class.
-     */
-    private final VisibleMemberMap visibleMemberMap;
-
-    /**
      * The writer to output the property documentation.
      */
     private final PropertyWriter writer;
@@ -69,7 +60,7 @@
     /**
      * The list of properties being documented.
      */
-    private final List<Element> properties;
+    private final List<? extends Element> properties;
 
     /**
      * The index of the current property that is being documented at this point
@@ -87,12 +78,9 @@
     private PropertyBuilder(Context context,
             TypeElement typeElement,
             PropertyWriter writer) {
-        super(context);
-        this.typeElement = typeElement;
+        super(context, typeElement);
         this.writer = writer;
-        visibleMemberMap = configuration.getVisibleMemberMap(typeElement,
-                VisibleMemberMap.Kind.PROPERTIES);
-        properties = visibleMemberMap.getMembers(typeElement);
+        properties = getVisibleMembers(PROPERTIES);
     }
 
     /**
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Thu Apr 26 17:59:02 2018 +0200
@@ -84,7 +84,6 @@
 doclet.noInheritedDoc=@inheritDoc used but {0} does not override or implement any method.
 # doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
-doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
 doclet.Requires_Summary=Requires
 doclet.Indirect_Requires_Summary=Indirect Requires
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties	Thu Apr 26 17:59:02 2018 +0200
@@ -75,7 +75,6 @@
 doclet.noInheritedDoc=@inheritDoc\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001{0}\u306F\u3069\u306E\u30E1\u30BD\u30C3\u30C9\u3082\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u5B9F\u88C5\u3057\u3066\u3044\u307E\u305B\u3093\u3002
 # doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
 doclet.tag_misuse={0}\u30BF\u30B0\u306F{1}\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u4F7F\u7528\u3067\u304D\u308B\u306E\u306F\u6B21\u306E\u30BF\u30A4\u30D7\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u306E\u307F\u3067\u3059: {2}\u3002
-doclet.javafx_tag_misuse=\u30BF\u30B0@propertyGetter\u3001@propertySetter\u304A\u3088\u3073@propertyDescription\u306F\u3001JavaFX\u306E\u30D7\u30ED\u30D1\u30C6\u30A3getter\u3068setter\u306E\u307F\u3067\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002
 doclet.Package_Summary=\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u6982\u8981
 doclet.Requires_Summary=\u5FC5\u8981
 doclet.Indirect_Requires_Summary=\u9593\u63A5\u7684\u306B\u5FC5\u8981
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties	Thu Apr 26 17:59:02 2018 +0200
@@ -75,7 +75,6 @@
 doclet.noInheritedDoc=\u4F7F\u7528\u4E86 @inheritDoc, \u4F46{0}\u672A\u8986\u76D6\u6216\u5B9E\u73B0\u4EFB\u4F55\u65B9\u6CD5\u3002
 # doclet.malformed_html_link_tag=<a> tag is malformed:\n"{0}"
 doclet.tag_misuse=\u4E0D\u80FD\u5728{1}\u6587\u6863\u4E2D\u4F7F\u7528\u6807\u8BB0{0}\u3002\u53EA\u80FD\u5728\u4EE5\u4E0B\u7C7B\u578B\u7684\u6587\u6863\u4E2D\u4F7F\u7528\u8BE5\u6807\u8BB0: {2}\u3002
-doclet.javafx_tag_misuse=\u6807\u8BB0 @propertyGetter, @propertySetter \u548C @propertyDescription \u53EA\u80FD\u5728 JavaFX \u5C5E\u6027 getter \u548C setter \u4E2D\u4F7F\u7528\u3002
 doclet.Package_Summary=\u7A0B\u5E8F\u5305\u6982\u8981
 doclet.Requires_Summary=\u5FC5\u9700\u9879
 doclet.Indirect_Requires_Summary=\u95F4\u63A5\u5FC5\u9700\u9879
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/TagletManager.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -26,7 +26,6 @@
 package jdk.javadoc.internal.doclets.toolkit.taglets;
 
 import java.io.*;
-import java.lang.reflect.InvocationTargetException;
 import java.util.*;
 
 import javax.lang.model.element.Element;
@@ -180,8 +179,7 @@
     private final boolean showauthor;
 
     /**
-     * True if we want to use JavaFX-related tags (@propertyGetter,
-     * @propertySetter, @propertyDescription, @defaultValue, @treatAsPrivate).
+     * True if we want to use JavaFX-related tags (@defaultValue, @treatAsPrivate).
      */
     private final boolean javafx;
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassTree.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, 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
@@ -161,7 +161,6 @@
      * have their own sub-class lists.
      *
      * @param classes all the classes in this run.
-     * @param configuration the current configuration of the doclet.
      */
     private void buildTree(Iterable<TypeElement> classes) {
         for (TypeElement aClass : classes) {
@@ -174,7 +173,7 @@
                 continue;
             }
 
-            if (utils.isHidden(aClass)) {
+            if (utils.hasHiddenTag(aClass)) {
                 continue;
             }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ClassUseMapper.java	Thu Apr 26 17:59:02 2018 +0200
@@ -47,7 +47,8 @@
 
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Map all class uses for a given class.
@@ -243,8 +244,9 @@
                 mapExecutable(ctor);
             }
 
-            VisibleMemberMap vmm = configuration.getVisibleMemberMap(aClass, Kind.METHODS);
-            List<ExecutableElement> methods = ElementFilter.methodsIn(vmm.getMembers(aClass));
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(aClass);
+            List<ExecutableElement> methods = ElementFilter.methodsIn(vmt.getMembers(METHODS));
+
             for (ExecutableElement method : methods) {
                 mapExecutable(method);
                 mapTypeParameters(classToMethodTypeParam, method, method);
@@ -554,8 +556,8 @@
      * Map the AnnotationType to the members that use them as type parameters.
      *
      * @param map the map the insert the information into.
-     * @param element whose type parameters are being checked.
-     * @param holder the holder that owns the type parameters.
+     * @param e whose type parameters are being checked.
+     * @param holder owning the type parameters.
      */
     private <T extends Element> void mapAnnotations(final Map<TypeElement, List<T>> map,
             Element e, final T holder) {
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocFinder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -276,9 +276,10 @@
             //NOTE:  When we fix the bug where ClassDoc.interfaceTypes() does
             //       not pass all implemented interfaces, we will use the
             //       appropriate element here.
-            ImplementedMethods implMethods
-                    = new ImplementedMethods((ExecutableElement) input.element, configuration);
-            List<ExecutableElement> implementedMethods = implMethods.build();
+            TypeElement encl = utils.getEnclosingTypeElement(input.element);
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(encl);
+            List<ExecutableElement> implementedMethods =
+                    vmt.getImplementedMethods((ExecutableElement)input.element);
             for (ExecutableElement implementedMethod : implementedMethods) {
                 inheritedSearchInput.element = implementedMethod;
                 output = search(configuration, inheritedSearchInput);
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/ImplementedMethods.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.*;
-
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.type.TypeMirror;
-
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-
-/**
- * For a given class method, build an array of interface methods which it
- * implements.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- */
-public class ImplementedMethods {
-
-    private final Map<ExecutableElement, TypeMirror> interfaces = new HashMap<>();
-    private final List<ExecutableElement> methlist = new ArrayList<>();
-    private final Utils utils;
-    private final TypeElement typeElement;
-    private final ExecutableElement method;
-
-    public ImplementedMethods(ExecutableElement method, BaseConfiguration configuration) {
-        this.method = method;
-        this.utils = configuration.utils;
-        typeElement = utils.getEnclosingTypeElement(method);
-    }
-
-    /**
-     * Return the array of interface methods which the method passed in the
-     * constructor is implementing. The search/build order is as follows:
-     * <pre>
-     * 1. Search in all the immediate interfaces which this method's class is
-     *    implementing. Do it recursively for the superinterfaces as well.
-     * 2. Traverse all the superclasses and search recursively in the
-     *    interfaces which those superclasses implement.
-     *</pre>
-     *
-     * @return SortedSet<ExecutableElement> of implemented methods.
-     */
-    public List<ExecutableElement> build() {
-        buildImplementedMethodList();
-        return methlist;
-    }
-
-    public TypeMirror getMethodHolder(ExecutableElement ee) {
-        return interfaces.get(ee);
-    }
-
-    /**
-     * Search for the method in the array of interfaces. If found check if it is
-     * overridden by any other subinterface method which this class
-     * implements. If it is not overidden, add it in the method list.
-     * Do this recursively for all the extended interfaces for each interface
-     * from the array passed.
-     */
-    private void buildImplementedMethodList() {
-        Set<TypeMirror> intfacs = utils.getAllInterfaces(typeElement);
-        for (TypeMirror interfaceType : intfacs) {
-            ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method);
-            if (found != null) {
-                removeOverriddenMethod(found);
-                if (!overridingMethodFound(found)) {
-                    methlist.add(found);
-                    interfaces.put(found, interfaceType);
-                }
-            }
-        }
-    }
-
-    /**
-     * Search in the method list and check if it contains a method which
-     * is overridden by the method as parameter.  If found, remove the
-     * overridden method from the method list.
-     *
-     * @param method Is this method overriding a method in the method list.
-     */
-    private void removeOverriddenMethod(ExecutableElement method) {
-        TypeElement overriddenClass = utils.overriddenClass(method);
-        if (overriddenClass != null) {
-            for (int i = 0; i < methlist.size(); i++) {
-                TypeElement te = utils.getEnclosingTypeElement(methlist.get(i));
-                if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) {
-                    methlist.remove(i);  // remove overridden method
-                    return;
-                }
-            }
-        }
-    }
-
-    /**
-     * Search in the already found methods' list and check if it contains
-     * a method which is overriding the method parameter or is the method
-     * parameter itself.
-     *
-     * @param method MethodDoc Method to be searched in the Method List for
-     * an overriding method.
-     */
-    private boolean overridingMethodFound(ExecutableElement method) {
-        TypeElement containingClass = utils.getEnclosingTypeElement(method);
-        for (ExecutableElement listmethod : methlist) {
-            if (containingClass == utils.getEnclosingTypeElement(listmethod)) {
-                // it's the same method.
-                return true;
-            }
-            TypeElement te = utils.overriddenClass(listmethod);
-            if (te == null) {
-                continue;
-            }
-            if (te == containingClass || utils.isSubclassOf(te, containingClass)) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/IndexBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,7 +35,8 @@
 import jdk.javadoc.doclet.DocletEnvironment;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
 import jdk.javadoc.internal.doclets.toolkit.Messages;
-import jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberMap.Kind;
+
+import static jdk.javadoc.internal.doclets.toolkit.util.VisibleMemberTable.Kind.*;
 
 /**
  * Build the mapping of each Unicode character with it's member lists
@@ -165,8 +166,8 @@
     protected void putMembersInIndexMap(TypeElement te) {
         adjustIndexMap(utils.getAnnotationFields(te));
         adjustIndexMap(utils.getFields(te));
-        VisibleMemberMap vmm = configuration.getVisibleMemberMap(te, Kind.METHODS);
-        adjustIndexMap(vmm.getMembers(te));
+        VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+        adjustIndexMap(vmt.getMembers(METHODS));
         adjustIndexMap(utils.getConstructors(te));
         adjustIndexMap(utils.getEnumConstants(te));
     }
@@ -216,7 +217,7 @@
      * Should this element be added to the index map?
      */
     protected boolean shouldAddToIndexMap(Element element) {
-        if (utils.isHidden(element)) {
+        if (utils.hasHiddenTag(element)) {
             return false;
         }
 
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java	Thu Apr 26 17:59:02 2018 +0200
@@ -74,12 +74,10 @@
 import com.sun.source.doctree.DocTree.Kind;
 import com.sun.source.doctree.ParamTree;
 import com.sun.source.doctree.SerialFieldTree;
-import com.sun.source.doctree.StartElementTree;
 import com.sun.source.tree.CompilationUnitTree;
 import com.sun.source.tree.LineMap;
 import com.sun.source.util.DocSourcePositions;
 import com.sun.source.util.DocTrees;
-import com.sun.source.util.SimpleDocTreeVisitor;
 import com.sun.source.util.TreePath;
 import com.sun.tools.javac.model.JavacTypes;
 import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
@@ -95,7 +93,6 @@
 import static com.sun.source.doctree.DocTree.Kind.*;
 import static jdk.javadoc.internal.doclets.toolkit.builders.ConstantsSummaryBuilder.MAX_CONSTANT_VALUE_INDEX_LENGTH;
 
-
 /**
  * Utilities Class for Doclets.
  *
@@ -806,9 +803,8 @@
             if (te == null) {
                 return null;
             }
-            VisibleMemberMap vmm = configuration.getVisibleMemberMap(te,
-                    VisibleMemberMap.Kind.METHODS);
-            for (Element e : vmm.getMembers(te)) {
+            VisibleMemberTable vmt = configuration.getVisibleMemberTable(te);
+            for (Element e : vmt.getMembers(VisibleMemberTable.Kind.METHODS)) {
                 ExecutableElement ee = (ExecutableElement)e;
                 if (configuration.workArounds.overrides(method, ee, origin) &&
                         !isSimpleOverride(ee)) {
@@ -1167,7 +1163,7 @@
         }
         TypeElement superClass = asTypeElement(superType);
         // skip "hidden" classes
-        while ((superClass != null && isHidden(superClass))
+        while ((superClass != null && hasHiddenTag(superClass))
                 || (superClass != null &&  !isPublic(superClass) && !isLinkable(superClass))) {
             TypeMirror supersuperType = superClass.getSuperclass();
             TypeElement supersuperClass = asTypeElement(supersuperType);
@@ -1416,7 +1412,7 @@
      * @param e the queried element
      * @return true if it exists, false otherwise
      */
-    public boolean isHidden(Element e) {
+    public boolean hasHiddenTag(Element e) {
         // prevent needless tests on elements which are not included
         if (!isIncluded(e)) {
             return false;
@@ -1462,14 +1458,14 @@
                 new TreeSet<>(makeGeneralPurposeComparator());
         if (!javafx) {
             for (Element te : classlist) {
-                if (!isHidden(te)) {
+                if (!hasHiddenTag(te)) {
                     filteredOutClasses.add((TypeElement)te);
                 }
             }
             return filteredOutClasses;
         }
         for (Element e : classlist) {
-            if (isPrivate(e) || isPackagePrivate(e) || isHidden(e)) {
+            if (isPrivate(e) || isPackagePrivate(e) || hasHiddenTag(e)) {
                 continue;
             }
             filteredOutClasses.add((TypeElement)e);
@@ -2246,18 +2242,6 @@
         return convertToTypeElement(getItems(e, false, INTERFACE));
     }
 
-    List<Element> getNestedClasses(TypeElement e) {
-        List<Element> result = new ArrayList<>();
-        recursiveGetItems(result, e, true, CLASS);
-        return result;
-    }
-
-    List<Element> getNestedClassesUnfiltered(TypeElement e) {
-        List<Element> result = new ArrayList<>();
-        recursiveGetItems(result, e, false, CLASS);
-        return result;
-    }
-
     public List<Element> getEnumConstants(Element e) {
         return getItems(e, true, ENUM_CONSTANT);
     }
@@ -2381,7 +2365,6 @@
     }
 
     EnumSet<ElementKind> nestedKinds = EnumSet.of(ANNOTATION_TYPE, CLASS, ENUM, INTERFACE);
-
     void recursiveGetItems(Collection<Element> list, Element e, boolean filter, ElementKind... select) {
         list.addAll(getItems0(e, filter, select));
         List<Element> classes = getItems0(e, filter, nestedKinds);
@@ -2411,7 +2394,8 @@
     }
 
     private SimpleElementVisitor9<Boolean, Void> shouldDocumentVisitor = null;
-    private boolean shouldDocument(Element e) {
+
+    protected boolean shouldDocument(Element e) {
         if (shouldDocumentVisitor == null) {
             shouldDocumentVisitor = new SimpleElementVisitor9<Boolean, Void>() {
                 private boolean hasSource(TypeElement e) {
@@ -2422,6 +2406,10 @@
                 // handle types
                 @Override
                 public Boolean visitType(TypeElement e, Void p) {
+                    // treat inner classes etc as members
+                    if (e.getNestingKind().isNested()) {
+                        return defaultAction(e, p);
+                    }
                     return configuration.docEnv.isSelected(e) && hasSource(e);
                 }
 
@@ -3273,5 +3261,11 @@
             this.first = first;
             this.second = second;
         }
+
+        public String toString() {
+            StringBuffer out = new StringBuffer();
+            out.append(first + ":" + second);
+            return out.toString();
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberCache.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.toolkit.util;
+
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+/**
+ * This class manages the visible member table for each type element.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+
+public class VisibleMemberCache {
+    private final Map<TypeElement, VisibleMemberTable> cache;
+    private final BaseConfiguration configuration;
+
+    public VisibleMemberCache(BaseConfiguration configuration) {
+        this.configuration = configuration;
+        cache = new HashMap<>();
+    }
+
+    public VisibleMemberTable getVisibleMemberTable(TypeElement te) {
+        return cache.computeIfAbsent(te, t -> new VisibleMemberTable(t, configuration, this));
+    }
+}
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberMap.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,842 +0,0 @@
-/*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.javadoc.internal.doclets.toolkit.util;
-
-import java.util.*;
-import java.util.regex.Pattern;
-
-import javax.lang.model.element.Element;
-import javax.lang.model.element.ElementKind;
-import javax.lang.model.element.ExecutableElement;
-import javax.lang.model.element.TypeElement;
-import javax.lang.model.element.VariableElement;
-import javax.lang.model.type.TypeKind;
-import javax.lang.model.type.TypeMirror;
-import javax.lang.model.util.ElementFilter;
-
-import com.sun.source.doctree.DocCommentTree;
-import com.sun.source.doctree.DocTree;
-
-import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
-import jdk.javadoc.internal.doclets.toolkit.Messages;
-
-/**
- * A data structure that encapsulates the visible members of a particular
- * type for a given class tree.  To use this data structure, you must specify
- * the type of member you are interested in (nested class, field, constructor
- * or method) and the leaf of the class tree.  The data structure will map
- * all visible members in the leaf and classes above the leaf in the tree.
- *
- *  <p><b>This is NOT part of any supported API.
- *  If you write code that depends on this, you do so at your own risk.
- *  This code and its internal interfaces are subject to change or
- *  deletion without notice.</b>
- *
- * @author Atul M Dambalkar
- * @author Jamie Ho (rewrite)
- */
-public class VisibleMemberMap {
-
-    private boolean noVisibleMembers = true;
-
-    public static enum Kind {
-        INNER_CLASSES,
-        ENUM_CONSTANTS,
-        FIELDS,
-        CONSTRUCTORS,
-        METHODS,
-        ANNOTATION_TYPE_FIELDS,
-        ANNOTATION_TYPE_MEMBER_OPTIONAL,
-        ANNOTATION_TYPE_MEMBER_REQUIRED,
-        PROPERTIES;
-
-        public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
-        public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
-        public static String getNavLinkLabels(Kind kind) {
-            switch (kind) {
-                case INNER_CLASSES:
-                    return "doclet.navNested";
-                case ENUM_CONSTANTS:
-                    return "doclet.navEnum";
-                case FIELDS:
-                    return "doclet.navField";
-                case CONSTRUCTORS:
-                    return "doclet.navConstructor";
-                case METHODS:
-                    return "doclet.navMethod";
-                default:
-                    throw new AssertionError("unknown kind:" + kind);
-            }
-        }
-    }
-
-    public static final String STARTLEVEL = "start";
-
-    // properties aren't named setA* or getA*
-    private static final Pattern GETTERSETTERPATTERN = Pattern.compile("[sg]et\\p{Upper}.*");
-    /**
-     * List of TypeElement objects for which ClassMembers objects are built.
-     */
-    private final Set<TypeElement> visibleClasses;
-
-    /**
-     * Map for each member name on to a map which contains members with same
-     * name-signature. The mapped map will contain mapping for each MemberDoc
-     * onto it's respecive level string.
-     */
-    private final Map<Object, Map<Element, String>> memberNameMap = new HashMap<>();
-
-    /**
-     * Map of class and it's ClassMembers object.
-     */
-    private final Map<TypeElement, ClassMembers> classMap = new HashMap<>();
-
-    /**
-     * Type whose visible members are requested.  This is the leaf of
-     * the class tree being mapped.
-     */
-    private final TypeElement typeElement;
-
-    /**
-     * Member kind: InnerClasses/Fields/Methods?
-     */
-    public final Kind kind;
-
-    /**
-     * The configuration this VisibleMemberMap was created with.
-     */
-    private final BaseConfiguration configuration;
-    private final Messages messages;
-    private final Utils utils;
-    private final Comparator<Element> comparator;
-
-    private final Map<TypeElement, List<Element>> propertiesCache;
-    private final Map<Element, Element> classPropertiesMap;
-    private final Map<Element, GetterSetter> getterSetterMap;
-
-    /**
-     * Construct a VisibleMemberMap of the given type for the given class.
-     *
-     * @param typeElement whose members are being mapped.
-     * @param kind the kind of member that is being mapped.
-     * @param configuration the configuration to use to construct this
-     * VisibleMemberMap. If the field configuration.nodeprecated is true the
-     * deprecated members are excluded from the map. If the field
-     * configuration.javafx is true the JavaFX features are used.
-     */
-    public VisibleMemberMap(TypeElement typeElement,
-                            Kind kind,
-                            BaseConfiguration configuration) {
-        this.typeElement = typeElement;
-        this.kind = kind;
-        this.configuration = configuration;
-        this.messages = configuration.getMessages();
-        this.utils = configuration.utils;
-        propertiesCache = configuration.propertiesCache;
-        classPropertiesMap = configuration.classPropertiesMap;
-        getterSetterMap = configuration.getterSetterMap;
-        comparator  = utils.makeGeneralPurposeComparator();
-        visibleClasses = new LinkedHashSet<>();
-        new ClassMembers(typeElement, STARTLEVEL).build();
-    }
-
-    /**
-     * Return the list of visible classes in this map.
-     *
-     * @return the list of visible classes in this map.
-     */
-    public SortedSet<TypeElement> getVisibleClasses() {
-        SortedSet<TypeElement> vClasses = new TreeSet<>(comparator);
-        vClasses.addAll(visibleClasses);
-        return vClasses;
-    }
-
-    /**
-     * Returns the first method where the given method is visible.
-     * @param e the method whose visible enclosing type is to be found.
-     * @return the method found or null
-     */
-    public ExecutableElement getVisibleMethod(ExecutableElement e) {
-        if (kind != Kind.METHODS || e.getKind() != ElementKind.METHOD) {
-            throw new AssertionError("incompatible member type or visible member map" + e);
-        }
-        // start with the current class
-        for (Element m : getMembers(typeElement)) {
-            ExecutableElement mthd = (ExecutableElement)m;
-            if (utils.executableMembersEqual(mthd, e)) {
-                return mthd;
-            }
-        }
-
-        for (TypeElement te : visibleClasses) {
-            if (te == typeElement)
-                continue;
-            for (Element m : getMembers(te)) {
-                ExecutableElement mthd = (ExecutableElement)m;
-                if (utils.executableMembersEqual(mthd, e)) {
-                    return mthd;
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Returns the property field documentation belonging to the given member.
-     * @param element the member for which the property documentation is needed.
-     * @return the property field documentation, null if there is none.
-     */
-    public Element getPropertyElement(Element element) {
-        return classPropertiesMap.get(element);
-    }
-
-    /**
-     * Returns the getter documentation belonging to the given property method.
-     * @param propertyMethod the method for which the getter is needed.
-     * @return the getter documentation, null if there is none.
-     */
-    public Element getGetterForProperty(Element propertyMethod) {
-        return getterSetterMap.get(propertyMethod).getGetter();
-    }
-
-    /**
-     * Returns the setter documentation belonging to the given property method.
-     * @param propertyMethod the method for which the setter is needed.
-     * @return the setter documentation, null if there is none.
-     */
-    public Element getSetterForProperty(Element propertyMethod) {
-        return getterSetterMap.get(propertyMethod).getSetter();
-    }
-
-    /**
-     * Return the package private members inherited by the class.  Only return
-     * if parent is package private and not documented.
-     *
-     * @return the package private members inherited by the class.
-     */
-    private List<Element> getInheritedPackagePrivateMethods() {
-        List<Element> results = new ArrayList<>();
-        for (TypeElement currentClass : visibleClasses) {
-            if (currentClass != typeElement &&
-                utils.isPackagePrivate(currentClass) &&
-                !utils.isLinkable(currentClass)) {
-                // Document these members in the child class because
-                // the parent is inaccessible.
-                results.addAll(classMap.get(currentClass).members);
-            }
-        }
-        return results;
-    }
-
-    /**
-     * Returns a list of visible enclosed members of the mapped type element.
-     *
-     * In the case of methods, the list may contain those methods that are
-     * extended with no specification changes as indicated by the existence
-     * of a sole &commat;inheritDoc or devoid of any API commments.
-     *
-     * This list may also contain appended members, inherited by inaccessible
-     * super types. These members are documented in the subtype when the
-     * super type is not documented.
-     *
-     * @return a list of visible enclosed members
-     */
-
-    public List<Element> getLeafMembers() {
-        List<Element> result = new ArrayList<>();
-        result.addAll(getMembers(typeElement));
-        result.addAll(getInheritedPackagePrivateMethods());
-        return result;
-    }
-
-    // Cache to improve performance
-    private HashMap<ExecutableElement, Boolean> overridenMethodCache = new HashMap<>();
-
-    private boolean hasOverridden(ExecutableElement method) {
-        return overridenMethodCache.computeIfAbsent(method, m -> hasOverriddenCompute(m));
-    }
-
-    private boolean hasOverriddenCompute(ExecutableElement method) {
-        if (kind != Kind.METHODS) {
-            throw new AssertionError("Unexpected kind: " + kind);
-        }
-        for (TypeElement t : visibleClasses) {
-            for (Element member : classMap.get(t).members) {
-                ExecutableElement inheritedMethod = (ExecutableElement)member;
-                if (utils.elementUtils.overrides(method, inheritedMethod, t)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns a list of enclosed members for the given type.
-     *
-     * @param typeElement the given type
-     *
-     * @return a list of enclosed members
-     */
-    public List<Element> getMembers(TypeElement typeElement) {
-        List<Element> result = new ArrayList<>();
-        if (this.kind == Kind.METHODS) {
-            for (Element member : classMap.get(typeElement).members) {
-                ExecutableElement method = (ExecutableElement)member;
-                if (hasOverridden(method)) {
-                    if (!utils.isSimpleOverride(method)) {
-                        result.add(method);
-                    }
-                } else {
-                    result.add(method);
-                }
-            }
-        } else {
-            result.addAll(classMap.get(typeElement).members);
-        }
-        return result;
-    }
-
-    public boolean hasMembers(TypeElement typeElement) {
-        return !classMap.get(typeElement).members.isEmpty();
-    }
-
-    private void fillMemberLevelMap(List<? extends Element> list, String level) {
-        for (Element element : list) {
-            Object key = getMemberKey(element);
-            Map<Element, String> memberLevelMap = memberNameMap.get(key);
-            if (memberLevelMap == null) {
-                memberLevelMap = new HashMap<>();
-                memberNameMap.put(key, memberLevelMap);
-            }
-            memberLevelMap.put(element, level);
-        }
-    }
-
-    private void purgeMemberLevelMap(Iterable<? extends Element> list, String level) {
-        for (Element element : list) {
-            Object key = getMemberKey(element);
-            Map<Element, String> memberLevelMap = memberNameMap.get(key);
-            if (memberLevelMap != null && level.equals(memberLevelMap.get(element)))
-                memberLevelMap.remove(element);
-        }
-    }
-
-    /**
-     * Represents a class member.
-     */
-    private class ClassMember {
-        private Set<Element> members;
-
-        public ClassMember(Element element) {
-            members = new HashSet<>();
-            members.add(element);
-        }
-
-        public boolean isEqual(ExecutableElement method) {
-            for (Element member : members) {
-                if (member.getKind() != ElementKind.METHOD)
-                    continue;
-                ExecutableElement thatMethod = (ExecutableElement) member;
-                if (utils.executableMembersEqual(method, thatMethod) &&
-                        !utils.isSimpleOverride(thatMethod)) {
-                    members.add(method);
-                    return true;
-                }
-            }
-            return false;
-        }
-    }
-
-    /**
-     * A data structure that represents the class members for
-     * a visible class.
-     */
-    private class ClassMembers {
-
-        /**
-         * The mapping class, whose inherited members are put in the
-         * {@link #members} list.
-         */
-        private final TypeElement typeElement;
-
-        /**
-         * List of members from the mapping class.
-         */
-        private List<Element> members = null;
-
-        /**
-         * Level/Depth of inheritance.
-         */
-        private final String level;
-
-        private ClassMembers(TypeElement mappingClass, String level) {
-            this.typeElement = mappingClass;
-            this.level = level;
-            if (classMap.containsKey(mappingClass) &&
-                        level.startsWith(classMap.get(mappingClass).level)) {
-                //Remove lower level class so that it can be replaced with
-                //same class found at higher level.
-                purgeMemberLevelMap(getClassMembers(mappingClass, false),
-                    classMap.get(mappingClass).level);
-                classMap.remove(mappingClass);
-                visibleClasses.remove(mappingClass);
-            }
-            if (!classMap.containsKey(mappingClass)) {
-                classMap.put(mappingClass, this);
-                visibleClasses.add(mappingClass);
-            }
-        }
-
-        private void build() {
-            if (kind == Kind.CONSTRUCTORS) {
-                addMembers(typeElement);
-            } else {
-                mapClass();
-            }
-        }
-
-        private void mapClass() {
-            addMembers(typeElement);
-            List<? extends TypeMirror> interfaces = typeElement.getInterfaces();
-            for (TypeMirror anInterface : interfaces) {
-                String locallevel = level + 1;
-                ClassMembers cm = new ClassMembers(utils.asTypeElement(anInterface), locallevel);
-                cm.mapClass();
-            }
-            if (utils.isClass(typeElement)) {
-                TypeElement superclass = utils.getSuperClass(typeElement);
-                if (!(superclass == null || typeElement.equals(superclass))) {
-                    ClassMembers cm = new ClassMembers(superclass, level + "c");
-                    cm.mapClass();
-                }
-            }
-        }
-
-        /**
-         * Get all the valid members from the mapping class. Get the list of
-         * members for the class to be included into(ctii), also get the level
-         * string for ctii. If mapping class member is not already in the
-         * inherited member list and if it is visible in the ctii and not
-         * overridden, put such a member in the inherited member list.
-         * Adjust member-level-map, class-map.
-         */
-        private void addMembers(TypeElement fromClass) {
-            List<Element> result = new ArrayList<>();
-            for (Element element : getClassMembers(fromClass, true)) {
-                if (memberIsVisible(element)) {
-                    if (!isOverridden(element, level)) {
-                        if (!utils.isHidden(element)) {
-                            result.add(element);
-                        }
-                    }
-                }
-            }
-            if (members != null) {
-                throw new AssertionError("members should not be null");
-            }
-            members = Collections.unmodifiableList(result);
-            if (!members.isEmpty()) {
-                noVisibleMembers = false;
-            }
-            fillMemberLevelMap(getClassMembers(fromClass, false), level);
-        }
-
-        /**
-         * Is given element visible in given typeElement in terms of inheritance? The given element
-         * is visible in the given typeElement if it is public or protected and if it is
-         * package-private if it's containing class is in the same package as the given typeElement.
-         */
-        private boolean memberIsVisible(Element element) {
-            if (utils.getEnclosingTypeElement(element).equals(VisibleMemberMap.this.typeElement)) {
-                //Member is in class that we are finding visible members for.
-                //Of course it is visible.
-                return true;
-            } else if (utils.isPrivate(element)) {
-                //Member is in super class or implemented interface.
-                //Private, so not inherited.
-                return false;
-            } else if (utils.isPackagePrivate(element)) {
-                //Member is package private.  Only return true if its class is in
-                //same package.
-                return utils.containingPackage(element).equals(utils.containingPackage(VisibleMemberMap.this.typeElement));
-            } else {
-                //Public members are always inherited.
-                return true;
-            }
-        }
-
-        /**
-         * Return all available class members.
-         */
-        private List<? extends Element> getClassMembers(TypeElement te, boolean filter) {
-            if (utils.isEnum(te) && kind == Kind.CONSTRUCTORS) {
-                //If any of these rules are hit, return empty array because
-                //we don't document these members ever.
-                return Collections.emptyList();
-            }
-            List<? extends Element> list;
-            switch (kind) {
-                case ANNOTATION_TYPE_FIELDS:
-                    list = (filter)
-                            ? utils.getAnnotationFields(te)
-                            : utils.getAnnotationFieldsUnfiltered(te);
-                    break;
-                case ANNOTATION_TYPE_MEMBER_OPTIONAL:
-                    list = utils.isAnnotationType(te)
-                            ? filterAnnotations(te, false)
-                            : Collections.emptyList();
-                    break;
-                case ANNOTATION_TYPE_MEMBER_REQUIRED:
-                    list = utils.isAnnotationType(te)
-                            ? filterAnnotations(te, true)
-                            : Collections.emptyList();
-                    break;
-                case INNER_CLASSES:
-                    List<TypeElement> xlist = filter
-                            ? utils.getInnerClasses(te)
-                            : utils.getInnerClassesUnfiltered(te);
-                    list = new ArrayList<>(xlist);
-                    break;
-                case ENUM_CONSTANTS:
-                    list = utils.getEnumConstants(te);
-                    break;
-                case FIELDS:
-                    if (filter) {
-                        list = utils.isAnnotationType(te)
-                                ? utils.getAnnotationFields(te)
-                                : utils.getFields(te);
-                    } else {
-                        list = utils.isAnnotationType(te)
-                                ? utils.getAnnotationFieldsUnfiltered(te)
-                                : utils.getFieldsUnfiltered(te);
-                    }
-                    break;
-                case CONSTRUCTORS:
-                    list = utils.getConstructors(te);
-                    break;
-                case METHODS:
-                    list = filter ? utils.getMethods(te) : utils.getMethodsUnfiltered(te);
-                    checkOnPropertiesTags(list);
-                    break;
-                case PROPERTIES:
-                    list = properties(te, filter);
-                    break;
-                default:
-                    list = Collections.emptyList();
-            }
-            // Deprected members should be excluded or not?
-            if (configuration.nodeprecated) {
-                return utils.excludeDeprecatedMembers(list);
-            }
-            return list;
-        }
-
-        /**
-         * Filter the annotation type members and return either the required
-         * members or the optional members, depending on the value of the
-         * required parameter.
-         *
-         * @param typeElement The annotation type to process.
-         * @param required
-         * @return the annotation type members and return either the required
-         * members or the optional members, depending on the value of the
-         * required parameter.
-         */
-        private List<Element> filterAnnotations(TypeElement typeElement, boolean required) {
-            List<Element> members = utils.getAnnotationMethods(typeElement);
-            List<Element> targetMembers = new ArrayList<>();
-            for (Element member : members) {
-                ExecutableElement ee = (ExecutableElement)member;
-                if ((required && ee.getDefaultValue() == null)
-                        || ((!required) && ee.getDefaultValue() != null)) {
-                    targetMembers.add(member);
-                }
-            }
-            return targetMembers;
-        }
-
-        /**
-         * Is member overridden? The member is overridden if it is found in the
-         * same level hierarchy e.g. member at level "11" overrides member at
-         * level "111".
-         */
-        private boolean isOverridden(Element element, String level) {
-            Object key = getMemberKey(element);
-            Map<?, String> memberLevelMap = (Map<?, String>) memberNameMap.get(key);
-            if (memberLevelMap == null)
-                return false;
-            for (String mappedlevel : memberLevelMap.values()) {
-                if (mappedlevel.equals(STARTLEVEL)
-                        || (level.startsWith(mappedlevel)
-                        && !level.equals(mappedlevel))) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private List<Element> properties(final TypeElement typeElement, final boolean filter) {
-            final List<ExecutableElement> allMethods = filter
-                    ? utils.getMethods(typeElement)
-                    : utils.getMethodsUnfiltered(typeElement);
-            final List<VariableElement> allFields = utils.getFieldsUnfiltered(typeElement);
-
-            if (propertiesCache.containsKey(typeElement)) {
-                return propertiesCache.get(typeElement);
-            }
-
-            final List<Element> result = new ArrayList<>();
-
-            for (final Element propertyMethod : allMethods) {
-                ExecutableElement ee = (ExecutableElement)propertyMethod;
-                if (!isPropertyMethod(ee)) {
-                    continue;
-                }
-
-                final ExecutableElement getter = getterForField(allMethods, ee);
-                final ExecutableElement setter = setterForField(allMethods, ee);
-                final VariableElement field = fieldForProperty(allFields, ee);
-
-                addToPropertiesMap(setter, getter, ee, field);
-                getterSetterMap.put(propertyMethod, new GetterSetter(getter, setter));
-                result.add(ee);
-            }
-            propertiesCache.put(typeElement, result);
-            return result;
-        }
-
-        private void addToPropertiesMap(ExecutableElement setter,
-                                        ExecutableElement getter,
-                                        ExecutableElement propertyMethod,
-                                        VariableElement field) {
-            if (field == null || utils.getDocCommentTree(field) == null) {
-                addToPropertiesMap(setter, propertyMethod);
-                addToPropertiesMap(getter, propertyMethod);
-                addToPropertiesMap(propertyMethod, propertyMethod);
-            } else {
-                addToPropertiesMap(getter, field);
-                addToPropertiesMap(setter, field);
-                addToPropertiesMap(propertyMethod, field);
-            }
-        }
-
-        private void addToPropertiesMap(Element propertyMethod,
-                                        Element commentSource) {
-            if (null == propertyMethod || null == commentSource) {
-                return;
-            }
-            DocCommentTree docTree = utils.getDocCommentTree(propertyMethod);
-
-            /* The second condition is required for the property buckets. In
-             * this case the comment is at the property method (not at the field)
-             * and it needs to be listed in the map.
-             */
-            if ((docTree == null) || propertyMethod.equals(commentSource)) {
-                classPropertiesMap.put(propertyMethod, commentSource);
-            }
-        }
-
-        private ExecutableElement getterForField(List<ExecutableElement> methods,
-                                         ExecutableElement propertyMethod) {
-            final String propertyMethodName = utils.getSimpleName(propertyMethod);
-            final String fieldName = propertyMethodName.substring(0,
-                            propertyMethodName.lastIndexOf("Property"));
-            final String fieldNameUppercased =
-                    "" + Character.toUpperCase(fieldName.charAt(0))
-                                            + fieldName.substring(1);
-            final String getterNamePattern;
-            final String fieldTypeName = propertyMethod.getReturnType().toString();
-            if ("boolean".equals(fieldTypeName)
-                    || fieldTypeName.endsWith("BooleanProperty")) {
-                getterNamePattern = "(is|get)" + fieldNameUppercased;
-            } else {
-                getterNamePattern = "get" + fieldNameUppercased;
-            }
-
-            for (ExecutableElement method : methods) {
-                if (Pattern.matches(getterNamePattern, utils.getSimpleName(method))) {
-                    if (method.getParameters().isEmpty() &&
-                            utils.isPublic(method) || utils.isProtected(method)) {
-                        return method;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private ExecutableElement setterForField(List<ExecutableElement> methods,
-                                         ExecutableElement propertyMethod) {
-            final String propertyMethodName = utils.getSimpleName(propertyMethod);
-            final String fieldName =
-                    propertyMethodName.substring(0,
-                            propertyMethodName.lastIndexOf("Property"));
-            final String fieldNameUppercased =
-                    "" + Character.toUpperCase(fieldName.charAt(0))
-                                             + fieldName.substring(1);
-            final String setter = "set" + fieldNameUppercased;
-
-            for (ExecutableElement method : methods) {
-                if (setter.equals(utils.getSimpleName(method))) {
-                    if (method.getParameters().size() == 1
-                            && method.getReturnType().getKind() == TypeKind.VOID
-                            && (utils.isPublic(method) || utils.isProtected(method))) {
-                        return method;
-                    }
-                }
-            }
-            return null;
-        }
-
-        private VariableElement fieldForProperty(List<VariableElement> fields, ExecutableElement property) {
-
-            for (VariableElement field : fields) {
-                final String fieldName = utils.getSimpleName(field);
-                final String propertyName = fieldName + "Property";
-                if (propertyName.equals(utils.getSimpleName(property))) {
-                    return field;
-                }
-            }
-            return null;
-        }
-
-        private boolean isPropertyMethod(ExecutableElement method) {
-            if (!configuration.javafx) {
-               return false;
-            }
-            if (!utils.getSimpleName(method).endsWith("Property")) {
-                return false;
-            }
-
-            if (!memberIsVisible(method)) {
-                return false;
-            }
-
-            if (GETTERSETTERPATTERN.matcher(utils.getSimpleName(method)).matches()) {
-                return false;
-            }
-            if (!method.getTypeParameters().isEmpty()) {
-                return false;
-            }
-            return method.getParameters().isEmpty()
-                    && method.getReturnType().getKind() != TypeKind.VOID;
-        }
-
-        private void checkOnPropertiesTags(List<? extends Element> members) {
-            for (Element e: members) {
-                ExecutableElement ee = (ExecutableElement)e;
-                if (utils.isIncluded(ee)) {
-                    CommentHelper ch = utils.getCommentHelper(ee);
-                    for (DocTree tree: utils.getBlockTags(ee)) {
-                        String tagName = ch.getTagName(tree);
-                        if (tagName.equals("@propertySetter")
-                                || tagName.equals("@propertyGetter")
-                                || tagName.equals("@propertyDescription")) {
-                            if (!isPropertyGetterOrSetter(members, ee)) {
-                                messages.warning(ch.getDocTreePath(tree),
-                                        "doclet.javafx_tag_misuse");
-                            }
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        private boolean isPropertyGetterOrSetter(List<? extends Element> members,
-                                                 ExecutableElement method) {
-            String propertyName = utils.propertyName(method);
-            if (!propertyName.isEmpty()) {
-                String propertyMethodName = propertyName + "Property";
-                for (Element member: members) {
-                    if (utils.getSimpleName(member).equals(propertyMethodName)) {
-                        return true;
-                    }
-                }
-            }
-            return false;
-        }
-    }
-
-    public class GetterSetter {
-        private final Element getter;
-        private final Element setter;
-
-        public GetterSetter(Element getter, Element setter) {
-            this.getter = getter;
-            this.setter = setter;
-        }
-
-        public Element getGetter() {
-            return getter;
-        }
-
-        public Element getSetter() {
-            return setter;
-        }
-    }
-
-    /**
-     * Return true if this map has no visible members.
-     *
-     * @return true if this map has no visible members.
-     */
-    public boolean noVisibleMembers() {
-        return noVisibleMembers;
-    }
-
-    private ClassMember getClassMember(ExecutableElement member) {
-        for (Object key : memberNameMap.keySet()) {
-            if (key instanceof String) {
-                continue;
-            }
-            if (((ClassMember) key).isEqual(member)) {
-                return (ClassMember) key;
-            }
-        }
-        return new ClassMember(member);
-    }
-
-    /**
-     * Return the key to the member map for the given member.
-     */
-    private Object getMemberKey(Element element) {
-        if (utils.isConstructor(element)) {
-            return utils.getSimpleName(element) + utils.flatSignature((ExecutableElement)element);
-        } else if (utils.isMethod(element)) {
-            return getClassMember((ExecutableElement) element);
-        } else if (utils.isField(element) || utils.isEnumConstant(element) || utils.isAnnotationType(element)) {
-            return utils.getSimpleName(element);
-        } else { // it's a class or interface
-            String classOrIntName = utils.getSimpleName(element);
-            //Strip off the containing class name because we only want the member name.
-            classOrIntName = classOrIntName.indexOf('.') != 0
-                    ? classOrIntName.substring(classOrIntName.lastIndexOf('.'))
-                    : classOrIntName;
-            return "clint" + classOrIntName;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/VisibleMemberTable.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,992 @@
+/*
+ * Copyright (c) 2018, 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 jdk.javadoc.internal.doclets.toolkit.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.SimpleElementVisitor9;
+import java.lang.ref.SoftReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumMap;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import jdk.javadoc.internal.doclets.toolkit.BaseConfiguration;
+import jdk.javadoc.internal.doclets.toolkit.PropertyUtils;
+
+/**
+ * This class computes the main data structure for the doclet's
+ * operations. Essentially, the implementation encapsulating the
+ * javax.lang.models view of what can be documented about a
+ * type element's members.
+ * <p>
+ * The general operations are as follows:
+ * <p>
+ * Members: these are the members from jx.l.m's view but
+ * are structured along the kinds of this class.
+ * <p>
+ * Extra Members: these are members enclosed in an undocumented
+ * package-private type element, and may not be linkable (or documented),
+ * however, the members of such a type element may be documented, as if
+ * declared in the sub type, only if the enclosing type is not being
+ * documented by a filter such as -public, -protected, etc.
+ * <p>
+ * Visible Members: these are the members that are "visible"
+ * and available and should be documented, in a type element.
+ * <p>
+ * The basic rule for computation: when considering a type element,
+ * besides its immediate direct types and interfaces, the computation
+ * should not expand to any other type in the inheritance hierarchy.
+ * <p>
+ * This table generates all the data structures it needs for each
+ * type, as its own view, and will present some form of this to the
+ * doclet as and when required to.
+ *
+ * <p><b>This is NOT part of any supported API.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ *
+ */
+
+public class VisibleMemberTable {
+
+    public enum Kind {
+        INNER_CLASSES,
+        ENUM_CONSTANTS,
+        FIELDS,
+        CONSTRUCTORS,
+        METHODS,
+        ANNOTATION_TYPE_FIELDS,
+        ANNOTATION_TYPE_MEMBER_OPTIONAL,
+        ANNOTATION_TYPE_MEMBER_REQUIRED,
+        PROPERTIES;
+
+        public static final EnumSet<Kind> summarySet = EnumSet.range(INNER_CLASSES, METHODS);
+        public static final EnumSet<Kind> detailSet = EnumSet.range(ENUM_CONSTANTS, METHODS);
+    }
+
+    final TypeElement te;
+    final TypeElement parent;
+
+    final BaseConfiguration config;
+    final Utils utils;
+    final VisibleMemberCache mcache;
+
+    private List<VisibleMemberTable> allSuperclasses;
+    private List<VisibleMemberTable> allSuperinterfaces;
+    private List<VisibleMemberTable> parents;
+
+
+    private Map<Kind, List<Element>> extraMembers = new EnumMap<>(Kind.class);
+    private Map<Kind, List<Element>> visibleMembers = null;
+    private Map<ExecutableElement, PropertyMembers> propertyMap = new HashMap<>();
+
+    // Keeps track of method overrides
+    Map<ExecutableElement, OverridingMethodInfo> overriddenMethodTable
+            = new LinkedHashMap<>();
+
+    protected VisibleMemberTable(TypeElement typeElement, BaseConfiguration configuration,
+                                 VisibleMemberCache mcache) {
+        config = configuration;
+        utils = configuration.utils;
+        te = typeElement;
+        parent = utils.getSuperClass(te);
+        this.mcache = mcache;
+        allSuperclasses = new ArrayList<>();
+        allSuperinterfaces = new ArrayList<>();
+        parents = new ArrayList<>();
+    }
+
+    private synchronized void ensureInitialized() {
+        if (visibleMembers != null)
+            return;
+
+        visibleMembers = new EnumMap<>(Kind.class);
+        for (Kind kind : Kind.values()) {
+            visibleMembers.put(kind, new ArrayList<>());
+        }
+        computeParents();
+        computeVisibleMembers();
+    }
+
+    List<? extends Element> getExtraMembers(Kind kind) {
+        ensureInitialized();
+        return visibleMembers.getOrDefault(kind, Collections.emptyList());
+    }
+
+    List<VisibleMemberTable> getAllSuperclasses() {
+        ensureInitialized();
+        return allSuperclasses;
+    }
+
+    List<VisibleMemberTable> getAllSuperinterfaces() {
+        ensureInitialized();
+        return allSuperinterfaces;
+    }
+
+    /**
+     * Returns a list of all visible enclosed members of a type element,
+     * and inherited members.
+     * <p>
+     * Notes:
+     * a. The list may or may not contain simple overridden methods.
+     * A simple overridden method is one that overrides a super method
+     * with no specification changes as indicated by the existence of a
+     * sole &commat;inheritDoc or devoid of any API commments.
+     * <p>
+     * b.The list may contain (extra) members, inherited by inaccessible
+     * super types, primarily package private types. These members are
+     * required to be documented in the subtype when the super type is
+     * not documented.
+     *
+     * @param kind the member kind
+     * @return a list of all visible members
+     */
+    public List<? extends Element> getAllVisibleMembers(Kind kind) {
+        ensureInitialized();
+        return visibleMembers.getOrDefault(kind, Collections.emptyList());
+    }
+
+    /**
+     * Returns a list of visible enclosed members of a specified kind,
+     * filtered by the specified predicate.
+     * @param kind the member kind
+     * @param p the predicate used to filter the output
+     * @return a list of visible enclosed members
+     */
+    public List<? extends Element> getVisibleMembers(Kind kind, Predicate<Element> p) {
+        ensureInitialized();
+
+        return visibleMembers.getOrDefault(kind, Collections.emptyList()).stream()
+                .filter(p)
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * Returns a list of all enclosed members including any extra members.
+     * Typically called by various builders.
+     *
+     * @param kind the member kind
+     * @return a list of visible enclosed members
+     */
+    public List<? extends Element> getVisibleMembers(Kind kind) {
+        Predicate<Element> declaredAndLeafMembers = e -> {
+            TypeElement encl = utils.getEnclosingTypeElement(e);
+            return encl == te || isUndocumentedEnclosure(encl);
+        };
+        return getVisibleMembers(kind, declaredAndLeafMembers);
+    }
+
+    /**
+     * Returns a list of visible enclosed members of given kind,
+     * declared in this type element, and does not include
+     * any inherited members or extra members.
+     *
+     * @return a list of visible enclosed members in this type
+     */
+    public List<? extends Element> getMembers(Kind kind) {
+        Predicate<Element> onlyLocallyDeclaredMembers = e -> utils.getEnclosingTypeElement(e) == te;
+        return getVisibleMembers(kind, onlyLocallyDeclaredMembers);
+    }
+
+    /**
+     * Returns the overridden method, if it is simply overridding or the
+     * method is a member of a package private type, this method is
+     * primarily used to determine the location of a possible comment.
+     *
+     * @param e the method to check
+     * @return the method found or null
+     */
+    public ExecutableElement getOverriddenMethod(ExecutableElement e) {
+        ensureInitialized();
+
+        OverridingMethodInfo found = overriddenMethodTable.get(e);
+        if (found != null && (found.simpleOverride || isUndocumentedEnclosure(utils.getEnclosingTypeElement(e)))) {
+            return found.overrider;
+        }
+        return null;
+    }
+
+    /**
+     * Returns the simply overridden method.
+     * @param e the method to check
+     * @return the overridden method or null
+     */
+    public ExecutableElement getsimplyOverriddenMethod(ExecutableElement e) {
+        ensureInitialized();
+
+        OverridingMethodInfo found = overriddenMethodTable.get(e);
+        if (found != null && found.simpleOverride) {
+            return found.overrider;
+        }
+        return null;
+    }
+
+    /**
+     * Returns a set of visible type elements in this type element's lineage.
+     * <p>
+     * This method returns the super-types in the inheritance
+     * order C, B, A, j.l.O. The super-interfaces however are
+     * alpha sorted and appended to the resulting set.
+     *
+     * @return the list of visible classes in this map.
+     */
+    public Set<TypeElement> getVisibleTypeElements() {
+        ensureInitialized();
+        Set<TypeElement> result = new LinkedHashSet<>();
+
+        // Add this type element first.
+        result.add(te);
+
+        // Add the super classes.
+        allSuperclasses.stream()
+                .map(vmt -> vmt.te)
+                .forEach(result::add);
+
+        // ... and finally the sorted super interfaces.
+        allSuperinterfaces.stream()
+                .map(vmt -> vmt.te)
+                .sorted(utils.makeGeneralPurposeComparator())
+                .forEach(result::add);
+
+        return result;
+    }
+
+    /**
+     * Returns true if this table contains visible members.
+     *
+     * @return true if visible members are present.
+     */
+    public boolean hasVisibleMembers() {
+        for (Kind kind : Kind.values()) {
+            if (hasVisibleMembers(kind))
+                return true;
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this table contains visible members of
+     * the specified kind, including inhertied members.
+     *
+     * @return true if visible members are present.
+     */
+    public boolean hasVisibleMembers(Kind kind) {
+        ensureInitialized();
+        List<Element> elements = visibleMembers.get(kind);
+        return elements != null && !elements.isEmpty();
+    }
+
+    /**
+     * Returns the property field associated with the property method.
+     * @param propertyMethod the identifying property method
+     * @return the field or null if absent
+     */
+    public VariableElement getPropertyField(ExecutableElement propertyMethod) {
+        ensureInitialized();
+        PropertyMembers pm =  propertyMap.get(propertyMethod);
+        return pm == null ? null : pm.field;
+    }
+
+    /**
+     * Returns the getter method associated with the property method.
+     * @param propertyMethod the identifying property method
+     * @return the getter or null if absent
+     */
+    public ExecutableElement getPropertyGetter(ExecutableElement propertyMethod) {
+        ensureInitialized();
+        PropertyMembers pm =  propertyMap.get(propertyMethod);
+        return pm == null ? null : pm.getter;
+    }
+
+    /**
+     * Returns the setter method associated with the property method.
+     * @param propertyMethod the identifying property method
+     * @return the setter or null if absent
+     */
+    public ExecutableElement getPropertySetter(ExecutableElement propertyMethod) {
+        ensureInitialized();
+        PropertyMembers pm =  propertyMap.get(propertyMethod);
+        return pm == null ? null : pm.setter;
+    }
+
+    boolean isUndocumentedEnclosure(TypeElement encl) {
+        return utils.isPackagePrivate(encl) && !utils.isLinkable(encl);
+    }
+
+    private void computeParents() {
+        for (TypeMirror intfType : te.getInterfaces()) {
+            TypeElement intfc = utils.asTypeElement(intfType);
+            if (intfc != null) {
+                VisibleMemberTable vmt = mcache.getVisibleMemberTable(intfc);
+                allSuperinterfaces.add(vmt);
+                parents.add(vmt);
+                allSuperinterfaces.addAll(vmt.getAllSuperinterfaces());
+            }
+        }
+
+        if (parent != null) {
+            VisibleMemberTable vmt = mcache.getVisibleMemberTable(parent);
+            allSuperclasses.add(vmt);
+            allSuperclasses.addAll(vmt.getAllSuperclasses());
+            // Add direct super interfaces of a super class, if any.
+            allSuperinterfaces.addAll(vmt.getAllSuperinterfaces());
+            parents.add(vmt);
+        }
+    }
+
+    private void computeVisibleMembers() {
+
+        // Note: these have some baggage, and are redundant,
+        // allow this to be GC'ed.
+        LocalMemberTable lmt = new LocalMemberTable();
+
+        for (Kind k : Kind.values()) {
+            computeLeafMembers(lmt, k);
+            computeVisibleMembers(lmt, k);
+        }
+        // All members have been computed, compute properties.
+        computeVisibleProperties(lmt);
+    }
+
+    private void computeLeafMembers(LocalMemberTable lmt, Kind kind) {
+        List<Element> list = new ArrayList<>();
+        if (isUndocumentedEnclosure(te)) {
+            list.addAll(lmt.getOrderedMembers(kind));
+        }
+        parents.forEach(pvmt -> {
+            list.addAll(pvmt.getExtraMembers(kind));
+        });
+        extraMembers.put(kind, Collections.unmodifiableList(list));
+    }
+
+    void computeVisibleMembers(LocalMemberTable lmt, Kind kind) {
+        switch (kind) {
+            case FIELDS: case INNER_CLASSES:
+                computeVisibleFieldsAndInnerClasses(lmt, kind);
+                return;
+
+            case METHODS:
+                computeVisibleMethods(lmt);
+                return;
+
+            // Defer properties related computations for later.
+            case PROPERTIES:
+                return;
+
+            default:
+                List<Element> list = lmt.getOrderedMembers(kind).stream()
+                        .filter(this::mustDocument)
+                        .collect(Collectors.toList());
+                visibleMembers.put(kind, Collections.unmodifiableList(list));
+                break;
+        }
+    }
+
+    private boolean mustDocument(Element e) {
+        return !utils.hasHiddenTag(e) && utils.shouldDocument(e);
+    }
+
+    private boolean allowInheritedMembers(Element e, Kind kind, LocalMemberTable lmt) {
+        return isInherited(e) && !isMemberHidden(e, kind, lmt);
+    }
+
+    private boolean isInherited(Element e) {
+        if (utils.isPrivate(e))
+            return false;
+
+        if (utils.isPackagePrivate(e))
+            // Allowed iff this type-element is in the same package as the element
+            return utils.containingPackage(e).equals(utils.containingPackage(te));
+
+        return true;
+    }
+
+    private boolean isMemberHidden(Element inheritedMember, Kind kind, LocalMemberTable lmt) {
+        Elements elementUtils = config.docEnv.getElementUtils();
+        switch(kind) {
+            default:
+                List<Element> list = lmt.getMembers(inheritedMember, kind);
+                if (list.isEmpty())
+                    return false;
+                return elementUtils.hides(list.get(0), inheritedMember);
+            case METHODS: case CONSTRUCTORS: // Handled elsewhere.
+                throw new IllegalArgumentException("incorrect kind");
+        }
+    }
+
+    private void computeVisibleFieldsAndInnerClasses(LocalMemberTable lmt, Kind kind) {
+        Set<Element> result = new LinkedHashSet<>();
+        for (VisibleMemberTable pvmt : parents) {
+            result.addAll(pvmt.getExtraMembers(kind));
+            result.addAll(pvmt.getAllVisibleMembers(kind));
+        }
+
+        // Filter out members in the inherited list that are hidden
+        // by this type or should not be inherited at all.
+        List<Element> list = result.stream()
+                .filter(e -> allowInheritedMembers(e, kind, lmt)).collect(Collectors.toList());
+
+        // Prefix local results first
+        list.addAll(0, lmt.getOrderedMembers(kind));
+
+        // Filter out elements that should not be documented
+        list = list.stream()
+                .filter(this::mustDocument)
+                .collect(Collectors.toList());
+
+        visibleMembers.put(kind, Collections.unmodifiableList(list));
+    }
+
+    private void computeVisibleMethods(LocalMemberTable lmt) {
+        Set<Element> inheritedMethods = new LinkedHashSet<>();
+        Map<ExecutableElement, List<ExecutableElement>> overriddenByTable = new HashMap<>();
+        for (VisibleMemberTable pvmt : parents) {
+            // Merge the lineage overrides into local table
+            pvmt.overriddenMethodTable.entrySet().forEach(e -> {
+                OverridingMethodInfo p = e.getValue();
+                if (!p.simpleOverride) { // consider only real overrides
+                    List<ExecutableElement> list = overriddenByTable.computeIfAbsent(p.overrider,
+                            k -> new ArrayList<>());
+                    list.add(e.getKey());
+                }
+            });
+            inheritedMethods.addAll(pvmt.getAllVisibleMembers(Kind.METHODS));
+
+            // Copy the extra members (if any) from the lineage.
+            if (!utils.shouldDocument(pvmt.te)) {
+                List<? extends Element> extraMethods = pvmt.getExtraMembers(Kind.METHODS);
+
+                if (lmt.getOrderedMembers(Kind.METHODS).isEmpty()) {
+                    inheritedMethods.addAll(extraMethods);
+                    continue;
+                }
+
+                // Check if an extra-method ought to percolate through.
+                for (Element extraMethod : extraMethods) {
+                    boolean found = false;
+
+                    List<Element> lmethods = lmt.getMembers(extraMethod, Kind.METHODS);
+                    for (Element lmethod : lmethods) {
+                        ExecutableElement method = (ExecutableElement)lmethod;
+                        found = utils.elementUtils.overrides(method,
+                                (ExecutableElement)extraMethod, te);
+                        if (found)
+                            break;
+                    }
+                    if (!found)
+                        inheritedMethods.add(extraMethod);
+                }
+            }
+        }
+
+        // Filter out inherited methods that:
+        // a. cannot override (private instance members)
+        // b. are overridden and should not be visible in this type
+        // c. are hidden in the type being considered
+        // see allowInheritedMethods, which performs the above actions
+        List<Element> list = inheritedMethods.stream()
+                .filter(e -> allowInheritedMethods((ExecutableElement)e, overriddenByTable, lmt))
+                .collect(Collectors.toList());
+
+        // Filter out the local methods, that do not override or simply
+        // overrides a super method, or those methods that should not
+        // be visible.
+        Predicate<ExecutableElement> isVisible = m -> {
+            OverridingMethodInfo p = overriddenMethodTable.getOrDefault(m, null);
+            return p == null || !p.simpleOverride;
+        };
+        List<Element> mlist = lmt.getOrderedMembers(Kind.METHODS);
+        List<Element> llist = mlist.stream()
+                .map(m -> (ExecutableElement)m)
+                .filter(isVisible)
+                .collect(Collectors.toList());
+
+        // Merge the above lists, making sure the local methods precede
+        // the others
+        list.addAll(0, llist);
+
+        // Final filtration of elements
+        list = list.stream()
+                .filter(this::mustDocument)
+                .collect(Collectors.toList());
+
+        visibleMembers.put(Kind.METHODS, Collections.unmodifiableList(list));
+
+        // Copy over overridden tables from the lineage, and finish up.
+        for (VisibleMemberTable pvmt : parents) {
+            overriddenMethodTable.putAll(pvmt.overriddenMethodTable);
+        }
+        overriddenMethodTable = Collections.unmodifiableMap(overriddenMethodTable);
+    }
+
+    boolean isEnclosureInterface(Element e) {
+        TypeElement enclosing = utils.getEnclosingTypeElement(e);
+        return utils.isInterface(enclosing);
+    }
+
+    boolean allowInheritedMethods(ExecutableElement inheritedMethod,
+                                  Map<ExecutableElement, List<ExecutableElement>> inheritedOverriddenTable,
+                                  LocalMemberTable lmt) {
+
+        if (!isInherited(inheritedMethod))
+            return false;
+
+        final boolean haveStatic = utils.isStatic(inheritedMethod);
+        final boolean inInterface = isEnclosureInterface(inheritedMethod);
+
+        // Static methods in interfaces are never documented.
+        if (haveStatic && inInterface) {
+            return false;
+        }
+
+        // Multiple-Inheritance: remove the interface method that may have
+        // been overridden by another interface method in the hierarchy
+        //
+        // Note: The following approach is very simplistic and is compatible
+        // with old VMM. A future enhancement, may include a contention breaker,
+        // to correctly eliminate those methods that are merely definitions
+        // in favor of concrete overriding methods, for instance those that have
+        // API documentation and are not abstract OR default methods.
+        if (inInterface) {
+            List<ExecutableElement> list = inheritedOverriddenTable.get(inheritedMethod);
+            if (list != null) {
+                boolean found = list.stream()
+                        .anyMatch(this::isEnclosureInterface);
+                if (found)
+                    return false;
+            }
+        }
+
+        Elements elementUtils = config.docEnv.getElementUtils();
+
+        // Check the local methods in this type.
+        List<Element> lMethods = lmt.getMembers(inheritedMethod, Kind.METHODS);
+        for (Element lMethod : lMethods) {
+            // Ignore private methods or those methods marked with
+            // a "hidden" tag.
+            if (utils.isPrivate(lMethod))
+                continue;
+
+            // Remove methods that are "hidden", in JLS terms.
+            if (haveStatic && utils.isStatic(lMethod) &&
+                    elementUtils.hides(lMethod, inheritedMethod)) {
+                return false;
+            }
+
+            // Check for overriding methods.
+            if (elementUtils.overrides((ExecutableElement)lMethod, inheritedMethod,
+                    utils.getEnclosingTypeElement(lMethod))) {
+
+                // Disallow package-private super methods to leak in
+                TypeElement encl = utils.getEnclosingTypeElement(inheritedMethod);
+                if (isUndocumentedEnclosure(encl)) {
+                    overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+                            l -> new OverridingMethodInfo(inheritedMethod, false));
+                    return false;
+                }
+                boolean simpleOverride = utils.isSimpleOverride((ExecutableElement)lMethod);
+                overriddenMethodTable.computeIfAbsent((ExecutableElement)lMethod,
+                        l -> new OverridingMethodInfo(inheritedMethod, simpleOverride));
+                return simpleOverride;
+            }
+        }
+        return true;
+    }
+
+    /*
+     * This class encapsulates the details of local members, orderedMembers
+     * contains the members in the declaration order, additionally a
+     * HashMap is maintained for performance optimization to lookup
+     * members. As a future enhancement is perhaps to consolidate the ordering
+     * into a Map, capturing the insertion order, thereby eliminating an
+     * ordered list.
+     */
+    class LocalMemberTable {
+
+        // Maintains declaration order
+        private final Map<Kind, List<Element>> orderedMembers;
+
+        // Performance optimization
+        private final Map<Kind, Map<String, List<Element>>> memberMap;
+
+        LocalMemberTable() {
+            orderedMembers = new EnumMap<>(Kind.class);
+            memberMap = new EnumMap<>(Kind.class);
+
+            List<? extends Element> elements = te.getEnclosedElements();
+            for (Element e : elements) {
+                if (config.nodeprecated && utils.isDeprecated(e)) {
+                    continue;
+                }
+                switch (e.getKind()) {
+                    case CLASS:
+                    case INTERFACE:
+                    case ENUM:
+                    case ANNOTATION_TYPE:
+                        addMember(e, Kind.INNER_CLASSES);
+                        break;
+                    case FIELD:
+                        addMember(e, Kind.FIELDS);
+                        addMember(e, Kind.ANNOTATION_TYPE_FIELDS);
+                        break;
+                    case METHOD:
+                        ExecutableElement ee = (ExecutableElement)e;
+                        if (utils.isAnnotationType(te)) {
+                            addMember(e, ee.getDefaultValue() == null
+                                    ? Kind.ANNOTATION_TYPE_MEMBER_REQUIRED
+                                    : Kind.ANNOTATION_TYPE_MEMBER_OPTIONAL);
+                        }
+                        addMember(e, Kind.METHODS);
+                        break;
+                    case CONSTRUCTOR:
+                        if (!utils.isEnum(te))
+                            addMember(e, Kind.CONSTRUCTORS);
+                        break;
+                    case ENUM_CONSTANT:
+                        addMember(e, Kind.ENUM_CONSTANTS);
+                        break;
+                }
+            }
+
+            // Freeze the data structures
+            for (Kind kind : Kind.values()) {
+                orderedMembers.computeIfPresent(kind, (k, v) -> Collections.unmodifiableList(v));
+                orderedMembers.computeIfAbsent(kind, t -> Collections.emptyList());
+
+                memberMap.computeIfPresent(kind, (k, v) -> Collections.unmodifiableMap(v));
+                memberMap.computeIfAbsent(kind, t -> Collections.emptyMap());
+            }
+        }
+
+        String getMemberKey(Element e) {
+            return new SimpleElementVisitor9<String, Void>() {
+                @Override
+                public String visitExecutable(ExecutableElement e, Void aVoid) {
+                    return e.getSimpleName() + ":" + e.getParameters().size();
+                }
+
+                @Override
+                protected String defaultAction(Element e, Void aVoid) {
+                    return e.getSimpleName().toString();
+                }
+            }.visit(e);
+        }
+
+        void addMember(Element e, Kind kind) {
+            List<Element> list = orderedMembers.computeIfAbsent(kind, k -> new ArrayList<>());
+            list.add(e);
+
+            Map<String, List<Element>> map = memberMap.computeIfAbsent(kind, k -> new HashMap<>());
+            list = map.computeIfAbsent(getMemberKey(e), l -> new ArrayList<>());
+            list.add(e);
+        }
+
+        List<Element> getOrderedMembers(Kind kind) {
+            return orderedMembers.get(kind);
+        }
+
+        List<Element> getMembers(Element e, Kind kind) {
+            String key = getMemberKey(e);
+            return getMembers(key, kind);
+        }
+
+        List<Element> getMembers(String key, Kind kind) {
+            Map <String, List<Element>> map = memberMap.get(kind);
+            return map.getOrDefault(key, Collections.emptyList());
+        }
+
+        List<Element> getPropertyMethods(String methodName, int argcount) {
+            return getMembers(methodName + ":" + argcount, Kind.METHODS).stream()
+                    .filter(m -> (utils.isPublic(m) || utils.isProtected(m)))
+                    .collect(Collectors.toList());
+        }
+    }
+
+    /**
+     * The properties triad for a property method.
+     */
+    static class PropertyMembers {
+        final VariableElement field;
+        final ExecutableElement getter;
+        final ExecutableElement setter;
+
+        PropertyMembers(VariableElement field, ExecutableElement getter, ExecutableElement setter) {
+            this.field = field;
+            this.getter = getter;
+            this.setter = setter;
+        }
+
+        public String toString() {
+            return ("field: " + field + ", getter: " + getter + ", setter: " + setter);
+        }
+    }
+
+    /*
+     * JavaFX convention notes.
+     * A JavaFX property-method is a method, which ends with "Property" in
+     * its name, takes no parameters and typically returns a subtype of javafx.beans.
+     * ReadOnlyProperty, in the strictest sense. However, it may not always
+     * be possible for the doclet to have access to j.b.ReadOnlyProperty,
+     * for this reason the strict check is disabled via an undocumented flag.
+     *
+     * Note, a method should not be considered as a property-method,
+     * if it satisfied the previously stated conditions AND if the
+     * method begins with "set", "get" or "is".
+     *
+     * Supposing we have  {@code BooleanProperty acmeProperty()}, then the
+     * property-name  is "acme".
+     *
+     * Property field, one may or may not exist and could be private, and
+     * should match the property-method.
+     *
+     * A property-setter is a method starting with "set", and the
+     * first character of the upper-cased starting character of the property name, the
+     * method must take 1 argument and must return a <code>void</code>.
+     *
+     * Using the above example {@code void setAcme(Something s)} can be
+     * considered as a property-setter of the property "acme".
+     *
+     * A property-getter is a method  starting with "get" and the first character
+     * upper-cased property-name, having no parameters. A method that does not take any
+     * parameters and starting with "is" and an upper-cased property-name,
+     * returning a primitive type boolean or BooleanProperty can also be
+     * considered as a getter, however there must be only one getter for every property.
+     *
+     * For example {@code Object getAcme()} is a property-getter, and
+     * {@code boolean isFoo()}
+     */
+    private void computeVisibleProperties(LocalMemberTable lmt) {
+        if (!config.javafx)
+            return;
+
+        PropertyUtils pUtils = config.propertyUtils;
+        List<ExecutableElement> list = visibleMembers.getOrDefault(Kind.METHODS, Collections.emptyList())
+                .stream()
+                .map(m -> (ExecutableElement)m)
+                .filter(pUtils::isPropertyMethod)
+                .collect(Collectors.toList());
+
+        visibleMembers.put(Kind.PROPERTIES, Collections.unmodifiableList(list));
+
+        List<ExecutableElement> propertyMethods = list.stream()
+                .filter(e -> utils.getEnclosingTypeElement(e) == te)
+                .collect(Collectors.toList());
+
+        // Compute additional properties related sundries.
+        for (ExecutableElement propertyMethod : propertyMethods) {
+            String baseName = pUtils.getBaseName(propertyMethod);
+            List<Element> flist = lmt.getMembers(baseName, Kind.FIELDS);
+            Element field = flist.isEmpty() ? null : flist.get(0);
+
+            Element getter = null, setter = null;
+            List<Element> found = lmt.getPropertyMethods(pUtils.getGetName(propertyMethod), 0);
+            if (!found.isEmpty()) {
+                // Getters have zero params, no overloads! pick the first.
+                getter = found.get(0);
+            }
+            if (getter == null) {
+                // Check if isProperty methods are present ?
+                found = lmt.getPropertyMethods(pUtils.getIsName(propertyMethod), 0);
+                if (!found.isEmpty()) {
+                    String propertyTypeName = propertyMethod.getReturnType().toString();
+                    // Check if the return type of property method matches an isProperty method.
+                    if (pUtils.hasIsMethod(propertyMethod)) {
+                        // Getters have zero params, no overloads!, pick the first.
+                        getter = found.get(0);
+                    }
+                }
+            }
+            found = lmt.getPropertyMethods(pUtils.getSetName(propertyMethod), 1);
+            if (found != null) {
+                for (Element e : found) {
+                    if (pUtils.isValidSetterMethod((ExecutableElement)e)) {
+                        setter = e;
+                        break;
+                    }
+                }
+            }
+
+            propertyMap.put(propertyMethod, new PropertyMembers((VariableElement)field,
+                    (ExecutableElement)getter, (ExecutableElement)setter));
+
+            // Debugging purposes
+            // System.out.println("te: " + te + ": " + utils.getEnclosingTypeElement(propertyMethod) +
+            //        ":" + propertyMethod.toString() + "->" + propertyMap.get(propertyMethod));
+        }
+    }
+
+
+    // Future cleanups
+
+    Map<ExecutableElement, SoftReference<ImplementedMethods>> implementMethodsFinders = new HashMap<>();
+
+    private ImplementedMethods getImplementedMethodsFinder(ExecutableElement method) {
+        SoftReference<ImplementedMethods> imf = implementMethodsFinders.get(method);
+        // IMF does not exist or referent was gc'ed away ?
+        if (imf == null || imf.get() == null) {
+            imf = new SoftReference<>(new ImplementedMethods(method));
+            implementMethodsFinders.put(method, imf);
+        }
+        return imf.get();
+    }
+
+    public List<ExecutableElement> getImplementedMethods(ExecutableElement method) {
+        ImplementedMethods imf = getImplementedMethodsFinder(method);
+        return imf.getImplementedMethods().stream()
+                .filter(m -> getsimplyOverriddenMethod(m) == null)
+                .collect(Collectors.toList());
+    }
+
+    public TypeMirror getImplementedMethodHolder(ExecutableElement method,
+                                                 ExecutableElement implementedMethod) {
+        ImplementedMethods imf = getImplementedMethodsFinder(method);
+        return imf.getMethodHolder(implementedMethod);
+    }
+
+    private class ImplementedMethods {
+
+        private final Map<ExecutableElement, TypeMirror> interfaces = new HashMap<>();
+        private final List<ExecutableElement> methlist = new ArrayList<>();
+        private final TypeElement typeElement;
+        private final ExecutableElement method;
+
+        public ImplementedMethods(ExecutableElement method) {
+            this.method = method;
+            typeElement = utils.getEnclosingTypeElement(method);
+            Set<TypeMirror> intfacs = utils.getAllInterfaces(typeElement);
+            /*
+             * Search for the method in the list of interfaces. If found check if it is
+             * overridden by any other subinterface method which this class
+             * implements. If it is not overidden, add it in the method list.
+             * Do this recursively for all the extended interfaces for each interface
+             * from the list.
+             */
+            for (TypeMirror interfaceType : intfacs) {
+                ExecutableElement found = utils.findMethod(utils.asTypeElement(interfaceType), method);
+                if (found != null) {
+                    removeOverriddenMethod(found);
+                    if (!overridingMethodFound(found)) {
+                        methlist.add(found);
+                        interfaces.put(found, interfaceType);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Return the list of interface methods which the method passed in the
+         * constructor is implementing. The search/build order is as follows:
+         * <pre>
+         * 1. Search in all the immediate interfaces which this method's class is
+         *    implementing. Do it recursively for the superinterfaces as well.
+         * 2. Traverse all the superclasses and search recursively in the
+         *    interfaces which those superclasses implement.
+         *</pre>
+         *
+         * @return SortedSet<ExecutableElement> of implemented methods.
+         */
+        List<ExecutableElement> getImplementedMethods() {
+            return methlist;
+        }
+
+        TypeMirror getMethodHolder(ExecutableElement ee) {
+            return interfaces.get(ee);
+        }
+
+        /**
+         * Search in the method list and check if it contains a method which
+         * is overridden by the method as parameter.  If found, remove the
+         * overridden method from the method list.
+         *
+         * @param method Is this method overriding a method in the method list.
+         */
+        private void removeOverriddenMethod(ExecutableElement method) {
+            TypeElement overriddenClass = utils.overriddenClass(method);
+            if (overriddenClass != null) {
+                for (int i = 0; i < methlist.size(); i++) {
+                    TypeElement te = utils.getEnclosingTypeElement(methlist.get(i));
+                    if (te == overriddenClass || utils.isSubclassOf(overriddenClass, te)) {
+                        methlist.remove(i);  // remove overridden method
+                        return;
+                    }
+                }
+            }
+        }
+
+        /**
+         * Search in the already found methods' list and check if it contains
+         * a method which is overriding the method parameter or is the method
+         * parameter itself.
+         *
+         * @param method method to be searched
+         */
+        private boolean overridingMethodFound(ExecutableElement method) {
+            TypeElement containingClass = utils.getEnclosingTypeElement(method);
+            for (ExecutableElement listmethod : methlist) {
+                if (containingClass == utils.getEnclosingTypeElement(listmethod)) {
+                    // it's the same method.
+                    return true;
+                }
+                TypeElement te = utils.overriddenClass(listmethod);
+                if (te == null) {
+                    continue;
+                }
+                if (te == containingClass || utils.isSubclassOf(te, containingClass)) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    /**
+     * A simple container to encapsulate an overriding method
+     * and the type of override.
+     */
+    static class OverridingMethodInfo {
+        final ExecutableElement overrider;
+        final boolean simpleOverride;
+
+        public OverridingMethodInfo(ExecutableElement overrider, boolean simpleOverride) {
+            this.overrider = overrider;
+            this.simpleOverride = simpleOverride;
+        }
+    }
+}
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ColumnFormat.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ColumnFormat.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -41,6 +41,7 @@
     private String format;
     private String header;
     private Expression expression;
+    private boolean required = false;
     private Object previousValue;
 
     public ColumnFormat(int number) {
@@ -71,6 +72,9 @@
             // the raw data.
             format="0";
         }
+
+        // Adjust required flag
+        expression.setRequired(required);
     }
 
     public void setWidth(int width) {
@@ -121,6 +125,14 @@
         this.expression = e;
     }
 
+    public void setRequired(boolean r) {
+        this.required = r;
+    }
+
+    public boolean isRequired() {
+        return this.required;
+    }
+
     public void setPreviousValue(Object o) {
         this.previousValue = o;
     }
@@ -141,7 +153,8 @@
         System.out.println(indent + indentAmount + "name=" + name
                 + ";data=" + expression.toString() + ";header=" + header
                 + ";format=" + format + ";width=" + width
-                + ";scale=" + scale.toString() + ";align=" + align.toString());
+                + ";scale=" + scale.toString() + ";align=" + align.toString()
+                + ";required=" + required);
 
         for (Iterator<OptionFormat> i = children.iterator();  i.hasNext(); /* empty */) {
             OptionFormat of = i.next();
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/Expression.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/Expression.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -40,6 +40,7 @@
     private Expression right;
     private Operator operator;
     private int ordinal = nextOrdinal++;
+    private boolean required = false;
 
     Expression() {
         if (debug) {
@@ -52,6 +53,7 @@
             System.out.println("Setting left on " + ordinal + " to " + left);
         }
         this.left = left;
+        this.left.setRequired(required);
     }
 
     Expression getLeft() {
@@ -63,6 +65,7 @@
             System.out.println("Setting right on " + ordinal + " to " + right);
         }
         this.right = right;
+        this.right.setRequired(required);
     }
 
     Expression getRight() {
@@ -80,6 +83,20 @@
         return operator;
     }
 
+    void setRequired(boolean r) {
+        this.required = r;
+        if (left != null) {
+            left.setRequired(required);
+        }
+        if (right != null) {
+            right.setRequired(required);
+        }
+    }
+
+    boolean isRequired() {
+        return required;
+    }
+
     public String toString() {
         StringBuilder b = new StringBuilder();
         b.append('(');
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/ExpressionResolver.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
                     System.err.println("Warning: Unresolved Symbol: "
                                        + id.getName() + " substituted NaN");
                 }
-                return new Literal(Double.valueOf(Double.NaN));
+                return new Literal(e.isRequired() ? 0.0d : Double.NaN);
             }
             if (m.getVariability() == Variability.CONSTANT) {
                 if (debug) {
@@ -131,7 +131,9 @@
                                        + " (right = " + rn.doubleValue() + ")"
                                        + " to literal value " + result);
                 }
-                return new Literal(Double.valueOf(result));
+                var literal = new Literal(result);
+                literal.setRequired(e.isRequired());
+                return literal;
             }
         }
 
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/Parser.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -60,13 +60,15 @@
     private static final String FORMAT = "format";
     private static final String ALIGN = "align";
     private static final String SCALE = "scale";
+    private static final String REQUIRED = "required";
 
     private static final String START = OPTION;
 
     private static final Set<String> scaleKeyWords = Scale.keySet();
     private static final Set<String> alignKeyWords = Alignment.keySet();
+    private static final Set<String> boolKeyWords = Set.of("true", "false");
     private static String[] otherKeyWords = {
-        OPTION, COLUMN, DATA, HEADER, WIDTH, FORMAT, ALIGN, SCALE
+        OPTION, COLUMN, DATA, HEADER, WIDTH, FORMAT, ALIGN, SCALE, REQUIRED
     };
 
     private static char[] infixOps = {
@@ -445,6 +447,16 @@
     }
 
     /**
+     * requiredstmt -> 'required' expression
+     */
+    private void requiredStmt(ColumnFormat cf) throws ParserException, IOException {
+        match(REQUIRED);
+        Token t = matchOne(boolKeyWords);
+        cf.setRequired(Boolean.parseBoolean(t.sval));
+        log(pdebug, "Parsed: required -> " + cf.isRequired());
+    }
+
+    /**
      * statementlist -> optionalstmt statementlist
      * optionalstmt -> 'data' expression
      *                 'header' quotedstring
@@ -452,6 +464,7 @@
      *                 'format' formatstring
      *                 'align' alignspec
      *                 'scale' scalespec
+     *                 'required' boolean
      */
     private void statementList(ColumnFormat cf)
                  throws ParserException, IOException {
@@ -472,6 +485,8 @@
                 alignStmt(cf);
             } else if (lookahead.sval.compareTo(SCALE) == 0) {
                 scaleStmt(cf);
+            } else if (lookahead.sval.compareTo(REQUIRED) == 0) {
+                requiredStmt(cf);
             } else {
                 return;
             }
--- a/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jcmd/share/classes/sun/tools/jstat/resources/jstat_options	Thu Apr 26 17:59:02 2018 +0200
@@ -277,6 +277,7 @@
     width 8
     scale sec
     format "0.000"
+    required true
   }
 }
 
@@ -537,6 +538,7 @@
     width 8
     scale sec
     format "0.000"
+    required true
   }
   column {
     header "^LGCC"	/* Last GC Cause */
@@ -835,6 +837,7 @@
     width 8
     scale sec
     format "0.000"
+    required true
   }
 }
 
@@ -917,6 +920,7 @@
     width 8
     scale sec
     format "0.000"
+    required true
   }
 }
 
@@ -1015,6 +1019,7 @@
     width 8
     scale sec
     format "0.000"
+    required true
   }
 }
 
@@ -1121,6 +1126,7 @@
     width 8
     scale sec
     format "0.000"
+    required true
   }
 }
 
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java	Thu Apr 26 17:59:02 2018 +0200
@@ -209,6 +209,7 @@
     static final EditorSetting BUILT_IN_EDITOR = new EditorSetting(null, false);
 
     private boolean debug = false;
+    private int debugFlags = 0;
     public boolean testPrompt = false;
     private Startup startup = null;
     private boolean isCurrentlyRunningStartup = false;
@@ -261,25 +262,28 @@
         MODULE_PATH("--module-path", true),
         ADD_MODULES("--add-modules", false),
         ADD_EXPORTS("--add-exports", false),
-        TO_COMPILER("-C", false, false, true, false),
-        TO_REMOTE_VM("-R", false, false, false, true),;
+        ENABLE_PREVIEW("--enable-preview", true),
+        SOURCE_RELEASE("-source", true, true, true, false, false),  // virtual option, generated by --enable-preview
+        TO_COMPILER("-C", false, false, true, false, false),
+        TO_REMOTE_VM("-R", false, false, false, true, false),;
         final String optionFlag;
         final boolean onlyOne;
         final boolean passFlag;
         final boolean toCompiler;
         final boolean toRemoteVm;
+        final boolean showOption;
 
         private OptionKind(String optionFlag, boolean onlyOne) {
-            this(optionFlag, onlyOne, true, true, true);
+            this(optionFlag, onlyOne, true, true, true, true);
         }
 
-        private OptionKind(String optionFlag, boolean onlyOne, boolean passFlag,
-                boolean toCompiler, boolean toRemoteVm) {
+        private OptionKind(String optionFlag, boolean onlyOne, boolean passFlag, boolean toCompiler, boolean toRemoteVm, boolean showOption) {
             this.optionFlag = optionFlag;
             this.onlyOne = onlyOne;
             this.passFlag = passFlag;
             this.toCompiler = toCompiler;
             this.toRemoteVm = toRemoteVm;
+            this.showOption= showOption;
         }
 
     }
@@ -314,8 +318,8 @@
             return selectOptions(e -> e.getKey().toCompiler);
         }
 
-        String[] commonOptions() {
-            return selectOptions(e -> e.getKey().passFlag);
+        String[] shownOptions() {
+            return selectOptions(e -> e.getKey().showOption);
         }
 
         void addAll(OptionKind kind, Collection<String> vals) {
@@ -348,6 +352,7 @@
         private final OptionSpec<String> argModulePath = parser.accepts("module-path").withRequiredArg();
         private final OptionSpec<String> argAddModules = parser.accepts("add-modules").withRequiredArg();
         private final OptionSpec<String> argAddExports = parser.accepts("add-exports").withRequiredArg();
+        private final OptionSpecBuilder  argEnablePreview = parser.accepts("enable-preview");
         private final NonOptionArgumentSpec<String> argNonOptions = parser.nonOptions();
 
         private Options opts = new Options();
@@ -449,6 +454,13 @@
                     .map(mp -> mp.contains("=") ? mp : mp + "=ALL-UNNAMED")
                     .collect(toList())
             );
+            if (options.has(argEnablePreview)) {
+                opts.addAll(OptionKind.ENABLE_PREVIEW, List.of(
+                        OptionKind.ENABLE_PREVIEW.optionFlag));
+                opts.addAll(OptionKind.SOURCE_RELEASE, List.of(
+                        OptionKind.SOURCE_RELEASE.optionFlag,
+                        System.getProperty("java.specification.version")));
+            }
 
             if (failed) {
                 exitCode = 1;
@@ -1062,6 +1074,7 @@
             builder.executionEngine(executionControlSpec);
         }
         state = builder.build();
+        InternalDebugControl.setDebugFlags(state, debugFlags);
         shutdownSubscription = state.onShutdown((JShell deadState) -> {
             if (deadState == state) {
                 hardmsg("jshell.msg.terminated");
@@ -2234,11 +2247,10 @@
             InternalDebugControl.setDebugFlags(state, debug ? DBG_GEN : 0);
             fluff("Debugging %s", debug ? "on" : "off");
         } else {
-            int flags = 0;
             for (char ch : arg.toCharArray()) {
                 switch (ch) {
                     case '0':
-                        flags = 0;
+                        debugFlags = 0;
                         debug = false;
                         fluff("Debugging off");
                         break;
@@ -2247,36 +2259,41 @@
                         fluff("REPL tool debugging on");
                         break;
                     case 'g':
-                        flags |= DBG_GEN;
+                        debugFlags |= DBG_GEN;
                         fluff("General debugging on");
                         break;
                     case 'f':
-                        flags |= DBG_FMGR;
+                        debugFlags |= DBG_FMGR;
                         fluff("File manager debugging on");
                         break;
                     case 'c':
-                        flags |= DBG_COMPA;
+                        debugFlags |= DBG_COMPA;
                         fluff("Completion analysis debugging on");
                         break;
                     case 'd':
-                        flags |= DBG_DEP;
+                        debugFlags |= DBG_DEP;
                         fluff("Dependency debugging on");
                         break;
                     case 'e':
-                        flags |= DBG_EVNT;
+                        debugFlags |= DBG_EVNT;
                         fluff("Event debugging on");
                         break;
                     case 'w':
-                        flags |= DBG_WRAP;
+                        debugFlags |= DBG_WRAP;
                         fluff("Wrap debugging on");
                         break;
+                    case 'b':
+                        cmdout.printf("RemoteVM Options: %s\nCompiler options: %s\n",
+                                Arrays.toString(options.remoteVmOptions()),
+                                Arrays.toString(options.compilerOptions()));
+                        break;
                     default:
                         error("Unknown debugging option: %c", ch);
-                        fluff("Use: 0 r g f c d e w");
+                        fluff("Use: 0 r g f c d e w b");
                         return false;
                 }
             }
-            InternalDebugControl.setDebugFlags(state, flags);
+            InternalDebugControl.setDebugFlags(state, debugFlags);
         }
         return true;
     }
@@ -3112,7 +3129,7 @@
         if (rawargs.trim().isEmpty()) {
             // No arguments, display current settings (as option flags)
             StringBuilder sb = new StringBuilder();
-            for (String a : options.commonOptions()) {
+            for (String a : options.shownOptions()) {
                 sb.append(
                         a.startsWith("-")
                             ? sb.length() > 0
--- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n.properties	Thu Apr 26 17:59:02 2018 +0200
@@ -205,6 +205,7 @@
 \    --add-modules <module>(,<module>)*\n\
 \                          Specify modules to resolve, or all modules on the\n\
 \                            module path if <module> is ALL-MODULE-PATHs\n\
+\    --enable-preview      Allow code to depend on preview features of this release\n\
 \    --startup <file>      One run replacement for the startup definitions\n\
 \    --no-startup          Do not run the startup definitions\n\
 \    --feedback <mode>     Specify the initial feedback mode. The mode may be\n\
--- a/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java	Thu Apr 26 17:59:02 2018 +0200
@@ -82,7 +82,6 @@
 import com.sun.tools.javac.comp.Resolve;
 import com.sun.tools.javac.parser.Parser;
 import com.sun.tools.javac.parser.ParserFactory;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
 import com.sun.tools.javac.tree.JCTree.JCExpression;
 import com.sun.tools.javac.tree.JCTree.JCTypeCast;
 import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
@@ -91,6 +90,7 @@
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Log.DiscardDiagnosticHandler;
 import com.sun.tools.javac.util.Names;
+import static jdk.internal.jshell.debug.InternalDebugControl.DBG_FMGR;
 import jdk.jshell.Snippet.Status;
 
 /**
@@ -202,6 +202,7 @@
                             .map(in -> sh.sourceToFileObject(fileManager, in))
                             .collect(Collectors.toList());
             DiagnosticCollector<JavaFileObject> diagnostics = new DiagnosticCollector<>();
+            state.debug(DBG_FMGR, "Task (%s %s) Options: %s\n", this, compilationUnits, allOptions);
             return javacTaskPool.getTask(null, fileManager, diagnostics, allOptions, null,
                                          compilationUnits, task -> {
                  JavacTaskImpl jti = (JavacTaskImpl) task;
--- a/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectorExtImpl.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectorExtImpl.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, 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
@@ -28,7 +28,6 @@
 import com.sun.management.GarbageCollectionNotificationInfo;
 import com.sun.management.GarbageCollectorMXBean;
 import com.sun.management.GcInfo;
-import java.lang.management.ManagementFactory;
 import java.lang.management.MemoryPoolMXBean;
 import java.util.List;
 import javax.management.ListenerNotFoundException;
@@ -38,6 +37,7 @@
 import javax.management.NotificationListener;
 import javax.management.openmbean.CompositeData;
 import sun.management.GarbageCollectorImpl;
+import sun.management.ManagementFactoryHelper;
 
 /**
  * Implementation class for the garbage collector.
@@ -59,12 +59,8 @@
     private String[] poolNames = null;
     private synchronized String[] getAllPoolNames() {
         if (poolNames == null) {
-            List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans();
-            poolNames = new String[pools.size()];
-            int i = 0;
-            for (MemoryPoolMXBean m : pools) {
-                poolNames[i++] = m.getName();
-            }
+            // The order of all memory pool names is important as GcInfo is also created with same order.
+            poolNames = ManagementFactoryHelper.getAllMemoryPoolNames();
         }
         return poolNames;
     }
--- a/src/jdk.pack/share/native/common-unpack/utils.h	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.pack/share/native/common-unpack/utils.h	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, 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
@@ -33,16 +33,16 @@
 #endif
 
 // overflow management
-#define OVERFLOW ((uint)-1)
-#define PSIZE_MAX (OVERFLOW/2)  /* normal size limit */
+#define POVERFLOW ((uint)-1)
+#define PSIZE_MAX (POVERFLOW/2)  /* normal size limit */
 
 inline size_t scale_size(size_t size, size_t scale) {
-  return (size > PSIZE_MAX / scale) ? OVERFLOW : size * scale;
+  return (size > PSIZE_MAX / scale) ? POVERFLOW : size * scale;
 }
 
 inline size_t add_size(size_t size1, size_t size2) {
   return ((size1 | size2 | (size1 + size2)) > PSIZE_MAX)
-    ? OVERFLOW
+    ? POVERFLOW
     : size1 + size2;
 }
 
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptObject.java	Thu Apr 26 17:59:02 2018 +0200
@@ -2969,7 +2969,7 @@
     }
 
     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final int callSiteFlags) {
-        if (getMap().containsArrayKeys()) {
+        if (hasDefinedArrayProperties()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
@@ -2981,7 +2981,7 @@
     }
 
     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final int callSiteFlags) {
-         if (getMap().containsArrayKeys()) {
+         if (hasDefinedArrayProperties()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
@@ -2993,7 +2993,7 @@
     }
 
     private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final int callSiteFlags) {
-        if (getMap().containsArrayKeys()) {
+        if (hasDefinedArrayProperties()) {
             final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
             if (find != null) {
@@ -3004,6 +3004,15 @@
         return false;
     }
 
+    private boolean hasDefinedArrayProperties() {
+        for (ScriptObject obj = this; obj != null; obj = obj.getProto()) {
+            if (obj.getMap().containsArrayKeys()) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     //value agnostic
     private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final int callSiteFlags) {
         if (longIndex >= oldLength) {
--- a/test/hotspot/gtest/memory/test_metaspace_allocation.cpp	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/gtest/memory/test_metaspace_allocation.cpp	Thu Apr 26 17:59:02 2018 +0200
@@ -26,6 +26,7 @@
 #include "memory/allocation.inline.hpp"
 #include "memory/metaspace.hpp"
 #include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
 #include "runtime/os.hpp"
 #include "utilities/align.hpp"
 #include "utilities/debug.hpp"
@@ -104,7 +105,12 @@
     // Let every ~10th space be an anonymous one to test different allocation patterns.
     const Metaspace::MetaspaceType msType = (os::random() % 100 < 10) ?
       Metaspace::AnonymousMetaspaceType : Metaspace::StandardMetaspaceType;
-    _spaces[i].space = new ClassLoaderMetaspace(_spaces[i].lock, msType);
+    {
+      // Pull lock during space creation, since this is what happens in the VM too
+      // (see ClassLoaderData::metaspace_non_null(), which we mimick here).
+      MutexLockerEx ml(_spaces[i].lock,  Mutex::_no_safepoint_check_flag);
+      _spaces[i].space = new ClassLoaderMetaspace(_spaces[i].lock, msType);
+    }
     _spaces[i].allocated = 0;
     ASSERT_TRUE(_spaces[i].space != NULL);
   }
@@ -171,6 +177,7 @@
             } else {
               size = os::random() % 64;
             }
+            // Note: In contrast to space creation, no need to lock here. ClassLoaderMetaspace::allocate() will lock itself.
             MetaWord* const p = _spaces[index].space->allocate(size, mdType);
             if (p == NULL) {
               // We very probably did hit the metaspace "until-gc" limit.
@@ -196,6 +203,7 @@
           force_switch = true;
         } else {
           assert(_spaces[index].space != NULL && _spaces[index].allocated > 0, "Sanity");
+          // Note: do not lock here. In the "wild" (the VM), we do not so either (see ~ClassLoaderData()).
           delete _spaces[index].space;
           _spaces[index].space = NULL;
           _spaces[index].allocated = 0;
--- a/test/hotspot/jtreg/ProblemList-graal.txt	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/ProblemList-graal.txt	Thu Apr 26 17:59:02 2018 +0200
@@ -73,3 +73,14 @@
 compiler/compilercontrol/directives/LogTest.java                8181753   generic-all
 
 gc/g1/ihop/TestIHOPStatic.java                                  8199486   generic-all
+
+compiler/jvmci/compilerToVM/ReprofileTest.java                  8201333   generic-all
+
+compiler/tiered/TieredLevelsTest.java                           8202124   generic-all
+compiler/tiered/NonTieredLevelsTest.java                        8202124   generic-all
+compiler/intrinsics/mathexact/sanity/SubtractExactLongTest.java 8202124   generic-all
+
+compiler/jvmci/meta/StableFieldTest.java                        CODETOOLS-7902162   generic-all
+compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/HotSpotConstantReflectionProviderTest.java   CODETOOLS-7902162   generic-all
+compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/MemoryAccessProviderTest.java                CODETOOLS-7902162   generic-all
+compiler/jvmci/events/JvmciShutdownEventTest.java               CODETOOLS-7902162   generic-all
--- a/test/hotspot/jtreg/ProblemList.txt	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/ProblemList.txt	Thu Apr 26 17:59:02 2018 +0200
@@ -80,11 +80,6 @@
 
 serviceability/sa/TestRevPtrsForInvokeDynamic.java   8191270 generic-all
 serviceability/sa/sadebugd/SADebugDTest.java         8163805 generic-all
-serviceability/tmtools/jstat/GcTest01.java           8199519 generic-all
-serviceability/tmtools/jstat/GcTest02.java           8199519 generic-all
-serviceability/tmtools/jstat/GcCauseTest01.java      8199519 generic-all
-serviceability/tmtools/jstat/GcCauseTest02.java      8199519 generic-all
-serviceability/tmtools/jstat/GcCauseTest03.java      8199519 generic-all
 
 #############################################################################
 
@@ -97,12 +92,5 @@
 # Java EE Module Removal
 #
 
-runtime/appcds/jigsaw/classpathtests/ClassPathTests.java                       8194310    generic-all  Java EE Module Removal
-runtime/appcds/jigsaw/overridetests/OverrideTests.java                         8194310    generic-all  Java EE Module Removal
-runtime/SharedArchiveFile/BootAppendTests.java                                 8194310    generic-all  Java EE Module Removal
-runtime/modules/PatchModule/PatchModuleClassList.java                          8194310    generic-all  Java EE Module Removal
 compiler/c2/Test8007294.java                                                   8194310    generic-all  Java EE Module Removal
 compiler/c2/Test6852078.java                                                   8194310    generic-all  Java EE Module Removal
-runtime/AppCDS/HelloExtTest.java                                               8194310    generic-all  Java EE Module Removal
-runtime/AppCDS/javaldr/CheckAnonymousClass.java                                8194310    generic-all  Java EE Module Removal
-runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java          8194310    generic-all  Java EE Module Removal
--- a/test/hotspot/jtreg/TEST.groups	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/TEST.groups	Thu Apr 26 17:59:02 2018 +0200
@@ -145,7 +145,9 @@
 
 ctw_2 = \
   applications/ctw/modules/java_base.java \
-  applications/ctw/modules/java_desktop.java
+  applications/ctw/modules/java_base_2.java \
+  applications/ctw/modules/java_desktop.java \
+  applications/ctw/modules/java_desktop_2.java
 
 ctw_3 = \
   applications/ctw/modules/javafx_graphics.java \
--- a/test/hotspot/jtreg/applications/ctw/modules/java_base.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_base.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @summary run CTW for all classes from java.base module
+ * @summary run CTW for some classes from java.base module
  *
  * @library /test/lib / /testlibrary/ctw/src
  * @modules java.base/jdk.internal.jimage
@@ -34,5 +34,5 @@
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base 0% 50%
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_base_2.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for some classes from java.base module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ *          java.base/jdk.internal.misc
+ *          java.base/jdk.internal.reflect
+ * @modules java.base
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                                sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.base 50% 100%
+ */
--- a/test/hotspot/jtreg/applications/ctw/modules/java_desktop.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_desktop.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @summary run CTW for all classes from java.desktop module
+ * @summary run CTW for some classes from java.desktop module
  *
  * @library /test/lib / /testlibrary/ctw/src
  * @modules java.base/jdk.internal.jimage
@@ -34,5 +34,5 @@
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop 0% 50%
  */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/applications/ctw/modules/java_desktop_2.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @summary run CTW for some classes from java.desktop module
+ *
+ * @library /test/lib / /testlibrary/ctw/src
+ * @modules java.base/jdk.internal.jimage
+ *          java.base/jdk.internal.misc
+ *          java.base/jdk.internal.reflect
+ * @modules java.desktop
+ *
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *                                sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/timeout=7200 sun.hotspot.tools.ctw.CtwRunner modules:java.desktop 50% 100%
+ */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/compiler/uncommontrap/FoldedIfNonDomMidIf.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * @test
+ * @bug 8201368
+ * @summary IfNode::fold_compares() may lead to incorrect execution
+ *
+ * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation FoldedIfNonDomMidIf
+ *
+ */
+
+public class FoldedIfNonDomMidIf {
+    public static void main(String[] args) {
+        for (int i = 0; i < 20_000; i++) {
+            test_helper(0, 0);
+            test_helper(20, 0);
+            test(12);
+        }
+        if (test(14) != null) {
+            throw new RuntimeException("Incorrect code execution");
+        }
+    }
+
+    private static Object test(int i) {
+        return test_helper(i, 0x42);
+    }
+
+    static class A {
+
+    }
+
+    static final MyException myex = new MyException();
+
+    private static Object test_helper(int i, int j) {
+        Object res = null;
+        try {
+            if (i < 10) {
+                throw myex;
+            }
+
+            if (i == 14) {
+
+            }
+
+            if (i > 15) {
+                throw myex;
+            }
+        } catch (MyException e) {
+            if (j == 0x42) {
+                res = new A();
+            }
+        }
+        return res;
+    }
+
+    private static class MyException extends Exception {
+    }
+}
--- a/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/CDSCompressedKPtrs/XShareAuto.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,7 +25,7 @@
  * @test
  * @requires vm.cds
  * @bug 8005933
- * @summary Test that -Xshare:auto uses CDS when explicitly specified with -server.
+ * @summary -Xshare:auto is the default when -Xshare is not specified
  * @library /test/lib
  * @modules java.base/jdk.internal.misc
  *          java.management
@@ -45,34 +45,30 @@
         output.shouldContain("Loading classes to share");
         output.shouldHaveExitValue(0);
 
-        pb = ProcessTools.createJavaProcessBuilder(
-            "-server", "-XX:+UnlockDiagnosticVMOptions",
-            "-XX:SharedArchiveFile=./XShareAuto.jsa", "-version");
-        output = new OutputAnalyzer(pb.start());
-        String outputString = output.getOutput();
-        // We asked for server but it could be aliased to something else
-        if (outputString.contains("Server VM") && !outputString.contains("emulated-client")) {
-            // In server case we don't expect to see sharing flag
-            output.shouldNotContain("sharing");
+
+        // We have 2 test cases:
+        String cases[] = {
+            "-Xshare:auto",    // case [1]: -Xshare:auto is explicitly specified.
+            "-showversion"     // case [2]: -Xshare:auto is not explicitly specified,
+                               //           but VM should still use it by default.
+        };
+
+        for (String x : cases) {
+            pb = ProcessTools.createJavaProcessBuilder(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=./XShareAuto.jsa",
+                "-Xlog:cds",
+                x,
+                "-version");
+            output = new OutputAnalyzer(pb.start());
+            String outputString = output.getOutput();
+
+            if (!outputString.contains("Unable to map")) {
+                // sharing may not be enabled if XShareAuto.jsa cannot be mapped due to
+                // ASLR.
+                output.shouldContain("sharing");
+            }
             output.shouldHaveExitValue(0);
         }
-        else {
-            System.out.println("Skipping test - no Server VM available");
-            return;
-        }
-
-        pb = ProcessTools.createJavaProcessBuilder(
-            "-server", "-Xshare:auto", "-XX:+UnlockDiagnosticVMOptions",
-            "-XX:SharedArchiveFile=./XShareAuto.jsa", "-Xlog:cds", "-version");
-        output = new OutputAnalyzer(pb.start());
-        try {
-            output.shouldContain("sharing");
-        } catch (RuntimeException e) {
-            // if sharing failed due to ASLR or similar reasons,
-            // check whether sharing was attempted at all (UseSharedSpaces)
-            output.shouldContain("UseSharedSpaces:");
-            output.shouldNotContain("Unable to map %s");
-        }
-        output.shouldHaveExitValue(0);
     }
 }
--- a/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/CompressedOops/CompressedClassPointers.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -42,6 +42,8 @@
             "-XX:SharedBaseAddress=8g",
             "-Xmx128m",
             "-Xlog:gc+metaspace=trace",
+            "-Xshare:off",
+            "-Xlog:cds=trace",
             "-XX:+VerifyBeforeGC", "-version");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldContain("Narrow klass base: 0x0000000000000000");
@@ -54,6 +56,8 @@
             "-XX:CompressedClassSpaceSize=3g",
             "-Xmx128m",
             "-Xlog:gc+metaspace=trace",
+            "-Xshare:off",
+            "-Xlog:cds=trace",
             "-XX:+VerifyBeforeGC", "-version");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldContain("Narrow klass base: 0x0000000000000000, Narrow klass shift: 3");
@@ -66,6 +70,8 @@
             "-Xmx30g",
             "-XX:-UseAOT", // AOT explicitly set klass shift to 3.
             "-Xlog:gc+metaspace=trace",
+            "-Xshare:off",
+            "-Xlog:cds=trace",
             "-XX:+VerifyBeforeGC", "-version");
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
         output.shouldNotContain("Narrow klass base: 0x0000000000000000");
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/BootAppendTests.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -27,11 +27,12 @@
  * @summary Testing -Xbootclasspath/a support for CDS
  * @requires vm.cds
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ *          java.base/jdk.internal.misc
  *          java.management
  *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @compile javax/sound/sampled/MyClass.jasm
- * @compile org/omg/CORBA/Context.jasm
+ * @compile javax/annotation/processing/FilerException.jasm
  * @compile nonjdk/myPackage/MyClass.java
  * @build LoadClass
  * @run main/othervm BootAppendTests
@@ -53,7 +54,8 @@
 public class BootAppendTests {
     private static final String APP_CLASS = "LoadClass";
     private static final String BOOT_APPEND_MODULE_CLASS = "javax/sound/sampled/MyClass";
-    private static final String BOOT_APPEND_DUPLICATE_MODULE_CLASS = "org/omg/CORBA/Context";
+    private static final String BOOT_APPEND_DUPLICATE_MODULE_CLASS =
+        "javax/annotation/processing/FilerException";
     private static final String BOOT_APPEND_CLASS = "nonjdk/myPackage/MyClass";
     private static final String BOOT_APPEND_MODULE_CLASS_NAME =
         BOOT_APPEND_MODULE_CLASS.replace('/', '.');
@@ -141,21 +143,21 @@
     //          from -Xbootclasspath/a. Verify the behavior is the same at runtime
     //          when CDS is enabled.
     //
-    //          The org.omg.CORBA.Context is a boot module class. The class on
-    //          the -Xbootclasspath/a path that has the same fully-qualified name
-    //          should not be loaded at runtime when CDS is enabled.
-    //          The one from the boot modules should be loaded instead.
+    //          The javax/annotation/processing/FilerException is a platform module
+    //          class. The class on the -Xbootclasspath/a path that has the same
+    //          fully-qualified name should not be loaded at runtime when CDS is enabled.
+    //          The one from the platform modules should be loaded instead.
     public static void testBootAppendDuplicateModuleClass() throws Exception {
         for (String mode : modes) {
             CDSOptions opts = (new CDSOptions())
                 .setXShareMode(mode).setUseVersion(false)
-                .addPrefix("--add-modules", "java.corba", "-showversion",
+                .addPrefix("-showversion",
                            "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar)
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
 
             OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
-            CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context source: jrt:/java.corba");
+            CDSTestUtils.checkExec(out, opts, "[class,load] javax.annotation.processing.FilerException source: jrt:/java.compiler");
         }
     }
 
@@ -164,9 +166,9 @@
     //          using --limit-modules. Verify the behavior is the same at runtime when CDS
     //          is enabled.
     //
-    //          The java.desktop module is excluded using --limit-modules at runtime,
-    //          javax.sound.sampled.MyClass is archived from -Xbootclasspath/a. It can be
-    //          loaded from the archive at runtime.
+    //          The java.desktop module is excluded using --limit-modules at runtime
+    //          CDS will be disabled with the --limit-modules option during runtime.
+    //          javax.sound.sampled.MyClass will be loaded from the jar at runtime.
     public static void testBootAppendExcludedModuleClass() throws Exception {
         for (String mode : modes) {
             CDSOptions opts = (new CDSOptions())
@@ -175,13 +177,18 @@
                            "--limit-modules=java.base", "-cp", appJar)
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_MODULE_CLASS_NAME);
-
-            OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
-            CDSTestUtils.checkExec(out, opts, "[class,load] javax.sound.sampled.MyClass");
-
-            // When CDS is enabled, the shared class should be loaded from the archive.
+            CDSTestUtils.Result res = CDSTestUtils.run(opts);
+            String MATCH_PATTERN =
+                ".class.load. javax.sound.sampled.MyClass source:.*bootAppend.jar*";
             if (mode.equals("on")) {
-                CDSTestUtils.checkExec(out, opts, "[class,load] javax.sound.sampled.MyClass source: shared objects file");
+                res.assertSilentlyDisabledCDS(out -> {
+                    out.shouldHaveExitValue(0)
+                       .shouldMatch(MATCH_PATTERN);
+                    });
+            } else {
+                res.assertNormalExit(out -> {
+                    out.shouldMatch(MATCH_PATTERN);
+                    });
             }
         }
     }
@@ -192,10 +199,12 @@
     //          --limit-modules. Verify the behavior is the same at runtime
     //          when CDS is enabled.
     //
-    //          The org.omg.CORBA.Context is a boot module class. The class
-    //          on -Xbootclasspath/a that has the same fully-qualified name
-    //          as org.omg.CORBA.Context can be loaded at runtime when
-    //          java.corba is excluded.
+    //          The javax.annotation.processing.FilerException is a platform module class.
+    //          The class on -Xbootclasspath/a that has the same fully-qualified name
+    //          as javax.annotation.processing.FilerException can be loaded at runtime when
+    //          java.compiler is excluded.
+    //          CDS is disabled during runtime if the --limit-modules option is
+    //          specified.
     public static void testBootAppendDuplicateExcludedModuleClass() throws Exception {
         for (String mode : modes) {
             CDSOptions opts = (new CDSOptions())
@@ -205,14 +214,18 @@
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
 
-            OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
-            CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context");
-            if (!CDSTestUtils.isUnableToMap(out)) {
-                if (mode.equals("off")) {
-                    out.shouldMatch(".*\\[class,load\\] org.omg.CORBA.Context source:.*bootAppend.jar");
-                } else {
-                    CDSTestUtils.checkExec(out, opts, "[class,load] org.omg.CORBA.Context source: shared objects file");
-                }
+            CDSTestUtils.Result res = CDSTestUtils.run(opts);
+            String MATCH_PATTERN =
+                ".class.load. javax.annotation.processing.FilerException source:.*bootAppend.jar*";
+            if (mode.equals("on")) {
+                res.assertSilentlyDisabledCDS(out -> {
+                    out.shouldHaveExitValue(0)
+                       .shouldMatch(MATCH_PATTERN);
+                    });
+            } else {
+                res.assertNormalExit(out -> {
+                    out.shouldMatch(MATCH_PATTERN);
+                    });
             }
         }
     }
@@ -222,8 +235,9 @@
     //          the same at runtime when CDS is enabled.
     //
     //          The nonjdk.myPackage is not defined in named modules. The
-    //          archived nonjdk.myPackage.MyClass from -Xbootclasspath/a
-    //          can be loaded at runtime when CDS is enabled.
+    //          nonjdk.myPackage.MyClass will be loaded from the jar in
+    //          -Xbootclasspath/a since CDS will be disabled with the
+    //          --limit-modules option.
     public static void testBootAppendClass() throws Exception {
         for (String mode : modes) {
             CDSOptions opts = (new CDSOptions())
@@ -233,21 +247,26 @@
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_CLASS_NAME);
 
-            OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
-            CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass");
-
-            // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded
-            // from the shared archive.
+            CDSTestUtils.Result res = CDSTestUtils.run(opts);
+            String MATCH_PATTERN =
+                ".class.load. nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
             if (mode.equals("on")) {
-                CDSTestUtils.checkExec(out, opts,
-                    "[class,load] nonjdk.myPackage.MyClass source: shared objects file");
+                res.assertSilentlyDisabledCDS(out -> {
+                    out.shouldHaveExitValue(0)
+                       .shouldMatch(MATCH_PATTERN);
+                    });
+            } else {
+                res.assertNormalExit(out -> {
+                    out.shouldMatch(MATCH_PATTERN);
+                    });
             }
         }
     }
 
     // Test #6: This is similar to Test #5. During runtime, an extra dir
     //          is appended to the bootclasspath. It should not invalidate
-    //          the shared archive.
+    //          the shared archive. However, CDS will be disabled with the
+    //          --limit-modules in the command line.
     public static void testBootAppendExtraDir() throws Exception {
         for (String mode : modes) {
             CDSOptions opts = (new CDSOptions())
@@ -257,14 +276,18 @@
                 .addSuffix("-Xlog:class+load=info",
                            APP_CLASS, BOOT_APPEND_CLASS_NAME);
 
-            OutputAnalyzer out = CDSTestUtils.runWithArchive(opts);
-            CDSTestUtils.checkExec(out, opts, "[class,load] nonjdk.myPackage.MyClass");
-
-            // If CDS is enabled, the nonjdk.myPackage.MyClass should be loaded
-            // from the shared archive.
+            CDSTestUtils.Result res = CDSTestUtils.run(opts);
+            String MATCH_PATTERN =
+                ".class.load. nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
             if (mode.equals("on")) {
-                CDSTestUtils.checkExec(out, opts,
-                    "[class,load] nonjdk.myPackage.MyClass source: shared objects file");
+                res.assertSilentlyDisabledCDS(out -> {
+                    out.shouldHaveExitValue(0)
+                       .shouldMatch(MATCH_PATTERN);
+                    });
+            } else {
+                res.assertNormalExit(out -> {
+                    out.shouldMatch(MATCH_PATTERN);
+                    });
             }
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/SharedArchiveFile/javax/annotation/processing/FilerException.jasm	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018, 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 javax/annotation/processing;
+
+public class FilerException
+    version 51:0
+{
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+    aload_0;
+    invokespecial   Method java/lang/Object."<init>":"()V";
+    return;
+}
+
+
+public Method toString:"()Ljava/lang/String;"
+    stack 1 locals 1
+{
+    ldc String "hi";
+    areturn; 
+}
+
+}
--- a/test/hotspot/jtreg/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +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/omg/CORBA;
-
-public class Context 
-    version 51:0
-{
-
-public Method "<init>":"()V"
-    stack 1 locals 1
-{
-    aload_0;
-    invokespecial   Method java/lang/Object."<init>":"()V";
-    return;
-}
-
-
-public Method toString:"()Ljava/lang/String;"
-    stack 1 locals 1
-{
-    ldc String "hi";
-    areturn; 
-}
-
-}
--- a/test/hotspot/jtreg/runtime/appcds/HelloExtTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/HelloExtTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -51,8 +51,8 @@
     String bootClassPath = "-Xbootclasspath/a:" + whiteBoxJar;
 
     TestCommon.dump(appJar,
-        TestCommon.list("org/omg/CORBA/ORB", "[Ljava/lang/Comparable;"),
-        bootClassPath, "-verbose:class", "--add-modules", "java.corba");
+        TestCommon.list("javax/annotation/processing/FilerException", "[Ljava/lang/Comparable;"),
+        bootClassPath, "-verbose:class");
 
     String prefix = ".class.load. ";
     String class_pattern = ".*LambdaForm[$]MH[/][0123456789].*";
@@ -60,14 +60,14 @@
     String pattern = prefix + class_pattern + suffix;
 
     TestCommon.run("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
-            "-cp", appJar, bootClassPath, "-verbose:class", "--add-modules", "java.corba", "HelloExt")
+            "-cp", appJar, bootClassPath, "-verbose:class", "HelloExt")
         .assertNormalExit(output -> output.shouldNotMatch(pattern));
 
 
     TestCommon.run("-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
             "-cp", appJar, bootClassPath, "-verbose:class",
             "-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary",
-            "--add-modules", "java.corba", "HelloExt")
+            "HelloExt")
         .assertNormalExit(output ->  output.shouldNotMatch(class_pattern));
   }
 }
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/AnonVmClassesDuringDump.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/javaldr/AnonVmClassesDuringDump.java	Thu Apr 26 17:59:02 2018 +0200
@@ -61,8 +61,22 @@
                             // Set the following property to see logs for dynamically generated classes
                             // in STDOUT
                             "-Djava.lang.invoke.MethodHandle.DUMP_CLASS_FILES=true");
+
+        String prefix = ".class.load. ";
+        // class name pattern like the following:
+        // jdk.internal.loader.BuiltinClassLoader$$Lambda$1/1816757085
+        // java.lang.invoke.LambdaForm$MH/1585787493
+        String class_pattern = ".*Lambda([a-z0-9$]+)/([0-9]+).*";
+        String suffix = ".*source: shared objects file.*";
+        String pattern = prefix + class_pattern + suffix;
+        // during run time, anonymous classes shouldn't be loaded from the archive
         TestCommon.run("-cp", appJar, "Hello")
-            .assertNormalExit();
+            .assertNormalExit(output -> output.shouldNotMatch(pattern));
+
+        // inspect the archive and make sure no anonymous class is in there
+        TestCommon.run("-cp", appJar,
+            "-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary", "Hello")
+            .assertNormalExit(output -> output.shouldNotMatch(class_pattern));
     }
 }
 
--- a/test/hotspot/jtreg/runtime/appcds/javaldr/CheckAnonymousClass.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, 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.
- *
- */
-
-/*
- * @test
- * @summary ensure no anonymous class is being dumped into the CDS archive
- * @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/appcds
- * @modules jdk.jartool/sun.tools.jar
- * @compile ../test-classes/Hello.java
- * @run main CheckAnonymousClass
- */
-
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class CheckAnonymousClass {
-
-  public static void main(String[] args) throws Exception {
-    JarBuilder.build("hello", "Hello");
-
-    String appJar = TestCommon.getTestJar("hello.jar");
-
-    TestCommon.dump(appJar, TestCommon.list("Hello", "org/omg/CORBA/ORB"),
-        "--add-modules", "java.corba", "-Xlog:class+load=info");
-
-    String prefix = ".class.load. ";
-    // class name pattern like the following:
-    // jdk.internal.loader.BuiltinClassLoader$$Lambda$1/1816757085
-    // java.lang.invoke.LambdaForm$MH/1585787493
-    String class_pattern = ".*Lambda([a-z0-9$]+)/([0-9]+).*";
-    String suffix = ".*source: shared objects file.*";
-    String pattern = prefix + class_pattern + suffix;
-    // during run time, anonymous classes shouldn't be loaded from the archive
-    TestCommon.run("-XX:+UnlockDiagnosticVMOptions",
-        "-cp", appJar, "-Xlog:class+load=info", "--add-modules", "java.corba", "Hello")
-      .assertNormalExit(output -> output.shouldNotMatch(pattern));
-
-    // inspect the archive and make sure no anonymous class is in there
-    TestCommon.run("-XX:+UnlockDiagnosticVMOptions",
-        "-cp", appJar, "-Xlog:class+load=info", "-XX:+PrintSharedArchiveAndExit",
-        "-XX:+PrintSharedDictionary", "--add-modules", "java.corba", "Hello")
-      .assertNormalExit(output -> output.shouldNotMatch(class_pattern));
-  }
-}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java	Thu Apr 26 17:59:02 2018 +0200
@@ -32,7 +32,7 @@
  *          jdk.jartool/sun.tools.jar
  *          jdk.internal.jvmstat/sun.jvmstat.monitor
  * @compile src/jdk/test/Main.java
- * @compile src/com/sun/tools/javac/Main2.jasm
+ * @compile src/com/sun/tools/javac/MyMain.jasm
  * @compile src/sun/nio/cs/ext/MyClass.java
  * @compile src/sun/nio/cs/ext1/MyClass.java
  * @run main BootAppendTests
@@ -52,7 +52,7 @@
     private static final Path CLASSES_DIR = Paths.get("classes");
 
     private static final String MAIN_CLASS = "jdk.test.Main";
-    private static final String APP_MODULE_CLASS = "com/sun/tools/javac/Main2";
+    private static final String APP_MODULE_CLASS = "com/sun/tools/javac/MyMain";
     private static final String BOOT_APPEND_MODULE_CLASS = "sun/nio/cs/ext/MyClass";
     private static final String BOOT_APPEND_CLASS = "sun/nio/cs/ext1/MyClass";
     private static final String[] ARCHIVE_CLASSES =
@@ -239,7 +239,7 @@
             MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT")
             .assertSilentlyDisabledCDS(out -> {
                 out.shouldHaveExitValue(0)
-                   .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+                   .shouldMatch(".class.load. com.sun.tools.javac.MyMain source:.*bootAppend.jar");
             });
     }
 
@@ -253,7 +253,7 @@
             MAIN_CLASS, "Test #10", APP_MODULE_CLASS, "true", "BOOT")
             .assertSilentlyDisabledCDS(out -> {
                 out.shouldHaveExitValue(0)
-                   .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+                   .shouldMatch(".class.load. com.sun.tools.javac.MyMain source:.*bootAppend.jar");
             });
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/ClassPathTests.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -27,12 +27,13 @@
  * @requires vm.cds & !vm.graal.enabled
  * @library ../..
  * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules jdk.jartool/sun.tools.jar
+ * @modules java.compiler
+ *          java.base/jdk.internal.misc
+ *          jdk.jartool/sun.tools.jar
  * @compile src/jdk/test/Main.java
  * @compile src/com/sun/tools/javac/Main.jasm
- * @compile src/com/sun/tools/javac/Main2.jasm
- * @compile src/javax/activation/UnsupportedDataTypeException2.jasm
+ * @compile src/com/sun/tools/javac/MyMain.jasm
+ * @compile ../../../SharedArchiveFile/javax/annotation/processing/FilerException.jasm
  * @run main ClassPathTests
  * @summary AppCDS tests for testing classpath/package conflicts
  */
@@ -73,8 +74,8 @@
 
     // test classes to archive. These are both in UPGRADED_MODULES
     private static final String JIMAGE_CLASS      = "com/sun/tools/javac/Main";
-    private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main2";
-    private static final String PLATFORM_ARCHIVE_CLASS = "javax/activation/UnsupportedDataTypeException2";
+    private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/MyMain";
+    private static final String PLATFORM_ARCHIVE_CLASS = "javax/annotation/processing/FilerException";
     private static final String[] ARCHIVE_CLASSES = {APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, JIMAGE_CLASS};
     private static final int NUMBER_OF_TEST_CASES = 10;
 
@@ -111,15 +112,17 @@
         // dump the archive with altnernate jdk.comiler and jdk.activation classes in the class list
         OutputAnalyzer output1  = TestCommon.dump(appJar, TestCommon.list(ARCHIVE_CLASSES));
         TestCommon.checkDump(output1);
-        // Only a class that belongs to a module which is not defined by default
-        // can be found. In this case the PLATFORM_ARCHIVE_CLASS belongs
-        // to the java.activation which is not defined by default; it is the only
-        // class can be found during dumping.
+        // The PLATFORM_ARCHIVE_CLASS belongs to the java.compiler
+        // module will be found from the module during dumping.
+        // The JIMAGE_CLASS will be found from the jdk.compiler module during
+        // dumping.
+        // The APP_ARCHIVE_CLASS, which belongs to a package within the
+        // jdk.compiler module, will not be found during dump time.
         for (String archiveClass : ARCHIVE_CLASSES) {
-            if (archiveClass.equals(PLATFORM_ARCHIVE_CLASS)) {
+            if (archiveClass.equals(APP_ARCHIVE_CLASS)) {
+                output1.shouldContain("Preload Warning: Cannot find " + archiveClass);
+            } else {
                 output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
-            } else {
-                output1.shouldContain("Preload Warning: Cannot find " + archiveClass);
             }
         }
 
@@ -146,82 +149,86 @@
         CDSTestUtils.runWithArchiveAndCheck(opts);
     }
 
-    // For tests #3 and #4, we need to "--add-modules java.activation" since the
-    // java.activation module won't be defined by default.
-
     // #3: Archived classpath class in same package as jimage ext class. With AppCDS.
-    // Should fail to load.
+    // The class should be loaded from the module.
     public void testExtClassWithAppCDS() throws Exception {
         OutputAnalyzer output = TestCommon.exec(
-            appJar, "--add-modules", "java.activation", MAIN_CLASS,
-            "Test #3", PLATFORM_ARCHIVE_CLASS, "false"); // last 3 args passed to test
+            appJar, MAIN_CLASS,
+            "Test #3", PLATFORM_ARCHIVE_CLASS, "true", "EXT"); // last 4 args passed to test
         TestCommon.checkExec(output);
     }
 
     // #4: Archived classpath class in same package as jimage ext class. Without AppCDS.
-    // Should fail to load.
+    // The class should be loaded from the module.
     public void testExtClassWithoutAppCDS() throws Exception {
         CDSOptions opts = (new CDSOptions())
-            .addPrefix("-cp", appJar, "--add-modules", "java.activation")
+            .addPrefix("-cp", appJar)
             .setArchiveName(testArchiveName)
-            .addSuffix(MAIN_CLASS, "Test #4", PLATFORM_ARCHIVE_CLASS, "false");
+            .addSuffix(MAIN_CLASS, "Test #4", PLATFORM_ARCHIVE_CLASS, "true", "EXT");
 
         CDSTestUtils.runWithArchiveAndCheck(opts);
     }
 
     // #5: Archived classpath class in same package as jimage app class. With AppCDS.
-    // Should load because --limit-modules is used.
+    // Should load with CDS disabled because --limit-modules is used.
     public void testAppClassWithLimitModsWithAppCDS() throws Exception {
-        OutputAnalyzer output = TestCommon.exec(
-            appJar,
-            "--limit-modules", "java.base",
-            MAIN_CLASS,
-            "Test #5", APP_ARCHIVE_CLASS, "true"); // last 3 args passed to test
-        TestCommon.checkExec(output);
+        TestCommon.run("-cp", appJar,
+                       "--limit-modules", "java.base",
+                       MAIN_CLASS,
+                       "Test #5", APP_ARCHIVE_CLASS, "true") // last 3 args passed to test
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0);
+            });
     }
 
     // #6: Archived classpath class in same package as jimage app class. Without AppCDS.
-    // Should load because --limit-modules is used.
+    // Should load with CDS disabled because --limit-modules is used.
     public void testAppClassWithLimitModsWithoutAppCDS() throws Exception {
         CDSOptions opts = (new CDSOptions())
             .addPrefix("-cp", appJar, "--limit-modules", "java.base")
             .setArchiveName(testArchiveName)
             .addSuffix(MAIN_CLASS, "Test #6", APP_ARCHIVE_CLASS, "true");
-
-        CDSTestUtils.runWithArchiveAndCheck(opts);
+        CDSTestUtils.run(opts)
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0);
+            });
     }
 
     // #7: Archived classpath class in same package as jimage ext class. With AppCDS.
-    // Should load because --limit-modules is used.
+    // Should load with CDS disabled because --limit-modules is used.
     public void testExtClassWithLimitModsWithAppCDS() throws Exception {
-        OutputAnalyzer output = TestCommon.exec(
-            appJar,
-            "--limit-modules", "java.base",
-            MAIN_CLASS,
-            "Test #7", PLATFORM_ARCHIVE_CLASS, "true"); // last 3 args passed to test
-        TestCommon.checkExec(output);
+        TestCommon.run("-cp", appJar,
+                       "--limit-modules", "java.base",
+                       MAIN_CLASS,
+                       "Test #7", PLATFORM_ARCHIVE_CLASS, "true") // last 3 args passed to test
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0);
+            });
     }
 
     // #8: Archived classpath class in same package as jimage ext class. Without AppCDS.
-    // Should load because --limit-modules is used.
+    // Should load with CDS disabled because --limit-modules is used.
     public void testExtClassWithLimitModsWithoutAppCDS() throws Exception {
         CDSOptions opts = (new CDSOptions())
             .addPrefix("-cp", appJar, "--limit-modules", "java.base")
             .setArchiveName(testArchiveName)
             .addSuffix(MAIN_CLASS, "Test #8", PLATFORM_ARCHIVE_CLASS, "true");
-
-        CDSTestUtils.runWithArchiveAndCheck(opts);
+        CDSTestUtils.run(opts)
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0);
+            });
     }
 
     // #9: Archived classpath class with same name as jimage app class. With AppCDS.
-    // Should load because --limit-modules is used.
+    // Should load with CDS disabled because --limit-modules is used.
     public void testReplacingJImageClassWithAppCDS() throws Exception {
-        OutputAnalyzer output = TestCommon.exec(
-            appJar,
-            "--limit-modules", "java.base", "-XX:+TraceClassLoading",
-            MAIN_CLASS,
-            "Test #9", JIMAGE_CLASS, "true"); // last 3 args passed to test
-        TestCommon.checkExec(output);
+        TestCommon.run("-cp", appJar,
+                       "--limit-modules", "java.base",
+                       MAIN_CLASS,
+                       "Test #9", JIMAGE_CLASS, "true") // last 3 args passed to test
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0);
+            });
     }
 
     // #10: Archived classpath class with same name as jimage app class. Without AppCDS.
@@ -233,8 +240,9 @@
             .addPrefix("-cp", appJar, "--limit-modules", "java.base")
             .setArchiveName(testArchiveName)
             .addSuffix(MAIN_CLASS, "Test #10", JIMAGE_CLASS, "true");
-
-        CDSTestUtils.runWithArchiveAndCheck(opts);
+        CDSTestUtils.run(opts)
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0);
+            });
     }
-
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/DummyClassesInBootClassPath.java	Thu Apr 26 17:59:02 2018 +0200
@@ -27,11 +27,11 @@
  * @summary Ensure that classes found in jimage takes precedence over classes found in -Xbootclasspath/a.
  * @requires vm.cds
  * @library /test/lib /test/hotspot/jtreg/runtime/appcds
- * @modules java.activation
+ * @modules java.compiler
  *          jdk.jartool/sun.tools.jar
  * @compile ../../test-classes/DummyClassHelper.java
  * @compile ../../test-classes/java/net/HttpCookie.jasm
- * @compile ../../test-classes/javax/activation/MimeType.jasm
+ * @compile ../../../SharedArchiveFile/javax/annotation/processing/FilerException.jasm
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  * @run main DummyClassesInBootClassPath
@@ -57,21 +57,20 @@
 
     public static void main(String[] args) throws Exception {
         String classNames[] = { "java/net/HttpCookie",
-                                "javax/activation/MimeType"};
+                                "javax/annotation/processing/FilerException"};
         JarBuilder.build("dummyClasses", classNames[0], classNames[1]);
 
         String appJar = TestCommon.getTestJar("dummyClasses.jar");
         OutputAnalyzer dumpOutput = TestCommon.dump(
-            appJar, classNames, "-Xbootclasspath/a:" + appJar,
-            "--add-modules", "java.activation");
+            appJar, classNames, "-Xbootclasspath/a:" + appJar);
         List<String> argsList = new ArrayList<String>();
         for (int i = 0; i < classNames.length; i++) {
             argsList.add(classNames[i].replace('/', '.'));
         }
         String[] arguments = new String[argsList.size()];
         arguments = argsList.toArray(arguments);
-        Testcommon.run(
-            "--add-modules", "java.activation", "-Xbootclasspath/a:" + appJar,
+        TestCommon.run(
+            "-Xbootclasspath/a:" + appJar,
             "DummyClassHelper", arguments[0], arguments[1])
           .assertNormalExit(output -> checkOutput(output, classNames));
 
@@ -80,14 +79,14 @@
         String bootClassPath = "-Xbootclasspath/a:" + appJar +
             File.pathSeparator + whiteBoxJar;
         dumpOutput = TestCommon.dump(
-            appJar, classNames, bootClassPath, "--add-modules", "java.activation");
+            appJar, classNames, bootClassPath);
         argsList.add("testWithWhiteBox");
         arguments = new String[argsList.size()];
         arguments = argsList.toArray(arguments);
         String[] opts = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI",
-            "--add-modules", "java.activation", bootClassPath, "-Xlog:class+path=trace",
+            bootClassPath, "-Xlog:class+path=trace",
             "DummyClassHelper", arguments[0], arguments[1], arguments[2]};
-        Testcommon.run(opts)
+        TestCommon.run(opts)
           .assertNormalExit(output -> checkOutput(output, classNames));
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/Main2.jasm	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package com/sun/tools/javac;
-
-public class Main2
-    version 51:0
-{
-
-public Method "<init>":"()V"
-    stack 1 locals 1
-{
-    aload_0;
-    invokespecial   Method java/lang/Object."<init>":"()V";
-    return;
-}
-
-public Method toString:"()Ljava/lang/String;"
-    stack 1 locals 1
-{
-    ldc String "hi";
-    areturn;
-}
-
-} // end class Main2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/com/sun/tools/javac/MyMain.jasm	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016, 2018, 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 com/sun/tools/javac;
+
+public class MyMain
+    version 51:0
+{
+
+public Method "<init>":"()V"
+    stack 1 locals 1
+{
+    aload_0;
+    invokespecial   Method java/lang/Object."<init>":"()V";
+    return;
+}
+
+public Method toString:"()Ljava/lang/String;"
+    stack 1 locals 1
+{
+    ldc String "hi";
+    areturn;
+}
+
+} // end class Main2
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/javax/activation/UnsupportedDataTypeException2.jasm	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package javax/activation;
-
-public class UnsupportedDataTypeException2
-    version 51:0
-{
-
-public Method "<init>":"()V"
-    stack 1 locals 1
-{
-    aload_0;
-    invokespecial   Method java/lang/Object."<init>":"()V";
-    return;
-}
-
-public Method toString:"()Ljava/lang/String;"
-    stack 1 locals 1
-{
-    ldc String "hi";
-    areturn;
-}
-
-} // end class UnsupportedDataTypeException2
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/src/jdk/test/Main.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -96,10 +96,12 @@
                 }
                 // Make sure we got the right version of the class. toString() of an instance
                 // of the overridden version of the class should return "hi".
-                String s = clazz.newInstance().toString();
-                if (!s.equals("hi")) {
-                    throw new RuntimeException(testName + " FAILED: toString() returned \"" + s
-                                               + "\" instead of \"hi\"" );
+                if (actualLoader == SYS_LOADER) {
+                    String s = clazz.newInstance().toString();
+                    if (!s.equals("hi")) {
+                        throw new RuntimeException(testName + " FAILED: toString() returned \"" + s
+                                                   + "\" instead of \"hi\"" );
+                    }
                 }
                 System.out.println(testName + " PASSED: class loaded as expected.");
             } else {
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/OverrideTests.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -67,7 +67,7 @@
     private static final Path MODS_DIR = Paths.get("mods");
 
     // the module that is upgraded
-    private static final String[] UPGRADED_MODULES = {"jdk.compiler", "java.activation"};
+    private static final String[] UPGRADED_MODULES = {"jdk.compiler", "java.net.http"};
     private static final Path[] UPGRADEDMODS_DIR = {Paths.get("upgradedmod1"), Paths.get("upgradedmod2")};
 
     // the test module
@@ -76,7 +76,7 @@
 
     // test classes to archive. These are both in UPGRADED_MODULES
     private static final String APP_ARCHIVE_CLASS = "com/sun/tools/javac/Main";
-    private static final String PLATFORM_ARCHIVE_CLASS = "javax/activation/UnsupportedDataTypeException";
+    private static final String PLATFORM_ARCHIVE_CLASS = "java/net/http/HttpTimeoutException";
     private static final String[] ARCHIVE_CLASSES = {APP_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS};
     private static String testArchiveName;
 
@@ -94,10 +94,10 @@
         int i = 0;
         for (String upgradedMod : UPGRADED_MODULES) {
             compiled = CompilerUtils.compile(
-                SRC_DIR.resolve(upgradedMod),
-                UPGRADEDMODS_DIR[i].resolve(upgradedMod)
+                SRC_DIR.resolve(UPGRADED_MODULES[i]),
+                UPGRADEDMODS_DIR[i].resolve(UPGRADED_MODULES[i])
             );
-            Asserts.assertTrue(compiled, upgradedMod + " did not compile");
+            Asserts.assertTrue(compiled, UPGRADED_MODULES[i] + " did not compile");
             i++;
         }
 
@@ -110,22 +110,12 @@
         );
         Asserts.assertTrue(compiled, TEST_MODULE + " did not compile");
 
-        // the java.activation module is not defined by default; --add-modules is required.
-        // dumping without "--add-modules java.activation"
-        // the class in the javax.activation package cannot be found
-        OutputAnalyzer output1  = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES));
-        TestCommon.checkDump(output1);
-        output1.shouldContain(
-            "Preload Warning: Cannot find javax/activation/UnsupportedDataTypeException");
-
-        // dump the archive with jdk.comiler and java.activation classes in the class list
-        // with "--add-modules java.activation"
-        output1  = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES),
-            "--add-modules", "java.activation");
-        TestCommon.checkDump(output1);
+        // dump the archive with jdk.compiler and java.net.http classes in the class list
+        OutputAnalyzer output  = TestCommon.dump(null /* appJar*/, TestCommon.list(ARCHIVE_CLASSES));
+        TestCommon.checkDump(output);
         // Make sure all the classes where successfully archived.
         for (String archiveClass : ARCHIVE_CLASSES) {
-            output1.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
+            output.shouldNotContain("Preload Warning: Cannot find " + archiveClass);
         }
 
         testArchiveName = TestCommon.getCurrentArchiveName();
@@ -147,11 +137,11 @@
     /**
      * PLATFORM Class Overriding Tests
      *
-     * Archive PLATFORM class javax.activation.UnsupportedDataTypeException from module jdk.activation.
-     *  -At run time, upgrade module jdk.activation using --upgrade-module-path.
-     *   Class.forname(UnsupportedDataTypeException) MUST NOT load the archived UnsupportedDataTypeException.
-     *  -At run time, module jdk.activation also exists in --module-path.
-     *   Class.forname(UnsupportedDataTypeException) MUST load the archived UnsupportedDataTypeException.
+     * Archive PLATFORM class java.net.http.HttpTimeoutException from module java.net.http.
+     *  -At run time, upgrade module java.net.http using --upgrade-module-path.
+     *   Class.forname(HttpTimeoutException) MUST NOT load the archived HttpTimeoutException.
+     *  -At run time, module java.net.http also exists in --module-path.
+     *   Class.forname(HttpTimeoutException) MUST load the archived HttpTimeoutException.
      */
     public void testPlatformClassOverriding() throws Exception {
         testClassOverriding(PLATFORM_ARCHIVE_CLASS, "platform");
@@ -173,25 +163,16 @@
         prefix[0] = "-cp";
         prefix[1] = "\"\"";
         prefix[2] = "--add-modules";
-        prefix[3] = "java.activation";
+        prefix[3] = "java.net.http";
 
         // Run the test with --upgrade-module-path set to alternate location of archiveClass
         // The alternate version of archiveClass SHOULD be found.
-        output = TestCommon.execModule(
-            prefix,
-            UPGRADEDMODS_DIR[upgradeModIdx].toString(),
-            MODS_DIR.toString(),
-            mid,
-            archiveClass, loaderName, "true"); // last 3 args passed to test
-        if (isAppLoader) {
-            try {
-                output.shouldContain(expectedException);
-            } catch (Exception e) {
-                TestCommon.checkCommonExecExceptions(output, e);
-            }
-        } else {
-            TestCommon.checkExec(output);
-        }
+        TestCommon.runWithModules(prefix,
+                                  UPGRADEDMODS_DIR[upgradeModIdx].toString(),
+                                  MODS_DIR.toString(),
+                                  mid,
+                                  archiveClass, loaderName, "true") // last 3 args passed to test
+            .ifNoMappingFailure(out -> out.shouldContain(expectedException));
 
         // Now run this same test again, but this time without AppCDS. Behavior should be the same.
         CDSOptions opts = (new CDSOptions())
@@ -203,26 +184,21 @@
 
         output = CDSTestUtils.runWithArchive(opts);
 
-        if (isAppLoader) {
-            try {
-                output.shouldContain(expectedException);
-            } catch (Exception e) {
-                TestCommon.checkCommonExecExceptions(output, e);
-            }
-        } else {
-            if (!CDSTestUtils.isUnableToMap(output))
-                output.shouldHaveExitValue(0);
+        try {
+            output.shouldContain(expectedException);
+        } catch (Exception e) {
+            TestCommon.checkCommonExecExceptions(output, e);
         }
 
         // Run the test with -p set to alternate location of archiveClass.
         // The alternate version of archiveClass SHOULD NOT be found.
-        output = TestCommon.execModule(
+        TestCommon.runWithModules(
             prefix,
             null,
             UPGRADEDMODS_DIR[upgradeModIdx].toString() + java.io.File.pathSeparator + MODS_DIR.toString(),
             mid,
-            archiveClass, loaderName, "false"); // last 3 args passed to test
-        TestCommon.checkExec(output);
+            archiveClass, loaderName, "false") // last 3 args passed to test
+            .assertNormalExit();
 
         // Now  run this same test again, but this time without AppCDS. Behavior should be the same.
         opts = (new CDSOptions())
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/javax/activation/UnsupportedDataTypeException.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2015, 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 javax.activation;
-
-import java.io.IOException;
-
-public class UnsupportedDataTypeException extends IOException {
-    public UnsupportedDataTypeException() {
-    }
-
-    public String toString() {
-        return "hi";
-    }
-}
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.activation/module-info.java	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- */
-
-module java.activation {
-    exports javax.activation;
-}
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.net.http/java/net/http/HttpTimeoutException.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, 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 java.net.http;
+
+public class HttpTimeoutException {
+    public String toString() {
+        return "hi";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/java.net.http/module-info.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2015, 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.
+ *
+ */
+
+module java.net.http {
+    exports java.net.http;
+}
+
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/jdk/test/Main.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,11 +73,15 @@
         Class<?> clazz = Class.forName(className, true, loader);
         // Make sure we got the expected defining ClassLoader
         testLoader(clazz, loader);
-        // Create an instance and see what toString() returns
-        String s = clazz.newInstance().toString();
+
+        String s = null;
+        if (shouldOverride) {
+          // Create an instance and see what toString() returns
+          clazz.newInstance().toString();
+        }
         // The overridden version of the class should return "hi". Make sure
         // it does only if we are expecting to have loaded the overridden version.
-        assertTrue(s.equals("hi") == shouldOverride);
+        assertTrue("hi".equals(s) == shouldOverride);
     }
 
     /**
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/overridetests/src/test/module-info.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,5 +24,5 @@
 
 module test {
     requires jdk.compiler;
-    requires java.activation;
+    requires java.compiler;
 }
--- a/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/test-classes/HelloExt.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, 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
@@ -27,7 +27,7 @@
 public class HelloExt {
    public static void main(String[] args) throws Throwable {
 
-       String className = "org.omg.CORBA.ORB";
+       String className = "javax.annotation.processing.FilerException";
        Class cls = Class.forName(className);
 
        ClassLoader loader = cls.getClassLoader();
--- a/test/hotspot/jtreg/runtime/appcds/test-classes/javax/activation/MimeType.jasm	Mon Apr 23 12:53:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-/*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-package javax/activation;
-
-public class MimeType
-    version 51:0
-{
-
-public Method thisClassIsDummy:"()V"
-    stack 0 locals 0
-{
-    return;
-}
-
-} // end class MimeType
--- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleClassList.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, 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
@@ -40,7 +40,7 @@
 
 public class PatchModuleClassList {
     private static final String BOOT_CLASS = "javax/naming/spi/NamingManager";
-    private static final String PLATFORM_CLASS = "javax/transaction/InvalidTransactionException";
+    private static final String PLATFORM_CLASS = "java/sql/ResultSet";
 
     public static void main(String args[]) throws Throwable {
         // Case 1. A class to be loaded by the boot class loader
@@ -68,7 +68,9 @@
             "-XX:DumpLoadedClassList=" + classList,
             "--patch-module=java.naming=" + moduleJar,
             "PatchModuleMain", BOOT_CLASS.replace('/', '.'));
-        new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
+        OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("I pass!");
+        oa.shouldHaveExitValue(0);
 
         // check the generated classlist file
         String content = new String(Files.readAllBytes(Paths.get(classList)));
@@ -78,30 +80,32 @@
 
         // Case 2. A class to be loaded by the platform class loader
 
-        // Create a class file in the module java.transaction. This class file
-        // will be put in the javatransaction.jar file.
-        source = "package javax.transaction; "                 +
-                 "public class InvalidTransactionException { " +
+        // Create a class file in the module java.sql. This class file
+        // will be put in the javasql.jar file.
+        source = "package java.sql; "                 +
+                 "public class ResultSet { " +
                  "    static { "                               +
-                 "        System.out.println(\"I pass!\"); "   +
+                 "        System.out.println(\"I pass too!\"); "   +
                  "    } "                                      +
                  "}";
 
         ClassFileInstaller.writeClassToDisk(PLATFORM_CLASS,
-             InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.transaction"),
+             InMemoryJavaCompiler.compile(PLATFORM_CLASS.replace('/', '.'), source, "--patch-module=java.sql"),
              System.getProperty("test.classes"));
 
-        // Build the jar file that will be used for the module "java.transaction".
-        BasicJarBuilder.build("javatransaction", PLATFORM_CLASS);
-        moduleJar = BasicJarBuilder.getTestJar("javatransaction.jar");
+        // Build the jar file that will be used for the module "java.sql".
+        BasicJarBuilder.build("javasql", PLATFORM_CLASS);
+        moduleJar = BasicJarBuilder.getTestJar("javasql.jar");
 
-        classList = "javatransaction.list";
+        classList = "javasql.list";
         pb = ProcessTools.createJavaProcessBuilder(
             true,
             "-XX:DumpLoadedClassList=" + classList,
-            "--patch-module=java.naming=" + moduleJar,
+            "--patch-module=java.sql=" + moduleJar,
             "PatchModuleMain", PLATFORM_CLASS.replace('/', '.'));
-        new OutputAnalyzer(pb.start()).shouldHaveExitValue(0);
+        OutputAnalyzer oa2 = new OutputAnalyzer(pb.start());
+        oa2.shouldContain("I pass too!");
+        oa2.shouldHaveExitValue(0);
 
         // check the generated classlist file
         content = new String(Files.readAllBytes(Paths.get(classList)));
--- a/test/hotspot/jtreg/runtime/whitebox/WBStackSize.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/whitebox/WBStackSize.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, 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
@@ -29,7 +29,8 @@
  * @build sun.hotspot.WhiteBox
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
- * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xss512k WBStackSize
+ * @comment Must use the same stacksize for Java threads and compiler threads in case of thread recycling
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xss512k -XX:CompilerThreadStackSize=512 WBStackSize
  */
 
 /*
@@ -82,9 +83,7 @@
     }
 
     public static void main(String[] args) {
-        boolean isCompilerThread = Thread.currentThread().getName().indexOf(" CompilerThread") > 0;
-        long configStackSize = isCompilerThread ? wb.getIntxVMFlag("CompilerThreadStackSize") * K
-                                                : wb.getIntxVMFlag("ThreadStackSize") * K;
+        long configStackSize = wb.getIntxVMFlag("ThreadStackSize") * K;
         System.out.println("ThreadStackSize VM option: " + configStackSize);
 
         long stackProtectionSize = wb.getIntxVMFlag("StackShadowPages") * wb.getVMPageSize();
@@ -95,7 +94,7 @@
 
         if (Math.abs(actualStackSize - configStackSize) > configStackSize * 0.1) {
             throw new RuntimeException("getThreadFullStackSize value [" + actualStackSize
-                                     + "] should be within 90%..110% of the value returned by HotSpotDiagnosticMXBean");
+                                     + "] should be within 90%..110% of ThreadStackSize value");
         }
 
         long remainingStackSize = wb.getThreadRemainingStackSize();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSCore.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8174994
+ * @summary Test the clhsdb commands 'printmdo', 'printall' on a CDS enabled corefile.
+ * @requires vm.cds
+ * @requires os.family != "windows"
+ * @requires vm.flavor == "server"
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSCore
+ */
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import java.io.IOException;
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.Asserts;
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import jdk.internal.misc.Unsafe;
+import java.util.Scanner;
+
+class CrashApp {
+    public static void main(String[] args) {
+        Unsafe.getUnsafe().putInt(0L, 0);
+    }
+}
+
+public class ClhsdbCDSCore {
+
+    private static final String TEST_CDS_CORE_FILE_NAME = "cds_core_file";
+    private static final String LOCATIONS_STRING = "location: ";
+    private static final String RUN_SHELL_NO_LIMIT = "ulimit -c unlimited && ";
+    private static final String SHARED_ARCHIVE_NAME = "ArchiveForClhsdbCDSCore.jsa";
+    private static final String CORE_PATTERN_FILE_NAME = "/proc/sys/kernel/core_pattern";
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting ClhsdbCDSCore test");
+        cleanup();
+
+        try {
+            CDSOptions opts = (new CDSOptions()).setArchiveName(SHARED_ARCHIVE_NAME);
+            CDSTestUtils.createArchiveAndCheck(opts);
+
+            String[] jArgs = {
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=" + SHARED_ARCHIVE_NAME,
+                "-XX:+CreateCoredumpOnCrash",
+                "-Xshare:auto",
+                "-XX:+ProfileInterpreter",
+                "--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED",
+                CrashApp.class.getName()
+            };
+
+            OutputAnalyzer crashOut;
+            try {
+               List<String> options = new ArrayList<>();
+               options.addAll(Arrays.asList(jArgs));
+               crashOut =
+                   ProcessTools.executeProcess(getTestJavaCommandlineWithPrefix(
+                   RUN_SHELL_NO_LIMIT, options.toArray(new String[0])));
+            } catch (Throwable t) {
+               throw new Error("Can't execute the java cds process.", t);
+            }
+
+            System.out.println(crashOut.getOutput());
+            String crashOutputString = crashOut.getOutput();
+            String coreFileLocation = getCoreFileLocation(crashOutputString);
+            if (coreFileLocation == null) {
+                if (Platform.isOSX()) {
+                    File coresDir = new File("/cores");
+                    if (!coresDir.isDirectory() || !coresDir.canWrite()) {
+                        throw new Error("cores is not a directory or does not have write permissions");
+                    }
+                } else if (Platform.isLinux()) {
+                    // Check if a crash report tool is installed.
+                    File corePatternFile = new File(CORE_PATTERN_FILE_NAME);
+                    Scanner scanner = new Scanner(corePatternFile);
+                    while (scanner.hasNextLine()) {
+                        String line = scanner.nextLine();
+                        line = line.trim();
+                        System.out.println(line);
+                        if (line.startsWith("|")) {
+                            System.out.println(
+                                "\nThis system uses a crash report tool ($cat /proc/sys/kernel/core_pattern).\n" +
+                                "Core files might not be generated. Please reset /proc/sys/kernel/core_pattern\n" +
+                                "to enable core generation. Skipping this test.");
+                            cleanup();
+                            return;
+                        }
+                    }
+                }
+                throw new Error("Couldn't find core file location in: '" + crashOutputString + "'");
+            }
+            try {
+                Asserts.assertGT(new File(coreFileLocation).length(), 0L, "Unexpected core size");
+                Files.move(Paths.get(coreFileLocation), Paths.get(TEST_CDS_CORE_FILE_NAME));
+            } catch (IOException ioe) {
+                throw new Error("Can't move core file: " + ioe, ioe);
+            }
+
+            ClhsdbLauncher test = new ClhsdbLauncher();
+
+            // Ensure that UseSharedSpaces is turned on.
+            List<String> cmds = List.of("flags UseSharedSpaces");
+
+            String useSharedSpacesOutput = test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds,
+                                                          null, null);
+
+            if (useSharedSpacesOutput == null) {
+                // Output could be null due to attach permission issues.
+                System.out.println("Could not determine the UseSharedSpaces value - test skipped.");
+                cleanup();
+                return;
+            }
+
+            if (!useSharedSpacesOutput.contains("true")) {
+                // CDS archive is not mapped. Skip the rest of the test.
+                System.out.println("The CDS archive is not mapped - test skipped.");
+                cleanup();
+                return;
+            }
+
+            cmds = List.of("printmdo -a", "printall");
+
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            Map<String, List<String>> unExpStrMap = new HashMap<>();
+            expStrMap.put("printmdo -a", List.of(
+                "CounterData",
+                "BranchData"));
+            unExpStrMap.put("printmdo -a", List.of(
+                "No suitable match for type of address"));
+            expStrMap.put("printall", List.of(
+                "aload_0",
+                "Constant Pool of",
+                "public static void main(java.lang.String[])",
+                "Bytecode",
+                "invokevirtual",
+                "checkcast",
+                "Exception Table",
+                "invokedynamic"));
+            unExpStrMap.put("printall", List.of(
+                "sun.jvm.hotspot.types.WrongTypeException",
+                "No suitable match for type of address"));
+            test.runOnCore(TEST_CDS_CORE_FILE_NAME, cmds, expStrMap, unExpStrMap);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        }
+        cleanup();
+        System.out.println("Test PASSED");
+    }
+
+    // lets search for a few possible locations using process output and return existing location
+    private static String getCoreFileLocation(String crashOutputString) {
+        Asserts.assertTrue(crashOutputString.contains(LOCATIONS_STRING),
+            "Output doesn't contain the location of core file.");
+        String stringWithLocation = Arrays.stream(crashOutputString.split("\\r?\\n"))
+            .filter(str -> str.contains(LOCATIONS_STRING))
+            .findFirst()
+            .get();
+        stringWithLocation = stringWithLocation.substring(stringWithLocation
+            .indexOf(LOCATIONS_STRING) + LOCATIONS_STRING.length());
+        String coreWithPid;
+        if (stringWithLocation.contains("or ")) {
+            Matcher m = Pattern.compile("or.* ([^ ]+[^\\)])\\)?").matcher(stringWithLocation);
+            if (!m.find()) {
+                throw new Error("Couldn't find path to core inside location string");
+            }
+            coreWithPid = m.group(1);
+        } else {
+            coreWithPid = stringWithLocation.trim();
+        }
+        if (new File(coreWithPid).exists()) {
+            return coreWithPid;
+        }
+        String justCore = Paths.get("core").toString();
+        if (new File(justCore).exists()) {
+            return justCore;
+        }
+        Path coreWithPidPath = Paths.get(coreWithPid);
+        String justFile = coreWithPidPath.getFileName().toString();
+        if (new File(justFile).exists()) {
+            return justFile;
+        }
+        Path parent = coreWithPidPath.getParent();
+        if (parent != null) {
+            String coreWithoutPid = parent.resolve("core").toString();
+            if (new File(coreWithoutPid).exists()) {
+                return coreWithoutPid;
+            }
+        }
+        return null;
+    }
+
+    private static String[] getTestJavaCommandlineWithPrefix(String prefix, String... args) {
+        try {
+            String cmd = ProcessTools.getCommandLine(ProcessTools.createJavaProcessBuilder(true, args));
+            return new String[]{"sh", "-c", prefix + cmd};
+        } catch (Throwable t) {
+            throw new Error("Can't create process builder: " + t, t);
+        }
+    }
+
+    private static void cleanup() {
+        remove(TEST_CDS_CORE_FILE_NAME);
+        remove(SHARED_ARCHIVE_NAME);
+    }
+
+    private static void remove(String item) {
+        File toDelete = new File(item);
+        toDelete.delete();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbCDSJstackPrintAll.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8174994
+ * @summary Test the clhsdb commands 'jstack', 'printall' with CDS enabled
+ * @requires vm.cds
+ * @library /test/lib
+ * @run main/othervm/timeout=2400 -Xmx1g ClhsdbCDSJstackPrintAll
+ */
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.HashMap;
+import jdk.test.lib.cds.CDSTestUtils;
+import jdk.test.lib.cds.CDSOptions;
+import jdk.test.lib.apps.LingeredApp;
+
+public class ClhsdbCDSJstackPrintAll {
+
+    public static void main(String[] args) throws Exception {
+        System.out.println("Starting ClhsdbCDSJstackPrintAll test");
+        String sharedArchiveName = "ArchiveForClhsdbJstackPrintAll.jsa";
+        LingeredApp theApp = null;
+
+        try {
+            CDSOptions opts = (new CDSOptions()).setArchiveName(sharedArchiveName);
+            CDSTestUtils.createArchiveAndCheck(opts);
+
+            ClhsdbLauncher test = new ClhsdbLauncher();
+            List<String> vmArgs = Arrays.asList(
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:SharedArchiveFile=" + sharedArchiveName,
+                "-Xshare:auto");
+            theApp = LingeredApp.startApp(vmArgs);
+            System.out.println("Started LingeredApp with pid " + theApp.getPid());
+
+            // Ensure that UseSharedSpaces is turned on.
+            List<String> cmds = List.of("flags UseSharedSpaces");
+
+            String useSharedSpacesOutput = test.run(theApp.getPid(), cmds,
+                                                    null, null);
+
+            if (useSharedSpacesOutput == null) {
+                // Attach permission issues.
+                System.out.println("Could not determine the UseSharedSpaces value - test skipped.");
+                LingeredApp.stopApp(theApp);
+                return;
+            }
+
+            if (!useSharedSpacesOutput.contains("true")) {
+                // CDS archive is not mapped. Skip the rest of the test.
+                System.out.println("The CDS archive is not mapped - test skipped.");
+                LingeredApp.stopApp(theApp);
+                return;
+            }
+
+            cmds = List.of("jstack -v", "printall");
+
+            Map<String, List<String>> expStrMap = new HashMap<>();
+            Map<String, List<String>> unExpStrMap = new HashMap<>();
+            expStrMap.put("jstack -v", List.of(
+                "No deadlocks found",
+                "Common-Cleaner",
+                "Signal Dispatcher",
+                "Method*",
+                "LingeredApp.main"));
+            unExpStrMap.put("jstack -v", List.of(
+                "sun.jvm.hotspot.types.WrongTypeException",
+                "No suitable match for type of address"));
+            expStrMap.put("printall", List.of(
+                "aload_0",
+                "Constant Pool of",
+                "public static void main(java.lang.String[])",
+                "Bytecode",
+                "invokevirtual",
+                "checkcast",
+                "Exception Table",
+                "invokedynamic"));
+            unExpStrMap.put("printall", List.of(
+                "No suitable match for type of address"));
+            test.run(theApp.getPid(), cmds, expStrMap, unExpStrMap);
+        } catch (Exception ex) {
+            throw new RuntimeException("Test ERROR " + ex, ex);
+        } finally {
+            LingeredApp.stopApp(theApp);
+        }
+        System.out.println("Test PASSED");
+    }
+}
--- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLauncher.java	Thu Apr 26 17:59:02 2018 +0200
@@ -29,6 +29,7 @@
 import jdk.test.lib.apps.LingeredApp;
 import jdk.test.lib.Platform;
 import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.JDKToolFinder;
 import jdk.test.lib.process.OutputAnalyzer;
 
 /**
@@ -68,6 +69,27 @@
 
     /**
      *
+     * Launches 'jhsdb clhsdb' and loads a core file.
+     * @param coreFileName - Name of the corefile to be loaded.
+     */
+    private void loadCore(String coreFileName)
+        throws IOException {
+
+        JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb");
+        launcher.addToolArg("clhsdb");
+        launcher.addToolArg("--core=" + coreFileName);
+        launcher.addToolArg("--exe=" + JDKToolFinder.getTestJDKTool("java"));
+        System.out.println("Starting clhsdb against corefile " + coreFileName +
+                           " and exe " + JDKToolFinder.getTestJDKTool("java"));
+
+        ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
+        processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
+
+        toolProcess = processBuilder.start();
+    }
+
+    /**
+     *
      * Runs 'jhsdb clhsdb' commands and checks for expected and unexpected strings.
      * @param commands  - clhsdb commands to execute.
      * @param expectedStrMap - Map of expected strings per command which need to
@@ -159,4 +181,32 @@
         attach(lingeredAppPid);
         return runCmd(commands, expectedStrMap, unExpectedStrMap);
     }
+
+    /**
+     *
+     * Launches 'jhsdb clhsdb', loads a core file, executes the commands,
+     * checks for expected and unexpected strings.
+     * @param coreFileName - Name of the core file to be debugged.
+     * @param commands  - clhsdb commands to execute.
+     * @param expectedStrMap - Map of expected strings per command which need to
+     *                         be checked in the output of the command.
+     * @param unExpectedStrMap - Map of unexpected strings per command which should
+     *                           not be present in the output of the command.
+     * @return Output of the commands as a String.
+     */
+    public String runOnCore(String coreFileName,
+                            List<String> commands,
+                            Map<String, List<String>> expectedStrMap,
+                            Map<String, List<String>> unExpectedStrMap)
+        throws IOException, InterruptedException {
+
+        if (!Platform.shouldSAAttach()) {
+            // Silently skip the test if we don't have enough permissions to attach
+            System.out.println("SA attach not expected to work - test skipped.");
+            return null;
+        }
+
+        loadCore(coreFileName);
+        return runCmd(commands, expectedStrMap, unExpectedStrMap);
+    }
 }
--- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcCauseResults.java	Thu Apr 26 17:59:02 2018 +0200
@@ -74,10 +74,18 @@
         assertThat(GCT >= 0, "Incorrect time value for GCT");
         assertThat(GCT >= YGCT, "GCT < YGCT (total garbage collection time < young generation garbage collection time)");
 
-        int CGC = getIntValue("CGC");
-        float CGCT = getFloatValue("CGCT");
-        assertThat(CGCT >= 0, "Incorrect time value for CGCT");
+        int CGC = 0;
+        float CGCT = 0.0f;
+        try {
+            CGC = getIntValue("CGC");
+        } catch (NumberFormatException e) {
+            if (!e.getMessage().equals("Unparseable number: \"-\"")) {
+                throw e;
+            }
+        }
         if (CGC > 0) {
+            CGCT = getFloatValue("CGCT");
+            assertThat(CGCT >= 0, "Incorrect time value for CGCT");
             assertThat(CGCT > 0, "Number of concurrent GC events is " + CGC + ", but CGCT is 0");
         }
 
--- a/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/tmtools/jstat/utils/JstatGcResults.java	Thu Apr 26 17:59:02 2018 +0200
@@ -103,10 +103,18 @@
         assertThat(GCT >= 0, "Incorrect time value for GCT");
         assertThat(GCT >= YGCT, "GCT < YGCT (total garbage collection time < young generation garbage collection time)");
 
-        int CGC = getIntValue("CGC");
-        float CGCT = getFloatValue("CGCT");
-        assertThat(CGCT >= 0, "Incorrect time value for CGCT");
+        int CGC = 0;
+        float CGCT = 0.0f;
+        try {
+            CGC = getIntValue("CGC");
+        } catch (NumberFormatException e) {
+            if (!e.getMessage().equals("Unparseable number: \"-\"")) {
+                throw e;
+            }
+        }
         if (CGC > 0) {
+            CGCT = getFloatValue("CGCT");
+            assertThat(CGCT >= 0, "Incorrect time value for CGCT");
             assertThat(CGCT > 0, "Number of concurrent GC events is " + CGC + ", but CGCT is 0");
         }
 
--- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/CtwRunner.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -52,11 +52,17 @@
     private static final Predicate<String> IS_CLASS_LINE = Pattern.compile(
             "^\\[\\d+\\]\\s*\\S+\\s*$").asPredicate();
 
+    private static final String USAGE = "Usage: CtwRunner <artifact to compile> [start[%] stop[%]]";
+
     public static void main(String[] args) throws Exception {
-        if (args.length != 1) {
-            throw new Error("Usage: <artifact to compile>");
+        CtwRunner runner;
+        switch (args.length) {
+            case 1: runner = new CtwRunner(args[0]); break;
+            case 3: runner = new CtwRunner(args[0], args[1], args[2]); break;
+            default: throw new Error(USAGE);
         }
-        new CtwRunner(args[0]).run();
+
+        runner.run();
     }
 
     private final List<Throwable> errors;
@@ -64,7 +70,10 @@
     private final Path targetPath;
     private final String targetName;
 
-    private CtwRunner(String target) {
+    private final int start, stop;
+    private final boolean isStartStopPercentage;
+
+    private CtwRunner(String target, String start, String stop) {
         if (target.startsWith("modules")) {
             targetPath = Paths
                     .get(Utils.TEST_JDK)
@@ -82,8 +91,29 @@
         }
         this.target = target;
         errors = new ArrayList<>();
+
+        if (start.endsWith("%") && stop.endsWith("%")) {
+            int startPercentage = Integer.parseInt(start.substring(0, start.length() - 1));;
+            int stopPercentage = Integer.parseInt(stop.substring(0, stop.length() - 1));
+            if (startPercentage < 0 || startPercentage > 100 ||
+                stopPercentage < 0 || stopPercentage > 100) {
+                throw new Error(USAGE);
+            }
+            this.start = startPercentage;
+            this.stop = stopPercentage;
+            this.isStartStopPercentage = true;
+        } else if (!start.endsWith("%") && !stop.endsWith("%")) {
+            this.start = Integer.parseInt(start);
+            this.stop = Integer.parseInt(stop);
+            this.isStartStopPercentage = false;
+        } else {
+            throw new Error(USAGE);
+        }
     }
 
+    private CtwRunner(String target) {
+        this(target, "0%", "100%");
+    }
 
     private void run() {
         startCtwforAllClasses();
@@ -105,15 +135,44 @@
         }
     }
 
+    private long start(long totalClassCount) {
+        if (isStartStopPercentage) {
+            return totalClassCount * start / 100;
+        } else if (start > totalClassCount) {
+            System.err.println("WARNING: start [" + start + "] > totalClassCount [" + totalClassCount + "]");
+            return totalClassCount;
+        } else {
+            return start;
+        }
+    }
+
+    private long stop(long totalClassCount) {
+        if (isStartStopPercentage) {
+            return totalClassCount * stop / 100;
+        } else if (stop > totalClassCount) {
+            System.err.println("WARNING: stop [" + start + "] > totalClassCount [" + totalClassCount + "]");
+            return totalClassCount;
+        } else {
+            return stop;
+        }
+    }
 
     private void startCtwforAllClasses() {
-        long classStart = 0L;
-        long classCount = classCount();
+        long totalClassCount = classCount();
+
+        long classStart = start(totalClassCount);
+        long classStop = stop(totalClassCount);
+
+        long classCount = classStop - classStart;
         Asserts.assertGreaterThan(classCount, 0L,
                 target + "(at " + targetPath + ") does not have any classes");
+
+        System.out.printf("Compiling %d classes (of %d total classes) starting at %d and ending at %d\n",
+                          classCount, totalClassCount, classStart, classStop);
+
         boolean done = false;
         while (!done) {
-            String[] cmd = cmd(classStart);
+            String[] cmd = cmd(classStart, classStop);
             try {
                 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
                         /* addTestVmAndJavaOptions = */ true,
@@ -138,11 +197,11 @@
                 Pair<String, Long> lastClass = getLastClass(out);
                 if (exitCode == 0) {
                     long lastIndex = lastClass == null ? -1 : lastClass.second;
-                    if (lastIndex != classCount) {
+                    if (lastIndex != classStop) {
                         errors.add(new Error(phase + ": Unexpected zero exit code"
                                 + "before finishing all compilations."
                                 + " lastClass[" + lastIndex
-                                + "] != classCount[" + classCount + "]"));
+                                + "] != classStop[" + classStop + "]"));
                     } else {
                         System.out.println("Executed CTW for all " + classCount
                                 + " classes in " + target + "(at " + targetPath + ")");
@@ -197,7 +256,7 @@
         return null;
     }
 
-    private String[] cmd(long classStart) {
+    private String[] cmd(long classStart, long classStop) {
         String phase = phaseName(classStart);
         return new String[] {
                 "-Xbatch",
@@ -206,6 +265,7 @@
                 "-XX:+UnlockDiagnosticVMOptions",
                 // define phase start
                 "-DCompileTheWorldStartAt=" + classStart,
+                "-DCompileTheWorldStopAt=" + classStop,
                 // CTW library uses WhiteBox API
                 "-XX:+WhiteBoxAPI", "-Xbootclasspath/a:.",
                 // export jdk.internal packages used by CTW library
--- a/test/jdk/ProblemList.txt	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/ProblemList.txt	Thu Apr 26 17:59:02 2018 +0200
@@ -510,8 +510,10 @@
 
 # jdk_io
 
+java/io/FileOutputStream/AtomicAppend.java                      8202062 macosx-all
 java/io/pathNames/GeneralWin32.java                             8180264 windows-all
 
+
 ############################################################################
 
 # jdk_management
@@ -545,9 +547,11 @@
 
 java/nio/Buffer/EqualsCompareTest.java                          8193917 solaris-all
 
-java/nio/channels/Selector/Wakeup.java                          6963118 windows-all
+java/nio/channels/DatagramChannel/ChangingAddress.java          7141822 macosx-all
 
-java/nio/channels/DatagramChannel/ChangingAddress.java          7141822 macosx-all
+java/nio/channels/FileChannel/AtomicAppend.java                 8202062 macosx-all
+
+java/nio/channels/Selector/Wakeup.java                          6963118 windows-all
 
 java/nio/file/WatchService/Basic.java                           7158947 solaris-all Solaris 11
 java/nio/file/WatchService/MayFlies.java                        7158947 solaris-all Solaris 11
@@ -586,6 +590,7 @@
 
 javax/net/ssl/DTLS/PacketLossRetransmission.java                8169086 macosx-x64
 javax/net/ssl/DTLS/RespondToRetransmit.java                     8169086 macosx-x64
+javax/net/ssl/DTLS/CipherSuite.java                             8202059 macosx-x64
 
 sun/security/krb5/auto/UnboundSSL.java                          8180265 windows-all
 sun/security/provider/KeyStore/DKSTest.sh                       8180266 windows-all
@@ -738,6 +743,8 @@
 
 com/sun/jdi/RedefineImplementor.sh                              8004127 generic-all
 
+com/sun/jdi/JdbExprTest.sh                                      8185803 generic-all
+
 com/sun/jdi/JdbMethodExitTest.sh                                8171483 generic-all
 
 com/sun/jdi/RepStep.java                                        8043571 generic-all
--- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, 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
@@ -29,8 +29,8 @@
  * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false
  * @modules java.management/sun.management
  *          jdk.management
- * @run     main/othervm GarbageCollectionNotificationContentTest
- */
+ * @run     main/othervm -Xms64m -Xmx64m GarbageCollectionNotificationContentTest
+  */
 
 import java.util.*;
 import java.lang.management.*;
@@ -97,7 +97,7 @@
         System.gc();
         // Allocation of many short living and small objects to trigger minor GC
         Object data[] = new Object[32];
-        for(int i = 0; i<100000000; i++) {
+        for(int i = 0; i<10000000; i++) {
             data[i%32] = new int[8];
         }
         int wakeup = 0;
@@ -139,6 +139,8 @@
             System.out.println("Usage for pool " + poolname);
             System.out.println("   Before GC: " + busage);
             System.out.println("   After GC: " + ausage);
+
+            checkMemoryUsage(poolname, busage, ausage);
         }
 
         // check if memory usage for all memory pools are returned
@@ -150,4 +152,13 @@
             }
         }
     }
+
+    private static void checkMemoryUsage(String poolname, MemoryUsage busage, MemoryUsage ausage) throws Exception {
+        if (poolname.contains("Eden Space") && busage.getUsed() > 0) {
+            // Used size at Eden Space should be decreased or
+            if (busage.getUsed() <= ausage.getUsed()) {
+                throw new RuntimeException("Used size at Eden Space should be decreased.");
+            }
+        }
+    }
 }
--- a/test/jdk/java/nio/channels/Selector/SelectAndCancel.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/java/nio/channels/Selector/SelectAndCancel.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -23,65 +23,61 @@
 
 /* @test
  * @bug 4729342
+ * @library /test/lib
+ * @build jdk.test.lib.Utils
+ * @run main SelectAndCancel
  * @summary Check for CancelledKeyException when key cancelled during select
  */
 
-import java.nio.channels.*;
-import java.io.IOException;
-import java.net.*;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.ServerSocketChannel;
+import java.util.concurrent.CountDownLatch;
 
 public class SelectAndCancel {
-    static SelectionKey sk;
+    static volatile SelectionKey sk;
+    static volatile Throwable ex;
 
     /*
      * CancelledKeyException is the failure symptom of 4729342
      * NOTE: The failure is timing dependent and is not always
      * seen immediately when the bug is present.
      */
-    public static void main(String[] args) throws Exception {
+    public static void main(String[] args) throws Throwable {
         final Selector selector = Selector.open();
-        final ServerSocketChannel ssc =
-            ServerSocketChannel.open().bind(new InetSocketAddress(0));
-        final InetSocketAddress isa =
-            new InetSocketAddress(InetAddress.getLocalHost(), ssc.socket().getLocalPort());
+        final ServerSocketChannel ssc = ServerSocketChannel.open().bind(
+                new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+        final InetSocketAddress isa = (InetSocketAddress)ssc.getLocalAddress();
+        final CountDownLatch signal = new CountDownLatch(1);
 
         // Create and start a selector in a separate thread.
-        new Thread(new Runnable() {
+        Thread t = new Thread(new Runnable() {
                 public void run() {
                     try {
                         ssc.configureBlocking(false);
                         sk = ssc.register(selector, SelectionKey.OP_ACCEPT);
+                        signal.countDown();
                         selector.select();
-                    } catch (IOException e) {
-                        System.err.println("error in selecting thread");
-                        e.printStackTrace();
+                    } catch (Throwable e) {
+                        ex = e;
                     }
                 }
-            }).start();
+            });
+        t.start();
 
-        // Wait for above thread to get to select() before we call close.
-        Thread.sleep(3000);
+        signal.await();
+        // Wait for above thread to get to select() before we call cancel.
+        Thread.sleep((long)(300 * jdk.test.lib.Utils.TIMEOUT_FACTOR));
 
-        // Try to close. This should wakeup select.
-        new Thread(new Runnable() {
-                public void run() {
-                    try {
-                        SocketChannel sc = SocketChannel.open();
-                        sc.connect(isa);
-                        ssc.close();
-                        sk.cancel();
-                        sc.close();
-                    } catch (IOException e) {
-                        System.err.println("error in closing thread");
-                        System.err.println(e);
-                    }
-                }
-            }).start();
-
-        // Wait for select() to be awakened, which should be done by close.
-        Thread.sleep(3000);
-
-        selector.wakeup();
+        // CancelledKeyException should not be thrown.
+        ssc.close();
+        sk.cancel();
         selector.close();
+        t.join();
+        if (ex != null) {
+            throw ex;
+        }
     }
 }
--- a/test/jdk/java/security/AccessController/DoPrivAccompliceTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/java/security/AccessController/DoPrivAccompliceTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -104,7 +104,7 @@
         ProcessTools.executeTestJava(commands)
                     .shouldHaveExitValue(0)
                     .shouldContain(userName)
-                    .stderrShouldBeEmpty();
+                    .stderrShouldBeEmptyIgnoreVMWarnings();
 
         createPolicyFile(jarFile2, policy);
         System.out.println("Created policy for " + jarFile2);
--- a/test/jdk/sun/security/krb5/auto/Renewal.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/krb5/auto/Renewal.java	Thu Apr 26 17:59:02 2018 +0200
@@ -161,8 +161,10 @@
             return;
         }
         long change = (t.getTime() - System.currentTimeMillis()) / 1000;
-        if (change > duration + 20 || change < duration - 20) {
-            throw new Exception(t + " is not " + duration);
+        //accounting the delay factor in processing the instructions on host mc
+        if (change > duration + 40 || change < duration - 40) {
+            throw new Exception("Timestamp is " + t + ", actual difference "
+                    + change + " is not " + duration);
         }
     }
 }
--- a/test/jdk/sun/security/tools/keytool/KeyToolTest.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/tools/keytool/KeyToolTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, 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
@@ -65,6 +65,7 @@
 import java.security.NoSuchAlgorithmException;
 import java.util.*;
 import java.security.cert.X509Certificate;
+import jdk.test.lib.util.FileUtils;
 import sun.security.util.ObjectIdentifier;
 
 public class KeyToolTest {
@@ -118,9 +119,10 @@
         if (debug) {
             System.err.println("Removing " + filename);
         }
-        new File(filename).delete();
-        if (new File(filename).exists()) {
-            throw new RuntimeException("Error deleting " + filename);
+        try{
+            FileUtils.deleteFileIfExistsWithRetry(Paths.get(filename));
+        }catch(IOException e) {
+            throw new RuntimeException("Error deleting " + filename, e);
         }
     }
 
--- a/test/jdk/sun/security/tools/keytool/autotest.sh	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/tools/keytool/autotest.sh	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,9 @@
 # @test
 # @summary (almost) all keytool behaviors
 # @author Weijun Wang
-#
+# @library /test/lib
+# @build jdk.test.lib.util.FileUtils
+# @run shell/timeout=600 autotest.sh
 # This test is only executed on several platforms
 #
 # set a few environment variables so that the shell-script can run stand-alone
@@ -92,6 +94,14 @@
     exit 0;
     ;;
 esac
+case "$OS" in
+  Windows_* | CYGWIN* )
+    PS=";"
+    ;;
+  * )
+    PS=":"
+    ;;
+esac
 
 if [ "$LIBNAME" = "" ]; then
   echo "Cannot find libsoftokn3.so"
@@ -103,8 +113,7 @@
 EXTRAOPTS="--add-exports java.base/sun.security.tools.keytool=ALL-UNNAMED \
  --add-exports java.base/sun.security.util=ALL-UNNAMED \
  --add-exports java.base/sun.security.x509=ALL-UNNAMED"
-
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file \
+${COMPILEJAVA}${FS}bin${FS}javac -classpath ${TESTCLASSPATH} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file \
         ${TESTSRC}${FS}KeyToolTest.java || exit 10
 
 NSS=${TESTSRC}${FS}..${FS}..${FS}pkcs11${FS}nss
@@ -116,8 +125,7 @@
 
 chmod u+w key3.db
 chmod u+w cert8.db
-
-echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -Dnss \
+echo | ${TESTJAVA}${FS}bin${FS}java -classpath .${PS}${TESTCLASSPATH} ${TESTVMOPTS} ${EXTRAOPTS} -Dnss \
    -Dnss.lib=${LIBNAME} \
    KeyToolTest
 status=$?
--- a/test/jdk/sun/security/tools/keytool/standard.sh	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/security/tools/keytool/standard.sh	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,8 @@
 # @test
 # @summary (almost) all keytool behaviors
 # @author Weijun Wang
+# @library /test/lib
+# @build jdk.test.lib.util.FileUtils
 # @run shell/timeout=600 standard.sh
 # @key intermittent
 
@@ -57,14 +59,22 @@
     exit 1;
     ;;
 esac
+case "$OS" in
+  Windows_* | CYGWIN* )
+    PS=";"
+    ;;
+  * )
+    PS=":"
+    ;;
+esac
 
 EXTRAOPTS="--add-exports java.base/sun.security.tools.keytool=ALL-UNNAMED \
  --add-exports java.base/sun.security.util=ALL-UNNAMED \
  --add-exports java.base/sun.security.x509=ALL-UNNAMED"
 
-${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
+${COMPILEJAVA}${FS}bin${FS}javac -classpath ${TESTCLASSPATH} ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} ${EXTRAOPTS} -d . -XDignore.symbol.file ${TESTSRC}${FS}KeyToolTest.java || exit 10
 
-echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} ${EXTRAOPTS} -Dfile KeyToolTest
+echo | ${TESTJAVA}${FS}bin${FS}java -classpath .${PS}${TESTCLASSPATH} ${TESTVMOPTS} ${EXTRAOPTS} -Dfile KeyToolTest
 status=$?
 
 exit $status
--- a/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcCapacityOutput1.awk	Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*(-|[0-9]+)$/	{
 	    datalines++;
 	}
 
--- a/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcMetaCapacityOutput1.awk	Thu Apr 26 17:59:02 2018 +0200
@@ -14,7 +14,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/	{
 	    datalines++;
 	}
 
--- a/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcNewCapacityOutput1.awk	Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*(-|[0-9]+)$/	{
 	    datalines++;
 	}
 
--- a/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcOldCapacityOutput1.awk	Thu Apr 26 17:59:02 2018 +0200
@@ -14,7 +14,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/	{
 	    datalines++;
 	}
 
--- a/test/jdk/sun/tools/jstat/gcOldOutput1.awk	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcOldOutput1.awk	Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/	{
 	    datalines++;
 	}
 
--- a/test/jdk/sun/tools/jstat/gcOutput1.awk	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/jdk/sun/tools/jstat/gcOutput1.awk	Thu Apr 26 17:59:02 2018 +0200
@@ -15,7 +15,7 @@
 	    headerlines++;
 	}
 
-/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/	{
+/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*(-|[0-9]+)[ ]*(-|[0-9]+\.[0-9]+)[ ]*[0-9]+\.[0-9]+$/	{
 	    datalines++;
 	}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestFxProperties.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8025091
+ * @summary Tests the basic selection of FX related property methods, fields,
+ *          setters and getters, by executing this test in the strict mode.
+ * @library ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester propgen.PropGen
+ * @run main TestFxProperties
+ */
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class TestFxProperties extends JavadocTester {
+
+    public static void main(String... args) throws Exception {
+        TestFxProperties tester = new TestFxProperties();
+        if (!tester.sanity()) {
+            return;
+        }
+        tester.runTests();
+    }
+
+    // Check if FX modules are available.
+    boolean sanity() {
+        ClassLoader cl = this.getClass().getClassLoader();
+        try {
+            cl.loadClass("javafx.beans.Observable");
+        } catch (ClassNotFoundException cnfe) {
+            System.out.println("Note: javafx.beans.Observable: not found, test passes vacuously");
+            return false;
+        }
+        return true;
+    }
+
+    @Test
+    void test1() throws Exception {
+        Path srcdir = Paths.get("src-propgen");
+        Files.createDirectory(srcdir);
+        new propgen.PropGen(srcdir).run();
+        Path srcfile = Paths.get(srcdir.toString(), "Demo.java");
+
+        javadoc("-d", "out-propgen",
+                "--javafx",
+                srcfile.toString());
+        checkExit(Exit.OK);
+        checkOrder("Demo.html",
+                "PROPERTY SUMMARY",
+                "Property for fgp.",
+                "Property for fgsp.",
+                "Property for fp.",
+                "Property for fsp.",
+                "Property for gp.",
+                "Property for gsp.",
+                "Property for p.",
+                "Property for sp.",
+                "FIELD SUMMARY",
+                "Field for f.",
+                "Field for fg.",
+                "Field for fgp.",
+                "Field for fgs.",
+                "Field for fgsp.",
+                "Field for fp.",
+                "Field for fs.",
+                "Field for fsp.",
+                "CONSTRUCTOR SUMMARY"
+        );
+
+        checkOrder("Demo.html",
+                "METHOD SUMMARY",
+                "Getter for fg.",
+                "Getter for fgp.",
+                "Getter for fgs.",
+                "Getter for fgsp.",
+                "Getter for g.",
+                "Getter for gp.",
+                "Getter for gs.",
+                "Getter for gsp.",
+                "Setter for fgs.",
+                "Setter for fgsp.",
+                "Setter for fs.",
+                "Setter for fsp.",
+                "Setter for gs.",
+                "Setter for gsp.",
+                "Setter for s.",
+                "Setter for sp.",
+                "Methods inherited");
+    }
+}
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java	Thu Apr 26 17:59:02 2018 +0200
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 8162363
- *      8167967 8172528 8175200 8178830 8182257 8186332 8182765
+ *      8167967 8172528 8175200 8178830 8182257 8186332 8182765 8025091
  * @summary Test of the JavaFX doclet features.
  * @author jvalenta
  * @library ../lib
@@ -45,6 +45,7 @@
         javadoc("-d", "out1",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg1");
         checkExit(Exit.OK);
@@ -174,6 +175,7 @@
                 "-html4",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg1");
         checkExit(Exit.OK);
@@ -200,6 +202,7 @@
         javadoc("-d", "out2a",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg2");
         checkExit(Exit.OK);
@@ -255,6 +258,7 @@
                 "-html4",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "pkg2");
         checkExit(Exit.OK);
@@ -390,6 +394,7 @@
     void test4() {
         javadoc("-d", "out4",
                 "--javafx",
+                "--disable-javafx-strict-checks",
                 "-Xdoclint:none",
                 "-sourcepath", testSrc,
                 "-package",
--- a/test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/pkg1/C.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -60,27 +60,28 @@
 
     public final void setRate(double value) {}
 
-    public final double getRate() {}
+    public final double getRate() { return 1.0d; }
 
-    public final DoubleProperty rateProperty() {}
+    public final DoubleProperty rateProperty() { return null; }
 
     private BooleanProperty paused;
 
     public final void setPaused(boolean value) {}
 
-    public final double isPaused() {}
+    public final double isPaused() { return 3.14d; }
 
     /**
      * Defines if paused. The second line.
      * @defaultValue false
+     * @return foo
      */
-    public final BooleanProperty pausedProperty() {}
+    public final BooleanProperty pausedProperty() { return null; }
 
     class DoubleProperty {}
 
     class BooleanProperty {}
 
-    public final BooleanProperty setTestMethodProperty() {}
+    public final BooleanProperty setTestMethodProperty() { return null; }
 
     private class Inner {
         private BooleanProperty testMethodProperty() {}
@@ -94,8 +95,8 @@
 
         public final void setRate(double value) {}
 
-        public final double getRate() {}
+        public final double getRate() { return 3.14d; }
 
-        public final DoubleProperty rateProperty() {}
+        public final DoubleProperty rateProperty() { return null; }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testJavaFX/propgen/PropGen.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2018, 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 propgen;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class PropGen {
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) throws IOException {
+        new PropGen().run();
+    }
+
+    final PrintStream out;
+
+    final Path outFile;
+    final ByteArrayOutputStream baos;
+
+    PropGen() {
+        out = System.out;
+        outFile = null;
+        baos = null;
+    }
+
+    public PropGen(Path outDir) throws IOException {
+        outFile = Paths.get(outDir.toString(), "Demo.java");
+        baos = new ByteArrayOutputStream();
+        out = new PrintStream(baos);
+    }
+
+    enum Kind {
+        FIELD(1),
+        GETTER(2),
+        SETTER(4),
+        PROPERTY(8);
+        Kind(int bit) {
+            this.bit = bit;
+        }
+        int bit;
+    }
+
+    public void run() throws IOException {
+        out.println("import javafx.beans.property.Property;");
+        out.println("public class Demo {");
+        for (int i = 1; i < 16; i++) {
+            Set<Kind> set = EnumSet.noneOf(Kind.class);
+            for (Kind k : Kind.values()) {
+                if ((i & k.bit) == k.bit) {
+                    set.add(k);
+                }
+            }
+            addItems(set);
+        }
+        out.println("}");
+        if (baos != null && outFile != null) {
+            Files.write(outFile, baos.toByteArray());
+        }
+    }
+
+    void addItems(Set<Kind> kinds) {
+        String name = kinds.stream()
+                .map(k -> k.name())
+                .map(s -> s.substring(0, 1))
+                .collect(Collectors.joining(""))
+                .toLowerCase();
+        if (kinds.contains(Kind.FIELD)) {
+            out.println("    /** Field for " + name + ". */");
+            out.println("    public Property " + name + ";");
+        }
+        if (kinds.contains(Kind.GETTER)) {
+            out.println("    /**");
+            out.println("     * Getter for " + name + ".");
+            out.println("     * @return a " + name);
+            out.println("     */");
+            out.println("    public Object " + mname("get", name) + "() { return null; }");
+        }
+        if (kinds.contains(Kind.SETTER)) {
+            out.println("    /**");
+            out.println("     * Setter for " + name + ".");
+            out.println("     * @param o a " + name);
+            out.println("     */");
+            out.println("    public void " + mname("set", name) + "(Object o) {  }");
+        }
+        if (kinds.contains(Kind.PROPERTY)) {
+            out.println("    /**");
+            out.println("     * Property for " + name + ".");
+            out.println("     * @return the property for " + name);
+            out.println("     */");
+            out.println("    public Property " + name + "Property() { return null; }");
+        }
+        out.println();
+    }
+
+    String mname(String prefix, String base) {
+        return prefix + Character.toUpperCase(base.charAt(0)) + base.substring(1);
+    }
+
+}
--- a/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testOptions/TestOptions.java	Thu Apr 26 17:59:02 2018 +0200
@@ -181,6 +181,7 @@
         javadoc("-d", "out-9",
                 "-linksource",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "-package",
                 "linksource");
@@ -254,6 +255,7 @@
                 "-html4",
                 "-linksource",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "-package",
                 "linksource");
--- a/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testOrdering/TestOrdering.java	Thu Apr 26 17:59:02 2018 +0200
@@ -578,6 +578,7 @@
         void run() {
             tester.javadoc("-d", "out-5",
                     "-javafx",
+                    "--disable-javafx-strict-checks",
                     "-sourcepath", tester.testSrc(new File(".").getPath()),
                     "pkg5"
             );
--- a/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testOverriddenMethods/TestOverrideMethods.java	Thu Apr 26 17:59:02 2018 +0200
@@ -43,6 +43,7 @@
         javadoc("-d", "out-bad-option",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "--override-methods=nonsense",
                 "pkg5");
 
@@ -55,6 +56,7 @@
         javadoc("-d", "out-detail",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "--override-methods=detail",
                 "pkg5");
 
@@ -66,6 +68,7 @@
         javadoc("-d", "out-summary",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "--override-methods=summary",
                 "pkg5");
 
--- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java	Thu Apr 26 17:59:02 2018 +0200
@@ -42,6 +42,7 @@
     void testArrays() {
         javadoc("-d", "out",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "pkg");
         checkExit(Exit.OK);
@@ -113,6 +114,7 @@
         javadoc("-d", "out-html4",
                 "-html4",
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-sourcepath", testSrc,
                 "pkg");
         checkExit(Exit.OK);
--- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java	Thu Apr 26 17:59:02 2018 +0200
@@ -285,6 +285,7 @@
         javadoc("-d", "out-9",
                 "-sourcepath", testSrc,
                 "-javafx",
+                "--disable-javafx-strict-checks",
                 "-package",
                 "-use",
                 "pkgfx", "pkg3");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/javadoc/doclet/testVisibleMembers/TestVisibleMembers.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,685 @@
+/*
+ * Copyright (c) 2002, 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8025091 8198890
+ * @summary Verify the presence visible members in the case of
+ *          member hiding and overridding.
+ * @library /tools/lib ../lib
+ * @modules jdk.javadoc/jdk.javadoc.internal.tool
+ * @build JavadocTester toolbox.ToolBox builder.ClassBuilder
+ * @run main TestVisibleMembers
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import builder.AbstractBuilder;
+import builder.AbstractBuilder.Comment.Kind;
+import builder.ClassBuilder;
+import builder.ClassBuilder.*;
+
+import toolbox.ToolBox;
+import builder.ClassBuilder;
+
+public class TestVisibleMembers extends JavadocTester {
+
+    final ToolBox tb;
+    public static void main(String... args) throws Exception {
+        TestVisibleMembers tester = new TestVisibleMembers();
+        tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
+    }
+
+    TestVisibleMembers() {
+        tb = new ToolBox();
+    }
+
+    @Test
+    void testChronoDiamondLeafDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitChronoDiamondLeaf(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.C",
+                "C", "with", "java.lang.Object", "obj",  "Method with in p.C",
+                "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.C",
+                "METHOD DETAIL");
+        checkOutput("p/C.html", false, "BImpl");
+
+        checkOrder("p/E.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.E",
+                "C", "with", "java.lang.Object", "Method with in p.E",
+                "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.E",
+                "METHOD DETAIL");
+        checkOutput("p/E.html", false, "EImpl");
+    }
+
+    @Test
+    void testChronoDiamondLeafSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitChronoDiamondLeaf(srcDir);
+
+        Path outDir = base.resolve("out-member");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.C",
+                "C", "with", "java.lang.Object", "obj", "Method with in p.C",
+                "C", "with", "java.lang.Object", "obj", "long", "lvalue", "Method with in p.C",
+                "METHOD DETAIL");
+        checkOutput("p/C.html", false, "BImpl");
+
+        checkOrder("p/E.html", "METHOD SUMMARY",
+                "boolean", "equals", "java.lang.Object", "Method equals in p.E",
+                "C", "with", "java.lang.Object", "Method with in p.E",
+                "C", "with", "java.lang.Object", "long", "lvalue", "Method with in p.E",
+                "METHOD DETAIL");
+        checkOutput("p/E.html", false, "EImpl");
+    }
+
+    // see j.t.TemporalAdjuster
+    void emitChronoDiamondLeaf(Path srcDir) throws Exception {
+
+        // Interface A
+        MethodBuilder mbWith1 = MethodBuilder
+                .parse("default Object with(Object obj) {return null;}");
+        MethodBuilder mbWith2 = MethodBuilder
+                .parse("default Object with(Object obj, long lvalue) {return null;}");
+
+        new ClassBuilder(tb, "p.A")
+                .setModifiers("public", "interface")
+                .addMembers(mbWith1, mbWith2)
+                .write(srcDir);
+
+        // Interface B
+        mbWith1.setComments("{@inheritDoc}", "@param obj an object",
+                "@return something");
+
+        mbWith2.setComments("{@inheritDoc}", "@param obj an object",
+                "@param lvalue an lvalue", "@return something");
+
+        new ClassBuilder(tb, "p.B")
+                .setModifiers( "public", "interface")
+                .setExtends("A")
+                .addMembers(mbWith1, mbWith2)
+                .write(srcDir);
+
+        // Class BImpl
+        MethodBuilder mb31 = MethodBuilder.parse("C with(Object obj) {return null;}");
+        MethodBuilder mb32 = MethodBuilder.parse("C with(Object obj, Long lobj) {return null;}");
+        new ClassBuilder(tb, "p.BImpl<C extends B>")
+                .setModifiers( "abstract", "class")
+                .addImplements("B")
+                .addMembers(mb31, mb32)
+                .write(srcDir);
+
+        // Class C
+        new ClassBuilder(tb, "p.C")
+                .setModifiers("public", "class")
+                .setExtends("BImpl")
+                .addMembers(mbWith1.setReturn("C")
+                        .setModifiers("public")
+                        .setComments(AbstractBuilder.Comment.Kind.AUTO))
+                .addMembers(mbWith2.setReturn("C")
+                        .setModifiers("public")
+                        .setComments(AbstractBuilder.Comment.Kind.AUTO))
+                .addMembers(MethodBuilder.parse("public boolean equals(Object obj) { return false;}"))
+                .write(srcDir);
+
+        // Class EImpl
+        MethodBuilder mb41 = MethodBuilder.parse("C with(Object obj) {return null;}")
+                .setComments(Kind.NO_API_COMMENT);
+        MethodBuilder mb42 = MethodBuilder.parse("C with(Object obj, Long lobj) {return null;}");
+        new ClassBuilder(tb, "p.EImpl<C extends B>")
+                .setModifiers( "abstract", "class")
+                .addImplements("B")
+                .addMembers(mb41, mb42)
+                .write(srcDir);
+
+        // Class E
+        MethodBuilder mb51 = MethodBuilder.parse("public C with(Object obj) {return null;}");
+        MethodBuilder mb52 = MethodBuilder.parse("public C with(Object obj, long lvalue) {return null;}");
+        MethodBuilder mb53 = MethodBuilder.parse("public boolean equals(Object obj) { return false;}");
+        new ClassBuilder(tb, "p.E")
+                .setModifiers("public", "class")
+                .setExtends("EImpl")
+                .addMembers(mb51, mb52, mb53)
+                .write(srcDir);
+    }
+
+    @Test
+    void testNestedInterfaceDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitNestedInterface(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/TA.html", false, "getTA");
+
+        checkOrder("p/Bar.html",
+                "doSomething()",
+                "getTA()");
+    }
+
+    @Test
+    void testNestedInterfaceSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitNestedInterface(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOutput("p/TA.html", false, "getTA");
+
+        checkOrder("p/Bar.html",
+                "doSomething()",
+                "getTA()");
+
+        checkOrder("p/Foo.html",
+                "Methods declared in",
+                "Bar.html",
+                "getTA");
+    }
+
+    // See jx.s.TransferHandler
+    void emitNestedInterface(Path srcDir) throws Exception {
+
+        ClassBuilder innerI = new ClassBuilder(tb, "HasTA")
+                .setModifiers("interface");
+        MethodBuilder interfaceMethod = MethodBuilder.parse("public TA getTa();")
+                .setComments(Kind.NO_API_COMMENT);
+        innerI.addMembers(interfaceMethod);
+
+        new ClassBuilder(tb, "p.TA")
+                .setModifiers("public", "class")
+                .addImplements("java.io.Serializable")
+                .addNestedClasses(innerI)
+                .write(srcDir);
+
+        new ClassBuilder(tb, "p.Foo")
+                .setModifiers("public", "class")
+                .setExtends("Bar")
+                .write(srcDir);
+
+        new ClassBuilder(tb, "p.Bar")
+                .setModifiers("public", "abstract", "class")
+                .addImplements("TA.HasTA")
+                .addMembers(
+                    MethodBuilder.parse("public void doSomething(){}"),
+                    MethodBuilder.parse("public TA getTA(){return null;}")
+                ).write(srcDir);
+    }
+
+    @Test
+    void testStreamsMissingLinksDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitStreamsMissingLinks(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "method()",
+                "See Also:",
+                "sub()",
+                "sub1()");
+
+        checkOrder("p/ILong.html",
+                "METHOD DETAIL",
+                "default", "void", "forEach", "java.util.function.Consumer",
+                "java.lang.Long", "action",
+                "Do you see me", "#forEach(java.util.function.LongConsumer)",
+                "forEach(LongConsumer)",
+                "END OF CLASS DATA");
+
+        checkOrder("p/IImpl.html",
+                "METHOD DETAIL",
+                "Method sub in p.IImpl",
+                "Specified by:", "I.html", "II.html",
+                "END OF CLASS DATA");
+    }
+
+    @Test
+    void testStreamsMissingLinksSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitStreamsMissingLinks(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "method()", "See Also:", "sub()", "I.sub1()",
+                "public", "void", "m", "Method in C. See", "I.length()"
+                );
+
+        checkOrder("p/ILong.html",
+                "METHOD DETAIL",
+                "default", "void", "forEach", "java.util.function.Consumer",
+                "java.lang.Long", "action",
+                "Do you see me", "QLong.html#forEach(Q)",
+                "QLong.forEach(LongConsumer)",
+                "END OF CLASS DATA");
+
+        checkOrder("p/IImpl.html",
+                "METHOD DETAIL",
+                "Method sub in p.IImpl",
+                "Specified by:", "I.html",
+                "END OF CLASS DATA");
+
+        checkUnique("p/IImpl.html", "Specified by:");
+    }
+
+    // see j.u.Spliterator
+    void emitStreamsMissingLinks(Path srcDir) throws Exception {
+        new ClassBuilder(tb, "p.I")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        MethodBuilder.parse("public I sub();"),
+                        MethodBuilder.parse("public I sub1();"),
+                        MethodBuilder.parse("public int length();")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.A")
+                .setModifiers("abstract", "class")
+                .addImplements("I")
+                .addMembers(
+                        MethodBuilder.parse("public I sub() {}"),
+                        MethodBuilder.parse("public I sub1() {}"),
+                        MethodBuilder.parse("public int length(){return 0;}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void m(){}")
+                        .setComments("Method in C. See {@link #length()}.")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.C")
+                .setModifiers("public", "class")
+                .setExtends("A").addImplements("I")
+                .addMembers(
+                        MethodBuilder.parse("public I sub() {return null;}"),
+                        MethodBuilder.parse("public I sub1() {return null;}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse(" public void method() {}")
+                                .setComments("A method ", "@see #sub", "@see #sub1"),
+                        MethodBuilder.parse("public int length(){return 1;}")
+                                .setComments(Kind.NO_API_COMMENT)
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.II")
+                .setModifiers("public", "interface")
+                .setExtends("I")
+                .addMembers(
+                        MethodBuilder.parse("default public I sub() {return null;}")
+                            .setComments(Kind.NO_API_COMMENT)
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.IImpl")
+                .setModifiers("public", "class")
+                .addImplements("II")
+                .addMembers(
+                    MethodBuilder.parse("public I sub() {return null;}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.QLong<P, Q, R>")
+                .setModifiers("public interface")
+                .addMembers(
+                        MethodBuilder.parse("default void forEach(Q action) {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.ILong")
+                .addImports("java.util.function.*")
+                .setModifiers("public", "interface")
+                .setExtends("QLong<Long, LongConsumer, Object>")
+                .addMembers(
+                        MethodBuilder.parse("default void forEach(LongConsumer action) {}")
+                            .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("default void forEach(Consumer<Long> action) {}")
+                            .setComments("Do you see me {@link #forEach(LongConsumer)} ?")
+                ).write(srcDir);
+    }
+
+    @Test
+    void testVisibleMemberTableDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitVisibleMemberTable(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "m()", "Method m in p.B",
+                "public", "void", "n()", "Method n in p.A",
+                "public", "void", "o()", "Description copied from class:", ">A<", "Method o in p.A",
+                "public", "void", "p()", "Method p in p.B",
+                "END OF CLASS DATA");
+
+        checkOutput("p/C.html", false,
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/D.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.D",
+                "void", "n", "Method n in p.D",
+                "void", "o", "Method o in p.D",
+                "void", "p", "Method p in p.D",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/D.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/E.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.B",
+                "void", "n", "Method n in p.A",
+                "void", "o", "Method o in p.A",
+                "void", "p", "Method p in p.B",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/E.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+    }
+
+    @Test
+    void testVisibleMemberTableSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitVisibleMemberTable(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.B",
+                "void", "n", "Method n in p.A",
+                "void", "o", "Method o in p.A",
+                "void", "p", "Method p in p.B",
+                "CONSTRUCTOR DETAIL");
+
+        checkOrder("p/C.html",
+                "METHOD DETAIL",
+                "public", "void", "m()", "Method m in p.B",
+                "public", "void", "n()", "Method n in p.A",
+                "public", "void", "o()", "Description copied from class:", ">A<", "Method o in p.A",
+                "public", "void", "p()", "Method p in p.B",
+                "END OF CLASS DATA");
+
+        checkOutput("p/C.html", false,
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/D.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.D",
+                "void", "n", "Method n in p.D",
+                "void", "o", "Method o in p.D",
+                "void", "p", "Method p in p.D",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/D.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+
+        checkOrder("p/E.html",
+                "METHOD SUMMARY",
+                "void", "m", "Method m in p.B",
+                "void", "n", "Method n in p.A",
+                "void", "o", "Method o in p.A",
+                "void", "p", "Method p in p.B",
+                "CONSTRUCTOR DETAIL");
+
+        checkOutput("p/E.html", false,
+                "Description copied from class:",
+                "Overrides",
+                "Methods declared in class p");
+
+    }
+
+    // emit a matrix of method variants
+    void emitVisibleMemberTable(Path srcDir) throws Exception {
+        new ClassBuilder(tb, "p.A")
+                .setModifiers("public", "class")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}"),
+                        MethodBuilder.parse("public void n() {}"),
+                        MethodBuilder.parse("public void o() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.B")
+                .setModifiers("class")
+                .setExtends("A")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}"),
+                        MethodBuilder.parse("public void n() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void o() {}")
+                        .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void p() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.C")
+                .setModifiers("public", "class")
+                .setExtends("B")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void n() {}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void o() {}")
+                                .setComments(Kind.NO_API_COMMENT),
+                        MethodBuilder.parse("public void p() {}")
+                                .setComments(Kind.NO_API_COMMENT)
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.D")
+                .setModifiers("public", "class")
+                .setExtends("B")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}"),
+                        MethodBuilder.parse("public void n() {}"),
+                        MethodBuilder.parse("public void o() {}"),
+                        MethodBuilder.parse("public void p() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.E")
+                .setModifiers("public", "class")
+                .setExtends("B")
+                .addMembers(
+                        MethodBuilder.parse("public void m() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void n() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void o() {}")
+                                .setComments(Kind.INHERIT_DOC),
+                        MethodBuilder.parse("public void p() {}")
+                                .setComments(Kind.INHERIT_DOC)
+                ).write(srcDir);
+    }
+
+    @Test
+    void testHiddenMembersDetail(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitHiddenMembers(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=detail",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C1.html",
+                "FIELD SUMMARY",
+                "Fields inherited from interface", "I1", "field2",
+                "Fields inherited from interface", "I2", "field2",
+                "Fields inherited from interface", "I3", "field",
+                "METHOD SUMMARY",
+                "Methods inherited from interface", "I1", "method2",
+                "Methods inherited from interface", "I2", "method2",
+                "Methods inherited from interface", "I3", "method",
+                "CONSTRUCTOR DETAIL");
+
+        checkOrder("p/C2.html",
+                "FIELD SUMMARY",
+                "int", "field", "Field field in p.C2",
+                "Fields inherited from interface", "I1", "field2",
+                "Fields inherited from interface", "I2", "field2",
+                "METHOD SUMMARY",
+                "void", "method", "Method method in p.C2",
+                "void", "method2", "Method method2 in p.C2");
+
+    }
+
+    @Test
+    void testHiddenMembersSummary(Path base) throws Exception {
+        Path srcDir = base.resolve("src");
+        emitHiddenMembers(srcDir);
+
+        Path outDir = base.resolve("out");
+        javadoc("-d", outDir.toString(),
+                "-html5",
+                "--override-methods=summary",
+                "-sourcepath", srcDir.toString(),
+                "p");
+        checkExit(Exit.OK);
+
+        checkOrder("p/C1.html",
+                "Field Summary",
+                "Fields declared in interface", "I1", "field2",
+                "Fields declared in interface", "I2", "field2",
+                "Fields declared in interface", "I3", "field",
+                "Method Summary",
+                "Methods declared in interface", "I1", "method2",
+                "Methods declared in interface", "I2", "method2",
+                "Methods declared in interface", "I3", "method",
+                "Constructor Detail");
+
+        checkOrder("p/C2.html",
+                "Field Summary",
+                "int", "field", "Field field in p.C2",
+                "Fields declared in interface", "I1", "field2",
+                "Fields declared in interface", "I2", "field2",
+                "Method Summary",
+                "void", "method", "Method method in p.C2",
+                "void", "method2", "Method method2 in p.C2");
+
+    }
+
+    void emitHiddenMembers(Path srcDir) throws Exception {
+        new ClassBuilder(tb, "p.I1")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        FieldBuilder.parse("public static int field = 3;"),
+                        FieldBuilder.parse("public static int field2 = 3;"),
+                        MethodBuilder.parse("public void method();"),
+                        MethodBuilder.parse("public void method2();"),
+                        MethodBuilder.parse("public static void staticMethod() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.I2")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        FieldBuilder.parse("public static int field = 3;"),
+                        FieldBuilder.parse("public static int field2 = 3;"),
+                        MethodBuilder.parse("public void method();"),
+                        MethodBuilder.parse("public void method2();"),
+                        MethodBuilder.parse("public static void staticMethod() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.I3")
+                .setExtends("I1, I2")
+                .setModifiers("public", "interface")
+                .addMembers(
+                        FieldBuilder.parse("public static int field = 3;"),
+                        MethodBuilder.parse("public void method();"),
+                        MethodBuilder.parse("public static void staticMethod() {}")
+                ).write(srcDir);
+
+        new ClassBuilder(tb, "p.C1")
+                .setModifiers("public", "abstract", "class")
+                .addImplements("I3")
+                .write(srcDir);
+
+        new ClassBuilder(tb, "p.C2")
+                .setExtends("C1")
+                .setModifiers("public", "abstract", "class")
+                .addMembers(
+                        FieldBuilder.parse("public int field;"),
+                        MethodBuilder.parse("public void method(){}"),
+                        MethodBuilder.parse("public void method2(){}")
+                ).write(srcDir);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/jdk/jshell/ToolEnablePreviewTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8199193
+ * @summary Tests for the --enable-preview option
+ * @run testng ToolEnablePreviewTest
+ */
+
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertTrue;
+
+public class ToolEnablePreviewTest extends ReplToolTesting {
+
+    @Test
+    public void testOptionDebug() {
+        String release = System.getProperty("java.specification.version");
+        test(
+                (a) -> assertCommand(a, "/debug b",
+                        "RemoteVM Options: []\n"
+                        + "Compiler options: []"),
+                (a) -> assertCommand(a, "/env --enable-preview",
+                        "|  Setting new options and restoring state."),
+                (a) -> assertCommandCheckOutput(a, "/debug b", s -> {
+                    assertTrue(s.contains("RemoteVM Options: [--enable-preview]"));
+                    assertTrue(s.contains("Compiler options: [-source, " + release + ", --enable-preview]")
+                            || s.contains("Compiler options: [--enable-preview, -source, " + release + "]"),
+                            "\nExpected -- " + "Compiler options: [-source, " + release + ", --enable-preview]"
+                            + "\nOr -- " + "Compiler options: [--enable-preview, -source, " + release + "]"
+                            + "\nBut got -- " + s);
+                })
+        );
+    }
+
+    @Test
+    public void testCommandLineFlag() {
+        String release = System.getProperty("java.specification.version");
+        test(new String[] {"--enable-preview"},
+                (a) -> assertCommandCheckOutput(a, "/debug b", s -> {
+                    assertTrue(s.contains("RemoteVM Options: [--enable-preview]"));
+                    assertTrue(s.contains("Compiler options: [-source, " + release + ", --enable-preview]")
+                            || s.contains("Compiler options: [--enable-preview, -source, " + release + "]"),
+                            "\nExpected -- " + "Compiler options: [-source, " + release + ", --enable-preview]"
+                            + "\nOr -- " + "Compiler options: [--enable-preview, -source, " + release + "]"
+                            + "\nBut got -- " + s);
+                })
+        );
+    }
+
+    @Test
+    public void testCompilerTestFlagEnv() {
+        test(new String[] {"-C", "-XDforcePreview"},
+                (a) -> assertCommandOutputContains(a, "Function<Integer,Integer> f = i -> i + i",
+                        "Error", "preview feature"),
+                (a) -> assertCommand(a, "/env --enable-preview",
+                        "|  Setting new options and restoring state."),
+                (a) -> assertCommandOutputContains(a, "Function<Integer,Integer> f = i -> i + i",
+                        "f ==> ")
+        );
+    }
+
+    @Test
+    public void testCompilerTestFlag() {
+        test(new String[] {"-C", "-XDforcePreview", "--enable-preview"},
+                (a) -> assertCommandOutputContains(a, "Function<Integer,Integer> f = i -> i + i",
+                        "f ==> "),
+                (a) -> assertCommandOutputContains(a, "f.apply(2)", "==> 4")
+        );
+    }
+
+}
--- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_1.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_1.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, T6722234d.A,java.lang.Object, T6722234d.B,T6722234d.A)
+T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: T6722234d.A,java.lang.Object), (compiler.misc.lower.bounds: T6722234d.B,T6722234d.A))
 - compiler.misc.where.description.typevar: Z,{(compiler.misc.where.typevar: Z, java.lang.Object, kindname.method, <Z>m(Z,Z))}
 1 error
--- a/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_2.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/Diagnostics/6722234/T6722234d_2.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, T6722234d.A,Object, T6722234d.B,T6722234d.A)
+T6722234d.java:18:20: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: T6722234d.A,Object), (compiler.misc.lower.bounds: T6722234d.B,T6722234d.A))
 - compiler.misc.where.description.typevar: Z,{(compiler.misc.where.typevar: Z, Object, kindname.method, <Z>m(Z,Z))}
 1 error
--- a/test/langtools/tools/javac/Diagnostics/6799605/T6799605.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/Diagnostics/6799605/T6799605.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.incompatible.eq.upper.bounds: T, compiler.misc.type.captureof: 1, ?, T6799605<T>)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
+T6799605.java:17:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.incompatible.bounds: T, (compiler.misc.eq.bounds: compiler.misc.type.captureof: 1, ?), (compiler.misc.upper.bounds: T6799605<T>))),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
 T6799605.java:18:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.incompatible.eq.bounds: T, compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T))}
 T6799605.java:19:9: compiler.err.cant.apply.symbols: kindname.method, m, T6799605<compiler.misc.type.captureof: 1, ?>,T6799605<compiler.misc.type.captureof: 2, ?>,T6799605<compiler.misc.type.captureof: 3, ?>,{(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.method, T6799605, <T>m(T6799605<T>,T6799605<T>,T6799605<T>), (compiler.misc.incompatible.eq.bounds: T, compiler.misc.type.captureof: 3, ?,compiler.misc.type.captureof: 2, ?,compiler.misc.type.captureof: 1, ?))}
 3 errors
--- a/test/langtools/tools/javac/T8171325/NPEClearingLocalClassNameIndexesTest.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/T8171325/NPEClearingLocalClassNameIndexesTest.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,6 +1,6 @@
-NPEClearingLocalClassNameIndexesTest.java:18:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.upper.lower.bounds: C, java.lang.Object,java.util.List<A>, java.lang.String)
+NPEClearingLocalClassNameIndexesTest.java:18:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.bounds: C, (compiler.misc.upper.bounds: java.lang.Object,java.util.List<A>), (compiler.misc.lower.bounds: java.lang.String))
 NPEClearingLocalClassNameIndexesTest.java:18:42: compiler.err.cant.resolve.location: kindname.class, NoSuch, , , (compiler.misc.location: kindname.class, NPEClearingLocalClassNameIndexesTest, null)
-NPEClearingLocalClassNameIndexesTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.upper.lower.bounds: C, java.lang.Object,java.util.List<A>, java.lang.String)
+NPEClearingLocalClassNameIndexesTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, f, java.util.List<A>, java.lang.String, kindname.class, NPEClearingLocalClassNameIndexesTest, (compiler.misc.incompatible.bounds: C, (compiler.misc.upper.bounds: java.lang.Object,java.util.List<A>), (compiler.misc.lower.bounds: java.lang.String))
 NPEClearingLocalClassNameIndexesTest.java:19:42: compiler.err.cant.resolve.location: kindname.class, NoSuch, , , (compiler.misc.location: kindname.class, NPEClearingLocalClassNameIndexesTest, null)
 NPEClearingLocalClassNameIndexesTest.java:19:49: compiler.err.type.found.req: int, (compiler.misc.type.req.ref)
 5 errors
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8201281/NullInErrorMessageTest.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,30 @@
+/*
+ * @test  /nodynamiccopyright/
+ * @bug 8201281
+ * @summary Truncated error message with Incompatible : null
+ * @compile/fail/ref=NullInErrorMessageTest.out -XDrawDiagnostics NullInErrorMessageTest.java
+ */
+
+import java.util.concurrent.CompletionStage;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+public class NullInErrorMessageTest {
+    private CompletionStage<String> test() {
+        return null;
+    }
+
+    private CompletionStage<Integer> test2() {
+        return null;
+    }
+
+    public static <T> Function<Throwable, T> test3() {
+        return null;
+    }
+
+    private Supplier<CompletionStage<Integer>> createSupplier() {
+        return () -> test().thenCompose(value -> {
+            return () -> test2().exceptionally(test3());
+        });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/T8201281/NullInErrorMessageTest.out	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,2 @@
+NullInErrorMessageTest.java:26:40: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.infer.no.conforming.assignment.exists: U, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.not.a.functional.intf.1: java.util.concurrent.CompletionStage, (compiler.misc.incompatible.abstracts: kindname.interface, java.util.concurrent.CompletionStage)))))
+1 error
--- a/test/langtools/tools/javac/boxing/BoxingCaching.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/boxing/BoxingCaching.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2018, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 4990346
+ * @bug 4990346 8200478
  * @summary Verify autoboxed values are cached as required.
  * @author Joseph D. Darcy
  */
@@ -155,7 +155,7 @@
             Long L = (long)(i-128);
             if (L != results[i]) {
                 cached = false;
-                System.err.println("Integer value " + L +
+                System.err.println("Long value " + L +
                                    " is not cached appropriately.");
             }
         }
--- a/test/langtools/tools/javac/diags/examples.not-yet.txt	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples.not-yet.txt	Thu Apr 26 17:59:02 2018 +0200
@@ -73,7 +73,6 @@
 compiler.misc.kindname.type.variable
 compiler.misc.kindname.type.variable.bound
 compiler.misc.kindname.value
-compiler.misc.incompatible.eq.lower.bounds              # cannot happen?
 compiler.misc.module.name.mismatch
 compiler.misc.module.non.zero.opens                     # bad class file
 compiler.misc.no.unique.minimal.instance.exists
@@ -151,6 +150,7 @@
 compiler.misc.locn.module_source_path                         # fragment uninteresting in and of itself
 compiler.misc.locn.system_modules                             # fragment uninteresting in and of itself
 compiler.misc.locn.upgrade_module_path                        # fragment uninteresting in and of itself
+compiler.misc.inferred.do.not.conform.to.eq.bounds            # hard to generate, could probably be removed
 
 # The following are new module-related messages, that need new  examples to be created
 compiler.err.duplicate.module.on.path
--- a/test/langtools/tools/javac/diags/examples/CantApplyDiamond1.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/CantApplyDiamond1.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -23,7 +23,9 @@
 
 // key: compiler.err.prob.found.req
 // key: compiler.misc.cant.apply.diamond.1
-// key: compiler.misc.incompatible.eq.upper.bounds
+// key: compiler.misc.incompatible.bounds
+// key: compiler.misc.eq.bounds
+// key: compiler.misc.upper.bounds
 // key: compiler.misc.diamond
 
 class CantApplyDiamond1<X> {
--- a/test/langtools/tools/javac/diags/examples/IncompatibleEqUpperBounds.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/IncompatibleEqUpperBounds.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018, 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
@@ -22,7 +22,9 @@
  */
 
 //key: compiler.err.cant.apply.symbol
-//key: compiler.misc.incompatible.eq.upper.bounds
+//key: compiler.misc.incompatible.bounds
+//key: compiler.misc.eq.bounds
+//key: compiler.misc.upper.bounds
 
 import java.util.List;
 
--- a/test/langtools/tools/javac/diags/examples/InferredDoNotConformToEq.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/InferredDoNotConformToEq.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -22,7 +22,8 @@
  */
 
 // key: compiler.err.cant.apply.symbol
-// key: compiler.misc.inferred.do.not.conform.to.eq.bounds
+// key: compiler.misc.inconvertible.types
+// key: compiler.misc.infer.no.conforming.assignment.exists
 // options: -source 7 -Xlint:-options
 
 import java.util.*;
--- a/test/langtools/tools/javac/diags/examples/InferredDoNotConformToUpper.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/InferredDoNotConformToUpper.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -22,7 +22,8 @@
  */
 
 // key: compiler.err.cant.apply.symbol
-// key: compiler.misc.inferred.do.not.conform.to.upper.bounds
+// key: compiler.misc.inconvertible.types
+// key: compiler.misc.infer.no.conforming.assignment.exists
 // options: -source 7 -Xlint:-options
 
 import java.util.*;
--- a/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/diags/examples/WhereTypeVar2.java	Thu Apr 26 17:59:02 2018 +0200
@@ -21,10 +21,12 @@
  * questions.
  */
 
-// key: compiler.misc.incompatible.upper.lower.bounds
+// key: compiler.misc.incompatible.bounds
 // key: compiler.misc.where.description.typevar
 // key: compiler.misc.where.typevar
 // key: compiler.err.prob.found.req
+// key: compiler.misc.lower.bounds
+// key: compiler.misc.upper.bounds
 // options: --diags=formatterOptions=where
 // run: simple
 
--- a/test/langtools/tools/javac/generics/UnsoundInference.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/UnsoundInference.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-UnsoundInference.java:18:9: compiler.err.cant.apply.symbol: kindname.method, transferBug, Var[],java.util.Collection<Var>, java.lang.Object[],java.util.ArrayList<java.lang.String>, kindname.class, UnsoundInference, (compiler.misc.incompatible.eq.lower.bounds: Var, java.lang.String, java.lang.Object)
+UnsoundInference.java:18:9: compiler.err.cant.apply.symbol: kindname.method, transferBug, Var[],java.util.Collection<Var>, java.lang.Object[],java.util.ArrayList<java.lang.String>, kindname.class, UnsoundInference, (compiler.misc.incompatible.bounds: Var, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.lower.bounds: java.lang.Object))
 1 error
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg06.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg06.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-Neg06.java:18:36: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.IFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
-Neg06.java:19:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
-Neg06.java:20:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number))
+Neg06.java:18:36: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.IFoo), (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number)))
+Neg06.java:19:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number)))
+Neg06.java:20:37: compiler.err.prob.found.req: (compiler.misc.cant.apply.diamond.1: (compiler.misc.diamond: Neg06.CFoo), (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number)))
 3 errors
--- a/test/langtools/tools/javac/generics/diamond/neg/Neg07.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/diamond/neg/Neg07.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-Neg07.java:17:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String)
-Neg07.java:18:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String)
+Neg07.java:17:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String))
+Neg07.java:18:27: compiler.err.cant.apply.diamond.1: (compiler.misc.diamond: Neg07.Foo), (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String))
 2 errors
--- a/test/langtools/tools/javac/generics/inference/4941882/T4941882.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/4941882/T4941882.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T4941882.java:13:17: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: T, java.lang.Object[],java.lang.Object, float[],int[])
+T4941882.java:13:17: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: java.lang.Object[],java.lang.Object), (compiler.misc.lower.bounds: float[],int[]))
 1 error
--- a/test/langtools/tools/javac/generics/inference/6315770/T6315770.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6315770/T6315770.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
 T6315770.java:16:42: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.bounds: T, java.lang.String,java.lang.Integer,java.lang.Runnable)
-T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: T, java.lang.Integer,java.lang.Runnable, java.lang.String)
+T6315770.java:17:40: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: java.lang.Integer,java.lang.Runnable), (compiler.misc.lower.bounds: java.lang.String))
 2 errors
--- a/test/langtools/tools/javac/generics/inference/6611449/T6611449.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6611449/T6611449.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
-T6611449.java:18:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.infer.arg.length.mismatch: T))}
-T6611449.java:19:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer))}
-T6611449.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, T, int, kindname.class, T6611449<S>, (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer)
-T6611449.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, T,T, int,int, kindname.class, T6611449<S>, (compiler.misc.incompatible.upper.lower.bounds: T, S, java.lang.Integer)
+T6611449.java:18:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.infer.arg.length.mismatch: T))}
+T6611449.java:19:9: compiler.err.cant.apply.symbols: kindname.constructor, T6611449, int,int,{(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T), (compiler.misc.infer.arg.length.mismatch: T)),(compiler.misc.inapplicable.method: kindname.constructor, T6611449, <T>T6611449(T,T), (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer)))}
+T6611449.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m1, T, int, kindname.class, T6611449<S>, (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer))
+T6611449.java:21:9: compiler.err.cant.apply.symbol: kindname.method, m2, T,T, int,int, kindname.class, T6611449<S>, (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: S), (compiler.misc.lower.bounds: java.lang.Integer))
 4 errors
--- a/test/langtools/tools/javac/generics/inference/6638712/T6638712b.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6638712/T6638712b.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.Integer, java.lang.String,java.lang.Object)
+T6638712b.java:14:21: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: T, (compiler.misc.eq.bounds: java.lang.Integer), (compiler.misc.upper.bounds: java.lang.String,java.lang.Object))
 1 error
--- a/test/langtools/tools/javac/generics/inference/6638712/T6638712d.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6638712/T6638712d.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.incompatible.eq.lower.bounds: U, java.lang.String, java.lang.Integer)
+T6638712d.java:16:9: compiler.err.cant.apply.symbol: kindname.method, m, U,java.util.List<java.util.List<U>>, int,java.util.List<java.util.List<java.lang.String>>, kindname.class, T6638712d, (compiler.misc.incompatible.bounds: U, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.lower.bounds: java.lang.Integer))
 1 error
--- a/test/langtools/tools/javac/generics/inference/6638712/T6638712e.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6638712/T6638712e.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Boolean,java.lang.Object)
+T6638712e.java:17:27: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Object), (compiler.misc.upper.bounds: java.lang.Boolean,java.lang.Object))
 1 error
--- a/test/langtools/tools/javac/generics/inference/6650759/T6650759m.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/6650759/T6650759m.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Integer,java.lang.Object, java.lang.String)
+T6650759m.java:43:36: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Integer,java.lang.Object), (compiler.misc.lower.bounds: java.lang.String))
 1 error
--- a/test/langtools/tools/javac/generics/inference/7177306/T7177306b.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/7177306/T7177306b.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T7177306b.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<? super T>,S,java.lang.Class<java.lang.Object>, java.util.List<java.lang.Integer>,java.util.List<java.lang.String>,java.lang.Class, kindname.class, T7177306b, (compiler.misc.incompatible.eq.upper.bounds: T, java.lang.String, java.lang.Integer,java.lang.Object)
+T7177306b.java:15:9: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<? super T>,S,java.lang.Class<java.lang.Object>, java.util.List<java.lang.Integer>,java.util.List<java.lang.String>,java.lang.Class, kindname.class, T7177306b, (compiler.misc.incompatible.bounds: T, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Integer,java.lang.Object))
 1 error
--- a/test/langtools/tools/javac/generics/inference/7177306/T7177306e.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/7177306/T7177306e.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T7177306e.java:16:8: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<U>, java.util.List<java.util.List<?>>, kindname.class, T7177306e, (compiler.misc.incompatible.eq.upper.bounds: U, java.util.List<?>, java.util.List<compiler.misc.type.captureof: 1, ?>)
+T7177306e.java:16:8: compiler.err.cant.apply.symbol: kindname.method, m, java.util.List<U>, java.util.List<java.util.List<?>>, kindname.class, T7177306e, (compiler.misc.inferred.do.not.conform.to.eq.bounds: java.lang.Object, compiler.misc.type.captureof: 1, ?)
 1 error
--- a/test/langtools/tools/javac/generics/inference/8019824/T8019824.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/8019824/T8019824.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T8019824.java:9:25: compiler.err.cant.apply.symbol: kindname.method, make, java.lang.Class<C>, java.lang.Class<compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>>, kindname.class, T8019824, (compiler.misc.incompatible.eq.upper.bounds: C, compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>, T8019824.Foo<A,B>)
+T8019824.java:9:25: compiler.err.cant.apply.symbol: kindname.method, make, java.lang.Class<C>, java.lang.Class<compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>>, kindname.class, T8019824, (compiler.misc.incompatible.bounds: C, (compiler.misc.eq.bounds: compiler.misc.type.captureof: 1, ? extends T8019824.Foo<?,?>), (compiler.misc.upper.bounds: T8019824.Foo<A,B>))
 1 error
--- a/test/langtools/tools/javac/generics/inference/8062977/T8062977.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/8062977/T8062977.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
-T8062977.java:15:31: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<java.lang.Integer>[]&java.lang.Iterable<?>, java.util.List<java.lang.Integer>[],java.lang.Iterable<?>,java.lang.Object)
-T8062977.java:21:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Iterable<?>[]&java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>,java.lang.Iterable<?>[],java.lang.Object)
-T8062977.java:26:31: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.util.List<java.lang.Integer>[], java.util.List<java.lang.Integer>[],java.lang.Iterable<?>[][],java.lang.Object)
-T8062977.java:27:29: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Iterable<?>[][]&java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>,java.lang.Iterable<?>[][],java.lang.Object)
+T8062977.java:15:31: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>>, java.lang.Class<java.lang.Object>))
+T8062977.java:21:29: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>[]>, java.lang.Class<java.lang.Object>))
+T8062977.java:26:31: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>[][]>, java.lang.Class<java.lang.Object>))
+T8062977.java:27:29: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,B, (compiler.misc.inconvertible.types: java.lang.Class<java.lang.Iterable<?>[][]>, java.lang.Class<java.lang.Object>))
 4 errors
--- a/test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/inference/EagerReturnTypeResolution/PrimitiveTypeBoxingTest.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-PrimitiveTypeBoxingTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, m1, PrimitiveTypeBoxingTest.F<Z>,Z, @12,int, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Long,java.lang.Object, java.lang.Integer)
-PrimitiveTypeBoxingTest.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m2, Z,PrimitiveTypeBoxingTest.F<Z>, int,@16, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Long,java.lang.Object, java.lang.Integer)
+PrimitiveTypeBoxingTest.java:19:9: compiler.err.cant.apply.symbol: kindname.method, m1, PrimitiveTypeBoxingTest.F<Z>,Z, @12,int, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Long,java.lang.Object), (compiler.misc.lower.bounds: java.lang.Integer))
+PrimitiveTypeBoxingTest.java:20:9: compiler.err.cant.apply.symbol: kindname.method, m2, Z,PrimitiveTypeBoxingTest.F<Z>, int,@16, kindname.class, PrimitiveTypeBoxingTest, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Long,java.lang.Object), (compiler.misc.lower.bounds: java.lang.Integer))
 2 errors
--- a/test/langtools/tools/javac/generics/odersky/BadTest3.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/odersky/BadTest3.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-BadTest3.java:31:34: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: B, java.lang.String, BadTest3.Ord)
-BadTest3.java:33:13: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.upper.lower.bounds: B, BadTest3.I,BadTest3.J, List<B>)
-BadTest3.java:35:19: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.upper.lower.bounds: B, BadTest3.I,BadTest3.J, List<B>)
+BadTest3.java:31:34: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: B, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: BadTest3.Ord))
+BadTest3.java:33:13: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.bounds: B, (compiler.misc.upper.bounds: BadTest3.I,BadTest3.J), (compiler.misc.lower.bounds: List<B>))
+BadTest3.java:35:19: compiler.err.cant.apply.symbol: kindname.method, f, B, List<BadTest3.Ord>, kindname.class, BadTest3.Main, (compiler.misc.incompatible.bounds: B, (compiler.misc.upper.bounds: BadTest3.I,BadTest3.J), (compiler.misc.lower.bounds: List<B>))
 3 errors
--- a/test/langtools/tools/javac/generics/wildcards/6762569/T6762569b.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/generics/wildcards/6762569/T6762569b.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-T6762569b.java:13:9: compiler.err.cant.apply.symbol: kindname.method, m, T,java.util.List<? super java.util.List<T>>, java.lang.String,java.util.List<compiler.misc.type.captureof: 1, ? super java.util.List<? extends java.lang.Number>>, kindname.class, T6762569b, (compiler.misc.incompatible.upper.lower.bounds: T, java.lang.Number,java.lang.Object, java.lang.String)
+T6762569b.java:13:9: compiler.err.cant.apply.symbol: kindname.method, m, T,java.util.List<? super java.util.List<T>>, java.lang.String,java.util.List<compiler.misc.type.captureof: 1, ? super java.util.List<? extends java.lang.Number>>, kindname.class, T6762569b, (compiler.misc.incompatible.bounds: T, (compiler.misc.upper.bounds: java.lang.Number,java.lang.Object), (compiler.misc.lower.bounds: java.lang.String))
 1 error
--- a/test/langtools/tools/javac/lambda/8016177/T8016177g.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/8016177/T8016177g.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,3 +1,3 @@
-T8016177g.java:34:14: compiler.err.cant.apply.symbol: kindname.method, print, java.lang.String, Test.Person, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.upper.lower.bounds: R, java.lang.String,java.lang.Object, Test.Person))
+T8016177g.java:34:14: compiler.err.cant.apply.symbol: kindname.method, print, java.lang.String, Test.Person, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.bounds: R, (compiler.misc.upper.bounds: java.lang.String,java.lang.Object), (compiler.misc.lower.bounds: Test.Person)))
 T8016177g.java:35:20: compiler.err.cant.apply.symbol: kindname.method, abs, int, java.lang.Double, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Double, java.lang.Integer,java.lang.Object))
 2 errors
--- a/test/langtools/tools/javac/lambda/MethodReference41.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference41.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference41.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference41.SAM1, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String))))
-MethodReference41.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference41.SAM3, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference41.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference41.SAM1, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String)))))
+MethodReference41.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference41.SAM3, @12, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference41.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
 MethodReference41.java:41:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference41.SAM2), MethodReference41, kindname.method, m4(MethodReference41.SAM3), MethodReference41
 3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference42.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference42.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference42.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference42.SAM1, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)))
-MethodReference42.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference42.SAM3, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number)))
+MethodReference42.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference42.SAM1, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number))))
+MethodReference42.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference42.SAM3, @12, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Object), (compiler.misc.upper.bounds: java.lang.Number))))
 MethodReference42.java:41:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference42.SAM2), MethodReference42, kindname.method, m4(MethodReference42.SAM3), MethodReference42
 3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference43.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference43.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
-MethodReference43.java:45:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference43.SAM1, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String))))
-MethodReference43.java:47:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference43.java:45:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference43.SAM1, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String)))))
+MethodReference43.java:47:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
 MethodReference43.java:49:9: compiler.err.ref.ambiguous: m5, kindname.method, m5(MethodReference43.SAM3), MethodReference43, kindname.method, m5(MethodReference43.SAM4), MethodReference43
-MethodReference43.java:49:11: compiler.err.cant.apply.symbol: kindname.method, m5, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference43.java:49:11: compiler.err.cant.apply.symbol: kindname.method, m5, MethodReference43.SAM3, @12, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo<X>, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
 4 errors
--- a/test/langtools/tools/javac/lambda/MethodReference44.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference44.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference44.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference44.SAM1, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)))
-MethodReference44.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference44.SAM3, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number)))
+MethodReference44.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference44.SAM1, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Number))))
+MethodReference44.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference44.SAM3, @12, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Object), (compiler.misc.upper.bounds: java.lang.Number))))
 MethodReference44.java:43:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference44.SAM2), MethodReference44, kindname.method, g4(MethodReference44.SAM3), MethodReference44
 3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference46.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference46.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-MethodReference46.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference46.SAM1, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.String, kindname.class, MethodReference46, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.String))))
-MethodReference46.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference46.SAM3, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.Object, kindname.class, MethodReference46, (compiler.misc.incompatible.upper.lower.bounds: X, java.lang.Number, java.lang.Object))))
+MethodReference46.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference46.SAM1, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.String, kindname.class, MethodReference46, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.String)))))
+MethodReference46.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference46.SAM3, @12, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.Object, kindname.class, MethodReference46, (compiler.misc.incompatible.bounds: X, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: java.lang.Object)))))
 MethodReference46.java:43:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference46.SAM2), MethodReference46, kindname.method, g4(MethodReference46.SAM3), MethodReference46
 3 errors
--- a/test/langtools/tools/javac/lambda/MethodReference58.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference58.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-MethodReference58.java:41:23: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, Z, X, kindname.class, MethodReference58, (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.Number, X)))
+MethodReference58.java:41:23: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, g, Z, X, kindname.class, MethodReference58, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.Number), (compiler.misc.lower.bounds: X))))
 1 error
--- a/test/langtools/tools/javac/lambda/MethodReference68.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/MethodReference68.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @12,int, kindname.class, MethodReference68, (compiler.misc.incompatible.upper.lower.bounds: Z, MethodReference68.Foo,java.lang.Object, java.lang.Integer)
-1 error
\ No newline at end of file
+MethodReference68.java:21:10: compiler.err.cant.apply.symbol: kindname.method, g, MethodReference68.F<Z>,Z[], @12,int, kindname.class, MethodReference68, (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: MethodReference68.Foo,java.lang.Object), (compiler.misc.lower.bounds: java.lang.Integer))
+1 error
--- a/test/langtools/tools/javac/lambda/TargetType02.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/TargetType02.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,4 +1,4 @@
-TargetType02.java:33:14: compiler.err.prob.found.req: (compiler.misc.incompatible.upper.lower.bounds: Z, java.lang.String, java.lang.Integer)
+TargetType02.java:33:14: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: Z, (compiler.misc.upper.bounds: java.lang.String), (compiler.misc.lower.bounds: java.lang.Integer))
 TargetType02.java:34:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
 TargetType02.java:35:9: compiler.err.ref.ambiguous: call3, kindname.method, <Z>call3(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call3(TargetType02.S2<Z>), TargetType02
 TargetType02.java:37:20: compiler.err.ref.ambiguous: call4, kindname.method, <Z>call4(TargetType02.S1<Z>), TargetType02, kindname.method, <Z>call4(TargetType02.S2<Z>), TargetType02
--- a/test/langtools/tools/javac/lambda/TargetType14.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/TargetType14.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.lower.bounds: X, java.lang.Integer, java.lang.String)
+TargetType14.java:20:29: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.Integer), (compiler.misc.lower.bounds: java.lang.String))
 1 error
--- a/test/langtools/tools/javac/lambda/TargetType28.out	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/TargetType28.out	Thu Apr 26 17:59:02 2018 +0200
@@ -1,2 +1,2 @@
-TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Object,java.lang.Number)
+TargetType28.java:20:32: compiler.err.prob.found.req: (compiler.misc.incompatible.bounds: X, (compiler.misc.eq.bounds: java.lang.String), (compiler.misc.upper.bounds: java.lang.Object,java.lang.Number))
 1 error
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/lambda/deduplication/ClassFieldDeduplication.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8202141
+ * @summary Verify that .class synthetic Symbols are not duplicated.
+ * @library /tools/javac/lib
+ * @modules jdk.compiler/com.sun.tools.javac.api
+ *          jdk.compiler/com.sun.tools.javac.code
+ *          jdk.compiler/com.sun.tools.javac.tree
+ *          jdk.compiler/com.sun.tools.javac.util
+ * @build combo.ComboTestHelper
+ * @run main ClassFieldDeduplication
+ */
+
+import com.sun.source.util.TaskEvent;
+import com.sun.source.util.TaskListener;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.TreeScanner;
+import combo.ComboInstance;
+import combo.ComboParameter;
+import combo.ComboTestHelper;
+
+public class ClassFieldDeduplication extends ComboInstance<ClassFieldDeduplication> {
+
+    enum Type implements ComboParameter {
+        OBJECT("Object"),
+        PRIMITIVE("int"),
+        BOXED_PRIMITIVE("Integer"),
+        VOID("void"),
+        BOXED_VOID("Void"),
+        OBJECT_ARRAY("Object[]"),
+        PRIMITIVE_ARRAY("int[]"),
+        BOXED_PRIMITIVE_ARRAY("Integer[]"),
+        BOXED_VOID_ARRAY("Void[]");
+
+        String type;
+
+        Type(String type) {
+            this.type = type;
+        }
+
+        @Override
+        public String expand(String optParameter) {
+            return type;
+        }
+
+    }
+
+    public static void main(String... args) throws Exception {
+        new ComboTestHelper<ClassFieldDeduplication>()
+                .withDimension("TYPE", Type.values())
+                .run(ClassFieldDeduplication::new);
+    }
+
+    private static final String TEMPLATE =
+            "class Test { void t() { Object o1 = #{TYPE}.class; Object o2 = #{TYPE}.class; } }";
+
+    @Override
+    protected void doWork() throws Throwable {
+        newCompilationTask()
+                .withSourceFromTemplate(TEMPLATE)
+                .withListener(new TaskListener() {
+                    JCCompilationUnit cut;
+                        @Override
+                        public void finished(TaskEvent e) {
+                            if (e.getKind() == TaskEvent.Kind.PARSE) {
+                                if (cut != null)
+                                    throw new AssertionError();
+                                cut = (JCCompilationUnit) e.getCompilationUnit();
+                            }
+                            if (e.getKind() == TaskEvent.Kind.ANALYZE) {
+                                cut.accept(new TreeScanner() {
+                                    Symbol s;
+                                    @Override
+                                    public void visitSelect(JCFieldAccess tree) {
+                                        if (tree.name.contentEquals("class")) {
+                                            if (s == null) {
+                                                s = tree.sym;
+                                            } else if (s != tree.sym) {
+                                                throw new AssertionError("Duplicated field symbol.");
+                                            }
+                                        }
+                                        super.visitSelect(tree);
+                                    }
+                                });
+                            }
+                        }
+
+                })
+                .analyze(els -> {});
+    }
+
+}
--- a/test/langtools/tools/javac/lambda/deduplication/Deduplication.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/langtools/tools/javac/lambda/deduplication/Deduplication.java	Thu Apr 26 17:59:02 2018 +0200
@@ -38,6 +38,31 @@
                 (Runnable) () -> { ( (Runnable) () -> {} ).run(); }
         );
 
+        group(
+                (Runnable) () -> { Deduplication.class.toString(); },
+                (Runnable) () -> { Deduplication.class.toString(); }
+        );
+
+        group(
+                (Runnable) () -> { Integer[].class.toString(); },
+                (Runnable) () -> { Integer[].class.toString(); }
+        );
+
+        group(
+                (Runnable) () -> { char.class.toString(); },
+                (Runnable) () -> { char.class.toString(); }
+        );
+
+        group(
+                (Runnable) () -> { Void.class.toString(); },
+                (Runnable) () -> { Void.class.toString(); }
+        );
+
+        group(
+                (Runnable) () -> { void.class.toString(); },
+                (Runnable) () -> { void.class.toString(); }
+        );
+
         group((Function<String, Integer>) x -> x.hashCode());
         group((Function<Object, Integer>) x -> x.hashCode());
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/lib/builder/AbstractBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2018, 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 builder;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Collections;
+import java.util.List;
+
+public abstract class AbstractBuilder {
+
+    final String name;
+
+    Modifiers modifiers;
+    Comment comments;
+    String cname;
+
+    /**
+     * Constructs the base builder.
+     * @param modifiers for the class
+     * @param name of the element
+     */
+    public AbstractBuilder(Modifiers modifiers, String name) {
+        this.modifiers = modifiers;
+        this.name = name;
+        this.comments = new Comment(Comment.Kind.AUTO);
+    }
+
+    AbstractBuilder setModifiers(String... mods) {
+        this.modifiers = new Modifiers(mods);
+        return this;
+    }
+
+    /**
+     * Sets the enclosing type's name.
+     * @param className the enclosing type's name
+     */
+    void setClassName(String className) {
+        this.cname = className;
+    }
+
+    /**
+     * Sets the comment type for the member.
+     * @param comment for the member.
+     * @return this builder.
+     */
+    public AbstractBuilder setComments(Comment comment) {
+        this.comments = comment;
+        return this;
+    }
+
+    /**
+     * Sets the comments for the member.
+     * @param comments for the member.
+     * @return this builder.
+     */
+    public AbstractBuilder setComments(String... comments) {
+        this.comments = new Comment(comments);
+        return this;
+    }
+
+    /**
+     * Sets a comment for the element. Typically used to set
+     * user's preferences whether an automatic comment is
+     * required or no API comment.
+     *
+     * @param kind of comment, automatic or no comment.
+     * @return this builder.
+     */
+    public AbstractBuilder setComments(Comment.Kind kind) {
+        switch (kind) {
+            case NO_API_COMMENT: case AUTO: case INHERIT_DOC:
+                this.comments = new Comment(kind);
+                break;
+            default:
+                throw new IllegalArgumentException(kind + " not allowed");
+        }
+        return this;
+    }
+
+    /**
+     * The comment container.
+     */
+    public static class Comment {
+
+        /**
+         * The kinds of a comment.
+         */
+        public enum Kind {
+            /**
+             * user specified
+             */
+            USER,
+            /**
+             * no API comments
+             */
+            NO_API_COMMENT,
+            /**
+             * inserts the javadoc tag
+             */
+            INHERIT_DOC,
+            /**
+             * auto generate one
+             */
+            AUTO
+        }
+
+        final Kind kind;
+        final List<String> comments;
+
+        /**
+         * Construct an initial comment.
+         *
+         * @param kind
+         */
+        public Comment(Kind kind) {
+            this.kind = kind;
+            comments = Collections.emptyList();
+        }
+
+        /**
+         * Specify a user comment.
+         *
+         * @param comments the string of API comments.
+         */
+        public Comment(String... comments) {
+            kind = Kind.USER;
+            this.comments = comments == null
+                    ? Collections.emptyList()
+                    : List.of(comments);
+        }
+
+        @Override
+        public String toString() {
+            ClassBuilder.OutputWriter ow = new ClassBuilder.OutputWriter();
+            switch (kind) {
+                case USER:
+                    comments.forEach((s) -> ow.println("  " + s));
+                    break;
+                case INHERIT_DOC:
+                    ow.println("{@inheritDoc}");
+                    break;
+            }
+            return ow.toString();
+        }
+    }
+
+    /**
+     * The modifier representation for an element.
+     */
+    public static class Modifiers {
+        List<String> modifiers;
+
+        /**
+         * Constructs a modifier container.
+         * @param modifiers for an element.
+         */
+        public Modifiers(String... modifiers) {
+            this.modifiers = List.of(modifiers);
+        }
+
+        /**
+         * Constructs a modifier container.
+         * @param modifiers a list of modifier strings.
+         */
+        public Modifiers(List<String> modifiers) {
+            this.modifiers = modifiers;
+        }
+
+        /**
+         * Sets the modifiers for this element.
+         * @param modifiers
+         */
+        public void setModifiers(String... modifiers) {
+            this.modifiers = List.of(modifiers);
+        }
+
+        /**
+         * Sets the modifiers for this element.
+         * @param modifiers
+         */
+        public void setModifiers(List<String> modifiers) {
+            this.modifiers = modifiers;
+        }
+
+        @Override
+        public String toString() {
+            OutputWriter ow = new OutputWriter();
+            modifiers.forEach(i -> ow.print(i + " "));
+            return ow.toString();
+        }
+    }
+
+    /**
+     * The output writer.
+     */
+    public static class OutputWriter {
+        private final StringWriter sw = new StringWriter();
+        private final PrintWriter pw = new PrintWriter(sw);
+
+        @Override
+        public String toString() {
+            return sw.getBuffer().toString();
+        }
+
+        /**
+         * Prints a string without NL.
+         * @param s the string to print.
+         */
+        public void print(String s) {
+            pw.print(s);
+        }
+
+        /**
+         * Prints a string with a NL.
+         * @param s the string to print.
+         */
+        public void println(String s) {
+            pw.println(s);
+        }
+    }
+
+    /**
+     * A container to encapsulate a pair of values.
+     */
+    public static class Pair {
+        final String first;
+        final String second;
+
+        public Pair(String first, String second) {
+            this.first = first;
+            this.second = second;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/lib/builder/ClassBuilder.java	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,666 @@
+/*
+ * Copyright (c) 2018, 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 builder;
+
+import toolbox.ToolBox;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * Builder for type declarations.
+ * Note: this implementation does not support everything and is not
+ * exhaustive.
+ */
+public class ClassBuilder extends AbstractBuilder {
+
+    private final ToolBox tb;
+    private final String fqn;
+    private final String clsname;
+    private final String typeParameter;
+
+    private String pkg;
+    private final List<String> imports;
+
+    private String extendsType;
+    private final List<String> implementsTypes;
+    private final List<MemberBuilder> members;
+    private final List<ClassBuilder> inners;
+    private final List<ClassBuilder> nested;
+
+
+    final static Pattern CLASS_RE = Pattern.compile("(.*)(<.*>)");
+
+    /**
+     * Creates a class builder.
+     * @param tb the toolbox reference
+     * @param name the name of the type
+     */
+    public ClassBuilder(ToolBox tb, String name) {
+        super(new Modifiers(), name);
+        this.tb = tb;
+
+        Matcher m = CLASS_RE.matcher(name);
+        if (m.matches()) {
+            fqn = m.group(1);
+            typeParameter = m.group(2);
+        } else {
+            fqn = name;
+            typeParameter = null;
+        }
+        if (fqn.contains(".")) {
+            this.pkg = name.substring(0, fqn.lastIndexOf('.'));
+            clsname = fqn.substring(fqn.lastIndexOf('.') + 1);
+        } else {
+            clsname = fqn;
+        }
+        imports = new ArrayList<>();
+        implementsTypes = new ArrayList<>();
+        members = new ArrayList<>();
+        nested = new ArrayList<>();
+        inners = new ArrayList<>();
+    }
+
+    /**
+     * Adds an import(s).
+     * @param i the import type.
+     * @return this builder.
+     */
+    public ClassBuilder addImports(String i) {
+        imports.add(i);
+        return this;
+    }
+
+    /**
+     * Sets the modifiers for this builder.
+     * @param modifiers the modifiers
+     * @return this builder
+     */
+    public ClassBuilder setModifiers(String... modifiers) {
+        this.modifiers.setModifiers(modifiers);
+        return this;
+    }
+
+    /**
+     * Sets the enclosing type's name.
+     *
+     * @param className the enclosing type's name
+     */
+    @Override
+    void setClassName(String className) {
+        cname = className;
+    }
+
+    /**
+     * Sets a comment for the element.
+     *
+     * @param comments for the element
+     * @return this builder.
+     */
+    @Override
+    public ClassBuilder setComments(String... comments) {
+        super.setComments(comments);
+        return this;
+    }
+
+    /**
+     * Sets a comment for the element. Typically used to set
+     * the user's preferences whether an automatic comment is
+     * required or no API comment.
+     *
+     * @param kind of comment, automatic or no comment.
+     * @return this builder.
+     */
+    @Override
+    public ClassBuilder setComments(Comment.Kind kind) {
+        super.setComments(kind);
+        return this;
+    }
+
+    /**
+     * Set the super-type of the type.
+     * @param name of the super type.
+     * @return this builder.
+     */
+    public ClassBuilder setExtends(String name) {
+        extendsType = name;
+        return this;
+    }
+
+    /**
+     * Adds an implements declaration(s).
+     * @param names the interfaces
+     * @return this builder.
+     */
+    public ClassBuilder addImplements(String... names) {
+        implementsTypes.addAll(List.of(names));
+        return this;
+    }
+
+    /**
+     * Adds a member(s) to the class declaration.
+     * @param mbs the member builder(s) representing member(s).
+     * @return this builder
+     */
+    public ClassBuilder addMembers(MemberBuilder... mbs) {
+        for (MemberBuilder mb : mbs) {
+            members.add(mb);
+            mb.setClassName(fqn);
+        }
+        return this;
+    }
+
+    /**
+     * Adds nested-classes, to an outer class to an outer builder.
+     * @param cbs class builder(s) of the nested classes.
+     * @return this builder.
+     */
+    public ClassBuilder addNestedClasses(ClassBuilder... cbs) {
+        Stream.of(cbs).forEach(cb -> {
+            nested.add(cb);
+            cb.setClassName(fqn);
+        });
+        return this;
+    }
+
+    /**
+     * Adds inner-classes, to an an outer class builder.
+     * @param cbs class builder(s) of the inner classes.
+     * @return this builder.
+     */
+    public ClassBuilder addInnerClasses(ClassBuilder... cbs) {
+        Stream.of(cbs).forEach(cb -> {
+            inners.add(cb);
+            cb.setClassName(fqn);
+        });
+        return this;
+    }
+
+    @Override
+    public String toString() {
+        OutputWriter ow = new OutputWriter();
+        if (pkg != null)
+            ow.println("package " + pkg + ";");
+        imports.forEach(i -> ow.println("import " + i + ";"));
+        switch (comments.kind) {
+            case AUTO:
+                ow.println("/** Class " + fqn + " */");
+                break;
+            case USER:
+                ow.println("/** ");
+                comments.comments.forEach(c -> ow.println(" * " + c));
+                ow.println(" */");
+                break;
+            case NO_API_COMMENT:
+                ow.println("// NO_API_COMMENT");
+                break;
+        }
+        ow.print(modifiers.toString());
+        ow.print(clsname);
+        if (typeParameter != null) {
+            ow.print(typeParameter + " ");
+        } else {
+            ow.print(" ");
+        }
+        if (extendsType != null && !extendsType.isEmpty()) {
+            ow.print("extends " + extendsType + " ");
+        }
+        if (!implementsTypes.isEmpty()) {
+            ow.print("implements ");
+
+            ListIterator<String> iter = implementsTypes.listIterator();
+            while (iter.hasNext()) {
+                String s = iter.next() ;
+                ow.print(s);
+                if (iter.hasNext())
+                    ow.print(", ");
+            }
+        }
+        ow.print("{");
+        if (!nested.isEmpty()) {
+            ow.println("");
+            nested.forEach(m -> ow.println(m.toString()));
+        }
+
+        if (!members.isEmpty()) {
+            ow.println("");
+            members.forEach(m -> ow.println(m.toString()));
+        }
+
+        ow.println("}");
+        if (!inners.isEmpty()) {
+            ow.println(" {");
+            inners.forEach(m -> ow.println(m.toString()));
+            ow.println("}");
+        }
+        return ow.toString();
+    }
+
+    /**
+     * Writes out the java source for a type element. Package directories
+     * will be created as needed as inferred by the type name.
+     * @param srcDir the top level source directory.
+     * @throws IOException if an error occurs.
+     */
+    public void write(Path srcDir) throws IOException {
+        Files.createDirectories(srcDir);
+        Path outDir = srcDir;
+        if (pkg != null && !pkg.isEmpty()) {
+            String pdir = pkg.replace(".", "/");
+            outDir = Paths.get(srcDir.toString(), pdir);
+            Files.createDirectories(outDir);
+        }
+        Path filePath = Paths.get(outDir.toString(), clsname + ".java");
+        tb.writeFile(filePath, this.toString());
+    }
+
+    /**
+     * The member builder, this is the base class for all types of members.
+     */
+    public static abstract class MemberBuilder extends AbstractBuilder {
+        public MemberBuilder(Modifiers modifiers, String name) {
+            super(modifiers, name);
+        }
+
+        /**
+         * Sets the enclosing type's name.
+         * @param className the enclosing type's name
+         */
+        @Override
+        void setClassName(String className) {
+            cname = className;
+        }
+
+        /**
+         * Sets a comment for the element.
+         *
+         * @param comments for any element
+         * @return this builder.
+         */
+        @Override
+        public MemberBuilder setComments(String... comments) {
+            super.setComments(comments);
+            return this;
+        }
+
+        /**
+         * Sets a comment for the element. Typically used to set user's
+         * preferences whether an automatic comment is required or no API
+         * comment.
+         *
+         * @param kind of comment, automatic or no comment.
+         * @return this builder.
+         */
+        @Override
+        public MemberBuilder setComments(Comment.Kind kind) {
+            super.setComments(kind);
+            return this;
+        }
+
+        /**
+         * Sets a new modifier.
+         *
+         * @param modifiers
+         * @return this builder.
+         */
+        @Override
+        public MemberBuilder setModifiers(String... modifiers) {
+            super.setModifiers(modifiers);
+            return this;
+        }
+    }
+
+    /**
+     * The field builder.
+     */
+    public static class FieldBuilder extends MemberBuilder {
+        private String fieldType;
+        private String value;
+
+        private static final Pattern FIELD_RE = Pattern.compile("(.*)(\\s*=\\s*)(.*)(;)");
+
+        /**
+         * Constructs a field with the modifiers and name of the field.
+         * The builder by default is configured to auto generate the
+         * comments for the field.
+         * @param name of the field
+         */
+        public FieldBuilder(String name) {
+            super(new Modifiers(), name);
+            this.comments = new Comment(Comment.Kind.AUTO);
+        }
+
+        /**
+         * Returns a field builder by parsing the string.
+         * ex:  public static String myPlayingField;
+         * @param fieldString describing the field.
+         * @return a field builder.
+         */
+        public static FieldBuilder parse(String fieldString) {
+            String prefix;
+            String value = null;
+            Matcher m = FIELD_RE.matcher(fieldString);
+            if (m.matches()) {
+                prefix = m.group(1).trim();
+                value = m.group(3).trim();
+            } else {
+                int end = fieldString.lastIndexOf(';') > 0
+                        ? fieldString.lastIndexOf(';')
+                        : fieldString.length();
+                prefix = fieldString.substring(0, end).trim();
+            }
+            List<String> list = Stream.of(prefix.split(" "))
+                    .filter(s -> !s.isEmpty()).collect(Collectors.toList());
+            if (list.size() < 2) {
+                throw new IllegalArgumentException("incorrect field string: "
+                        + fieldString);
+            }
+            String name = list.get(list.size() - 1);
+            String fieldType = list.get(list.size() - 2);
+
+            FieldBuilder fb = new FieldBuilder(name);
+            fb.modifiers.setModifiers(list.subList(0, list.size() - 2));
+            fb.setFieldType(fieldType);
+            if (value != null)
+                fb.setValue(value);
+
+            return fb;
+        }
+
+        /**
+         * Sets the modifiers for this builder.
+         *
+         * @param mods
+         * @return this builder
+         */
+        public FieldBuilder setModifiers(String mods) {
+            this.modifiers.setModifiers(mods);
+            return this;
+        }
+
+        /**
+         * Sets the type of the field.
+         * @param fieldType the name of the type.
+         * @return this field builder.
+         */
+        public FieldBuilder setFieldType(String fieldType) {
+            this.fieldType = fieldType;
+            return this;
+        }
+
+        public FieldBuilder setValue(String value) {
+            this.value = value;
+            return this;
+        }
+
+        @Override
+        public String toString() {
+            String indent = "    ";
+            OutputWriter ow = new OutputWriter();
+            switch (comments.kind) {
+                case AUTO:
+                    ow.println(indent + "/** Field " +
+                            super.name + " in " + super.cname + " */");
+                    break;
+                case INHERIT_DOC: case USER:
+                    ow.println(indent + "/** " +
+                            comments.toString() + " */");
+                    break;
+                case NO_API_COMMENT:
+                    ow.println(indent + "// NO_API_COMMENT");
+                    break;
+            }
+            ow.print(indent + super.modifiers.toString() + " ");
+            ow.print(fieldType + " ");
+            ow.print(super.name);
+            if (value != null) {
+                ow.print(" = " + value);
+            }
+            ow.println(";");
+            return ow.toString();
+        }
+    }
+
+    /**
+     * The method builder.
+     */
+    public static class MethodBuilder extends MemberBuilder {
+
+        private final List<Pair> params;
+
+        private String returnType;
+        private List<String> body;
+
+        final static Pattern METHOD_RE = Pattern.compile("(.*)(\\()(.*)(\\))(.*)");
+
+        /**
+         * Constructs a method builder. The builder by default is configured
+         * to auto generate the comments for this method.
+         * @param name of the method.
+         */
+        public MethodBuilder(String name) {
+            super(new Modifiers(), name);
+            comments = new Comment(Comment.Kind.AUTO);
+            params = new ArrayList<>();
+            body = null;
+        }
+
+        /**
+         * Returns a method builder by parsing a string which
+         * describes a method.
+         * @param methodString the method description.
+         * @return a method builder.
+         */
+        public static MethodBuilder parse(String methodString) {
+            Matcher m = METHOD_RE.matcher(methodString);
+            if (!m.matches())
+                throw new IllegalArgumentException("string does not match: "
+                        + methodString);
+            String prefix = m.group(1);
+            String params = m.group(3);
+            String suffix = m.group(5).trim();
+
+            if (prefix.length() < 2) {
+                throw new IllegalArgumentException("incorrect method string: "
+                        + methodString);
+            }
+
+            String[] pa = prefix.split(" ");
+            List<String> list = List.of(pa);
+            String name = list.get(list.size() - 1);
+            String returnType = list.get(list.size() - 2);
+
+            MethodBuilder mb = new MethodBuilder(name);
+            mb.modifiers.setModifiers(list.subList(0, list.size() - 2));
+            mb.setReturn(returnType);
+
+            pa = params.split(",");
+            Stream.of(pa).forEach(p -> {
+                p = p.trim();
+                if (!p.isEmpty())
+                    mb.addParameter(p);
+            });
+            if (!suffix.isEmpty() || suffix.length() > 1) {
+                mb.setBody(suffix);
+            }
+            return mb;
+        }
+
+        /**
+         * Sets the modifiers for this builder.
+         *
+         * @param modifiers
+         * @return this builder
+         */
+        public MethodBuilder setModifiers(String modifiers) {
+            this.modifiers.setModifiers(modifiers);
+            return this;
+        }
+
+        @Override
+        public MethodBuilder setComments(String... comments) {
+            super.setComments(comments);
+            return this;
+        }
+
+        @Override
+        public MethodBuilder setComments(Comment.Kind kind) {
+            super.setComments(kind);
+            return this;
+        }
+
+        /**
+         * Sets a return type for a method.
+         * @param returnType the return type.
+         * @return this method builder.
+         */
+        public MethodBuilder setReturn(String returnType) {
+            this.returnType = returnType;
+            return this;
+        }
+
+        /**
+         * Adds a parameter(s) to the method method builder.
+         * @param params a pair consisting of type and parameter name.
+         * @return this method builder.
+         */
+        public MethodBuilder addParameters(Pair... params) {
+            this.params.addAll(List.of(params));
+            return this;
+        }
+
+        /**
+         * Adds a parameter to the method method builder.
+         * @param type the type of parameter.
+         * @param name the parameter name.
+         * @return this method builder.
+         */
+        public MethodBuilder addParameter(String type, String name) {
+            this.params.add(new Pair(type, name));
+            return this;
+        }
+
+        /**
+         * Adds a parameter to the method builder, by parsing the string.
+         * @param s the parameter description such as "Double voltage"
+         * @return this method builder.
+         */
+        public MethodBuilder addParameter(String s) {
+            String[] p = s.trim().split(" ");
+            return addParameter(p[0], p[p.length - 1]);
+        }
+
+        /**
+         * Sets the body of the method, described by the string.
+         * Such as "{", "double i = v/r;", "return i;", "}"
+         * @param body of the methods
+         * @return
+         */
+        public MethodBuilder setBody(String... body) {
+            if (body == null) {
+                this.body = null;
+            } else {
+                this.body = new ArrayList<>();
+                this.body.addAll(List.of(body));
+            }
+            return this;
+        }
+
+        @Override
+        public String toString() {
+            OutputWriter ow = new OutputWriter();
+            String indent = "    ";
+            switch (comments.kind) {
+                case AUTO:
+                    ow.println(indent + "/** Method " + super.name + " in " + super.cname);
+                    if (!params.isEmpty())
+                        params.forEach(p -> ow.println(indent + " * @param " + p.second + " a param"));
+                    if (returnType != null && !returnType.isEmpty() && !returnType.contains("void"))
+                        ow.println(indent + " * @return returns something");
+                    ow.println(indent + " */");
+                    break;
+                case INHERIT_DOC: case USER:
+                    ow.println(indent + "/** " + comments.toString() + " */");
+                    break;
+                case NO_API_COMMENT:
+                    ow.println(indent + "// NO_API_COMMENT");
+                    break;
+            }
+
+            ow.print(indent + super.modifiers.toString() + " ");
+            ow.print(returnType + " ");
+            ow.print(super.name + "(");
+            if (!params.isEmpty()) {
+                ListIterator<Pair> iter = params.listIterator();
+                while (iter.hasNext()) {
+                    Pair p = iter.next();
+                    ow.print(p.first + " " + p.second);
+                    if (iter.hasNext())
+                        ow.print(", ");
+                }
+            }
+            ow.print(")");
+            if (body == null) {
+                ow.println(";");
+            } else {
+                body.forEach(ow::println);
+            }
+            return ow.toString();
+        }
+    }
+
+//A sample, to test with an IDE.
+//    public static void main(String... args) throws IOException {
+//        ClassBuilder cb = new ClassBuilder(new ToolBox(), "foo.bar.Test<C extends A>");
+//        cb.addModifiers("public", "abstract", "static")
+//                .addImports("java.io").addImports("java.nio")
+//                .setComments("A comment")
+//                .addImplements("Serialization", "Something")
+//                .setExtends("java.lang.Object")
+//                .addMembers(
+//                        FieldBuilder.parse("public int xxx;"),
+//                        FieldBuilder.parse("public int yyy = 10;"),
+//                        MethodBuilder.parse("public static void main(A a, B b, C c);")
+//                            .setComments("CC"),
+//                        MethodBuilder.parse("void foo(){//do something}")
+//
+//                );
+//        ClassBuilder ic = new ClassBuilder(new ToolBox(), "IC");
+//        cb.addModifiers( "interface");
+//        cb.addNestedClasses(ic);
+//        System.out.println(cb.toString());
+//        cb.write(Paths.get("src-out"));
+//    }
+}
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java	Thu Apr 26 17:59:02 2018 +0200
@@ -366,6 +366,10 @@
         return new Result(opts, runWithArchive(opts));
     }
 
+    public static Result run(CDSOptions opts) throws Exception {
+        return new Result(opts, runWithArchive(opts));
+    }
+
     // Execute JVM with CDS archive, specify command line args suffix
     public static OutputAnalyzer runWithArchive(String... cliPrefix)
         throws Exception {
--- a/test/lib/jdk/test/lib/process/OutputAnalyzer.java	Mon Apr 23 12:53:43 2018 +0200
+++ b/test/lib/jdk/test/lib/process/OutputAnalyzer.java	Thu Apr 26 17:59:02 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -33,511 +33,525 @@
 
 public final class OutputAnalyzer {
 
-  private final String stdout;
-  private final String stderr;
-  private final int exitValue;
+    private final String stdout;
+    private final String stderr;
+    private final int exitValue;
+
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output and exit
+     * value from a Process
+     *
+     * @param process Process to analyze
+     * @throws IOException If an I/O error occurs.
+     */
+    public OutputAnalyzer(Process process) throws IOException {
+        OutputBuffer output = ProcessTools.getOutput(process);
+        exitValue = process.exitValue();
+        this.stdout = output.getStdout();
+        this.stderr = output.getStderr();
+    }
 
-  /**
-   * Create an OutputAnalyzer, a utility class for verifying output and exit
-   * value from a Process
-   *
-   * @param process Process to analyze
-   * @throws IOException If an I/O error occurs.
-   */
-  public OutputAnalyzer(Process process) throws IOException {
-    OutputBuffer output = ProcessTools.getOutput(process);
-    exitValue = process.exitValue();
-    this.stdout = output.getStdout();
-    this.stderr = output.getStderr();
-  }
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output
+     *
+     * @param buf String buffer to analyze
+     */
+    public OutputAnalyzer(String buf) {
+        this(buf, buf);
+    }
+
+    /**
+     * Create an OutputAnalyzer, a utility class for verifying output
+     *
+     * @param stdout stdout buffer to analyze
+     * @param stderr stderr buffer to analyze
+     */
+    public OutputAnalyzer(String stdout, String stderr) {
+        this.stdout = stdout;
+        this.stderr = stderr;
+        exitValue = -1;
+    }
+
+    /**
+     * Verify that the stdout contents of output buffer is empty
+     *
+     * @throws RuntimeException
+     *             If stdout was not empty
+     */
+    public void stdoutShouldBeEmpty() {
+        if (!getStdout().isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stdout was not empty");
+        }
+    }
 
-  /**
-   * Create an OutputAnalyzer, a utility class for verifying output
-   *
-   * @param buf String buffer to analyze
-   */
-  public OutputAnalyzer(String buf) {
-    this(buf, buf);
-  }
+    /**
+     * Verify that the stderr contents of output buffer is empty
+     *
+     * @throws RuntimeException
+     *             If stderr was not empty
+     */
+    public void stderrShouldBeEmpty() {
+        if (!getStderr().isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stderr was not empty");
+        }
+    }
+
+    /**
+     * Verify that the stderr contents of output buffer is empty,
+     * after filtering out the Hotspot warning messages
+     *
+     * @throws RuntimeException
+     *             If stderr was not empty
+     */
+    public void stderrShouldBeEmptyIgnoreVMWarnings() {
+        if (!getStderr().replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stderr was not empty");
+        }
+    }
 
-  /**
-   * Create an OutputAnalyzer, a utility class for verifying output
-   *
-   * @param stdout stdout buffer to analyze
-   * @param stderr stderr buffer to analyze
-   */
-  public OutputAnalyzer(String stdout, String stderr) {
-    this.stdout = stdout;
-    this.stderr = stderr;
-    exitValue = -1;
-  }
+    /**
+     * Verify that the stdout contents of output buffer is not empty
+     *
+     * @throws RuntimeException
+     *             If stdout was empty
+     */
+    public void stdoutShouldNotBeEmpty() {
+        if (getStdout().isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stdout was empty");
+        }
+    }
+
+    /**
+     * Verify that the stderr contents of output buffer is not empty
+     *
+     * @throws RuntimeException
+     *             If stderr was empty
+     */
+    public void stderrShouldNotBeEmpty() {
+        if (getStderr().isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stderr was empty");
+        }
+    }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer contains the string
+     *
+     * @param expectedString String that buffer should contain
+     * @throws RuntimeException If the string was not found
+     */
+    public OutputAnalyzer shouldContain(String expectedString) {
+        if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
+        }
+        return this;
+    }
 
-  /**
-   * Verify that the stdout contents of output buffer is empty
-   *
-   * @throws RuntimeException
-   *             If stdout was not empty
-   */
-  public void stdoutShouldBeEmpty() {
-    if (!getStdout().isEmpty()) {
-      reportDiagnosticSummary();
-      throw new RuntimeException("stdout was not empty");
+    /**
+     * Verify that the stdout contents of output buffer contains the string
+     *
+     * @param expectedString String that buffer should contain
+     * @throws RuntimeException If the string was not found
+     */
+    public OutputAnalyzer stdoutShouldContain(String expectedString) {
+        if (!stdout.contains(expectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
+        }
+        return this;
     }
-  }
+
+    /**
+     * Verify that the stderr contents of output buffer contains the string
+     *
+     * @param expectedString String that buffer should contain
+     * @throws RuntimeException If the string was not found
+     */
+    public OutputAnalyzer stderrShouldContain(String expectedString) {
+        if (!stderr.contains(expectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
+        }
+        return this;
+    }
 
-  /**
-   * Verify that the stderr contents of output buffer is empty
-   *
-   * @throws RuntimeException
-   *             If stderr was not empty
-   */
-  public void stderrShouldBeEmpty() {
-    if (!getStderr().isEmpty()) {
-      reportDiagnosticSummary();
-      throw new RuntimeException("stderr was not empty");
+    /**
+     * Verify that the stdout and stderr contents of output buffer does not contain the string
+     *
+     * @param expectedString String that the buffer should not contain
+     * @throws RuntimeException If the string was found
+     */
+    public OutputAnalyzer shouldNotContain(String notExpectedString) {
+        if (stdout.contains(notExpectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+        }
+        if (stderr.contains(notExpectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+        }
+        return this;
     }
-  }
+
+    /**
+     * Verify that the stdout and stderr contents of output buffer are empty
+     *
+     * @throws RuntimeException If the stdout and stderr are not empty
+     */
+    public OutputAnalyzer shouldBeEmpty() {
+        if (!stdout.isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stdout was not empty");
+        }
+        if (!stderr.isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stderr was not empty");
+        }
+        return this;
+    }
 
-  /**
-   * Verify that the stdout contents of output buffer is not empty
-   *
-   * @throws RuntimeException
-   *             If stdout was empty
-   */
-  public void stdoutShouldNotBeEmpty() {
-    if (getStdout().isEmpty()) {
-      reportDiagnosticSummary();
-      throw new RuntimeException("stdout was empty");
+    /**
+     * Verify that the stdout contents of output buffer does not contain the string
+     *
+     * @param expectedString String that the buffer should not contain
+     * @throws RuntimeException If the string was found
+     */
+    public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
+        if (stdout.contains(notExpectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
+        }
+        return this;
     }
-  }
+
+    /**
+     * Verify that the stderr contents of output buffer does not contain the string
+     *
+     * @param expectedString String that the buffer should not contain
+     * @throws RuntimeException If the string was found
+     */
+    public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
+        if (stderr.contains(notExpectedString)) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+        }
+        return this;
+    }
 
-  /**
-   * Verify that the stderr contents of output buffer is not empty
-   *
-   * @throws RuntimeException
-   *             If stderr was empty
-   */
-  public void stderrShouldNotBeEmpty() {
-    if (getStderr().isEmpty()) {
-      reportDiagnosticSummary();
-      throw new RuntimeException("stderr was empty");
+    /**
+     * Verify that the stdout and stderr contents of output buffer matches
+     * the pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public OutputAnalyzer shouldMatch(String pattern) {
+        Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (!stdoutMatcher.find() && !stderrMatcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                  + "' missing from stdout/stderr \n");
+        }
+        return this;
     }
-  }
+
+    /**
+     * Verify that the stdout contents of output buffer matches the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public OutputAnalyzer stdoutShouldMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (!matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                  + "' missing from stdout \n");
+        }
+        return this;
+    }
 
     /**
-   * Verify that the stdout and stderr contents of output buffer contains the string
-   *
-   * @param expectedString String that buffer should contain
-   * @throws RuntimeException If the string was not found
-   */
-  public OutputAnalyzer shouldContain(String expectedString) {
-    if (!stdout.contains(expectedString) && !stderr.contains(expectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + expectedString + "' missing from stdout/stderr \n");
-    }
-    return this;
-  }
-
-  /**
-   * Verify that the stdout contents of output buffer contains the string
-   *
-   * @param expectedString String that buffer should contain
-   * @throws RuntimeException If the string was not found
-   */
-  public OutputAnalyzer stdoutShouldContain(String expectedString) {
-    if (!stdout.contains(expectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + expectedString + "' missing from stdout \n");
-    }
-    return this;
-  }
+     * Verify that the stderr contents of output buffer matches the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public OutputAnalyzer stderrShouldMatch(String pattern) {
 
-  /**
-   * Verify that the stderr contents of output buffer contains the string
-   *
-   * @param expectedString String that buffer should contain
-   * @throws RuntimeException If the string was not found
-   */
-  public OutputAnalyzer stderrShouldContain(String expectedString) {
-    if (!stderr.contains(expectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + expectedString + "' missing from stderr \n");
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (!matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                  + "' missing from stderr \n");
+        }
+        return this;
     }
-    return this;
-  }
-
-  /**
-   * Verify that the stdout and stderr contents of output buffer does not contain the string
-   *
-   * @param expectedString String that the buffer should not contain
-   * @throws RuntimeException If the string was found
-   */
-  public OutputAnalyzer shouldNotContain(String notExpectedString) {
-    if (stdout.contains(notExpectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
-    }
-    if (stderr.contains(notExpectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
-    }
-    return this;
-  }
 
-  /**
-   * Verify that the stdout and stderr contents of output buffer are empty
-   *
-   * @throws RuntimeException If the stdout and stderr are not empty
-   */
-  public OutputAnalyzer shouldBeEmpty() {
-    if (!stdout.isEmpty()) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("stdout was not empty");
-    }
-    if (!stderr.isEmpty()) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("stderr was not empty");
+    /**
+     * Verify that the stdout and stderr contents of output buffer does not
+     * match the pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was found
+     */
+    public OutputAnalyzer shouldNotMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                    + "' found in stdout: '" + matcher.group() + "' \n");
+        }
+        matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                    + "' found in stderr: '" + matcher.group() + "' \n");
+        }
+        return this;
     }
-    return this;
-  }
-
-  /**
-   * Verify that the stdout contents of output buffer does not contain the string
-   *
-   * @param expectedString String that the buffer should not contain
-   * @throws RuntimeException If the string was found
-   */
-  public OutputAnalyzer stdoutShouldNotContain(String notExpectedString) {
-    if (stdout.contains(notExpectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + notExpectedString + "' found in stdout \n");
-    }
-    return this;
-  }
 
-  /**
-   * Verify that the stderr contents of output buffer does not contain the string
-   *
-   * @param expectedString String that the buffer should not contain
-   * @throws RuntimeException If the string was found
-   */
-  public OutputAnalyzer stderrShouldNotContain(String notExpectedString) {
-    if (stderr.contains(notExpectedString)) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("'" + notExpectedString + "' found in stderr \n");
+    /**
+     * Verify that the stdout contents of output buffer does not match the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was found
+     */
+    public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                    + "' found in stdout \n");
+        }
+        return this;
     }
-    return this;
-  }
-
-  /**
-   * Verify that the stdout and stderr contents of output buffer matches
-   * the pattern
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was not found
-   */
-  public OutputAnalyzer shouldMatch(String pattern) {
-      Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
-      Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-      if (!stdoutMatcher.find() && !stderrMatcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                + "' missing from stdout/stderr \n");
-      }
-      return this;
-  }
 
-  /**
-   * Verify that the stdout contents of output buffer matches the
-   * pattern
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was not found
-   */
-  public OutputAnalyzer stdoutShouldMatch(String pattern) {
-      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
-      if (!matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                + "' missing from stdout \n");
-      }
-      return this;
-  }
-
-  /**
-   * Verify that the stderr contents of output buffer matches the
-   * pattern
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was not found
-   */
-  public OutputAnalyzer stderrShouldMatch(String pattern) {
-
-      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-      if (!matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                + "' missing from stderr \n");
-      }
-      return this;
-  }
+    /**
+     * Verify that the stderr contents of output buffer does not match the
+     * pattern
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was found
+     */
+    public OutputAnalyzer stderrShouldNotMatch(String pattern) {
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                    + "' found in stderr \n");
+        }
+        return this;
+    }
 
-  /**
-   * Verify that the stdout and stderr contents of output buffer does not
-   * match the pattern
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was found
-   */
-  public OutputAnalyzer shouldNotMatch(String pattern) {
-      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
-      if (matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                  + "' found in stdout: '" + matcher.group() + "' \n");
-      }
-      matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-      if (matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                  + "' found in stderr: '" + matcher.group() + "' \n");
-      }
-      return this;
-  }
-
-  /**
-   * Verify that the stdout contents of output buffer does not match the
-   * pattern
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was found
-   */
-  public OutputAnalyzer stdoutShouldNotMatch(String pattern) {
-      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
-      if (matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                  + "' found in stdout \n");
-      }
-      return this;
-  }
+    /**
+     * Get the captured group of the first string matching the pattern.
+     * stderr is searched before stdout.
+     *
+     * @param pattern The multi-line pattern to match
+     * @param group The group to capture
+     * @return The matched string or null if no match was found
+     */
+    public String firstMatch(String pattern, int group) {
+        Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
+        if (stderrMatcher.find()) {
+            return stderrMatcher.group(group);
+        }
+        if (stdoutMatcher.find()) {
+            return stdoutMatcher.group(group);
+        }
+        return null;
+    }
 
-  /**
-   * Verify that the stderr contents of output buffer does not match the
-   * pattern
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was found
-   */
-  public OutputAnalyzer stderrShouldNotMatch(String pattern) {
-      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-      if (matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                  + "' found in stderr \n");
-      }
-      return this;
-  }
-
-  /**
-   * Get the captured group of the first string matching the pattern.
-   * stderr is searched before stdout.
-   *
-   * @param pattern The multi-line pattern to match
-   * @param group The group to capture
-   * @return The matched string or null if no match was found
-   */
-  public String firstMatch(String pattern, int group) {
-    Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-    Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout);
-    if (stderrMatcher.find()) {
-      return stderrMatcher.group(group);
+    /**
+     * Get the first string matching the pattern.
+     * stderr is searched before stdout.
+     *
+     * @param pattern The multi-line pattern to match
+     * @return The matched string or null if no match was found
+     */
+    public String firstMatch(String pattern) {
+        return firstMatch(pattern, 0);
     }
-    if (stdoutMatcher.find()) {
-      return stdoutMatcher.group(group);
-    }
-    return null;
-  }
 
-  /**
-   * Get the first string matching the pattern.
-   * stderr is searched before stdout.
-   *
-   * @param pattern The multi-line pattern to match
-   * @return The matched string or null if no match was found
-   */
-  public String firstMatch(String pattern) {
-    return firstMatch(pattern, 0);
-  }
+    /**
+     * Verify the exit value of the process
+     *
+     * @param expectedExitValue Expected exit value from process
+     * @throws RuntimeException If the exit value from the process did not match the expected value
+     */
+    public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
+        if (getExitValue() != expectedExitValue) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("Expected to get exit value of ["
+                    + expectedExitValue + "]\n");
+        }
+        return this;
+    }
 
-  /**
-   * Verify the exit value of the process
-   *
-   * @param expectedExitValue Expected exit value from process
-   * @throws RuntimeException If the exit value from the process did not match the expected value
-   */
-  public OutputAnalyzer shouldHaveExitValue(int expectedExitValue) {
-      if (getExitValue() != expectedExitValue) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("Expected to get exit value of ["
-                  + expectedExitValue + "]\n");
-      }
-      return this;
-  }
-
-  /**
-   * Verify the exit value of the process
-   *
-   * @param notExpectedExitValue Unexpected exit value from process
-   * @throws RuntimeException If the exit value from the process did match the expected value
-   */
-  public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
-      if (getExitValue() == notExpectedExitValue) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("Unexpected to get exit value of ["
-                  + notExpectedExitValue + "]\n");
-      }
-      return this;
-  }
+    /**
+     * Verify the exit value of the process
+     *
+     * @param notExpectedExitValue Unexpected exit value from process
+     * @throws RuntimeException If the exit value from the process did match the expected value
+     */
+    public OutputAnalyzer shouldNotHaveExitValue(int notExpectedExitValue) {
+        if (getExitValue() == notExpectedExitValue) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("Unexpected to get exit value of ["
+                    + notExpectedExitValue + "]\n");
+        }
+        return this;
+    }
 
 
-  /**
-   * Report summary that will help to diagnose the problem
-   * Currently includes:
-   *  - standard input produced by the process under test
-   *  - standard output
-   *  - exit code
-   *  Note: the command line is printed by the ProcessTools
-   */
-  public void reportDiagnosticSummary() {
-      String msg =
-          " stdout: [" + stdout + "];\n" +
-          " stderr: [" + stderr + "]\n" +
-          " exitValue = " + getExitValue() + "\n";
+    /**
+     * Report summary that will help to diagnose the problem
+     * Currently includes:
+     *  - standard input produced by the process under test
+     *  - standard output
+     *  - exit code
+     *  Note: the command line is printed by the ProcessTools
+     */
+    public void reportDiagnosticSummary() {
+        String msg =
+            " stdout: [" + stdout + "];\n" +
+            " stderr: [" + stderr + "]\n" +
+            " exitValue = " + getExitValue() + "\n";
 
-      System.err.println(msg);
-  }
+        System.err.println(msg);
+    }
 
-  /**
-   * Print the stdout buffer to the given {@code PrintStream}.
-   *
-   * @return this OutputAnalyzer
-   */
-  public OutputAnalyzer outputTo(PrintStream out) {
-      out.println(getStdout());
-      return this;
-  }
+    /**
+     * Print the stdout buffer to the given {@code PrintStream}.
+     *
+     * @return this OutputAnalyzer
+     */
+    public OutputAnalyzer outputTo(PrintStream out) {
+        out.println(getStdout());
+        return this;
+    }
 
-  /**
-   * Print the stderr buffer to the given {@code PrintStream}.
-   *
-   * @return this OutputAnalyzer
-   */
-  public OutputAnalyzer errorTo(PrintStream out) {
-      out.println(getStderr());
-      return this;
-  }
+    /**
+     * Print the stderr buffer to the given {@code PrintStream}.
+     *
+     * @return this OutputAnalyzer
+     */
+    public OutputAnalyzer errorTo(PrintStream out) {
+        out.println(getStderr());
+        return this;
+    }
 
-  /**
-   * Get the contents of the output buffer (stdout and stderr)
-   *
-   * @return Content of the output buffer
-   */
-  public String getOutput() {
-    return stdout + stderr;
-  }
+    /**
+     * Get the contents of the output buffer (stdout and stderr)
+     *
+     * @return Content of the output buffer
+     */
+    public String getOutput() {
+        return stdout + stderr;
+    }
 
-  /**
-   * Get the contents of the stdout buffer
-   *
-   * @return Content of the stdout buffer
-   */
-  public String getStdout() {
-    return stdout;
-  }
+    /**
+     * Get the contents of the stdout buffer
+     *
+     * @return Content of the stdout buffer
+     */
+    public String getStdout() {
+        return stdout;
+    }
 
-  /**
-   * Get the contents of the stderr buffer
-   *
-   * @return Content of the stderr buffer
-   */
-  public String getStderr() {
-    return stderr;
-  }
+    /**
+     * Get the contents of the stderr buffer
+     *
+     * @return Content of the stderr buffer
+     */
+    public String getStderr() {
+        return stderr;
+    }
 
-  /**
-   * Get the process exit value
-   *
-   * @return Process exit value
-   */
-  public int getExitValue() {
-    return exitValue;
-  }
+    /**
+     * Get the process exit value
+     *
+     * @return Process exit value
+     */
+    public int getExitValue() {
+        return exitValue;
+    }
 
-  /**
-   * Get the contents of the output buffer (stdout and stderr) as list of strings.
-   * Output will be split by newlines.
-   *
-   * @return Contents of the output buffer as list of strings
-   */
-  public List<String> asLines() {
-    return asLines(getOutput());
-  }
+    /**
+     * Get the contents of the output buffer (stdout and stderr) as list of strings.
+     * Output will be split by newlines.
+     *
+     * @return Contents of the output buffer as list of strings
+     */
+    public List<String> asLines() {
+        return asLines(getOutput());
+    }
 
-  private List<String> asLines(String buffer) {
-    return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
-  }
+    private List<String> asLines(String buffer) {
+        return Arrays.asList(buffer.split("(\\r\\n|\\n|\\r)"));
+    }
 
 
-  private static final String jvmwarningmsg = ".* VM warning:.*";
+    private static final String jvmwarningmsg = ".* VM warning:.*";
 
-  /**
-   * Verifies that the stdout and stderr contents of output buffer are empty, after
-   * filtering out the HotSpot warning messages.
-   *
-   * @throws RuntimeException If the stdout and stderr are not empty
-   */
-  public OutputAnalyzer shouldBeEmptyIgnoreVMWarnings() {
-    if (!stdout.isEmpty()) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("stdout was not empty");
+    /**
+     * Verifies that the stdout and stderr contents of output buffer are empty, after
+     * filtering out the HotSpot warning messages.
+     *
+     * @throws RuntimeException If the stdout and stderr are not empty
+     */
+    public OutputAnalyzer shouldBeEmptyIgnoreVMWarnings() {
+        if (!stdout.isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stdout was not empty");
+        }
+        if (!stderr.replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("stderr was not empty");
+        }
+        return this;
     }
-    if (!stderr.replaceAll(jvmwarningmsg + "\\R", "").isEmpty()) {
-        reportDiagnosticSummary();
-        throw new RuntimeException("stderr was not empty");
-    }
-    return this;
-  }
 
-  /**
-   * Verify that the stderr contents of output buffer matches the pattern,
-   * after filtering out the Hotespot warning messages
-   *
-   * @param pattern
-   * @throws RuntimeException If the pattern was not found
-   */
-  public OutputAnalyzer stderrShouldMatchIgnoreVMWarnings(String pattern) {
-      String stderr = this.stderr.replaceAll(jvmwarningmsg + "\\R", "");
-      Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
-      if (!matcher.find()) {
-          reportDiagnosticSummary();
-          throw new RuntimeException("'" + pattern
-                + "' missing from stderr \n");
-      }
-      return this;
-  }
+    /**
+     * Verify that the stderr contents of output buffer matches the pattern,
+     * after filtering out the Hotespot warning messages
+     *
+     * @param pattern
+     * @throws RuntimeException If the pattern was not found
+     */
+    public OutputAnalyzer stderrShouldMatchIgnoreVMWarnings(String pattern) {
+        String stderr = this.stderr.replaceAll(jvmwarningmsg + "\\R", "");
+        Matcher matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr);
+        if (!matcher.find()) {
+            reportDiagnosticSummary();
+            throw new RuntimeException("'" + pattern
+                  + "' missing from stderr \n");
+        }
+        return this;
+    }
 
-  /**
-   * Returns the contents of the output buffer (stdout and stderr), without those
-   * JVM warning msgs, as list of strings. Output is split by newlines.
-   *
-   * @return Contents of the output buffer as list of strings
-   */
-  public List<String> asLinesWithoutVMWarnings() {
-      return Arrays.asList(getOutput().split("\\R"))
-              .stream()
-              .filter(Pattern.compile(jvmwarningmsg).asPredicate().negate())
-              .collect(Collectors.toList());
-  }
+    /**
+     * Returns the contents of the output buffer (stdout and stderr), without those
+     * JVM warning msgs, as list of strings. Output is split by newlines.
+     *
+     * @return Contents of the output buffer as list of strings
+     */
+    public List<String> asLinesWithoutVMWarnings() {
+        return Arrays.asList(getOutput().split("\\R"))
+                .stream()
+                .filter(Pattern.compile(jvmwarningmsg).asPredicate().negate())
+                .collect(Collectors.toList());
+    }
 
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/JDK-8201466.js	Thu Apr 26 17:59:02 2018 +0200
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * JDK-8201466: Nashorn: defineProperty setters/getters on prototype object ignored with numeric property names
+ *
+ * @test
+ * @run
+ */
+
+var z = {}, s = null, g = null;
+
+Object.defineProperty(z,'0', {
+    get:function(){ g = 2; return 1;},
+    set:function(v){ s = v;}
+});
+
+var x = Object.create(z);
+x[0] = 3;
+
+Assert.assertTrue(x[0] === 1);
+Assert.assertTrue(g === 2);
+Assert.assertTrue(s === 3);
+