changeset 47284:59bdd7243c52 condy

Backed out changeset ed420ea71310
author mcimadamore
date Mon, 25 Sep 2017 15:37:25 +0100
parents ed420ea71310
children 8897d34c2185 b90a1b5b8142
files make/Bundles.gmk make/CopyImportModules.gmk make/CreateBuildJdkCopy.gmk make/CreateJmods.gmk make/Docs.gmk make/GenerateLinkOptData.gmk make/Images.gmk make/Init.gmk make/InitSupport.gmk make/Jprt.gmk make/MacBundles.gmk make/Main.gmk make/MainSupport.gmk make/ReleaseFile.gmk make/RunTests.gmk make/autoconf/Makefile.in make/autoconf/basics.m4 make/autoconf/basics_windows.m4 make/autoconf/boot-jdk.m4 make/autoconf/bootcycle-spec.gmk.in make/autoconf/buildjdk-spec.gmk.in make/autoconf/compare.sh.in make/autoconf/flags.m4 make/autoconf/generated-configure.sh make/autoconf/help.m4 make/autoconf/jdk-options.m4 make/autoconf/source-dirs.m4 make/autoconf/spec.gmk.in make/autoconf/toolchain.m4 make/common/JarArchive.gmk make/common/MakeBase.gmk make/common/NativeCompilation.gmk make/common/ZipArchive.gmk make/copy/Copy-java.base.gmk make/devkit/Makefile make/devkit/Tools.gmk make/gensrc/Gensrc-jdk.charsets.gmk make/gensrc/GensrcIcons.gmk make/hotspot/ide/CreateVSProject.gmk make/langtools/intellij/langtools.iml make/scripts/compare.sh make/test/JtregNativeHotspot.gmk make/test/JtregNativeJdk.gmk src/hotspot/cpu/x86/interp_masm_x86.cpp src/hotspot/cpu/x86/macroAssembler_x86.cpp src/hotspot/cpu/x86/templateTable_x86.cpp src/hotspot/share/c1/c1_GraphBuilder.cpp src/hotspot/share/ci/ciEnv.cpp src/hotspot/share/ci/ciReplay.cpp src/hotspot/share/ci/ciStreams.cpp src/hotspot/share/classfile/classFileParser.cpp src/hotspot/share/classfile/systemDictionary.cpp src/hotspot/share/classfile/systemDictionary.hpp src/hotspot/share/classfile/verifier.cpp src/hotspot/share/classfile/vmSymbols.cpp src/hotspot/share/classfile/vmSymbols.hpp src/hotspot/share/interpreter/bytecode.cpp src/hotspot/share/interpreter/bytecodeInterpreter.cpp src/hotspot/share/interpreter/bytecodeTracer.cpp src/hotspot/share/interpreter/interpreterRuntime.cpp src/hotspot/share/interpreter/linkResolver.cpp src/hotspot/share/interpreter/linkResolver.hpp src/hotspot/share/interpreter/rewriter.cpp src/hotspot/share/interpreter/templateTable.cpp src/hotspot/share/interpreter/templateTable.hpp src/hotspot/share/memory/universe.cpp src/hotspot/share/memory/universe.hpp src/hotspot/share/oops/constantPool.cpp src/hotspot/share/oops/constantPool.hpp src/hotspot/share/oops/generateOopMap.cpp src/hotspot/share/opto/parse2.cpp src/hotspot/share/prims/jvm.h src/hotspot/share/prims/jvmtiRedefineClasses.cpp src/hotspot/share/prims/methodHandles.cpp src/hotspot/share/runtime/globals.hpp src/hotspot/share/runtime/reflection.cpp src/hotspot/share/runtime/signature.cpp src/hotspot/share/runtime/signature.hpp src/hotspot/share/runtime/vmStructs.cpp src/hotspot/share/utilities/constantTag.cpp src/hotspot/share/utilities/constantTag.hpp src/hotspot/share/utilities/exceptions.cpp src/hotspot/share/utilities/exceptions.hpp src/hotspot/share/utilities/globalDefinitions.hpp src/java.base/share/classes/java/lang/invoke/CallSite.java src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java src/java.base/share/classes/java/lang/invoke/MethodHandles.java src/java.base/share/classes/java/lang/invoke/package-info.java src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java src/java.base/share/native/libjli/java.c src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/CPSelector.java src/sample/nashorn/java_completion.js test/jdk/java/lang/invoke/CallSiteTest.java test/jdk/java/lang/invoke/CallStaticInitOrder.java test/jdk/java/lang/invoke/InvokeDynamicPrintArgs.java test/jdk/java/lang/invoke/MethodHandleConstants.java
diffstat 112 files changed, 2237 insertions(+), 1172 deletions(-) [+]
line wrap: on
line diff
--- a/make/Bundles.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/Bundles.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -56,7 +56,7 @@
     $$(eval $1_$$d_RELATIVE_FILES := $$$$(patsubst $$d/%, %, \
         $$$$(filter $$d/%, $$$$($1_FILES)))) \
     $$(eval $1_$$d_LIST_FILE := \
-        $(SUPPORT_OUTPUTDIR)/bundles/_$1_$$$$(subst /,_,$$$$(patsubst $(OUTPUTDIR)/%,%,$$d)_files)) \
+        $(SUPPORT_OUTPUTDIR)/bundles/_$1_$$$$(subst /,_,$$$$(patsubst $(OUTPUT_ROOT)/%,%,$$d)_files)) \
   )
 
   ifneq ($$(filter %.tar.gz, $$($1_BUNDLE_NAME)), )
--- a/make/CopyImportModules.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/CopyImportModules.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -62,10 +62,10 @@
         FILES := $(filter %$(SHARED_LIBRARY_SUFFIX), $(call CacheFind, $(LIBS_DIR))), \
     ))
 
-    # Use relative links if the import dir is inside the OUTPUTDIR, otherwise
+    # Use relative links if the import dir is inside the OUTPUT_ROOT, otherwise
     # copy to avoid having automated systems following symlinks when deleting files,
     # or risk invalidating the build output from external changes.
-    ifeq ($(filter $(OUTPUTDIR)/%, $(LIBS_DIR)), )
+    ifeq ($(filter $(OUTPUT_ROOT)/%, $(LIBS_DIR)), )
       LINK_MACRO := install-file
       LOG_ACTION := Copying
     else
--- a/make/CreateBuildJdkCopy.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/CreateBuildJdkCopy.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -54,7 +54,7 @@
 ################################################################################
 
 $(eval $(call SetupCopyFiles, COPY_SUPPORT_HEADERS, \
-    SRC := $(OUTPUTDIR), \
+    SRC := $(BUILD_OUTPUT), \
     DEST := $(BUILDJDK_OUTPUTDIR), \
     FILES := $(call CacheFind, $(wildcard \
         $(addprefix $(SUPPORT_OUTPUTDIR)/headers/, $(MODULES_TO_COPY)))), \
@@ -65,7 +65,7 @@
 ################################################################################
 
 $(eval $(call SetupCopyFiles, COPY_JDK_LIB_FILES, \
-    SRC := $(OUTPUTDIR), \
+    SRC := $(BUILD_OUTPUT), \
     DEST := $(BUILDJDK_OUTPUTDIR), \
     FILES := $(JDK_OUTPUTDIR)/lib/tzdb.dat, \
 ))
--- a/make/CreateJmods.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/CreateJmods.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -130,7 +130,7 @@
 # Create jmods in a temp dir and then move them into place to keep the
 # module path in $(IMAGES_OUTPUTDIR)/jmods valid at all times.
 $(JMODS_DIR)/$(MODULE).jmod: $(DEPS)
-	$(call LogWarn, Creating $(patsubst $(OUTPUTDIR)/%, %, $@))
+	$(call LogWarn, Creating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
 	$(call MakeDir, $(JMODS_DIR) $(JMODS_TEMPDIR))
 	$(RM) $@ $(JMODS_TEMPDIR)/$(notdir $@)
 	$(JMOD) create \
--- a/make/Docs.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/Docs.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -532,7 +532,7 @@
 # Optional target which bundles all generated javadocs into a zip archive.
 
 JAVADOC_ZIP_NAME := jdk-$(VERSION_STRING)-docs.zip
-JAVADOC_ZIP_FILE := $(OUTPUTDIR)/bundles/$(JAVADOC_ZIP_NAME)
+JAVADOC_ZIP_FILE := $(OUTPUT_ROOT)/bundles/$(JAVADOC_ZIP_NAME)
 
 $(eval $(call SetupZipArchive, BUILD_JAVADOC_ZIP, \
     SRC := $(DOCS_OUTPUTDIR), \
--- a/make/GenerateLinkOptData.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/GenerateLinkOptData.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -59,8 +59,8 @@
 
 $(CLASSLIST_FILE): $(INTERIM_IMAGE_DIR)/bin/java$(EXE_SUFFIX) $(CLASSLIST_JAR)
 	$(call MakeDir, $(LINK_OPT_DIR))
-	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@))
-	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $(JLI_TRACE_FILE)))
+	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
+	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $(JLI_TRACE_FILE)))
 	$(FIXPATH) $(INTERIM_IMAGE_DIR)/bin/java -XX:DumpLoadedClassList=$@ \
 	    -Djava.lang.invoke.MethodHandle.TRACE_RESOLVE=true \
 	    -cp $(SUPPORT_OUTPUTDIR)/classlist.jar \
--- a/make/Images.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/Images.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -247,38 +247,38 @@
   endif
 
   $(JRE_IMAGE_DIR)/man/man1/%: $(MAN_SRC_DIR)/$(MAN1_SUBDIR)/%
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
 
   $(JDK_IMAGE_DIR)/man/man1/%: $(MAN_SRC_DIR)/$(MAN1_SUBDIR)/%
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
 
   $(JRE_IMAGE_DIR)/man/ja_JP.UTF-8/man1/%: $(MAN_SRC_DIR)/$(MAN1_SUBDIR)/ja/%
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
 
   $(JDK_IMAGE_DIR)/man/ja_JP.UTF-8/man1/%: $(MAN_SRC_DIR)/$(MAN1_SUBDIR)/ja/%
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
 
   ifeq ($(OPENJDK_TARGET_OS), solaris)
     $(JRE_IMAGE_DIR)/man/ja/man1/%: $(MAN_SRC_DIR)/$(MAN1_SUBDIR)/ja/%
-	$(call LogInfo, Converting $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Converting $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
 
     $(JDK_IMAGE_DIR)/man/ja/man1/%: $(MAN_SRC_DIR)/$(MAN1_SUBDIR)/ja/%
-	$(call LogInfo, Converting $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Converting $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
   endif
 
   ifneq ($(findstring $(OPENJDK_TARGET_OS), linux macosx), )
     $(JRE_IMAGE_DIR)/man/ja:
-	$(call LogInfo, Creating $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(CD) $(@D) && $(RM) ja && $(LN) -s ja_JP.UTF-8 ja
 
     $(JDK_IMAGE_DIR)/man/ja:
-	$(call LogInfo, Creating $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Creating $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(CD) $(@D) && $(RM) ja && $(LN) -s ja_JP.UTF-8 ja
   endif
 
@@ -312,7 +312,7 @@
 # src.zip
 
 $(JDK_IMAGE_DIR)/lib/src.zip: $(SUPPORT_OUTPUTDIR)/src.zip
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(install-file)
 
 JDK_TARGETS += $(JDK_IMAGE_DIR)/lib/src.zip
@@ -354,14 +354,14 @@
   GCOV_FIND_EXPR := -type f -name "*.gcno"
 
   $(eval $(call SetupCopyFiles,COPY_HOTSPOT_GCOV_GCNO, \
-      SRC := $(OUTPUTDIR), \
+      SRC := $(OUTPUT_ROOT), \
       DEST := $(SYMBOLS_IMAGE_DIR)/gcov, \
       FILES := $(shell $(FIND) $(HOTSPOT_OUTPUTDIR) $(GCOV_FIND_EXPR))))
 
   SYMBOLS_TARGETS += $(COPY_HOTSPOT_GCOV_GCNO)
 
   $(eval $(call SetupCopyFiles,COPY_JDK_GCOV_GCNO, \
-      SRC := $(OUTPUTDIR), \
+      SRC := $(OUTPUT_ROOT), \
       DEST := $(SYMBOLS_IMAGE_DIR)/gcov, \
       FILES := $(shell $(FIND) $(SUPPORT_OUTPUTDIR)/native $(GCOV_FIND_EXPR))))
 
--- a/make/Init.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/Init.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -265,7 +265,7 @@
         else
 	  $(ECHO) "Re-running configure using default settings"
         endif
-	( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \
+	( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \
 	    $(BASH) $(CONFIGURE_CMD) $(CONFIGURE_COMMAND_LINE) )
 
   ##############################################################################
--- a/make/InitSupport.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/InitSupport.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -349,8 +349,8 @@
   include $(TOPDIR)/make/common/MakeBase.gmk
 
   # Define basic logging setup
-  BUILD_LOG := $(OUTPUTDIR)/build.log
-  BUILD_PROFILE_LOG := $(OUTPUTDIR)/build-profile.log
+  BUILD_LOG := $(OUTPUT_ROOT)/build.log
+  BUILD_PROFILE_LOG := $(OUTPUT_ROOT)/build-profile.log
 
   BUILD_LOG_PIPE := > >($(TEE) -a $(BUILD_LOG)) 2> >($(TEE) -a $(BUILD_LOG) >&2) && wait
 
@@ -383,7 +383,7 @@
   # FAIL can be set to false to have the return value of compare be ignored.
   define ParseCompareBuild
     ifneq ($$(COMPARE_BUILD), )
-      COMPARE_BUILD_OUTPUTDIR := $(TOPDIR)/build/compare-build/$(CONF_NAME)
+      COMPARE_BUILD_OUTPUT_ROOT := $(TOPDIR)/build/compare-build/$(CONF_NAME)
       COMPARE_BUILD_FAIL := true
 
       ifneq ($$(findstring :, $$(COMPARE_BUILD)), )
@@ -443,16 +443,16 @@
         # Move the first build away temporarily
 	$(RM) -r $(TOPDIR)/build/.compare-build-temp
 	$(MKDIR) -p $(TOPDIR)/build/.compare-build-temp
-	$(MV) $(OUTPUTDIR) $(TOPDIR)/build/.compare-build-temp
+	$(MV) $(OUTPUT_ROOT) $(TOPDIR)/build/.compare-build-temp
         # Restore an old compare-build, or create a new compare-build directory.
-	if test -d $(COMPARE_BUILD_OUTPUTDIR); then \
-	  $(MV) $(COMPARE_BUILD_OUTPUTDIR) $(OUTPUTDIR); \
+	if test -d $(COMPARE_BUILD_OUTPUT_ROOT); then \
+	  $(MV) $(COMPARE_BUILD_OUTPUT_ROOT) $(OUTPUT_ROOT); \
 	else \
-	  $(MKDIR) -p $(OUTPUTDIR); \
+	  $(MKDIR) -p $(OUTPUT_ROOT); \
 	fi
         # Re-run configure with the same arguments (and possibly some additional),
         # must be done after patching.
-	( cd $(OUTPUTDIR) && PATH="$(ORIGINAL_PATH)" \
+	( cd $(OUTPUT_ROOT) && PATH="$(ORIGINAL_PATH)" \
 	    $(BASH) $(TOPDIR)/configure $(CONFIGURE_COMMAND_LINE) $(COMPARE_BUILD_CONF))
   endef
 
@@ -462,8 +462,8 @@
 	$(if $(COMPARE_BUILD_PATCH), $(PATCH) -R -p1 < $(COMPARE_BUILD_PATCH))
         # Move this build away and restore the original build
 	$(MKDIR) -p $(TOPDIR)/build/compare-build
-	$(MV) $(OUTPUTDIR) $(COMPARE_BUILD_OUTPUTDIR)
-	$(MV) $(TOPDIR)/build/.compare-build-temp/$(CONF_NAME) $(OUTPUTDIR)
+	$(MV) $(OUTPUT_ROOT) $(COMPARE_BUILD_OUTPUT_ROOT)
+	$(MV) $(TOPDIR)/build/.compare-build-temp/$(CONF_NAME) $(OUTPUT_ROOT)
 	$(RM) -r $(TOPDIR)/build/.compare-build-temp
   endef
 
@@ -472,11 +472,11 @@
         # Compare first and second build. Ignore any error code from compare.sh.
 	$(ECHO) "Comparing between comparison rebuild (this/new) and baseline (other/old)"
 	$(if $(COMPARE_BUILD_COMP_DIR), \
-	  +(cd $(COMPARE_BUILD_OUTPUTDIR) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \
-	      -2dirs $(COMPARE_BUILD_OUTPUTDIR)/$(COMPARE_BUILD_COMP_DIR) \
-	      $(OUTPUTDIR)/$(COMPARE_BUILD_COMP_DIR) $(COMPARE_BUILD_IGNORE_RESULT)), \
-	  +(cd $(COMPARE_BUILD_OUTPUTDIR) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \
-	      -o $(OUTPUTDIR) $(COMPARE_BUILD_IGNORE_RESULT)) \
+	  +(cd $(COMPARE_BUILD_OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \
+	      -2dirs $(COMPARE_BUILD_OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) \
+	      $(OUTPUT_ROOT)/$(COMPARE_BUILD_COMP_DIR) $(COMPARE_BUILD_IGNORE_RESULT)), \
+	  +(cd $(COMPARE_BUILD_OUTPUT_ROOT) && ./compare.sh $(COMPARE_BUILD_COMP_OPTS) \
+	      -o $(OUTPUT_ROOT) $(COMPARE_BUILD_IGNORE_RESULT)) \
 	)
   endef
 
--- a/make/Jprt.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/Jprt.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -94,7 +94,7 @@
   # Just fake the main bundle to satisfy JPRT
   jprt_bundle: $(JPRT_TARGET)
 	@$(call TargetEnter)
-	$(MKDIR) -p $(OUTPUTDIR)/bundles
+	$(MKDIR) -p $(BUILD_OUTPUT)/bundles
 	$(CD) $(TOPDIR) && $(TAR) cf - README | $(GZIP) > \
 	    $(JPRT_ARCHIVE_BUNDLE)
 	@$(call TargetExit)
--- a/make/MacBundles.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/MacBundles.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -57,23 +57,23 @@
 
   # Copy empty directories (jre/lib/applet).
   $(JDK_MACOSX_CONTENTS_DIR)/Home/%: $(JDK_IMAGE_DIR)/%
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(MKDIR) -p $(@D)
 	if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi
 
   $(JRE_MACOSX_CONTENTS_DIR)/Home/%: $(JRE_IMAGE_DIR)/%
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(MKDIR) -p $(@D)
 	if [ -d "$<" ]; then $(MKDIR) -p $@; else $(CP) -f -R -P '$<' '$@'; fi
 
   $(JDK_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib:
-	$(call LogInfo, Creating link $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(MKDIR) -p $(@D)
 	$(RM) $@
 	$(LN) -s ../Home/lib/jli/libjli.dylib $@
 
   $(JRE_MACOSX_CONTENTS_DIR)/MacOS/libjli.dylib:
-	$(call LogInfo, Creating link $(patsubst $(OUTPUTDIR)/%,%,$@))
+	$(call LogInfo, Creating link $(patsubst $(OUTPUT_ROOT)/%,%,$@))
 	$(MKDIR) -p $(@D)
 	$(RM) $@
 	$(LN) -s ../Home/lib/jli/libjli.dylib $@
--- a/make/Main.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/Main.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -928,7 +928,7 @@
 
 demos: demos-jdk
 
-# The "exploded image" is a locally runnable JDK in $(OUTPUTDIR)/jdk.
+# The "exploded image" is a locally runnable JDK in $(BUILD_OUTPUT)/jdk.
 exploded-image-base: $(ALL_MODULES)
 exploded-image: exploded-image-base release-file
 # When cross compiling, no need to optimize the exploded image since it won't
@@ -957,7 +957,7 @@
 
 mac-bundles: mac-bundles-jdk
 
-# The $(OUTPUTDIR)/images directory contain the resulting deliverables,
+# The $(BUILD_OUTPUT)/images directory contain the resulting deliverables,
 # and in line with this, our targets for creating these are named *-image[s].
 
 # This target builds the product images, e.g. the JRE and JDK image
@@ -1048,7 +1048,7 @@
 
 # Remove everything, except the output from configure.
 clean: $(CLEAN_DIR_TARGETS)
-	($(CD) $(OUTPUTDIR) && $(RM) -r build*.log*)
+	($(CD) $(OUTPUT_ROOT) && $(RM) -r build*.log*)
 	$(ECHO) Cleaned all build artifacts.
 
 clean-docs:
@@ -1081,14 +1081,14 @@
 # Remove everything, including configure configuration. If the output
 # directory was created by configure and now becomes empty, remove it as well.
 dist-clean: clean
-	($(CD) $(OUTPUTDIR) && \
+	($(CD) $(OUTPUT_ROOT) && \
 	    $(RM) -r *spec.gmk $(CONFIGURESUPPORT_OUTPUTDIR) Makefile compare.sh ide)
-	$(if $(filter $(CONF_NAME),$(notdir $(OUTPUTDIR))), \
-	  if test "x`$(LS) $(OUTPUTDIR)`" != x; then \
+	$(if $(filter $(CONF_NAME),$(notdir $(OUTPUT_ROOT))), \
+	  if test "x`$(LS) $(OUTPUT_ROOT)`" != x; then \
 	    $(ECHO) "Warning: Not removing non-empty configuration directory for '$(CONF_NAME)'" ; \
 	  else \
 	    ($(CD) $(TOPDIR) && $(ECHO) "Removing configuration directory for '$(CONF_NAME)'" \
-	        && $(RM) -r $(OUTPUTDIR)) \
+	        && $(RM) -r $(OUTPUT_ROOT)) \
 	  fi \
 	)
 	$(ECHO) Cleaned everything, you will have to re-run configure.
--- a/make/MainSupport.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/MainSupport.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -36,7 +36,7 @@
 	($(CD) $(TOPDIR)/test && $(MAKE) $(MAKE_ARGS) -j1 -k MAKEFLAGS= \
 	    JT_HOME=$(JT_HOME) PRODUCT_HOME=$(strip $2) \
 	    TEST_IMAGE_DIR=$(TEST_IMAGE_DIR) \
-	    ALT_OUTPUTDIR=$(OUTPUTDIR) TEST_JOBS=$(TEST_JOBS) \
+	    ALT_OUTPUTDIR=$(OUTPUT_ROOT) TEST_JOBS=$(TEST_JOBS) \
 	    JT_JAVA=$(BOOT_JDK) JIB_JAR=$(JIB_JAR) \
 	    JOBS=$(JOBS) $1) || true
 endef
@@ -54,7 +54,7 @@
 define CleanDir
 	@$(PRINTF) "Cleaning $(strip $1) build artifacts ..."
 	@$(PRINTF) "\n" $(LOG_DEBUG)
-	($(CD) $(OUTPUTDIR) && $(RM) -r $1)
+	($(CD) $(OUTPUT_ROOT) && $(RM) -r $1)
 	@$(PRINTF) " done\n"
 endef
 
--- a/make/ReleaseFile.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/ReleaseFile.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -54,7 +54,7 @@
 
 # Param 1 - The file containing the MODULES list
 define prepare-info-file
-  $(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%,%,$@))
+  $(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%,%,$@))
   $(call MakeDir, $(@D))
   $(RM) $@
 endef
--- a/make/RunTests.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/RunTests.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -38,8 +38,8 @@
 # Hook to include the corresponding custom file, if present.
 $(eval $(call IncludeCustomExtension, , RunTests.gmk))
 
-TEST_RESULTS_DIR := $(OUTPUTDIR)/test-results
-TEST_SUPPORT_DIR := $(OUTPUTDIR)/test-support
+TEST_RESULTS_DIR := $(BUILD_OUTPUT)/test-results
+TEST_SUPPORT_DIR := $(BUILD_OUTPUT)/test-support
 
 
 ################################################################################
@@ -392,27 +392,20 @@
 	$$(call LogWarn, Finished running test '$$($1_TEST)')
 	$$(call LogWarn, Test report is stored in $$(strip \
 	    $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
-	$$(if  $$(wildcard $$($1_RESULT_FILE)), \
-	  $$(eval $1_PASSED := $$(shell $$(AWK) '{ gsub(/[,;]/, ""); \
-	      for (i=1; i<=NF; i++) { if ($$$$i == "passed:") \
-	      print $$$$(i+1) } }' $$($1_RESULT_FILE))) \
-	  $$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \
-	  $$(eval $1_FAILED := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \
-	      for (i=1; i<=NF; i++) { if ($$$$i == "failed:") \
-	      print $$$$(i+1) } }' $$($1_RESULT_FILE))) \
-	  $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \
-	  $$(eval $1_ERROR := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \
-	      for (i=1; i<=NF; i++) { if ($$$$i == "error:") \
-	      print $$$$(i+1) } }' $$($1_RESULT_FILE))) \
-	  $$(if $$($1_ERROR), , $$(eval $1_ERROR := 0)) \
-	  $$(eval $1_TOTAL := $$(shell \
-	      $$(EXPR) $$($1_PASSED) + $$($1_FAILED) + $$($1_ERROR))) \
-	, \
-	  $$(eval $1_PASSED := 0) \
-	  $$(eval $1_FAILED := 0) \
-	  $$(eval $1_ERROR := 1) \
-	  $$(eval $1_TOTAL := 1) \
-	)
+	$$(eval $1_PASSED := $$(shell $$(AWK) '{ gsub(/[,;]/, ""); \
+	    for (i=1; i<=NF; i++) { if ($$$$i == "passed:") \
+	    print $$$$(i+1) } }' $$($1_RESULT_FILE)))
+	$$(if $$($1_PASSED), , $$(eval $1_PASSED := 0))
+	$$(eval $1_FAILED := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \
+	    for (i=1; i<=NF; i++) { if ($$$$i == "failed:") \
+	    print $$$$(i+1) } }' $$($1_RESULT_FILE)))
+	$$(if $$($1_FAILED), , $$(eval $1_FAILED := 0))
+	$$(eval $1_ERROR := $$(shell $$(AWK) '{gsub(/[,;]/, ""); \
+	    for (i=1; i<=NF; i++) { if ($$$$i == "error:") \
+	    print $$$$(i+1) } }' $$($1_RESULT_FILE)))
+	$$(if $$($1_ERROR), , $$(eval $1_ERROR := 0))
+	$$(eval $1_TOTAL := $$(shell \
+	    $$(EXPR) $$($1_PASSED) + $$($1_FAILED) + $$($1_ERROR)))
 
   $1: run-test-$1 parse-test-$1
 
--- a/make/autoconf/Makefile.in	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/Makefile.in	Mon Sep 25 15:37:25 2017 +0100
@@ -23,5 +23,5 @@
 
 # This Makefile was generated by configure @DATE_WHEN_CONFIGURED@
 # GENERATED FILE, DO NOT EDIT
-SPEC:=@OUTPUTDIR@/spec.gmk
+SPEC:=@OUTPUT_ROOT@/spec.gmk
 include @TOPDIR@/Makefile
--- a/make/autoconf/basics.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/basics.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -568,6 +568,8 @@
   # We can only call BASIC_FIXUP_PATH after BASIC_CHECK_PATHS_WINDOWS.
   BASIC_FIXUP_PATH(CURDIR)
   BASIC_FIXUP_PATH(TOPDIR)
+  # SRC_ROOT is a traditional alias for TOPDIR.
+  SRC_ROOT=$TOPDIR
 
   # Calculate a canonical version of TOPDIR for string comparisons
   CANONICAL_TOPDIR=$TOPDIR
@@ -768,13 +770,13 @@
       [ CONF_NAME=${with_conf_name} ])
   AC_ARG_WITH(output-base-dir, [AS_HELP_STRING([--with-output-base-dir],
       [override the default output base directory @<:@./build@:>@])],
-      [ OUTPUT_BASE=${with_output_base_dir} ], [ OUTPUT_BASE="$TOPDIR/build" ] )
+      [ OUTPUT_BASE=${with_output_base_dir} ], [ OUTPUT_BASE="$SRC_ROOT/build" ] )
 
   # Test from where we are running configure, in or outside of src root.
   AC_MSG_CHECKING([where to store configuration])
-  if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$TOPDIR/common" \
-      || test "x$CURDIR" = "x$TOPDIR/make/autoconf" \
-      || test "x$CURDIR" = "x$TOPDIR/make" ; then
+  if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" \
+      || test "x$CURDIR" = "x$SRC_ROOT/make/autoconf" \
+      || test "x$CURDIR" = "x$SRC_ROOT/make" ; then
     # We are running configure from the src root.
     # Create a default ./build/target-variant-debuglevel output root.
     if test "x${CONF_NAME}" = x; then
@@ -783,10 +785,10 @@
     else
       AC_MSG_RESULT([in build directory with custom name])
     fi
-    OUTPUTDIR="${OUTPUT_BASE}/${CONF_NAME}"
-    $MKDIR -p "$OUTPUTDIR"
-    if test ! -d "$OUTPUTDIR"; then
-      AC_MSG_ERROR([Could not create build directory $OUTPUTDIR])
+    OUTPUT_ROOT="${OUTPUT_BASE}/${CONF_NAME}"
+    $MKDIR -p "$OUTPUT_ROOT"
+    if test ! -d "$OUTPUT_ROOT"; then
+      AC_MSG_ERROR([Could not create build directory $OUTPUT_ROOT])
     fi
   else
     # We are running configure from outside of the src dir.
@@ -794,18 +796,18 @@
     # If configuration is situated in normal build directory, just use the build
     # directory name as configuration name, otherwise use the complete path.
     if test "x${CONF_NAME}" = x; then
-      CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${TOPDIR}/build/!!"`
+      CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${SRC_ROOT}/build/!!"`
     fi
-    OUTPUTDIR="$CURDIR"
+    OUTPUT_ROOT="$CURDIR"
     AC_MSG_RESULT([in current directory])
 
     # WARNING: This might be a bad thing to do. You need to be sure you want to
     # have a configuration in this directory. Do some sanity checks!
 
-    if test ! -e "$OUTPUTDIR/spec.gmk"; then
+    if test ! -e "$OUTPUT_ROOT/spec.gmk"; then
       # If we have a spec.gmk, we have run here before and we are OK. Otherwise, check for
       # other files
-      files_present=`$LS $OUTPUTDIR`
+      files_present=`$LS $OUTPUT_ROOT`
       # Configure has already touched config.log and confdefs.h in the current dir when this check
       # is performed.
       filtered_files=`$ECHO "$files_present" \
@@ -820,7 +822,7 @@
         AC_MSG_NOTICE([(as opposed to creating a configuration in <src_root>/build/<conf-name>).])
         AC_MSG_NOTICE([However, this directory is not empty. This is not allowed, since it could])
         AC_MSG_NOTICE([seriously mess up just about everything.])
-        AC_MSG_NOTICE([Try 'cd $TOPDIR' and restart configure])
+        AC_MSG_NOTICE([Try 'cd $SRC_ROOT' and restart configure])
         AC_MSG_NOTICE([(or create a new empty directory and cd to it).])
         AC_MSG_ERROR([Will not continue creating configuration in $CURDIR])
       fi
@@ -829,29 +831,29 @@
   AC_MSG_CHECKING([what configuration name to use])
   AC_MSG_RESULT([$CONF_NAME])
 
-  BASIC_FIXUP_PATH(OUTPUTDIR)
+  BASIC_FIXUP_PATH(OUTPUT_ROOT)
 
-  CONFIGURESUPPORT_OUTPUTDIR="$OUTPUTDIR/configure-support"
+  CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
   $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
 
-  SPEC="$OUTPUTDIR/spec.gmk"
+  SPEC="$OUTPUT_ROOT/spec.gmk"
   AC_SUBST(SPEC)
   AC_SUBST(CONF_NAME)
-  AC_SUBST(OUTPUTDIR)
+  AC_SUBST(OUTPUT_ROOT)
   AC_SUBST(CONFIGURESUPPORT_OUTPUTDIR)
 
   # The spec.gmk file contains all variables for the make system.
-  AC_CONFIG_FILES([$OUTPUTDIR/spec.gmk:$AUTOCONF_DIR/spec.gmk.in])
+  AC_CONFIG_FILES([$OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in])
   # The bootcycle-spec.gmk file contains support for boot cycle builds.
-  AC_CONFIG_FILES([$OUTPUTDIR/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in])
+  AC_CONFIG_FILES([$OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in])
   # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling.
-  AC_CONFIG_FILES([$OUTPUTDIR/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in])
+  AC_CONFIG_FILES([$OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in])
   # The compare.sh is used to compare the build output to other builds.
-  AC_CONFIG_FILES([$OUTPUTDIR/compare.sh:$AUTOCONF_DIR/compare.sh.in])
+  AC_CONFIG_FILES([$OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in])
   # The generated Makefile knows where the spec.gmk is and where the source is.
-  # You can run make from the OUTPUTDIR, or from the top-level Makefile
+  # You can run make from the OUTPUT_ROOT, or from the top-level Makefile
   # which will look for generated configurations
-  AC_CONFIG_FILES([$OUTPUTDIR/Makefile:$AUTOCONF_DIR/Makefile.in])
+  AC_CONFIG_FILES([$OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in])
 ])
 
 #%%% Simple tools %%%
@@ -1171,7 +1173,7 @@
 AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS],
 [
   if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    file_to_test="$TOPDIR/LICENSE"
+    file_to_test="$SRC_ROOT/LICENSE"
     if test `$STAT -c '%a' "$file_to_test"` -lt 400; then
       AC_MSG_ERROR([Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin.])
     fi
@@ -1184,7 +1186,7 @@
   BASIC_CHECK_LEFTOVER_OVERRIDDEN
 
   AC_MSG_CHECKING([if build directory is on local disk])
-  BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUTDIR,
+  BASIC_CHECK_DIR_ON_LOCAL_DISK($OUTPUT_ROOT,
       [OUTPUT_DIR_IS_LOCAL="yes"],
       [OUTPUT_DIR_IS_LOCAL="no"])
   AC_MSG_RESULT($OUTPUT_DIR_IS_LOCAL)
@@ -1196,7 +1198,7 @@
 
   # Before generating output files, test if they exist. If they do, this is a reconfigure.
   # Since we can't properly handle the dependencies for this, warn the user about the situation
-  if test -e $OUTPUTDIR/spec.gmk; then
+  if test -e $OUTPUT_ROOT/spec.gmk; then
     IS_RECONFIGURE=yes
   else
     IS_RECONFIGURE=no
@@ -1267,18 +1269,18 @@
   fi
 
   # Rotate our log file (configure.log)
-  if test -e "$OUTPUTDIR/configure.log.old"; then
-    $RM -f "$OUTPUTDIR/configure.log.old"
+  if test -e "$OUTPUT_ROOT/configure.log.old"; then
+    $RM -f "$OUTPUT_ROOT/configure.log.old"
   fi
-  if test -e "$OUTPUTDIR/configure.log"; then
-    $MV -f "$OUTPUTDIR/configure.log" "$OUTPUTDIR/configure.log.old" 2> /dev/null
+  if test -e "$OUTPUT_ROOT/configure.log"; then
+    $MV -f "$OUTPUT_ROOT/configure.log" "$OUTPUT_ROOT/configure.log.old" 2> /dev/null
   fi
 
   # Move configure.log from current directory to the build output root
   if test -e ./configure.log; then
-    $MV -f ./configure.log "$OUTPUTDIR/configure.log" 2> /dev/null
+    $MV -f ./configure.log "$OUTPUT_ROOT/configure.log" 2> /dev/null
   fi
 
   # Make the compare script executable
-  $CHMOD +x $OUTPUTDIR/compare.sh
+  $CHMOD +x $OUTPUT_ROOT/compare.sh
 ])
--- a/make/autoconf/basics_windows.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/basics_windows.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -382,7 +382,7 @@
   FIXPATH=
   if test "x$OPENJDK_BUILD_OS" = xwindows; then
     AC_MSG_CHECKING([if fixpath can be created])
-    FIXPATH_SRC="$TOPDIR/make/src/native/fixpath.c"
+    FIXPATH_SRC="$SRC_ROOT/make/src/native/fixpath.c"
     FIXPATH_BIN="$CONFIGURESUPPORT_OUTPUTDIR/bin/fixpath.exe"
     FIXPATH_DIR="$CONFIGURESUPPORT_OUTPUTDIR/fixpath"
     if test "x$OPENJDK_BUILD_OS_ENV" = xwindows.cygwin; then
--- a/make/autoconf/boot-jdk.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/boot-jdk.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -77,10 +77,10 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          [FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`]
+          [FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`]
           if test "x$FOUND_CORRECT_VERSION" = x; then
             AC_MSG_NOTICE([Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring])
-            AC_MSG_NOTICE([(Your Boot JDK must be version 8, 9 or 10)])
+            AC_MSG_NOTICE([(Your Boot JDK must be version 8 or 9)])
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -469,10 +469,10 @@
         BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
         # Extra M4 quote needed to protect [] in grep expression.
-        [FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"'`]
+        [FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"'`]
         if test "x$FOUND_CORRECT_VERSION" = x; then
           AC_MSG_NOTICE([Potential Build JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring])
-          AC_MSG_NOTICE([(Your Build JDK must be version 10)])
+          AC_MSG_NOTICE([(Your Build JDK must be version 9)])
           BUILD_JDK_FOUND=no
         else
           # We're done!
--- a/make/autoconf/bootcycle-spec.gmk.in	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/bootcycle-spec.gmk.in	Mon Sep 25 15:37:25 2017 +0100
@@ -48,9 +48,9 @@
 BOOT_JDK := $(JDK_IMAGE_DIR)
 
 # The bootcycle build has a different output directory
-OLD_OUTPUTDIR:=@OUTPUTDIR@
-OUTPUTDIR:=$(OLD_OUTPUTDIR)/bootcycle-build
-SJAVAC_SERVER_DIR:=$(patsubst $(OLD_OUTPUTDIR)%, $(OUTPUTDIR)%, $(SJAVAC_SERVER_DIR))
+OLD_BUILD_OUTPUT:=@BUILD_OUTPUT@
+BUILD_OUTPUT:=$(OLD_BUILD_OUTPUT)/bootcycle-build
+SJAVAC_SERVER_DIR:=$(patsubst $(OLD_BUILD_OUTPUT)%, $(BUILD_OUTPUT)%, $(SJAVAC_SERVER_DIR))
 
 JAVA_CMD:=$(BOOT_JDK)/bin/java
 JAVAC_CMD:=$(BOOT_JDK)/bin/javac
--- a/make/autoconf/buildjdk-spec.gmk.in	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/buildjdk-spec.gmk.in	Mon Sep 25 15:37:25 2017 +0100
@@ -43,10 +43,10 @@
 SYSROOT_LDFLAGS := @BUILD_SYSROOT_LDFLAGS@
 
 # These directories should not be moved to BUILDJDK_OUTPUTDIR
-HOTSPOT_OUTPUTDIR := $(patsubst $(OUTPUTDIR)%,$(BUILDJDK_OUTPUTDIR)%,$(HOTSPOT_OUTPUTDIR))
-SUPPORT_OUTPUTDIR := $(patsubst $(OUTPUTDIR)%,$(BUILDJDK_OUTPUTDIR)%,$(SUPPORT_OUTPUTDIR))
-JDK_OUTPUTDIR := $(patsubst $(OUTPUTDIR)%,$(BUILDJDK_OUTPUTDIR)%,$(JDK_OUTPUTDIR))
-IMAGES_OUTPUTDIR := $(patsubst $(OUTPUTDIR)%,$(BUILDJDK_OUTPUTDIR)%,$(IMAGES_OUTPUTDIR))
+HOTSPOT_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(HOTSPOT_OUTPUTDIR))
+SUPPORT_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(SUPPORT_OUTPUTDIR))
+JDK_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(JDK_OUTPUTDIR))
+IMAGES_OUTPUTDIR := $(patsubst $(BUILD_OUTPUT)%,$(BUILDJDK_OUTPUTDIR)%,$(IMAGES_OUTPUTDIR))
 
 OPENJDK_BUILD_CPU_LEGACY := @OPENJDK_BUILD_CPU_LEGACY@
 OPENJDK_BUILD_CPU_LEGACY_LIB := @OPENJDK_BUILD_CPU_LEGACY_LIB@
--- a/make/autoconf/compare.sh.in	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/compare.sh.in	Mon Sep 25 15:37:25 2017 +0100
@@ -69,15 +69,15 @@
 export UNPACK200="@FIXPATH@ @BOOT_JDK@/bin/unpack200"
 export UNARCHIVE="@UNZIP@ -q -o"
 
-export TOPDIR="@TOPDIR@"
-export OUTPUTDIR="@OUTPUTDIR@"
+export SRC_ROOT="@TOPDIR@"
+export OUTPUT_ROOT="@OUTPUT_ROOT@"
 
 if [ "@COMPILE_TYPE@" != "cross" ]; then
-    export JAVAP="@FIXPATH@ $OUTPUTDIR/jdk/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
-    export JIMAGE="@FIXPATH@ $OUTPUTDIR/jdk/bin/jimage"
+    export JAVAP="@FIXPATH@ $OUTPUT_ROOT/jdk/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
+    export JIMAGE="@FIXPATH@ $OUTPUT_ROOT/jdk/bin/jimage"
 elif [ "@CREATE_BUILDJDK@" = "true" ]; then
-    export JAVAP="@FIXPATH@ $OUTPUTDIR/buildjdk/jdk/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
-    export JIMAGE="@FIXPATH@ $OUTPUTDIR/buildjdk/jdk/bin/jimage"
+    export JAVAP="@FIXPATH@ $OUTPUT_ROOT/buildjdk/jdk/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
+    export JIMAGE="@FIXPATH@ $OUTPUT_ROOT/buildjdk/jdk/bin/jimage"
 else
     export JAVAP="@FIXPATH@ @BUILD_JDK@/bin/javap @JAVA_TOOL_FLAGS_SMALL@"
     export JIMAGE="@FIXPATH@ @BUILD_JDK@/bin/jimage"
@@ -88,16 +88,16 @@
 fi
 
 # Now locate the main script and run it.
-REAL_COMPARE_SCRIPT="$TOPDIR/make/scripts/compare.sh"
+REAL_COMPARE_SCRIPT="$SRC_ROOT/make/scripts/compare.sh"
 if [ ! -e "$REAL_COMPARE_SCRIPT" ]; then
   echo "Error: Cannot locate compare script, it should have been in $REAL_COMPARE_SCRIPT"
   exit 1
 fi
 
 # Rotate logs
-$RM $OUTPUTDIR/compare.log.old 2> /dev/null
-$MV $OUTPUTDIR/compare.log $OUTPUTDIR/compare.log.old 2> /dev/null
+$RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
+$MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
 
 export SCRIPT_DIR="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
 
-$BASH $TOPDIR/make/scripts/logger.sh $OUTPUTDIR/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
+$BASH $SRC_ROOT/make/scripts/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
--- a/make/autoconf/flags.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/flags.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -1313,7 +1313,7 @@
   $2LDFLAGS_JDKLIB="${$2LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}"
   if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     $2JAVA_BASE_LDFLAGS="${$2JAVA_BASE_LDFLAGS} \
-        -libpath:${OUTPUTDIR}/support/modules_libs/java.base"
+        -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
     $2JDKLIB_LIBS=""
   else
     $2JAVA_BASE_LDFLAGS="${$2JAVA_BASE_LDFLAGS} \
--- a/make/autoconf/generated-configure.sh	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/generated-configure.sh	Mon Sep 25 15:37:25 2017 +0100
@@ -870,6 +870,7 @@
 IMPORT_MODULES_LIBS
 IMPORT_MODULES_CMDS
 IMPORT_MODULES_CLASSES
+BUILD_OUTPUT
 EXTERNAL_BUILDJDK
 BUILD_JDK
 CREATE_BUILDJDK
@@ -951,7 +952,7 @@
 MAKE
 PKGHANDLER
 CONFIGURESUPPORT_OUTPUTDIR
-OUTPUTDIR
+OUTPUT_ROOT
 CONF_NAME
 SPEC
 SDKROOT
@@ -5115,7 +5116,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1506333008
+DATE_WHEN_GENERATED=1506027115
 
 ###############################################################################
 #
@@ -16803,6 +16804,8 @@
     fi
   fi
 
+  # SRC_ROOT is a traditional alias for TOPDIR.
+  SRC_ROOT=$TOPDIR
 
   # Calculate a canonical version of TOPDIR for string comparisons
   CANONICAL_TOPDIR=$TOPDIR
@@ -17556,16 +17559,16 @@
 if test "${with_output_base_dir+set}" = set; then :
   withval=$with_output_base_dir;  OUTPUT_BASE=${with_output_base_dir}
 else
-   OUTPUT_BASE="$TOPDIR/build"
+   OUTPUT_BASE="$SRC_ROOT/build"
 fi
 
 
   # Test from where we are running configure, in or outside of src root.
   { $as_echo "$as_me:${as_lineno-$LINENO}: checking where to store configuration" >&5
 $as_echo_n "checking where to store configuration... " >&6; }
-  if test "x$CURDIR" = "x$TOPDIR" || test "x$CURDIR" = "x$TOPDIR/common" \
-      || test "x$CURDIR" = "x$TOPDIR/make/autoconf" \
-      || test "x$CURDIR" = "x$TOPDIR/make" ; then
+  if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" \
+      || test "x$CURDIR" = "x$SRC_ROOT/make/autoconf" \
+      || test "x$CURDIR" = "x$SRC_ROOT/make" ; then
     # We are running configure from the src root.
     # Create a default ./build/target-variant-debuglevel output root.
     if test "x${CONF_NAME}" = x; then
@@ -17576,10 +17579,10 @@
       { $as_echo "$as_me:${as_lineno-$LINENO}: result: in build directory with custom name" >&5
 $as_echo "in build directory with custom name" >&6; }
     fi
-    OUTPUTDIR="${OUTPUT_BASE}/${CONF_NAME}"
-    $MKDIR -p "$OUTPUTDIR"
-    if test ! -d "$OUTPUTDIR"; then
-      as_fn_error $? "Could not create build directory $OUTPUTDIR" "$LINENO" 5
+    OUTPUT_ROOT="${OUTPUT_BASE}/${CONF_NAME}"
+    $MKDIR -p "$OUTPUT_ROOT"
+    if test ! -d "$OUTPUT_ROOT"; then
+      as_fn_error $? "Could not create build directory $OUTPUT_ROOT" "$LINENO" 5
     fi
   else
     # We are running configure from outside of the src dir.
@@ -17587,19 +17590,19 @@
     # If configuration is situated in normal build directory, just use the build
     # directory name as configuration name, otherwise use the complete path.
     if test "x${CONF_NAME}" = x; then
-      CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${TOPDIR}/build/!!"`
-    fi
-    OUTPUTDIR="$CURDIR"
+      CONF_NAME=`$ECHO $CURDIR | $SED -e "s!^${SRC_ROOT}/build/!!"`
+    fi
+    OUTPUT_ROOT="$CURDIR"
     { $as_echo "$as_me:${as_lineno-$LINENO}: result: in current directory" >&5
 $as_echo "in current directory" >&6; }
 
     # WARNING: This might be a bad thing to do. You need to be sure you want to
     # have a configuration in this directory. Do some sanity checks!
 
-    if test ! -e "$OUTPUTDIR/spec.gmk"; then
+    if test ! -e "$OUTPUT_ROOT/spec.gmk"; then
       # If we have a spec.gmk, we have run here before and we are OK. Otherwise, check for
       # other files
-      files_present=`$LS $OUTPUTDIR`
+      files_present=`$LS $OUTPUT_ROOT`
       # Configure has already touched config.log and confdefs.h in the current dir when this check
       # is performed.
       filtered_files=`$ECHO "$files_present" \
@@ -17619,8 +17622,8 @@
 $as_echo "$as_me: However, this directory is not empty. This is not allowed, since it could" >&6;}
         { $as_echo "$as_me:${as_lineno-$LINENO}: seriously mess up just about everything." >&5
 $as_echo "$as_me: seriously mess up just about everything." >&6;}
-        { $as_echo "$as_me:${as_lineno-$LINENO}: Try 'cd $TOPDIR' and restart configure" >&5
-$as_echo "$as_me: Try 'cd $TOPDIR' and restart configure" >&6;}
+        { $as_echo "$as_me:${as_lineno-$LINENO}: Try 'cd $SRC_ROOT' and restart configure" >&5
+$as_echo "$as_me: Try 'cd $SRC_ROOT' and restart configure" >&6;}
         { $as_echo "$as_me:${as_lineno-$LINENO}: (or create a new empty directory and cd to it)." >&5
 $as_echo "$as_me: (or create a new empty directory and cd to it)." >&6;}
         as_fn_error $? "Will not continue creating configuration in $CURDIR" "$LINENO" 5
@@ -17635,161 +17638,161 @@
 
   # Only process if variable expands to non-empty
 
-  if test "x$OUTPUTDIR" != x; then
-    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-
-  # Input might be given as Windows format, start by converting to
-  # unix format.
-  path="$OUTPUTDIR"
-  new_path=`$CYGPATH -u "$path"`
-
-  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
-  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
-  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
-  # "foo.exe" is OK but "foo" is an error.
-  #
-  # This test is therefore slightly more accurate than "test -f" to check for file precense.
-  # It is also a way to make sure we got the proper file name for the real test later on.
-  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
-  if test "x$test_shortpath" = x; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OUTPUTDIR, which resolves as \"$path\", is invalid." >&5
-$as_echo "$as_me: The path of OUTPUTDIR, which resolves as \"$path\", is invalid." >&6;}
-    as_fn_error $? "Cannot locate the the path of OUTPUTDIR" "$LINENO" 5
-  fi
-
-  # Call helper function which possibly converts this using DOS-style short mode.
-  # If so, the updated path is stored in $new_path.
-
-  input_path="$new_path"
-  # Check if we need to convert this using DOS-style short mode. If the path
-  # contains just simple characters, use it. Otherwise (spaces, weird characters),
-  # take no chances and rewrite it.
-  # Note: m4 eats our [], so we need to use [ and ] instead.
-  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
-  if test "x$has_forbidden_chars" != x; then
-    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
-    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
-    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
-    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
-      # Going to short mode and back again did indeed matter. Since short mode is
-      # case insensitive, let's make it lowercase to improve readability.
-      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-      # Now convert it back to Unix-style (cygpath)
-      input_path=`$CYGPATH -u "$shortmode_path"`
-      new_path="$input_path"
-    fi
-  fi
-
-  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
-  if test "x$test_cygdrive_prefix" = x; then
-    # As a simple fix, exclude /usr/bin since it's not a real path.
-    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
-      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
-      # a path prefixed by /cygdrive for fixpath to work.
-      new_path="$CYGWIN_ROOT_PATH$input_path"
-    fi
-  fi
-
-
-  if test "x$path" != "x$new_path"; then
-    OUTPUTDIR="$new_path"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OUTPUTDIR to \"$new_path\"" >&5
-$as_echo "$as_me: Rewriting OUTPUTDIR to \"$new_path\"" >&6;}
-  fi
-
-    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-
-  path="$OUTPUTDIR"
-  has_colon=`$ECHO $path | $GREP ^.:`
-  new_path="$path"
-  if test "x$has_colon" = x; then
-    # Not in mixed or Windows style, start by that.
-    new_path=`cmd //c echo $path`
-  fi
-
-
-  input_path="$new_path"
-  # Check if we need to convert this using DOS-style short mode. If the path
-  # contains just simple characters, use it. Otherwise (spaces, weird characters),
-  # take no chances and rewrite it.
-  # Note: m4 eats our [], so we need to use [ and ] instead.
-  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
-  if test "x$has_forbidden_chars" != x; then
-    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
-    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-  fi
-
-
-  windows_path="$new_path"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    unix_path=`$CYGPATH -u "$windows_path"`
-    new_path="$unix_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
-    new_path="$unix_path"
-  fi
-
-  if test "x$path" != "x$new_path"; then
-    OUTPUTDIR="$new_path"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OUTPUTDIR to \"$new_path\"" >&5
-$as_echo "$as_me: Rewriting OUTPUTDIR to \"$new_path\"" >&6;}
-  fi
-
-  # Save the first 10 bytes of this path to the storage, so fixpath can work.
-  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
-
-    else
-      # We're on a unix platform. Hooray! :)
-      path="$OUTPUTDIR"
-      has_space=`$ECHO "$path" | $GREP " "`
-      if test "x$has_space" != x; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OUTPUTDIR, which resolves as \"$path\", is invalid." >&5
-$as_echo "$as_me: The path of OUTPUTDIR, which resolves as \"$path\", is invalid." >&6;}
-        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
-      fi
-
-      # Use eval to expand a potential ~
-      eval path="$path"
-      if test ! -f "$path" && test ! -d "$path"; then
-        as_fn_error $? "The path of OUTPUTDIR, which resolves as \"$path\", is not found." "$LINENO" 5
-      fi
-
-      if test -d "$path"; then
-        OUTPUTDIR="`cd "$path"; $THEPWDCMD -L`"
-      else
-        dir="`$DIRNAME "$path"`"
-        base="`$BASENAME "$path"`"
-        OUTPUTDIR="`cd "$dir"; $THEPWDCMD -L`/$base"
-      fi
-    fi
-  fi
-
-
-  CONFIGURESUPPORT_OUTPUTDIR="$OUTPUTDIR/configure-support"
+  if test "x$OUTPUT_ROOT" != x; then
+    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+
+  # Input might be given as Windows format, start by converting to
+  # unix format.
+  path="$OUTPUT_ROOT"
+  new_path=`$CYGPATH -u "$path"`
+
+  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
+  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
+  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
+  # "foo.exe" is OK but "foo" is an error.
+  #
+  # This test is therefore slightly more accurate than "test -f" to check for file precense.
+  # It is also a way to make sure we got the proper file name for the real test later on.
+  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
+  if test "x$test_shortpath" = x; then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OUTPUT_ROOT, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is invalid." >&6;}
+    as_fn_error $? "Cannot locate the the path of OUTPUT_ROOT" "$LINENO" 5
+  fi
+
+  # Call helper function which possibly converts this using DOS-style short mode.
+  # If so, the updated path is stored in $new_path.
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
+    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
+    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
+      # Going to short mode and back again did indeed matter. Since short mode is
+      # case insensitive, let's make it lowercase to improve readability.
+      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+      # Now convert it back to Unix-style (cygpath)
+      input_path=`$CYGPATH -u "$shortmode_path"`
+      new_path="$input_path"
+    fi
+  fi
+
+  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
+  if test "x$test_cygdrive_prefix" = x; then
+    # As a simple fix, exclude /usr/bin since it's not a real path.
+    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
+      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
+      # a path prefixed by /cygdrive for fixpath to work.
+      new_path="$CYGWIN_ROOT_PATH$input_path"
+    fi
+  fi
+
+
+  if test "x$path" != "x$new_path"; then
+    OUTPUT_ROOT="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OUTPUT_ROOT to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting OUTPUT_ROOT to \"$new_path\"" >&6;}
+  fi
+
+    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+
+  path="$OUTPUT_ROOT"
+  has_colon=`$ECHO $path | $GREP ^.:`
+  new_path="$path"
+  if test "x$has_colon" = x; then
+    # Not in mixed or Windows style, start by that.
+    new_path=`cmd //c echo $path`
+  fi
+
+
+  input_path="$new_path"
+  # Check if we need to convert this using DOS-style short mode. If the path
+  # contains just simple characters, use it. Otherwise (spaces, weird characters),
+  # take no chances and rewrite it.
+  # Note: m4 eats our [], so we need to use [ and ] instead.
+  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
+  if test "x$has_forbidden_chars" != x; then
+    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
+    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
+  fi
+
+
+  windows_path="$new_path"
+  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
+    unix_path=`$CYGPATH -u "$windows_path"`
+    new_path="$unix_path"
+  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
+    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
+    new_path="$unix_path"
+  fi
+
+  if test "x$path" != "x$new_path"; then
+    OUTPUT_ROOT="$new_path"
+    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting OUTPUT_ROOT to \"$new_path\"" >&5
+$as_echo "$as_me: Rewriting OUTPUT_ROOT to \"$new_path\"" >&6;}
+  fi
+
+  # Save the first 10 bytes of this path to the storage, so fixpath can work.
+  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
+
+    else
+      # We're on a unix platform. Hooray! :)
+      path="$OUTPUT_ROOT"
+      has_space=`$ECHO "$path" | $GREP " "`
+      if test "x$has_space" != x; then
+        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of OUTPUT_ROOT, which resolves as \"$path\", is invalid." >&5
+$as_echo "$as_me: The path of OUTPUT_ROOT, which resolves as \"$path\", is invalid." >&6;}
+        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
+      fi
+
+      # Use eval to expand a potential ~
+      eval path="$path"
+      if test ! -f "$path" && test ! -d "$path"; then
+        as_fn_error $? "The path of OUTPUT_ROOT, which resolves as \"$path\", is not found." "$LINENO" 5
+      fi
+
+      if test -d "$path"; then
+        OUTPUT_ROOT="`cd "$path"; $THEPWDCMD -L`"
+      else
+        dir="`$DIRNAME "$path"`"
+        base="`$BASENAME "$path"`"
+        OUTPUT_ROOT="`cd "$dir"; $THEPWDCMD -L`/$base"
+      fi
+    fi
+  fi
+
+
+  CONFIGURESUPPORT_OUTPUTDIR="$OUTPUT_ROOT/configure-support"
   $MKDIR -p "$CONFIGURESUPPORT_OUTPUTDIR"
 
-  SPEC="$OUTPUTDIR/spec.gmk"
+  SPEC="$OUTPUT_ROOT/spec.gmk"
 
 
 
 
 
   # The spec.gmk file contains all variables for the make system.
-  ac_config_files="$ac_config_files $OUTPUTDIR/spec.gmk:$AUTOCONF_DIR/spec.gmk.in"
+  ac_config_files="$ac_config_files $OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in"
 
   # The bootcycle-spec.gmk file contains support for boot cycle builds.
-  ac_config_files="$ac_config_files $OUTPUTDIR/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in"
+  ac_config_files="$ac_config_files $OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in"
 
   # The buildjdk-spec.gmk file contains support for building a buildjdk when cross compiling.
-  ac_config_files="$ac_config_files $OUTPUTDIR/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in"
+  ac_config_files="$ac_config_files $OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in"
 
   # The compare.sh is used to compare the build output to other builds.
-  ac_config_files="$ac_config_files $OUTPUTDIR/compare.sh:$AUTOCONF_DIR/compare.sh.in"
+  ac_config_files="$ac_config_files $OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in"
 
   # The generated Makefile knows where the spec.gmk is and where the source is.
-  # You can run make from the OUTPUTDIR, or from the top-level Makefile
+  # You can run make from the OUTPUT_ROOT, or from the top-level Makefile
   # which will look for generated configurations
-  ac_config_files="$ac_config_files $OUTPUTDIR/Makefile:$AUTOCONF_DIR/Makefile.in"
+  ac_config_files="$ac_config_files $OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in"
 
 
 
@@ -25080,20 +25083,8 @@
   withval=$with_cacerts_file;
 fi
 
-  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cacerts file" >&5
-$as_echo_n "checking for cacerts file... " >&6; }
-  if test "x$with_cacerts_file" == x; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: default" >&5
-$as_echo "default" >&6; }
-  else
+  if test "x$with_cacerts_file" != x; then
     CACERTS_FILE=$with_cacerts_file
-    if test ! -f "$CACERTS_FILE"; then
-      { $as_echo "$as_me:${as_lineno-$LINENO}: result: fail" >&5
-$as_echo "fail" >&6; }
-      as_fn_error $? "Specified cacerts file \"$CACERTS_FILE\" does not exist" "$LINENO" 5
-    fi
-    { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CACERTS_FILE" >&5
-$as_echo "$CACERTS_FILE" >&6; }
   fi
 
 
@@ -25663,12 +25654,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -25865,12 +25856,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -26055,12 +26046,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -26244,12 +26235,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -26433,12 +26424,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -26613,12 +26604,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -26944,12 +26935,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -27275,12 +27266,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -27493,12 +27484,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -27676,12 +27667,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -27887,12 +27878,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -28070,12 +28061,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -28281,12 +28272,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -28464,12 +28455,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -28675,12 +28666,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -28858,12 +28849,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -29056,12 +29047,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -29237,12 +29228,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -29436,12 +29427,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -29617,12 +29608,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -29815,12 +29806,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -29996,12 +29987,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -30195,12 +30186,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -30376,12 +30367,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -30556,12 +30547,12 @@
           BOOT_JDK_VERSION=`"$BOOT_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
           # Extra M4 quote needed to protect [] in grep expression.
-          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"|\"9([\.+-].*)?\"|(1\.[89]\.)'`
+          FOUND_CORRECT_VERSION=`$ECHO $BOOT_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"|(1\.[89]\.)'`
           if test "x$FOUND_CORRECT_VERSION" = x; then
             { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Boot JDK found at $BOOT_JDK is incorrect JDK version ($BOOT_JDK_VERSION); ignoring" >&6;}
-            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8, 9 or 10)" >&5
-$as_echo "$as_me: (Your Boot JDK must be version 8, 9 or 10)" >&6;}
+            { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Boot JDK must be version 8 or 9)" >&5
+$as_echo "$as_me: (Your Boot JDK must be version 8 or 9)" >&6;}
             BOOT_JDK_FOUND=no
           else
             # We're done! :-)
@@ -31531,12 +31522,12 @@
         BUILD_JDK_VERSION=`"$BUILD_JDK/bin/java" -version 2>&1 | $HEAD -n 1`
 
         # Extra M4 quote needed to protect [] in grep expression.
-        FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | $EGREP '\"10([\.+-].*)?\"'`
+        FOUND_CORRECT_VERSION=`echo $BUILD_JDK_VERSION | $EGREP '\"9([\.+-].*)?\"'`
         if test "x$FOUND_CORRECT_VERSION" = x; then
           { $as_echo "$as_me:${as_lineno-$LINENO}: Potential Build JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring" >&5
 $as_echo "$as_me: Potential Build JDK found at $BUILD_JDK is incorrect JDK version ($BUILD_JDK_VERSION); ignoring" >&6;}
-          { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Build JDK must be version 10)" >&5
-$as_echo "$as_me: (Your Build JDK must be version 10)" >&6;}
+          { $as_echo "$as_me:${as_lineno-$LINENO}: (Your Build JDK must be version 9)" >&5
+$as_echo "$as_me: (Your Build JDK must be version 9)" >&6;}
           BUILD_JDK_FOUND=no
         else
           # We're done!
@@ -31732,9 +31723,9 @@
 ###############################################################################
 
 
-  OUTPUTDIR="$OUTPUTDIR"
-
-  JDK_OUTPUTDIR="$OUTPUTDIR/jdk"
+  BUILD_OUTPUT="$OUTPUT_ROOT"
+
+  JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
 
   # Where are the sources.
 
@@ -48759,138 +48750,6 @@
   elif test "x$with_jtreg" != xyes && test "x$with_jtreg" != x; then
     # An explicit path is specified, use it.
     JT_HOME="$with_jtreg"
-
-  # Only process if variable expands to non-empty
-
-  if test "x$JT_HOME" != x; then
-    if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-
-  # Input might be given as Windows format, start by converting to
-  # unix format.
-  path="$JT_HOME"
-  new_path=`$CYGPATH -u "$path"`
-
-  # Cygwin tries to hide some aspects of the Windows file system, such that binaries are
-  # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered
-  # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then
-  # "foo.exe" is OK but "foo" is an error.
-  #
-  # This test is therefore slightly more accurate than "test -f" to check for file precense.
-  # It is also a way to make sure we got the proper file name for the real test later on.
-  test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null`
-  if test "x$test_shortpath" = x; then
-    { $as_echo "$as_me:${as_lineno-$LINENO}: The path of JT_HOME, which resolves as \"$path\", is invalid." >&5
-$as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." >&6;}
-    as_fn_error $? "Cannot locate the the path of JT_HOME" "$LINENO" 5
-  fi
-
-  # Call helper function which possibly converts this using DOS-style short mode.
-  # If so, the updated path is stored in $new_path.
-
-  input_path="$new_path"
-  # Check if we need to convert this using DOS-style short mode. If the path
-  # contains just simple characters, use it. Otherwise (spaces, weird characters),
-  # take no chances and rewrite it.
-  # Note: m4 eats our [], so we need to use [ and ] instead.
-  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]`
-  if test "x$has_forbidden_chars" != x; then
-    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
-    shortmode_path=`$CYGPATH -s -m -a "$input_path"`
-    path_after_shortmode=`$CYGPATH -u "$shortmode_path"`
-    if test "x$path_after_shortmode" != "x$input_to_shortpath"; then
-      # Going to short mode and back again did indeed matter. Since short mode is
-      # case insensitive, let's make it lowercase to improve readability.
-      shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-      # Now convert it back to Unix-style (cygpath)
-      input_path=`$CYGPATH -u "$shortmode_path"`
-      new_path="$input_path"
-    fi
-  fi
-
-  test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/`
-  if test "x$test_cygdrive_prefix" = x; then
-    # As a simple fix, exclude /usr/bin since it's not a real path.
-    if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then
-      # The path is in a Cygwin special directory (e.g. /home). We need this converted to
-      # a path prefixed by /cygdrive for fixpath to work.
-      new_path="$CYGWIN_ROOT_PATH$input_path"
-    fi
-  fi
-
-
-  if test "x$path" != "x$new_path"; then
-    JT_HOME="$new_path"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting JT_HOME to \"$new_path\"" >&5
-$as_echo "$as_me: Rewriting JT_HOME to \"$new_path\"" >&6;}
-  fi
-
-    elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-
-  path="$JT_HOME"
-  has_colon=`$ECHO $path | $GREP ^.:`
-  new_path="$path"
-  if test "x$has_colon" = x; then
-    # Not in mixed or Windows style, start by that.
-    new_path=`cmd //c echo $path`
-  fi
-
-
-  input_path="$new_path"
-  # Check if we need to convert this using DOS-style short mode. If the path
-  # contains just simple characters, use it. Otherwise (spaces, weird characters),
-  # take no chances and rewrite it.
-  # Note: m4 eats our [], so we need to use [ and ] instead.
-  has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]`
-  if test "x$has_forbidden_chars" != x; then
-    # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \)
-    new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
-  fi
-
-
-  windows_path="$new_path"
-  if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    unix_path=`$CYGPATH -u "$windows_path"`
-    new_path="$unix_path"
-  elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then
-    unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'`
-    new_path="$unix_path"
-  fi
-
-  if test "x$path" != "x$new_path"; then
-    JT_HOME="$new_path"
-    { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting JT_HOME to \"$new_path\"" >&5
-$as_echo "$as_me: Rewriting JT_HOME to \"$new_path\"" >&6;}
-  fi
-
-  # Save the first 10 bytes of this path to the storage, so fixpath can work.
-  all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}")
-
-    else
-      # We're on a unix platform. Hooray! :)
-      path="$JT_HOME"
-      has_space=`$ECHO "$path" | $GREP " "`
-      if test "x$has_space" != x; then
-        { $as_echo "$as_me:${as_lineno-$LINENO}: The path of JT_HOME, which resolves as \"$path\", is invalid." >&5
-$as_echo "$as_me: The path of JT_HOME, which resolves as \"$path\", is invalid." >&6;}
-        as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5
-      fi
-
-      # Use eval to expand a potential ~
-      eval path="$path"
-      if test ! -f "$path" && test ! -d "$path"; then
-        as_fn_error $? "The path of JT_HOME, which resolves as \"$path\", is not found." "$LINENO" 5
-      fi
-
-      if test -d "$path"; then
-        JT_HOME="`cd "$path"; $THEPWDCMD -L`"
-      else
-        dir="`$DIRNAME "$path"`"
-        base="`$BASENAME "$path"`"
-        JT_HOME="`cd "$dir"; $THEPWDCMD -L`/$base"
-      fi
-    fi
-  fi
-
     if test ! -d "$JT_HOME"; then
       as_fn_error $? "jtreg home directory from --with-jtreg=$with_jtreg does not exist" "$LINENO" 5
     fi
@@ -52026,7 +51885,7 @@
   LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}"
   if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     JAVA_BASE_LDFLAGS="${JAVA_BASE_LDFLAGS} \
-        -libpath:${OUTPUTDIR}/support/modules_libs/java.base"
+        -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
     JDKLIB_LIBS=""
   else
     JAVA_BASE_LDFLAGS="${JAVA_BASE_LDFLAGS} \
@@ -52905,7 +52764,7 @@
   OPENJDK_BUILD_LDFLAGS_JDKLIB="${OPENJDK_BUILD_LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS}"
   if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     OPENJDK_BUILD_JAVA_BASE_LDFLAGS="${OPENJDK_BUILD_JAVA_BASE_LDFLAGS} \
-        -libpath:${OUTPUTDIR}/support/modules_libs/java.base"
+        -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
     OPENJDK_BUILD_JDKLIB_LIBS=""
   else
     OPENJDK_BUILD_JAVA_BASE_LDFLAGS="${OPENJDK_BUILD_JAVA_BASE_LDFLAGS} \
@@ -54287,7 +54146,7 @@
   if test "x$OPENJDK_BUILD_OS" = xwindows; then
     { $as_echo "$as_me:${as_lineno-$LINENO}: checking if fixpath can be created" >&5
 $as_echo_n "checking if fixpath can be created... " >&6; }
-    FIXPATH_SRC="$TOPDIR/make/src/native/fixpath.c"
+    FIXPATH_SRC="$SRC_ROOT/make/src/native/fixpath.c"
     FIXPATH_BIN="$CONFIGURESUPPORT_OUTPUTDIR/bin/fixpath.exe"
     FIXPATH_DIR="$CONFIGURESUPPORT_OUTPUTDIR/fixpath"
     if test "x$OPENJDK_BUILD_OS_ENV" = xwindows.cygwin; then
@@ -67657,7 +67516,7 @@
 # Check for some common pitfalls
 
   if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
-    file_to_test="$TOPDIR/LICENSE"
+    file_to_test="$SRC_ROOT/LICENSE"
     if test `$STAT -c '%a' "$file_to_test"` -lt 400; then
       as_fn_error $? "Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin." "$LINENO" 5
     fi
@@ -67693,7 +67552,7 @@
       OUTPUT_DIR_IS_LOCAL="yes"
     fi
   else
-    if $DF -l $OUTPUTDIR > /dev/null 2>&1; then
+    if $DF -l $OUTPUT_ROOT > /dev/null 2>&1; then
       OUTPUT_DIR_IS_LOCAL="yes"
     else
       OUTPUT_DIR_IS_LOCAL="no"
@@ -67710,7 +67569,7 @@
 
   # Before generating output files, test if they exist. If they do, this is a reconfigure.
   # Since we can't properly handle the dependencies for this, warn the user about the situation
-  if test -e $OUTPUTDIR/spec.gmk; then
+  if test -e $OUTPUT_ROOT/spec.gmk; then
     IS_RECONFIGURE=yes
   else
     IS_RECONFIGURE=no
@@ -68460,11 +68319,11 @@
 for ac_config_target in $ac_config_targets
 do
   case $ac_config_target in
-    "$OUTPUTDIR/spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUTDIR/spec.gmk:$AUTOCONF_DIR/spec.gmk.in" ;;
-    "$OUTPUTDIR/bootcycle-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUTDIR/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in" ;;
-    "$OUTPUTDIR/buildjdk-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUTDIR/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in" ;;
-    "$OUTPUTDIR/compare.sh") CONFIG_FILES="$CONFIG_FILES $OUTPUTDIR/compare.sh:$AUTOCONF_DIR/compare.sh.in" ;;
-    "$OUTPUTDIR/Makefile") CONFIG_FILES="$CONFIG_FILES $OUTPUTDIR/Makefile:$AUTOCONF_DIR/Makefile.in" ;;
+    "$OUTPUT_ROOT/spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in" ;;
+    "$OUTPUT_ROOT/bootcycle-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in" ;;
+    "$OUTPUT_ROOT/buildjdk-spec.gmk") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/buildjdk-spec.gmk:$AUTOCONF_DIR/buildjdk-spec.gmk.in" ;;
+    "$OUTPUT_ROOT/compare.sh") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in" ;;
+    "$OUTPUT_ROOT/Makefile") CONFIG_FILES="$CONFIG_FILES $OUTPUT_ROOT/Makefile:$AUTOCONF_DIR/Makefile.in" ;;
 
   *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
   esac
@@ -68924,20 +68783,20 @@
   fi
 
   # Rotate our log file (configure.log)
-  if test -e "$OUTPUTDIR/configure.log.old"; then
-    $RM -f "$OUTPUTDIR/configure.log.old"
-  fi
-  if test -e "$OUTPUTDIR/configure.log"; then
-    $MV -f "$OUTPUTDIR/configure.log" "$OUTPUTDIR/configure.log.old" 2> /dev/null
+  if test -e "$OUTPUT_ROOT/configure.log.old"; then
+    $RM -f "$OUTPUT_ROOT/configure.log.old"
+  fi
+  if test -e "$OUTPUT_ROOT/configure.log"; then
+    $MV -f "$OUTPUT_ROOT/configure.log" "$OUTPUT_ROOT/configure.log.old" 2> /dev/null
   fi
 
   # Move configure.log from current directory to the build output root
   if test -e ./configure.log; then
-    $MV -f ./configure.log "$OUTPUTDIR/configure.log" 2> /dev/null
+    $MV -f ./configure.log "$OUTPUT_ROOT/configure.log" 2> /dev/null
   fi
 
   # Make the compare script executable
-  $CHMOD +x $OUTPUTDIR/compare.sh
+  $CHMOD +x $OUTPUT_ROOT/compare.sh
 
 
 # Finally output some useful information to the user
@@ -68948,15 +68807,15 @@
   printf "====================================================\n"
   if test "x$no_create" != "xyes"; then
     if test "x$IS_RECONFIGURE" != "xyes"; then
-      printf "A new configuration has been successfully created in\n%s\n" "$OUTPUTDIR"
-    else
-      printf "The existing configuration has been successfully updated in\n%s\n" "$OUTPUTDIR"
+      printf "A new configuration has been successfully created in\n%s\n" "$OUTPUT_ROOT"
+    else
+      printf "The existing configuration has been successfully updated in\n%s\n" "$OUTPUT_ROOT"
     fi
   else
     if test "x$IS_RECONFIGURE" != "xyes"; then
       printf "A configuration has been successfully checked but not created\n"
     else
-      printf "The existing configuration has been successfully checked in\n%s\n" "$OUTPUTDIR"
+      printf "The existing configuration has been successfully checked in\n%s\n" "$OUTPUT_ROOT"
     fi
   fi
   if test "x$CONFIGURE_COMMAND_LINE" != x; then
--- a/make/autoconf/help.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/help.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -206,15 +206,15 @@
   printf "====================================================\n"
   if test "x$no_create" != "xyes"; then
     if test "x$IS_RECONFIGURE" != "xyes"; then
-      printf "A new configuration has been successfully created in\n%s\n" "$OUTPUTDIR"
+      printf "A new configuration has been successfully created in\n%s\n" "$OUTPUT_ROOT"
     else
-      printf "The existing configuration has been successfully updated in\n%s\n" "$OUTPUTDIR"
+      printf "The existing configuration has been successfully updated in\n%s\n" "$OUTPUT_ROOT"
     fi
   else
     if test "x$IS_RECONFIGURE" != "xyes"; then
       printf "A configuration has been successfully checked but not created\n"
     else
-      printf "The existing configuration has been successfully checked in\n%s\n" "$OUTPUTDIR"
+      printf "The existing configuration has been successfully checked in\n%s\n" "$OUTPUT_ROOT"
     fi
   fi
   if test "x$CONFIGURE_COMMAND_LINE" != x; then
--- a/make/autoconf/jdk-options.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/jdk-options.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -206,16 +206,8 @@
   # Choose cacerts source file
   AC_ARG_WITH(cacerts-file, [AS_HELP_STRING([--with-cacerts-file],
       [specify alternative cacerts file])])
-  AC_MSG_CHECKING([for cacerts file])
-  if test "x$with_cacerts_file" == x; then
-    AC_MSG_RESULT([default])
-  else
+  if test "x$with_cacerts_file" != x; then
     CACERTS_FILE=$with_cacerts_file
-    if test ! -f "$CACERTS_FILE"; then
-      AC_MSG_RESULT([fail])
-      AC_MSG_ERROR([Specified cacerts file "$CACERTS_FILE" does not exist])
-    fi
-    AC_MSG_RESULT([$CACERTS_FILE])
   fi
   AC_SUBST(CACERTS_FILE)
 
--- a/make/autoconf/source-dirs.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/source-dirs.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -25,9 +25,9 @@
 
 AC_DEFUN_ONCE([SRCDIRS_SETUP_DIRS],
 [
-  OUTPUTDIR="$OUTPUTDIR"
-  AC_SUBST(OUTPUTDIR)
-  JDK_OUTPUTDIR="$OUTPUTDIR/jdk"
+  BUILD_OUTPUT="$OUTPUT_ROOT"
+  AC_SUBST(BUILD_OUTPUT)
+  JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
 
   # Where are the sources.
   AC_SUBST(TOPDIR)
--- a/make/autoconf/spec.gmk.in	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/spec.gmk.in	Mon Sep 25 15:37:25 2017 +0100
@@ -125,12 +125,14 @@
 SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
 SYSROOT_LDFLAGS := @SYSROOT_LDFLAGS@
 
-# The top-level directory of the source repository
+# The top-level directory of the forest (SRC_ROOT is a traditional alias)
 TOPDIR:=@TOPDIR@
 # These two versions of TOPDIR are used in string comparisons
 ORIGINAL_TOPDIR:=@ORIGINAL_TOPDIR@
 CANONICAL_TOPDIR:=@CANONICAL_TOPDIR@
+SRC_ROOT:=@TOPDIR@
 
+OUTPUT_ROOT:=@OUTPUT_ROOT@
 
 IMPORT_MODULES_CLASSES:=@IMPORT_MODULES_CLASSES@
 IMPORT_MODULES_CMDS:=@IMPORT_MODULES_CMDS@
@@ -242,22 +244,29 @@
 
 # JDK_OUTPUTDIR specifies where a working jvm is built.
 # You can run $(JDK_OUTPUTDIR)/bin/java
+# Though the layout of the contents of $(JDK_OUTPUTDIR) is not
+# yet the same as a default installation.
+#
+# When you run "make install" it will create the standardized
+# layout for the jdk and the jre inside the IMAGES_OUTPUTDIR subdir.
+# Then it will copy the contents of the jdk into the installation
+# directory.
 
-OUTPUTDIR := @OUTPUTDIR@
+BUILD_OUTPUT:=@BUILD_OUTPUT@
 # Colon left out to be able to override IMAGES_OUTPUTDIR for bootcycle-images
-SUPPORT_OUTPUTDIR=$(OUTPUTDIR)/support
-BUILDTOOLS_OUTPUTDIR=$(OUTPUTDIR)/buildtools
+SUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/support
+BUILDTOOLS_OUTPUTDIR=$(BUILD_OUTPUT)/buildtools
 
-HOTSPOT_OUTPUTDIR=$(OUTPUTDIR)/hotspot
-JDK_OUTPUTDIR=$(OUTPUTDIR)/jdk
-IMAGES_OUTPUTDIR=$(OUTPUTDIR)/images
-BUNDLES_OUTPUTDIR=$(OUTPUTDIR)/bundles
-TESTMAKE_OUTPUTDIR=$(OUTPUTDIR)/test-make
-MAKESUPPORT_OUTPUTDIR=$(OUTPUTDIR)/make-support
+HOTSPOT_OUTPUTDIR=$(BUILD_OUTPUT)/hotspot
+JDK_OUTPUTDIR=$(BUILD_OUTPUT)/jdk
+IMAGES_OUTPUTDIR=$(BUILD_OUTPUT)/images
+BUNDLES_OUTPUTDIR=$(BUILD_OUTPUT)/bundles
+TESTMAKE_OUTPUTDIR=$(BUILD_OUTPUT)/test-make
+MAKESUPPORT_OUTPUTDIR=$(BUILD_OUTPUT)/make-support
 
 # This does not get overridden in a bootcycle build
 CONFIGURESUPPORT_OUTPUTDIR:=@CONFIGURESUPPORT_OUTPUTDIR@
-BUILDJDK_OUTPUTDIR=$(OUTPUTDIR)/buildjdk
+BUILDJDK_OUTPUTDIR=$(BUILD_OUTPUT)/buildjdk
 
 BUILD_FAILURE_HANDLER := @BUILD_FAILURE_HANDLER@
 
--- a/make/autoconf/toolchain.m4	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/autoconf/toolchain.m4	Mon Sep 25 15:37:25 2017 +0100
@@ -935,7 +935,6 @@
   elif test "x$with_jtreg" != xyes && test "x$with_jtreg" != x; then
     # An explicit path is specified, use it.
     JT_HOME="$with_jtreg"
-    BASIC_FIXUP_PATH([JT_HOME])
     if test ! -d "$JT_HOME"; then
       AC_MSG_ERROR([jtreg home directory from --with-jtreg=$with_jtreg does not exist])
     fi
--- a/make/common/JarArchive.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/common/JarArchive.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -211,7 +211,7 @@
   $1_SUPDATE_CONTENTS=$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @$$($1_BIN)/_the.$$($1_JARNAME)_contents $$(NEWLINE)
 
   # Use a slightly shorter name for logging, but with enough path to identify this jar.
-  $1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_JAR))
+  $1_NAME:=$$(subst $$(OUTPUT_ROOT)/,,$$($1_JAR))
 
   ifneq (,$$($1_CHECK_COMPRESS_JAR))
     $1_JAR_CREATE_OPTIONS := c0fm
--- a/make/common/MakeBase.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/common/MakeBase.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -82,7 +82,7 @@
 ### Functions for timers
 
 # Store the build times in this directory.
-BUILDTIMESDIR=$(OUTPUTDIR)/make-support/build-times
+BUILDTIMESDIR=$(OUTPUT_ROOT)/make-support/build-times
 
 # Record starting time for build of a sub repository.
 define RecordStartTime
@@ -155,7 +155,7 @@
       $(strip $(shell $(CAT) $(TOPDIR)/make/common/support/ListPathsSafely-pre-compress.incl)))
   compress_paths += \
       $(subst $(TOPDIR),X97, \
-      $(subst $(OUTPUTDIR),X98, \
+      $(subst $(OUTPUT_ROOT),X98, \
       $(subst X,X00, \
       $(subst $(SPACE),\n,$(strip $1)))))
   $(eval compress_paths += \
@@ -163,7 +163,7 @@
 
   decompress_paths=$(SED) -f $(TOPDIR)/make/common/support/ListPathsSafely-uncompress.sed \
       -e 's|X99|\\n|g' \
-      -e 's|X98|$(OUTPUTDIR)|g' -e 's|X97|$(TOPDIR)|g' \
+      -e 's|X98|$(OUTPUT_ROOT)|g' -e 's|X97|$(TOPDIR)|g' \
       -e 's|X00|X|g'
 
   ListPathsSafely_IfPrintf = \
@@ -359,11 +359,11 @@
     ifeq ($$(IS_GNU_TIME), yes)
       SHELL :=  $$(BASH) $$(TOPDIR)/make/scripts/shell-profiler.sh \
                 gnutime $$(TIME) \
-                $$(OUTPUTDIR)/build-profile.log $$(SHELL)
+                $$(OUTPUT_ROOT)/build-profile.log $$(SHELL)
     else ifneq ($$(FLOCK), )
       SHELL :=  $$(BASH) $$(TOPDIR)/make/scripts/shell-profiler.sh \
                 flock $$(FLOCK) \
-                $$(OUTPUTDIR)/build-profile.log $$(SHELL)
+                $$(OUTPUT_ROOT)/build-profile.log $$(SHELL)
     endif
   endif
 
@@ -707,7 +707,7 @@
   # 4 : Macro to call for copy operation
   # 5 : Action text to log
   $2: $1
-	$$(call LogInfo, $(strip $5) $$(patsubst $(OUTPUTDIR)/%,%,$$@))
+	$$(call LogInfo, $(strip $5) $$(patsubst $(OUTPUT_ROOT)/%,%,$$@))
 	$$($$(strip $4))
 
   $3 += $2
@@ -937,8 +937,8 @@
   $(call WriteFile, $2, $(strip $1).cmdline) \
   ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \
       ( exitcode=$(DOLLAR)? && \
-      $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).log && \
-      $(CP) $(strip $1).cmdline $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(OUTPUTDIR)/%,%,$(strip $1))).cmdline && \
+      $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(BUILD_OUTPUT)/%,%,$(strip $1))).log && \
+      $(CP) $(strip $1).cmdline $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(BUILD_OUTPUT)/%,%,$(strip $1))).cmdline && \
       exit $(DOLLAR)exitcode ) )
 
 ################################################################################
--- a/make/common/NativeCompilation.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/common/NativeCompilation.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -751,10 +751,10 @@
   # This is a rough heuristic and may not always print accurate information.
   $$($1_BUILD_INFO): $$($1_SRCS) $$($1_COMPILE_VARDEPS_FILE)
         ifeq ($$(wildcard $$($1_TARGET)),)
-	  $(ECHO) 'Creating $$(subst $$(OUTPUTDIR)/,,$$($1_TARGET)) from $$(words \
+	  $(ECHO) 'Creating $$(subst $$(BUILD_OUTPUT)/,,$$($1_TARGET)) from $$(words \
 	      $$(filter-out %.vardeps, $$?)) file(s)'
         else
-	  $(ECHO) $$(strip 'Updating $$(subst $$(OUTPUTDIR)/,,$$($1_TARGET))' \
+	  $(ECHO) $$(strip 'Updating $$(subst $$(BUILD_OUTPUT)/,,$$($1_TARGET))' \
 	      $$(if $$(filter-out %.vardeps, $$?), \
 	        'due to $$(words $$(filter-out %.vardeps, $$?)) file(s)', \
 	      $$(if $$(filter %.vardeps, $$?), 'due to makefile changes')))
@@ -946,9 +946,9 @@
       ifeq ($$(TOOLCHAIN_TYPE), clang)
         # There is no strlen function in make, but checking path depth is a
         # reasonable approximation.
-        ifneq ($$(word 10, $$(subst /, ,$$(OUTPUTDIR))), )
+        ifneq ($$(word 10, $$(subst /, ,$$(OUTPUT_ROOT))), )
           $1_LINK_OBJS_RELATIVE := true
-          $1_ALL_OBJS_RELATIVE := $$(patsubst $$(OUTPUTDIR)/%, %, $$($1_ALL_OBJS))
+          $1_ALL_OBJS_RELATIVE := $$(patsubst $$(OUTPUT_ROOT)/%, %, $$($1_ALL_OBJS))
         endif
       endif
     endif
@@ -976,7 +976,7 @@
 		  $$($1_STRIP_CMD)
                 else
 		  $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_link, \
-		      $$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \
+		      $$(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUT_ROOT) ; ) \
 		      $$($1_LD) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) $$($1_SYSROOT_LDFLAGS) \
 		      $(LD_OUT_OPTION)$$@ $$($1_LD_OBJ_ARG) $$($1_RES) $$($1_LIBS) \
 		      $$($1_EXTRA_LIBS)) ; \
--- a/make/common/ZipArchive.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/common/ZipArchive.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -95,7 +95,7 @@
   endif
 
   # Use a slightly shorter name for logging, but with enough path to identify this zip.
-  $1_NAME:=$$(subst $$(OUTPUTDIR)/,,$$($1_ZIP))
+  $1_NAME:=$$(subst $$(OUTPUT_ROOT)/,,$$($1_ZIP))
 
   # Now $1_ALL_SRCS should contain all sources that are going to be put into the zip.
   # I.e. the zip -i and -x options should match the filtering done in the makefile.
--- a/make/copy/Copy-java.base.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/copy/Copy-java.base.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -208,7 +208,7 @@
 CACERTS_DST := $(LIB_DST_DIR)/security/cacerts
 
 $(CACERTS_DST): $(CACERTS_FILE)
-	$(call LogInfo, Copying $(patsubst $(OUTPUTDIR)/%, %, $@))
+	$(call LogInfo, Copying $(patsubst $(OUTPUT_ROOT)/%, %, $@))
 	$(call install-file)
 
 TARGETS += $(CACERTS_DST)
--- a/make/devkit/Makefile	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/devkit/Makefile	Mon Sep 25 15:37:25 2017 +0100
@@ -75,12 +75,12 @@
   $(foreach p,$(filter-out $(me),$(platforms)),$(eval $(p) : $$(me)))
 endif
 
-OUTPUTDIR = $(abspath ../../build/devkit)
-RESULT = $(OUTPUTDIR)/result
+OUTPUT_ROOT = $(abspath ../../build/devkit)
+RESULT = $(OUTPUT_ROOT)/result
 
 submakevars = HOST=$@ BUILD=$(me) \
     RESULT=$(RESULT) PREFIX=$(RESULT)/$@ \
-    OUTPUTDIR=$(OUTPUTDIR)
+    OUTPUT_ROOT=$(OUTPUT_ROOT)
 $(platforms) :
 	@echo 'Building compilers for $@'
 	@echo 'Targets: $(platforms)'
--- a/make/devkit/Tools.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/devkit/Tools.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -121,13 +121,13 @@
 endif
 
 # Define directories
-RESULT := $(OUTPUTDIR)/result
-BUILDDIR := $(OUTPUTDIR)/$(HOST)/$(TARGET)
+RESULT := $(OUTPUT_ROOT)/result
+BUILDDIR := $(OUTPUT_ROOT)/$(HOST)/$(TARGET)
 PREFIX := $(RESULT)/$(HOST)
 TARGETDIR := $(PREFIX)/$(TARGET)
 SYSROOT := $(TARGETDIR)/sysroot
-DOWNLOAD := $(OUTPUTDIR)/download
-SRCDIR := $(OUTPUTDIR)/src
+DOWNLOAD := $(OUTPUT_ROOT)/download
+SRCDIR := $(OUTPUT_ROOT)/src
 
 # Marker file for unpacking rpms
 rpms := $(SYSROOT)/rpms_unpacked
--- a/make/gensrc/Gensrc-jdk.charsets.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/gensrc/Gensrc-jdk.charsets.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -72,7 +72,7 @@
 
 $(CHARSET_GENSRC_JAVA_DIR_CS)/sjis0213.dat: $(CHARSET_DATA_DIR)/sjis0213.map \
     $(BUILD_TOOLS_JDK)
-	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@))
+	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
 	$(call MakeDir, $(@D))
 	$(TOOL_CHARSETMAPPING) '$<' '$@' sjis0213
 
--- a/make/gensrc/GensrcIcons.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/gensrc/GensrcIcons.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -117,7 +117,7 @@
 
 
   $(GENSRC_OSX_ICONS): $(GENSRC_OSX_ICONS_SRC) $(BUILD_TOOLS_JDK)
-	$(call LogInfo, Generating $(patsubst $(OUTPUTDIR)/%, %, $@))
+	$(call LogInfo, Generating $(patsubst $(OUTPUT_ROOT)/%, %, $@))
 	$(call MakeDir, $(@D))
 	$(RM) $@ $@.tmp
 	$(ECHO) "static unsigned char sAWTIconData[] = { " >> $@.tmp
--- a/make/hotspot/ide/CreateVSProject.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/hotspot/ide/CreateVSProject.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -99,7 +99,7 @@
   # Run the ProjectCreator tool
   PROJECT_CREATOR_TOOL := $(JAVA_SMALL) -cp $(TOOLS_OUTPUTDIR) build.tools.projectcreator.ProjectCreator
 
-  IDE_OUTPUTDIR := $(OUTPUTDIR)/ide/hotspot-visualstudio
+  IDE_OUTPUTDIR := $(BUILD_OUTPUT)/ide/hotspot-visualstudio
 
   VCPROJ_FILE := $(IDE_OUTPUTDIR)/jvm.vcxproj
 
--- a/make/langtools/intellij/langtools.iml	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/langtools/intellij/langtools.iml	Mon Sep 25 15:37:25 2017 +0100
@@ -22,7 +22,11 @@
       <sourceFolder url="file://$MODULE_DIR$/src/jdk.jshell" isTestSource="false" />
       <sourceFolder url="file://$MODULE_DIR$/src/jdk.javadoc" isTestSource="false" />
       <excludeFolder url="file://$MODULE_DIR$/build" />
+      <excludeFolder url="file://$MODULE_DIR$/make" />
+      <excludeFolder url="file://$MODULE_DIR$/src" />
+      <excludeFolder url="file://$MODULE_DIR$/test" />
     </content>
+    <content url="file://$MODULE_DIR$/test/langtools"/>
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="inheritedJdk" />
   </component>
--- a/make/scripts/compare.sh	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/scripts/compare.sh	Mon Sep 25 15:37:25 2017 +0100
@@ -29,7 +29,7 @@
 ################################################################################
 
 # Check that we are run via the wrapper generated by configure
-if [ -z "$TOPDIR" ]; then
+if [ -z "$SRC_ROOT" ]; then
     echo "Error: You must run this script using build/[conf]/compare.sh"
     exit 1
 fi
@@ -56,7 +56,7 @@
     STAT_PRINT_SIZE="-c %s"
 fi
 
-COMPARE_EXCEPTIONS_INCLUDE="$TOPDIR/make/scripts/compare_exceptions.sh.incl"
+COMPARE_EXCEPTIONS_INCLUDE="$SRC_ROOT/make/scripts/compare_exceptions.sh.incl"
 if [ ! -e "$COMPARE_EXCEPTIONS_INCLUDE" ]; then
     echo "Error: Cannot locate the exceptions file, it should have been here: $COMPARE_EXCEPTIONS_INCLUDE"
     exit 1
--- a/make/test/JtregNativeHotspot.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/test/JtregNativeHotspot.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -117,7 +117,7 @@
     BUILD_HOTSPOT_JTREG_EXECUTABLES_CFLAGS_exeFPRegs := -MT
 endif
 
-BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(OUTPUTDIR)/support/test/hotspot/jtreg/native
+BUILD_HOTSPOT_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/hotspot/jtreg/native
 
 BUILD_HOTSPOT_JTREG_IMAGE_DIR := $(TEST_IMAGE_DIR)/hotspot/jtreg
 
--- a/make/test/JtregNativeJdk.gmk	Mon Sep 25 16:29:23 2017 +0200
+++ b/make/test/JtregNativeJdk.gmk	Mon Sep 25 15:37:25 2017 +0100
@@ -47,7 +47,7 @@
     $(TOPDIR)/test/jdk/java/lang/String/nativeEncoding \
     #
 
-BUILD_JDK_JTREG_OUTPUT_DIR := $(OUTPUTDIR)/support/test/jdk/jtreg/native
+BUILD_JDK_JTREG_OUTPUT_DIR := $(BUILD_OUTPUT)/support/test/jdk/jtreg/native
 
 BUILD_JDK_JTREG_IMAGE_DIR := $(TEST_IMAGE_DIR)/jdk/jtreg
 
--- a/src/hotspot/cpu/x86/interp_masm_x86.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -515,6 +515,8 @@
   // Add in the index
   addptr(result, tmp);
   load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  // The resulting oop is null if the reference is not yet resolved.
+  // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
 }
 
 // load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -834,7 +834,8 @@
   andq(rsp, -16);     // align stack as required by push_CPU_state and call
   push_CPU_state();   // keeps alignment at 16 bytes
   lea(c_rarg0, ExternalAddress((address) msg));
-  call_VM_leaf(CAST_FROM_FN_PTR(address, warning), c_rarg0);
+  lea(rax, ExternalAddress(CAST_FROM_FN_PTR(address, warning)));
+  call(rax);
   pop_CPU_state();
   mov(rsp, rbp);
   pop(rbp);
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -419,7 +419,7 @@
 void TemplateTable::ldc(bool wide) {
   transition(vtos, vtos);
   Register rarg = NOT_LP64(rcx) LP64_ONLY(c_rarg1);
-  Label call_ldc, notFloat, notClass, Done;
+  Label call_ldc, notFloat, notClass, notInt, Done;
 
   if (wide) {
     __ get_unsigned_2_byte_index_at_bcp(rbx, 1);
@@ -465,19 +465,18 @@
   __ jmp(Done);
 
   __ bind(notFloat);
-#ifdef ASSERT
-  {
-    Label L;
-    __ cmpl(rdx, JVM_CONSTANT_Integer);
-    __ jcc(Assembler::equal, L);
-    // String and Object are rewritten to fast_aldc
-    __ stop("unexpected tag type in ldc");
-    __ bind(L);
-  }
-#endif
-  // itos JVM_CONSTANT_Integer only
+  __ cmpl(rdx, JVM_CONSTANT_Integer);
+  __ jccb(Assembler::notEqual, notInt);
+
+  // itos
   __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset));
   __ push(itos);
+  __ jmp(Done);
+
+  // assume the tag is for condy; if not, the VM runtime will tell us
+  __ bind(notInt);
+  condy_helper(Done);
+
   __ bind(Done);
 }
 
@@ -487,6 +486,7 @@
 
   Register result = rax;
   Register tmp = rdx;
+  Register rarg = NOT_LP64(rcx) LP64_ONLY(c_rarg1);
   int index_size = wide ? sizeof(u2) : sizeof(u1);
 
   Label resolved;
@@ -496,17 +496,28 @@
   assert_different_registers(result, tmp);
   __ get_cache_index_at_bcp(tmp, 1, index_size);
   __ load_resolved_reference_at_index(result, tmp);
-  __ testl(result, result);
+  __ testptr(result, result);
   __ jcc(Assembler::notZero, resolved);
 
   address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc);
 
   // first time invocation - must resolve first
-  __ movl(tmp, (int)bytecode());
-  __ call_VM(result, entry, tmp);
-
+  __ movl(rarg, (int)bytecode());
+  __ call_VM(result, entry, rarg);
   __ bind(resolved);
 
+  { // Check for the null sentinel.
+    // If we just called the VM, that already did the mapping for us,
+    // but it's harmless to retry.
+    Label notNull;
+    ExternalAddress null_sentinel((address)Universe::the_null_sentinel_addr());
+    __ movptr(tmp, null_sentinel);
+    __ cmpptr(tmp, result);
+    __ jccb(Assembler::notEqual, notNull);
+    __ xorptr(result, result);  // NULL object reference
+    __ bind(notNull);
+  }
+
   if (VerifyOops) {
     __ verify_oop(result);
   }
@@ -514,7 +525,7 @@
 
 void TemplateTable::ldc2_w() {
   transition(vtos, vtos);
-  Label Long, Done;
+  Label notDouble, notLong, Done;
   __ get_unsigned_2_byte_index_at_bcp(rbx, 1);
 
   __ get_cpool_and_tags(rcx, rax);
@@ -522,25 +533,143 @@
   const int tags_offset = Array<u1>::base_offset_in_bytes();
 
   // get type
-  __ cmpb(Address(rax, rbx, Address::times_1, tags_offset),
-          JVM_CONSTANT_Double);
-  __ jccb(Assembler::notEqual, Long);
+  __ movzbl(rdx, Address(rax, rbx, Address::times_1, tags_offset));
+  __ cmpl(rdx, JVM_CONSTANT_Double);
+  __ jccb(Assembler::notEqual, notDouble);
 
   // dtos
   __ load_double(Address(rcx, rbx, Address::times_ptr, base_offset));
   __ push(dtos);
 
-  __ jmpb(Done);
-  __ bind(Long);
+  __ jmp(Done);
+  __ bind(notDouble);
+  __ cmpl(rdx, JVM_CONSTANT_Long);
+  __ jccb(Assembler::notEqual, notLong);
 
   // ltos
   __ movptr(rax, Address(rcx, rbx, Address::times_ptr, base_offset + 0 * wordSize));
   NOT_LP64(__ movptr(rdx, Address(rcx, rbx, Address::times_ptr, base_offset + 1 * wordSize)));
   __ push(ltos);
+  __ jmp(Done);
+
+  __ bind(notLong);
+  condy_helper(Done);
 
   __ bind(Done);
 }
 
+void TemplateTable::condy_helper(Label& Done) {
+  const Register obj = rax;
+  const Register off = rbx;
+  const Register flags = rcx;
+  const Register rarg = NOT_LP64(rcx) LP64_ONLY(c_rarg1);
+  __ movl(rarg, (int)bytecode());
+  call_VM(obj, CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_ldc), rarg);
+#ifndef _LP64
+  // borrow rdi from locals
+  __ get_thread(rdi);
+  __ get_vm_result_2(flags, rdi);
+  __ restore_locals();
+#else
+  __ get_vm_result_2(flags, r15_thread);
+#endif
+  // VMr = obj = base address to find primitive value to push
+  // VMr2 = flags = (tos, off) using format of CPCE::_flags
+  __ movl(off, flags);
+  __ andl(off, ConstantPoolCacheEntry::field_index_mask);
+  const Address field(obj, off, Address::times_1, 0*wordSize);
+
+  // What sort of thing are we loading?
+  __ shrl(flags, ConstantPoolCacheEntry::tos_state_shift);
+  __ andl(flags, ConstantPoolCacheEntry::tos_state_mask);
+
+  switch (bytecode()) {
+  case Bytecodes::_ldc:
+  case Bytecodes::_ldc_w:
+    {
+      // tos in (itos, ftos, stos, btos, ctos, ztos)
+      Label notInt, notFloat, notShort, notByte, notChar, notBool;
+      __ cmpl(flags, itos);
+      __ jcc(Assembler::notEqual, notInt);
+      // itos
+      __ movl(rax, field);
+      __ push(itos);
+      __ jmp(Done);
+
+      __ bind(notInt);
+      __ cmpl(flags, ftos);
+      __ jcc(Assembler::notEqual, notFloat);
+      // ftos
+      __ load_float(field);
+      __ push(ftos);
+      __ jmp(Done);
+
+      __ bind(notFloat);
+      __ cmpl(flags, stos);
+      __ jcc(Assembler::notEqual, notShort);
+      // stos
+      __ load_signed_short(rax, field);
+      __ push(stos);
+      __ jmp(Done);
+
+      __ bind(notShort);
+      __ cmpl(flags, btos);
+      __ jcc(Assembler::notEqual, notByte);
+      // btos
+      __ load_signed_byte(rax, field);
+      __ push(btos);
+      __ jmp(Done);
+
+      __ bind(notByte);
+      __ cmpl(flags, ctos);
+      __ jcc(Assembler::notEqual, notChar);
+      // ctos
+      __ load_unsigned_short(rax, field);
+      __ push(ctos);
+      __ jmp(Done);
+
+      __ bind(notChar);
+      __ cmpl(flags, ztos);
+      __ jcc(Assembler::notEqual, notBool);
+      // ztos
+      __ load_signed_byte(rax, field);
+      __ push(ztos);
+      __ jmp(Done);
+
+      __ bind(notBool);
+      break;
+    }
+
+  case Bytecodes::_ldc2_w:
+    {
+      Label notLong, notDouble;
+      __ cmpl(flags, ltos);
+      __ jcc(Assembler::notEqual, notLong);
+      // ltos
+      __ movptr(rax, field);
+      NOT_LP64(__ movptr(rdx, field.plus_disp(4)));
+      __ push(ltos);
+      __ jmp(Done);
+
+      __ bind(notLong);
+      __ cmpl(flags, dtos);
+      __ jcc(Assembler::notEqual, notDouble);
+      // dtos
+      __ load_double(field);
+      __ push(dtos);
+      __ jmp(Done);
+
+      __ bind(notDouble);
+      break;
+    }
+
+  default:
+    ShouldNotReachHere();
+  }
+
+  __ stop("bad ldc/condy");
+}
+
 void TemplateTable::locals_index(Register reg, int offset) {
   __ load_unsigned_byte(reg, at_bcp(offset));
   __ negptr(reg);
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -874,6 +874,8 @@
 void GraphBuilder::load_constant() {
   ciConstant con = stream()->get_constant();
   if (con.basic_type() == T_ILLEGAL) {
+    // FIXME: an unresolved ConstantDynamic can get here,
+    // and that should not terminate the whole compilation.
     BAILOUT("could not resolve a constant");
   } else {
     ValueType* t = illegalType;
@@ -893,11 +895,19 @@
         ciObject* obj = con.as_object();
         if (!obj->is_loaded()
             || (PatchALot && obj->klass() != ciEnv::current()->String_klass())) {
+          // A Class, MethodType, MethodHandle, or String.
+          // Unloaded condy nodes show up as T_ILLEGAL, above.
           patch_state = copy_state_before();
           t = new ObjectConstant(obj);
         } else {
-          assert(obj->is_instance(), "must be java_mirror of klass");
-          t = new InstanceConstant(obj->as_instance());
+          // Might be a Class, MethodType, MethodHandle, or ConstantDynamic
+          // result, which might turn out to be an array.
+          if (obj->is_null_object())
+            t = objectNull;
+          else if (obj->is_array())
+            t = new ArrayConstant(obj->as_array());
+          else
+            t = new InstanceConstant(obj->as_instance());
         }
         break;
        }
--- a/src/hotspot/share/ci/ciEnv.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/ci/ciEnv.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -584,8 +584,34 @@
   int index = pool_index;
   if (cache_index >= 0) {
     assert(index < 0, "only one kind of index at a time");
+    index = cpool->object_to_cp_index(cache_index);
     oop obj = cpool->resolved_references()->obj_at(cache_index);
     if (obj != NULL) {
+      if (obj == Universe::the_null_sentinel()) {
+        return ciConstant(T_OBJECT, get_object(NULL));
+      }
+      BasicType bt = T_OBJECT;
+      if (cpool->tag_at(index).is_constant_dynamic())
+        bt = FieldType::basic_type(cpool->uncached_signature_ref_at(index));
+      if (is_reference_type(bt)) {
+      } else {
+        // we have to unbox the primitive value
+        if (!is_java_primitive(bt))  return ciConstant();
+        jvalue value;
+        BasicType bt2 = java_lang_boxing_object::get_value(obj, &value);
+        assert(bt2 == bt, "");
+        switch (bt2) {
+        case T_DOUBLE:  return ciConstant(value.d);
+        case T_FLOAT:   return ciConstant(value.f);
+        case T_LONG:    return ciConstant(value.j);
+        case T_INT:     return ciConstant(bt2, value.i);
+        case T_SHORT:   return ciConstant(bt2, value.s);
+        case T_BYTE:    return ciConstant(bt2, value.b);
+        case T_CHAR:    return ciConstant(bt2, value.c);
+        case T_BOOLEAN: return ciConstant(bt2, value.z);
+        default:  return ciConstant();
+        }
+      }
       ciObject* ciobj = get_object(obj);
       if (ciobj->is_array()) {
         return ciConstant(T_ARRAY, ciobj);
@@ -594,7 +620,6 @@
         return ciConstant(T_OBJECT, ciobj);
       }
     }
-    index = cpool->object_to_cp_index(cache_index);
   }
   constantTag tag = cpool->tag_at(index);
   if (tag.is_int()) {
@@ -650,6 +675,8 @@
     ciSymbol* signature = get_symbol(cpool->method_handle_signature_ref_at(index));
     ciObject* ciobj     = get_unloaded_method_handle_constant(callee, name, signature, ref_kind);
     return ciConstant(T_OBJECT, ciobj);
+  } else if (tag.is_constant_dynamic()) {
+    return ciConstant();
   } else {
     ShouldNotReachHere();
     return ciConstant();
--- a/src/hotspot/share/ci/ciReplay.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/ci/ciReplay.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -721,6 +721,7 @@
         case JVM_CONSTANT_Float:
         case JVM_CONSTANT_MethodHandle:
         case JVM_CONSTANT_MethodType:
+        case JVM_CONSTANT_ConstantDynamic:
         case JVM_CONSTANT_InvokeDynamic:
           if (tag != cp->tag_at(i).value()) {
             report_error("tag mismatch: wrong class files?");
--- a/src/hotspot/share/ci/ciStreams.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/ci/ciStreams.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -254,7 +254,8 @@
 // constant.
 constantTag ciBytecodeStream::get_constant_pool_tag(int index) const {
   VM_ENTRY_MARK;
-  return _method->get_Method()->constants()->tag_at(index);
+  BasicType bt = _method->get_Method()->constants()->basic_type_for_constant_at(index);
+  return constantTag::ofBasicType(bt);
 }
 
 // ------------------------------------------------------------------
--- a/src/hotspot/share/classfile/classFileParser.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -202,6 +202,22 @@
         }
         break;
       }
+      case JVM_CONSTANT_ConstantDynamic : {
+        // TODO major version check
+        if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
+          classfile_parse_error(
+              "Class file version does not support constant tag %u in class file %s",
+              tag, CHECK);
+        }
+        cfs->guarantee_more(5, CHECK);  // bsm_index, nt, tag/access_flags
+        const u2 bootstrap_specifier_index = cfs->get_u2_fast();
+        const u2 name_and_type_index = cfs->get_u2_fast();
+        if (_max_bootstrap_specifier_index < (int) bootstrap_specifier_index) {
+          _max_bootstrap_specifier_index = (int) bootstrap_specifier_index;  // collect for later
+        }
+        cp->constant_dynamic_at_put(index, bootstrap_specifier_index, name_and_type_index);
+        break;
+      }
       case JVM_CONSTANT_InvokeDynamic : {
         if (_major_version < Verifier::INVOKEDYNAMIC_MAJOR_VERSION) {
           classfile_parse_error(
@@ -534,6 +550,18 @@
           ref_index, CHECK);
         break;
       }
+      case JVM_CONSTANT_ConstantDynamic: {
+        const int name_and_type_ref_index =
+          cp->invoke_dynamic_name_and_type_ref_index_at(index);
+
+        check_property(valid_cp_range(name_and_type_ref_index, length) &&
+          cp->tag_at(name_and_type_ref_index).is_name_and_type(),
+          "Invalid constant pool index %u in class file %s",
+          name_and_type_ref_index, CHECK);
+        // bootstrap specifier index must be checked later,
+        // when BootstrapMethods attr is available
+        break;
+      }
       case JVM_CONSTANT_InvokeDynamic: {
         const int name_and_type_ref_index =
           cp->invoke_dynamic_name_and_type_ref_index_at(index);
@@ -626,6 +654,27 @@
         }
         break;
       }
+      case JVM_CONSTANT_ConstantDynamic: {
+        const int name_and_type_ref_index =
+          cp->name_and_type_ref_index_at(index);
+        // already verified to be utf8
+        const int name_ref_index =
+          cp->name_ref_index_at(name_and_type_ref_index);
+        // already verified to be utf8
+        const int signature_ref_index =
+          cp->signature_ref_index_at(name_and_type_ref_index);
+        const Symbol* const name = cp->symbol_at(name_ref_index);
+        const Symbol* const signature = cp->symbol_at(signature_ref_index);
+        if (_need_verify) {
+          // ConstantDynamic name and signature are verified above, when iterating NameAndType_info.
+          // Need only to be sure signature is non-zero length and the right type.
+          if (signature->utf8_length() == 0 ||
+              signature->byte_at(0) == JVM_SIGNATURE_FUNC) {
+            throwIllegalSignature("ConstantDynamic", name, signature, CHECK);
+          }
+        }
+        break;
+      }
       case JVM_CONSTANT_InvokeDynamic:
       case JVM_CONSTANT_Fieldref:
       case JVM_CONSTANT_Methodref:
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -2636,6 +2636,92 @@
           InstanceKlass::cast(klass)->is_same_class_package(SystemDictionary::MethodHandle_klass()));  // java.lang.invoke
 }
 
+
+// Return the Java mirror (java.lang.Class instance) for a single-character
+// descriptor.  This result, when available, is the same as produced by the
+// heavier API point of the same name that takes a Symbol.
+oop SystemDictionary::find_java_mirror_for_type(char signature_char) {
+  return java_lang_Class::primitive_mirror(char2type(signature_char));
+}
+
+// Find or construct the Java mirror (java.lang.Class instance) for a
+// for the given field type signature, as interpreted relative to the
+// given class loader.  Handles primitives, void, references, arrays,
+// and all other reflectable types, except method types.
+// N.B.  Code in reflection should use this entry point.
+Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
+                                                   Klass* accessing_klass,
+                                                   Handle class_loader,
+                                                   Handle protection_domain,
+                                                   SignatureStream::FailureMode failure_mode,
+                                                   TRAPS) {
+  Handle empty;
+
+  assert(accessing_klass == NULL || (class_loader.is_null() && protection_domain.is_null()),
+         "one or the other, or perhaps neither");
+
+  Symbol* type = signature;
+  TempNewSymbol type_buf;
+  if (type->utf8_length() > 1 && type->byte_at(0) == ';') {
+    // Strip the quote, which may have come from CONSTANT_Class[";"+FD].
+    // (This logic corresponds to the use of "FieldType::is_obj"
+    // in resolve_or_null.  A field type can be unwrapped to a class
+    // type and vice versa.)
+    type = SymbolTable::new_symbol(type->as_C_string() + 1,
+                                   type->utf8_length() - 1, CHECK_(empty));
+    type_buf = type;  // will free later
+  }
+
+  // What we have here must be a valid field descriptor,
+  // and all valid field descriptors are supported.
+  // Produce the same java.lang.Class that reflection reports.
+  if (type->utf8_length() == 1) {
+
+    // It's a primitive.  (Void has a primitive mirror too.)
+    char ch = (char) type->byte_at(0);
+    assert(is_java_primitive(char2type(ch)) || ch == 'V', "");
+    return Handle(THREAD, find_java_mirror_for_type(ch));
+
+  } else if (FieldType::is_obj(type) || FieldType::is_array(type)) {
+
+    // It's a reference type.
+    if (accessing_klass != NULL) {
+      class_loader      = Handle(THREAD, accessing_klass->class_loader());
+      protection_domain = Handle(THREAD, accessing_klass->protection_domain());
+    }
+    Klass* constant_type_klass;
+    if (failure_mode == SignatureStream::ReturnNull) {
+      constant_type_klass = resolve_or_null(type, class_loader, protection_domain,
+                                            CHECK_(empty));
+    } else {
+      bool throw_error = (failure_mode == SignatureStream::NCDFError);
+      constant_type_klass = resolve_or_fail(type, class_loader, protection_domain,
+                                            throw_error, CHECK_(empty));
+    }
+    if (constant_type_klass == NULL) {
+      return Handle();  // report failure this way
+    }
+    Handle mirror(THREAD, constant_type_klass->java_mirror());
+
+    // Check accessibility, emulating ConstantPool::verify_constant_pool_resolve.
+    if (accessing_klass != NULL) {
+      Klass* sel_klass = constant_type_klass;
+      bool fold_type_to_class = true;
+      LinkResolver::check_klass_accessability(accessing_klass, sel_klass,
+                                              fold_type_to_class, CHECK_(empty));
+    }
+
+    return mirror;
+
+  }
+  // New cases like "QFoo;" would go here.
+
+  // Fall through to an error.
+  assert(false, "unsupported mirror syntax");
+  THROW_MSG_(vmSymbols::java_lang_InternalError(), "unsupported mirror syntax", empty);
+}
+
+
 // Ask Java code to find or construct a java.lang.invoke.MethodType for the given
 // signature, as interpreted relative to the given class loader.
 // Because of class loader constraints, all method handle usage must be
@@ -2690,15 +2776,13 @@
       pts->obj_at_put(arg++, mirror);
 
     // Check accessibility.
-    if (ss.is_object() && accessing_klass != NULL) {
+    if (!java_lang_Class::is_primitive(mirror) && accessing_klass != NULL) {
       Klass* sel_klass = java_lang_Class::as_Klass(mirror);
       mirror = NULL;  // safety
       // Emulate ConstantPool::verify_constant_pool_resolve.
-      if (sel_klass->is_objArray_klass())
-        sel_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass();
-      if (sel_klass->is_instance_klass()) {
-        LinkResolver::check_klass_accessability(accessing_klass, sel_klass, CHECK_(empty));
-      }
+      bool fold_type_to_class = true;
+      LinkResolver::check_klass_accessability(accessing_klass, sel_klass,
+                                              fold_type_to_class, CHECK_(empty));
     }
   }
   assert(arg == npts, "");
@@ -2776,9 +2860,60 @@
   return Handle(THREAD, (oop) result.get_jobject());
 }
 
+// Ask Java to compute a constant by invoking a BSM given a ConstantDynamic_info CP entry
+Handle SystemDictionary::link_constant_dynamic_constant(Klass* caller,
+                                                        int condy_index,
+                                                        Handle bootstrap_specifier,
+                                                        Symbol* name,
+                                                        Symbol* type,
+                                                        TRAPS) {
+  Handle empty;
+  Handle bsm, info;
+  if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
+    bsm = bootstrap_specifier;
+  } else {
+    assert(bootstrap_specifier->is_objArray(), "");
+    objArrayOop args = (objArrayOop) bootstrap_specifier();
+    assert(args->length() == 2, "");
+    bsm  = Handle(THREAD, args->obj_at(0));
+    info = Handle(THREAD, args->obj_at(1));
+  }
+  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
+            "caller must supply a valid BSM");
+
+  // This should not happen.  JDK code should take care of that.
+  if (caller == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad constantdynamic", empty);
+  }
+
+  Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
+
+  // Resolve the constant type in the context of the caller class
+  Handle type_mirror = find_java_mirror_for_type(type, caller, SignatureStream::NCDFError,
+                                                 CHECK_(empty));
+
+  // call java.lang.invoke.MethodHandleNatives::linkConstantDyanmic(caller, condy_index, bsm, type, info)
+  JavaCallArguments args;
+  args.push_oop(Handle(THREAD, caller->java_mirror()));
+  args.push_int(condy_index);
+  args.push_oop(bsm);
+  args.push_oop(constant_name);
+  args.push_oop(type_mirror);
+  args.push_oop(info);
+  JavaValue result(T_OBJECT);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::MethodHandleNatives_klass(),
+                         vmSymbols::linkConstantDynamic_name(),
+                         vmSymbols::linkConstantDynamic_signature(),
+                         &args, CHECK_(empty));
+
+  return Handle(THREAD, (oop) result.get_jobject());
+}
+
 // Ask Java code to find or construct a java.lang.invoke.CallSite for the given
 // name and signature, as interpreted relative to the given class loader.
 methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller,
+                                                              int indy_index,
                                                               Handle bootstrap_specifier,
                                                               Symbol* name,
                                                               Symbol* type,
@@ -2790,17 +2925,10 @@
   if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
     bsm = bootstrap_specifier;
   } else {
-    assert(bootstrap_specifier->is_objArray(), "");
-    objArrayHandle args(THREAD, (objArrayOop) bootstrap_specifier());
-    int len = args->length();
-    assert(len >= 1, "");
-    bsm = Handle(THREAD, args->obj_at(0));
-    if (len > 1) {
-      objArrayOop args1 = oopFactory::new_objArray(SystemDictionary::Object_klass(), len-1, CHECK_(empty));
-      for (int i = 1; i < len; i++)
-        args1->obj_at_put(i-1, args->obj_at(i));
-      info = Handle(THREAD, args1);
-    }
+    objArrayOop args = (objArrayOop) bootstrap_specifier();
+    assert(args->length() == 2, "");
+    bsm  = Handle(THREAD, args->obj_at(0));
+    info = Handle(THREAD, args->obj_at(1));
   }
   guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
             "caller must supply a valid BSM");
@@ -2816,9 +2944,10 @@
   objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty));
   assert(appendix_box->obj_at(0) == NULL, "");
 
-  // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, bsm, name, mtype, info, &appendix)
+  // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix)
   JavaCallArguments args;
   args.push_oop(Handle(THREAD, caller->java_mirror()));
+  args.push_int(indy_index);
   args.push_oop(bsm);
   args.push_oop(method_name);
   args.push_oop(method_type);
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -32,6 +32,7 @@
 #include "oops/symbol.hpp"
 #include "runtime/java.hpp"
 #include "runtime/reflectionUtils.hpp"
+#include "runtime/signature.hpp"
 #include "utilities/hashtable.hpp"
 #include "utilities/hashtable.inline.hpp"
 
@@ -523,6 +524,28 @@
   static methodHandle find_method_handle_intrinsic(vmIntrinsics::ID iid,
                                                    Symbol* signature,
                                                    TRAPS);
+
+  // compute java_mirror (java.lang.Class instance) for a type ("I", "[[B", "LFoo;", etc.)
+  // Either the accessing_klass or the CL/PD can be non-null, but not both.
+  static Handle    find_java_mirror_for_type(Symbol* signature,
+                                             Klass* accessing_klass,
+                                             Handle class_loader,
+                                             Handle protection_domain,
+                                             SignatureStream::FailureMode failure_mode,
+                                             TRAPS);
+  static Handle    find_java_mirror_for_type(Symbol* signature,
+                                             Klass* accessing_klass,
+                                             SignatureStream::FailureMode failure_mode,
+                                             TRAPS) {
+    // callee will fill in CL/PD from AK, if they are needed
+    return find_java_mirror_for_type(signature, accessing_klass, Handle(), Handle(),
+                                     failure_mode, THREAD);
+  }
+                                             
+
+  // fast short-cut for the one-character case:
+  static oop       find_java_mirror_for_type(char signature_char);
+
   // find a java.lang.invoke.MethodType object for a given signature
   // (asks Java to compute it if necessary, except in a compiler thread)
   static Handle    find_method_handle_type(Symbol* signature,
@@ -537,8 +560,17 @@
                                                Symbol* signature,
                                                TRAPS);
 
+  // ask Java to compute a constant by invoking a BSM given a ConstantDynamic_info CP entry
+  static Handle    link_constant_dynamic_constant(Klass* caller,
+                                                  int condy_index,
+                                                  Handle bootstrap_specifier,
+                                                  Symbol* name,
+                                                  Symbol* type,
+                                                  TRAPS);
+
   // ask Java to create a dynamic call site, while linking an invokedynamic op
   static methodHandle find_dynamic_call_site_invoker(Klass* caller,
+                                                     int indy_index,
                                                      Handle bootstrap_method,
                                                      Symbol* name,
                                                      Symbol* type,
--- a/src/hotspot/share/classfile/verifier.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/classfile/verifier.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -2054,19 +2054,21 @@
     const constantPoolHandle& cp, u2 bci, TRAPS) {
   verify_cp_index(bci, cp, index, CHECK_VERIFY(this));
   constantTag tag = cp->tag_at(index);
-  unsigned int types;
+  unsigned int types = 0;
   if (opcode == Bytecodes::_ldc || opcode == Bytecodes::_ldc_w) {
     if (!tag.is_unresolved_klass()) {
       types = (1 << JVM_CONSTANT_Integer) | (1 << JVM_CONSTANT_Float)
             | (1 << JVM_CONSTANT_String)  | (1 << JVM_CONSTANT_Class)
-            | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType);
+            | (1 << JVM_CONSTANT_MethodHandle) | (1 << JVM_CONSTANT_MethodType)
+            | (1 << JVM_CONSTANT_ConstantDynamic);
       // Note:  The class file parser already verified the legality of
       // MethodHandle and MethodType constants.
       verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this));
     }
   } else {
     assert(opcode == Bytecodes::_ldc2_w, "must be ldc2_w");
-    types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long);
+    types = (1 << JVM_CONSTANT_Double) | (1 << JVM_CONSTANT_Long)
+          | (1 << JVM_CONSTANT_ConstantDynamic);
     verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this));
   }
   if (tag.is_string() && cp->is_pseudo_string_at(index)) {
@@ -2101,6 +2103,30 @@
     current_frame->push_stack(
       VerificationType::reference_type(
         vmSymbols::java_lang_invoke_MethodType()), CHECK_VERIFY(this));
+  } else if (tag.is_constant_dynamic()) {
+    Symbol* constant_type = cp->uncached_signature_ref_at(index);
+    if (!SignatureVerifier::is_valid_type_signature(constant_type)) {
+      class_format_error(
+        "Invalid type for constant dynamic in class %s referenced "
+        "from constant pool index %d", _klass->external_name(), index);
+      return;
+    }
+    assert(sizeof(VerificationType) == sizeof(uintptr_t),
+          "buffer type must match VerificationType size");
+    uintptr_t constant_type_buffer[2];
+    VerificationType* v_constant_type = (VerificationType*)constant_type_buffer;
+    SignatureStream sig_stream(constant_type, false);
+    int n = change_sig_to_verificationType(
+      &sig_stream, v_constant_type, CHECK_VERIFY(this));
+    int opcode_n = (opcode == Bytecodes::_ldc2_w ? 2 : 1);
+    if (n != opcode_n) {
+      // wrong kind of ldc; reverify against updated type mask
+      types &= ~(1 << JVM_CONSTANT_ConstantDynamic);
+      verify_cp_type(bci, index, cp, types, CHECK_VERIFY(this));
+    }
+    for (int i = 0; i < n; i++) {
+      current_frame->push_stack(v_constant_type[i], CHECK_VERIFY(this));
+    }
   } else {
     /* Unreachable? verify_cp_type has already validated the cp type. */
     verify_error(
@@ -2665,7 +2691,7 @@
   // Make sure the constant pool item is the right type
   u2 index = bcs->get_index_u2();
   Bytecodes::Code opcode = bcs->raw_code();
-  unsigned int types;
+  unsigned int types = 0;
   switch (opcode) {
     case Bytecodes::_invokeinterface:
       types = 1 << JVM_CONSTANT_InterfaceMethodref;
--- a/src/hotspot/share/classfile/vmSymbols.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/classfile/vmSymbols.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -98,6 +98,14 @@
     _type_signatures[T_BOOLEAN] = bool_signature();
     _type_signatures[T_VOID]    = void_signature();
     // no single signatures for T_OBJECT or T_ARRAY
+#ifdef ASSERT
+    for (int i = (int)T_BOOLEAN; i < (int)T_VOID+1; i++) {
+      Symbol* s = _type_signatures[i];
+      if (s == NULL)  continue;
+      BasicType st = signature_type(s);
+      assert(st == i, "");
+    }
+#endif
   }
 
 #ifdef ASSERT
@@ -202,9 +210,11 @@
 
 BasicType vmSymbols::signature_type(const Symbol* s) {
   assert(s != NULL, "checking");
-  for (int i = T_BOOLEAN; i < T_VOID+1; i++) {
-    if (s == _type_signatures[i]) {
-      return (BasicType)i;
+  if (s->utf8_length() == 1) {
+    BasicType result = char2type(s->byte_at(0));
+    if (is_java_primitive(result) || result == T_VOID) {
+      assert(s == _type_signatures[result], "");
+      return result;
     }
   }
   return T_OBJECT;
--- a/src/hotspot/share/classfile/vmSymbols.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/classfile/vmSymbols.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -309,8 +309,10 @@
   template(linkMethodHandleConstant_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/invoke/MethodHandle;") \
   template(linkMethod_name,                           "linkMethod")                               \
   template(linkMethod_signature, "(Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/String;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
+  template(linkConstantDynamic_name,                  "linkConstantDynamic")                      \
+  template(linkConstantDynamic_signature, "(Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;") \
   template(linkCallSite_name,                         "linkCallSite")                             \
-  template(linkCallSite_signature, "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
+  template(linkCallSite_signature, "(Ljava/lang/Object;ILjava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/invoke/MemberName;") \
   template(setTargetNormal_name,                      "setTargetNormal")                          \
   template(setTargetVolatile_name,                    "setTargetVolatile")                        \
   template(setTarget_signature,                       "(Ljava/lang/invoke/MethodHandle;)V")       \
--- a/src/hotspot/share/interpreter/bytecode.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/bytecode.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -207,8 +207,7 @@
 
 BasicType Bytecode_loadconstant::result_type() const {
   int index = pool_index();
-  constantTag tag = _method->constants()->tag_at(index);
-  return tag.basic_type();
+  return _method->constants()->basic_type_for_constant_at(index);
 }
 
 oop Bytecode_loadconstant::resolve_constant(TRAPS) const {
@@ -217,6 +216,8 @@
   ConstantPool* constants = _method->constants();
   if (has_cache_index()) {
     return constants->resolve_cached_constant_at(index, THREAD);
+  } else if (_method->constants()->tag_at(index).is_constant_dynamic()) {
+    return constants->resolve_possibly_cached_constant_at(index, THREAD);
   } else {
     return constants->resolve_constant_at(index, THREAD);
   }
--- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -2371,6 +2371,30 @@
             THREAD->set_vm_result(NULL);
             break;
 
+          case JVM_CONSTANT_ConstantDynamic:
+            {
+              oop result = constants->resolved_references()->obj_at(index);
+              if (result == NULL) {
+                CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception);
+                result = THREAD->vm_result();
+              }
+              VERIFY_OOP(result);
+
+              jvalue value;
+              BasicType type = java_lang_boxing_object::get_value(result, &value);
+              switch (type) {
+              case T_FLOAT:   SET_STACK_FLOAT(value.f, 0); break;
+              case T_INT:     SET_STACK_INT(value.i, 0); break;
+              case T_SHORT:   SET_STACK_INT(value.s, 0); break;
+              case T_BYTE:    SET_STACK_INT(value.b, 0); break;
+              case T_CHAR:    SET_STACK_INT(value.c, 0); break;
+              case T_BOOLEAN: SET_STACK_INT(value.z, 0); break;
+              default:  ShouldNotReachHere();
+              }
+
+              break;
+            }
+
           default:  ShouldNotReachHere();
           }
           UPDATE_PC_AND_TOS_AND_CONTINUE(incr, 1);
@@ -2390,6 +2414,27 @@
           case JVM_CONSTANT_Double:
              SET_STACK_DOUBLE(constants->double_at(index), 1);
             break;
+
+          case JVM_CONSTANT_ConstantDynamic:
+            {
+              oop result = constants->resolved_references()->obj_at(index);
+              if (result == NULL) {
+                CALL_VM(InterpreterRuntime::resolve_ldc(THREAD, (Bytecodes::Code) opcode), handle_exception);
+                result = THREAD->vm_result();
+              }
+              VERIFY_OOP(result);
+
+              jvalue value;
+              BasicType type = java_lang_boxing_object::get_value(result, &value);
+              switch (type) {
+              case T_DOUBLE: SET_STACK_DOUBLE(value.d, 1); break;
+              case T_LONG:   SET_STACK_LONG(value.j, 1); break;
+              default:  ShouldNotReachHere();
+              }
+
+              break;
+            }
+
           default:  ShouldNotReachHere();
           }
           UPDATE_PC_AND_TOS_AND_CONTINUE(3, 2);
@@ -2407,7 +2452,7 @@
           incr = 3;
         }
 
-        // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
+        // We are resolved if the resolved_references array contains a non-null object (CallSite, etc.)
         // This kind of CP cache entry does not need to match the flags byte, because
         // there is a 1-1 relation between bytecode type and CP entry type.
         ConstantPool* constants = METHOD->constants();
@@ -2417,6 +2462,8 @@
                   handle_exception);
           result = THREAD->vm_result();
         }
+        if (result == Universe::the_null_sentinel())
+          result = NULL;
 
         VERIFY_OOP(result);
         SET_STACK_OBJECT(result, 0);
@@ -2428,7 +2475,7 @@
         u4 index = Bytes::get_native_u4(pc+1);
         ConstantPoolCacheEntry* cache = cp->constant_pool()->invokedynamic_cp_cache_entry_at(index);
 
-        // We are resolved if the resolved_references field contains a non-null object (CallSite, etc.)
+        // We are resolved if the resolved_references array contains a non-null object (CallSite, etc.)
         // This kind of CP cache entry does not need to match the flags byte, because
         // there is a 1-1 relation between bytecode type and CP entry type.
         if (! cache->is_resolved((Bytecodes::Code) opcode)) {
--- a/src/hotspot/share/interpreter/bytecodeTracer.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/bytecodeTracer.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -367,6 +367,7 @@
   case JVM_CONSTANT_Fieldref:
     break;
   case JVM_CONSTANT_NameAndType:
+  case JVM_CONSTANT_ConstantDynamic:
   case JVM_CONSTANT_InvokeDynamic:
     has_klass = false;
     break;
@@ -382,7 +383,7 @@
     Symbol* klass = constants->klass_name_at(constants->uncached_klass_ref_index_at(i));
     st->print_cr(" %d <%s.%s%s%s> ", i, klass->as_C_string(), name->as_C_string(), sep, signature->as_C_string());
   } else {
-    if (tag.is_invoke_dynamic()) {
+    if (tag.is_constant_dynamic() || tag.is_invoke_dynamic()) {
       int bsm = constants->invoke_dynamic_bootstrap_method_ref_index_at(i);
       st->print(" bsm=%d", bsm);
     }
--- a/src/hotspot/share/interpreter/interpreterRuntime.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -116,25 +116,56 @@
 IRT_END
 
 IRT_ENTRY(void, InterpreterRuntime::resolve_ldc(JavaThread* thread, Bytecodes::Code bytecode)) {
-  assert(bytecode == Bytecodes::_fast_aldc ||
+  assert(bytecode == Bytecodes::_ldc ||
+         bytecode == Bytecodes::_ldc_w ||
+         bytecode == Bytecodes::_ldc2_w ||
+         bytecode == Bytecodes::_fast_aldc ||
          bytecode == Bytecodes::_fast_aldc_w, "wrong bc");
   ResourceMark rm(thread);
+  const bool is_fast_aldc = (bytecode == Bytecodes::_fast_aldc ||
+                             bytecode == Bytecodes::_fast_aldc_w);
   methodHandle m (thread, method(thread));
   Bytecode_loadconstant ldc(m, bci(thread));
+
+  // Double-check the size.  (Condy can have any type.)
+  BasicType type = ldc.result_type();
+  switch (type2size[type]) {
+  case 2: guarantee(bytecode == Bytecodes::_ldc2_w, ""); break;
+  case 1: guarantee(bytecode != Bytecodes::_ldc2_w, ""); break;
+  default: ShouldNotReachHere();
+  }
+
+  // Resolve the constant.  This does not do unboxing.
+  // But it does replace Universe::the_null_sentinel by null.
   oop result = ldc.resolve_constant(CHECK);
+  assert(result != NULL || is_fast_aldc, "null result only valid for fast_aldc");
+
 #ifdef ASSERT
   {
     // The bytecode wrappers aren't GC-safe so construct a new one
     Bytecode_loadconstant ldc2(m, bci(thread));
-    oop coop = m->constants()->resolved_references()->obj_at(ldc2.cache_index());
-    assert(result == coop, "expected result for assembly code");
+    int rindex = ldc2.cache_index();
+    if (rindex < 0)
+      rindex = m->constants()->cp_to_object_index(ldc2.pool_index());
+    if (rindex >= 0) {
+      oop coop = m->constants()->resolved_references()->obj_at(rindex);
+      oop roop = (result == NULL ? Universe::the_null_sentinel() : result);
+      assert(roop == coop, "expected result for assembly code");
+    }
   }
 #endif
   thread->set_vm_result(result);
+  if (!is_fast_aldc) {
+    // Tell the interpreter how to unbox the primitive.
+    guarantee(java_lang_boxing_object::is_instance(result, type), "");
+    int offset = java_lang_boxing_object::value_offset_in_bytes(type);
+    intptr_t flags = ((as_TosState(type) << ConstantPoolCacheEntry::tos_state_shift)
+                      | (offset & ConstantPoolCacheEntry::field_index_mask));
+    thread->set_vm_result_2((Metadata*)flags);
+  }
 }
 IRT_END
 
-
 //------------------------------------------------------------------------------------------------------------------------
 // Allocation
 
--- a/src/hotspot/share/interpreter/linkResolver.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/linkResolver.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -39,6 +39,7 @@
 #include "memory/universe.inline.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/method.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jvm.h"
@@ -53,7 +54,6 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 
-
 //------------------------------------------------------------------------------------------------------------------------
 // Implementation of CallInfo
 
@@ -283,9 +283,21 @@
 //------------------------------------------------------------------------------------------------------------------------
 // Klass resolution
 
-void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass, TRAPS) {
+void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass,
+                                             bool fold_type_to_class, TRAPS) {
+  Klass* base_klass = sel_klass;
+  if (fold_type_to_class) {
+    if (sel_klass->is_objArray_klass()) {
+      base_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass();
+    }
+    // The element type could be a typeArray - we only need the access
+    // check if it is an reference to another class.
+    if (!base_klass->is_instance_klass()) {
+      return;  // no relevant check to do
+    }
+  }
   Reflection::VerifyClassAccessResults vca_result =
-    Reflection::verify_class_access(ref_klass, InstanceKlass::cast(sel_klass), true);
+    Reflection::verify_class_access(ref_klass, InstanceKlass::cast(base_klass), true);
   if (vca_result != Reflection::ACCESS_OK) {
     ResourceMark rm(THREAD);
     char* msg = Reflection::verify_class_access_msg(ref_klass,
@@ -1662,31 +1674,6 @@
   result.set_handle(resolved_klass, resolved_method, resolved_appendix, resolved_method_type, CHECK);
 }
 
-static void wrap_invokedynamic_exception(TRAPS) {
-  if (HAS_PENDING_EXCEPTION) {
-    // See the "Linking Exceptions" section for the invokedynamic instruction
-    // in JVMS 6.5.
-    if (PENDING_EXCEPTION->is_a(SystemDictionary::Error_klass())) {
-      // Pass through an Error, including BootstrapMethodError, any other form
-      // of linkage error, or say ThreadDeath/OutOfMemoryError
-      if (TraceMethodHandles) {
-        tty->print_cr("invokedynamic passes through an Error for " INTPTR_FORMAT, p2i((void *)PENDING_EXCEPTION));
-        PENDING_EXCEPTION->print();
-      }
-      return;
-    }
-
-    // Otherwise wrap the exception in a BootstrapMethodError
-    if (TraceMethodHandles) {
-      tty->print_cr("invokedynamic throws BSME for " INTPTR_FORMAT, p2i((void *)PENDING_EXCEPTION));
-      PENDING_EXCEPTION->print();
-    }
-    Handle nested_exception(THREAD, PENDING_EXCEPTION);
-    CLEAR_PENDING_EXCEPTION;
-    THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
-  }
-}
-
 void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) {
   Symbol* method_name       = pool->name_ref_at(index);
   Symbol* method_signature  = pool->signature_ref_at(index);
@@ -1696,10 +1683,11 @@
   Handle bootstrap_specifier;
   // Check if CallSite has been bound already:
   ConstantPoolCacheEntry* cpce = pool->invokedynamic_cp_cache_entry_at(index);
+  int pool_index = -1;
   if (cpce->is_f1_null()) {
-    int pool_index = cpce->constant_pool_index();
+    pool_index = cpce->constant_pool_index();
     oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, THREAD);
-    wrap_invokedynamic_exception(CHECK);
+    Exceptions::wrap_dynamic_exception(CHECK);
     assert(bsm_info != NULL, "");
     // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic.
     bootstrap_specifier = Handle(THREAD, bsm_info);
@@ -1709,7 +1697,7 @@
     Handle       appendix(   THREAD, cpce->appendix_if_resolved(pool));
     Handle       method_type(THREAD, cpce->method_type_if_resolved(pool));
     result.set_handle(method, appendix, method_type, THREAD);
-    wrap_invokedynamic_exception(CHECK);
+    Exceptions::wrap_dynamic_exception(CHECK);
     return;
   }
 
@@ -1722,10 +1710,11 @@
     tty->print("  BSM info: "); bootstrap_specifier->print();
   }
 
-  resolve_dynamic_call(result, bootstrap_specifier, method_name, method_signature, current_klass, CHECK);
+  resolve_dynamic_call(result, pool_index, bootstrap_specifier, method_name, method_signature, current_klass, CHECK);
 }
 
 void LinkResolver::resolve_dynamic_call(CallInfo& result,
+                                        int pool_index,
                                         Handle bootstrap_specifier,
                                         Symbol* method_name, Symbol* method_signature,
                                         Klass* current_klass,
@@ -1736,12 +1725,13 @@
   Handle       resolved_method_type;
   methodHandle resolved_method =
     SystemDictionary::find_dynamic_call_site_invoker(current_klass,
+                                                     pool_index,
                                                      bootstrap_specifier,
                                                      method_name, method_signature,
                                                      &resolved_appendix,
                                                      &resolved_method_type,
                                                      THREAD);
-  wrap_invokedynamic_exception(CHECK);
+  Exceptions::wrap_dynamic_exception(CHECK);
   result.set_handle(resolved_method, resolved_appendix, resolved_method_type, THREAD);
-  wrap_invokedynamic_exception(CHECK);
+  Exceptions::wrap_dynamic_exception(CHECK);
 }
--- a/src/hotspot/share/interpreter/linkResolver.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/linkResolver.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -275,7 +275,16 @@
                                       const constantPoolHandle& pool, int index, TRAPS);
  public:
   // constant pool resolving
-  static void check_klass_accessability(Klass* ref_klass, Klass* sel_klass, TRAPS);
+  static void check_klass_accessability(Klass* ref_klass, Klass* sel_klass,
+                                        bool fold_type_to_class, TRAPS);
+  // The optional 'fold_type_to_class' means that a derived type (array)
+  // is first converted to the class it is derived from (element type).
+  // If this element type is not a class, then the check passes quietly.
+  // This is usually what is needed, but a few existing uses might break
+  // if this flag were always turned on.  FIXME: See if it can be, always.
+  static void check_klass_accessability(Klass* ref_klass, Klass* sel_klass, TRAPS) {
+    return check_klass_accessability(ref_klass, sel_klass, false, THREAD);
+  }
 
   // static resolving calls (will not run any Java code);
   // used only from Bytecode_invoke::static_target
@@ -307,7 +316,7 @@
                                      bool check_null_and_abstract, TRAPS);
   static void resolve_handle_call   (CallInfo& result,
                                      const LinkInfo& link_info, TRAPS);
-  static void resolve_dynamic_call  (CallInfo& result, Handle bootstrap_specifier,
+  static void resolve_dynamic_call  (CallInfo& result, int pool_index, Handle bootstrap_specifier,
                                      Symbol* method_name, Symbol* method_signature,
                                      Klass* current_klass, TRAPS);
 
--- a/src/hotspot/share/interpreter/rewriter.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/rewriter.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -49,7 +49,8 @@
       case JVM_CONSTANT_Methodref         : // fall through
         add_cp_cache_entry(i);
         break;
-      case JVM_CONSTANT_String:
+      case JVM_CONSTANT_ConstantDynamic:
+      case JVM_CONSTANT_String            : // fall through
       case JVM_CONSTANT_MethodHandle      : // fall through
       case JVM_CONSTANT_MethodType        : // fall through
         add_resolved_references_entry(i);
@@ -322,7 +323,14 @@
     address p = bcp + offset;
     int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
     constantTag tag = _pool->tag_at(cp_index).value();
-    if (tag.is_method_handle() || tag.is_method_type() || tag.is_string()) {
+
+    if (tag.is_method_handle() ||
+        tag.is_method_type() ||
+        tag.is_string() ||
+        (tag.is_constant_dynamic() &&
+         // keep regular ldc interpreter logic for condy primitives
+         is_reference_type(FieldType::basic_type(_pool->uncached_signature_ref_at(cp_index))))
+        ) {
       int ref_index = cp_entry_to_resolved_references(cp_index);
       if (is_wide) {
         (*bcp) = Bytecodes::_fast_aldc_w;
--- a/src/hotspot/share/interpreter/templateTable.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/templateTable.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -278,7 +278,7 @@
   def(Bytecodes::_sipush              , ubcp|____|____|____, vtos, itos, sipush              ,  _           );
   def(Bytecodes::_ldc                 , ubcp|____|clvm|____, vtos, vtos, ldc                 ,  false       );
   def(Bytecodes::_ldc_w               , ubcp|____|clvm|____, vtos, vtos, ldc                 ,  true        );
-  def(Bytecodes::_ldc2_w              , ubcp|____|____|____, vtos, vtos, ldc2_w              ,  _           );
+  def(Bytecodes::_ldc2_w              , ubcp|____|clvm|____, vtos, vtos, ldc2_w              ,  _           );
   def(Bytecodes::_iload               , ubcp|____|clvm|____, vtos, itos, iload               ,  _           );
   def(Bytecodes::_lload               , ubcp|____|____|____, vtos, ltos, lload               ,  _           );
   def(Bytecodes::_fload               , ubcp|____|____|____, vtos, ftos, fload               ,  _           );
--- a/src/hotspot/share/interpreter/templateTable.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/interpreter/templateTable.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -295,6 +295,7 @@
   static void getstatic(int byte_no);
   static void putstatic(int byte_no);
   static void pop_and_check_object(Register obj);
+  static void condy_helper(Label& Done);  // shared by ldc instances
 
   static void _new();
   static void newarray();
--- a/src/hotspot/share/memory/universe.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/memory/universe.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -118,6 +118,7 @@
 oop Universe::_system_thread_group                    = NULL;
 objArrayOop Universe::_the_empty_class_klass_array    = NULL;
 Array<Klass*>* Universe::_the_array_interfaces_array = NULL;
+oop Universe::_the_null_sentinel                      = NULL;
 oop Universe::_the_null_string                        = NULL;
 oop Universe::_the_min_jint_string                   = NULL;
 LatestMethodCache* Universe::_finalizer_register_cache = NULL;
@@ -202,6 +203,7 @@
   assert(_mirrors[0] == NULL && _mirrors[T_BOOLEAN - 1] == NULL, "checking");
 
   f->do_oop((oop*)&_the_empty_class_klass_array);
+  f->do_oop((oop*)&_the_null_sentinel);
   f->do_oop((oop*)&_the_null_string);
   f->do_oop((oop*)&_the_min_jint_string);
   f->do_oop((oop*)&_out_of_memory_error_java_heap);
@@ -388,6 +390,11 @@
     initialize_basic_type_klass(longArrayKlassObj(), CHECK);
   } // end of core bootstrapping
 
+  {
+    Handle tns = java_lang_String::create_from_str("<null_sentinel>", CHECK);
+    _the_null_sentinel = tns();
+  }
+
   // Maybe this could be lifted up now that object array can be initialized
   // during the bootstrapping.
 
--- a/src/hotspot/share/memory/universe.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/memory/universe.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -141,6 +141,7 @@
   static oop          _system_thread_group;           // Reference to the system thread group object
 
   static objArrayOop  _the_empty_class_klass_array;   // Canonicalized obj array of type java.lang.Class
+  static oop          _the_null_sentinel;             // A unique object pointer unused except as a sentinel for null.
   static oop          _the_null_string;               // A cache of "null" as a Java string
   static oop          _the_min_jint_string;          // A cache of "-2147483648" as a Java string
   static LatestMethodCache* _finalizer_register_cache; // static method for registering finalizable objects
@@ -323,6 +324,9 @@
 
   static Method*      do_stack_walk_method()          { return _do_stack_walk_cache->get_method(); }
 
+  static oop          the_null_sentinel()             { return _the_null_sentinel;             }
+  static address      the_null_sentinel_addr()        { return (address) &_the_null_sentinel;  }
+
   // Function to initialize these
   static void initialize_known_methods(TRAPS);
 
--- a/src/hotspot/share/oops/constantPool.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/oops/constantPool.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -587,7 +587,6 @@
   return symbol_at(signature_index);
 }
 
-
 int ConstantPool::impl_name_and_type_ref_index_at(int which, bool uncached) {
   int i = which;
   if (!uncached && cache() != NULL) {
@@ -601,7 +600,7 @@
     // change byte-ordering and go via cache
     i = remap_instruction_operand_from_cache(which);
   } else {
-    if (tag_at(which).is_invoke_dynamic()) {
+    if (tag_at(which).is_invoke_dynamic() || tag_at(which).is_constant_dynamic()) {
       int pool_index = invoke_dynamic_name_and_type_ref_index_at(which);
       assert(tag_at(pool_index).is_name_and_type(), "");
       return pool_index;
@@ -652,16 +651,12 @@
 
 
 void ConstantPool::verify_constant_pool_resolve(const constantPoolHandle& this_cp, Klass* k, TRAPS) {
- if (k->is_instance_klass() || k->is_objArray_klass()) {
-    InstanceKlass* holder = this_cp->pool_holder();
-    Klass* elem = k->is_instance_klass() ? k : ObjArrayKlass::cast(k)->bottom_klass();
-
-    // The element type could be a typeArray - we only need the access check if it is
-    // an reference to another class
-    if (elem->is_instance_klass()) {
-      LinkResolver::check_klass_accessability(holder, elem, CHECK);
-    }
+  if (!(k->is_instance_klass() || k->is_objArray_klass())) {
+    return;  // short cut, typeArray klass is always accessible
   }
+  Klass* holder = this_cp->pool_holder();
+  bool fold_type_to_class = true;
+  LinkResolver::check_klass_accessability(holder, k, fold_type_to_class, CHECK);
 }
 
 
@@ -802,16 +797,30 @@
   }
 }
 
+BasicType ConstantPool::basic_type_for_constant_at(int which) {
+  constantTag tag = tag_at(which);
+  if (tag.is_constant_dynamic()) {
+    // have to look at the signature for this one
+    Symbol* constant_type = uncached_signature_ref_at(which);
+    return FieldType::basic_type(constant_type);
+  }
+  return tag.basic_type();
+}
+
 // Called to resolve constants in the constant pool and return an oop.
 // Some constant pool entries cache their resolved oop. This is also
 // called to create oops from constants to use in arguments for invokedynamic
-oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, TRAPS) {
+oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp,
+                                           int index, int cache_index,
+                                           bool* status_return, TRAPS) {
   oop result_oop = NULL;
   Handle throw_exception;
 
   if (cache_index == _possible_index_sentinel) {
     // It is possible that this constant is one which is cached in the objects.
     // We'll do a linear search.  This should be OK because this usage is rare.
+    // FIXME: If bootstrap specifiers stress this code, consider putting in
+    // a reverse index.  Binary search over a short array should do it.
     assert(index > 0, "valid index");
     cache_index = this_cp->cp_to_object_index(index);
   }
@@ -821,6 +830,12 @@
   if (cache_index >= 0) {
     result_oop = this_cp->resolved_references()->obj_at(cache_index);
     if (result_oop != NULL) {
+      if (result_oop == Universe::the_null_sentinel()) {
+        DEBUG_ONLY(int temp_index = (index >= 0 ? index : this_cp->object_to_cp_index(cache_index)));
+        assert(this_cp->tag_at(temp_index).is_constant_dynamic(), "only condy uses the null sentinel");
+        result_oop = NULL;
+      }
+      if (status_return != NULL)  (*status_return) = true;
       return result_oop;
       // That was easy...
     }
@@ -831,6 +846,35 @@
 
   constantTag tag = this_cp->tag_at(index);
 
+  if (status_return != NULL) {
+    // don't trigger resolution if the constant might need it
+    switch (tag.value()) {
+    case JVM_CONSTANT_Class:
+    {
+      CPKlassSlot kslot = this_cp->klass_slot_at(index);
+      int resolved_klass_index = kslot.resolved_klass_index();
+      if (this_cp->resolved_klasses()->at(resolved_klass_index) == NULL) {
+        (*status_return) = false;
+        return NULL;
+      }
+      // the klass is waiting in the CP; go get it
+      break;
+    }
+    case JVM_CONSTANT_String:
+    case JVM_CONSTANT_Integer:
+    case JVM_CONSTANT_Float:
+    case JVM_CONSTANT_Long:
+    case JVM_CONSTANT_Double:
+      // these guys trigger OOM at worst
+      break;
+    default:
+      (*status_return) = false;
+      return NULL;
+    }
+    // from now on there is either success or an OOME
+    (*status_return) = true;
+  }
+
   switch (tag.value()) {
 
   case JVM_CONSTANT_UnresolvedClass:
@@ -844,6 +888,48 @@
       break;
     }
 
+  case JVM_CONSTANT_ConstantDynamic:
+    {
+      Klass* current_klass = this_cp->pool_holder();
+      Symbol* constant_name       = this_cp->uncached_name_ref_at(index);
+      Symbol* constant_type       = this_cp->uncached_signature_ref_at(index);
+
+      Handle bootstrap_specifier;
+      oop bsm_info = this_cp->resolve_bootstrap_specifier_at(index, THREAD);
+      Exceptions::wrap_dynamic_exception(CHECK_NULL);
+      assert(bsm_info != NULL, "");
+      // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_ConstantDynamic.
+      bootstrap_specifier = Handle(THREAD, bsm_info);
+    
+      // Resolve the ConstantDynamic to invoke the BSM in order to obtain the resulting oop.
+      Handle value = SystemDictionary::link_constant_dynamic_constant(current_klass,
+                                                                      index,
+                                                                      bootstrap_specifier,
+                                                                      constant_name,
+                                                                      constant_type,
+                                                                      THREAD);
+      result_oop = value();
+      Exceptions::wrap_dynamic_exception(CHECK_NULL);
+      BasicType type = FieldType::basic_type(constant_type);
+      if (!is_reference_type(type)) {
+        // Make sure the primitive value is properly boxed.
+        // This is a JDK responsibility.
+        const char* fail = NULL;
+        if (result_oop == NULL) {
+          fail = "null result instead of box";
+        } else if (!is_java_primitive(type)) {
+          // FIXME: support value types via unboxing
+          fail = "can only handle references and primitives";
+        } else if (!java_lang_boxing_object::is_instance(result_oop, type)) {
+          fail = "primitive is not properly boxed";
+        }
+        if (fail != NULL) {
+          THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), fail);
+        }
+      }
+      break;
+    }
+
   case JVM_CONSTANT_String:
     assert(cache_index != _no_index_sentinel, "should have been set");
     if (this_cp->is_pseudo_string_at(index)) {
@@ -953,15 +1039,20 @@
     // The important thing here is that all threads pick up the same result.
     // It doesn't matter which racing thread wins, as long as only one
     // result is used by all threads, and all future queries.
-    oop old_result = this_cp->resolved_references()->atomic_compare_exchange_oop(cache_index, result_oop, NULL);
+    oop new_result = (result_oop == NULL ? Universe::the_null_sentinel() : result_oop);
+    oop old_result = this_cp->resolved_references()
+      ->atomic_compare_exchange_oop(cache_index, new_result, NULL);
     if (old_result == NULL) {
       return result_oop;  // was installed
     } else {
       // Return the winning thread's result.  This can be different than
       // the result here for MethodHandles.
+      if (old_result == Universe::the_null_sentinel())
+        old_result = NULL;
       return old_result;
     }
   } else {
+    assert(result_oop != Universe::the_null_sentinel(), "");
     return result_oop;
   }
 }
@@ -975,13 +1066,14 @@
 
 
 oop ConstantPool::resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS) {
-  assert(this_cp->tag_at(index).is_invoke_dynamic(), "Corrupted constant pool");
-
+  assert((this_cp->tag_at(index).is_invoke_dynamic() ||
+          this_cp->tag_at(index).is_constant_dynamic()), "Corrupted constant pool");
   Handle bsm;
   int argc;
   {
-    // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&type], plus optional arguments
-    // The bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
+    // JVM_CONSTANT_InvokeDynamic is an ordered pair of [bootm, name&mtype], plus optional arguments
+    // JVM_CONSTANT_ConstantDynamic is an ordered pair of [bootm, name&ftype], plus optional arguments
+    // In both cases, the bootm, being a JVM_CONSTANT_MethodHandle, has its own cache entry.
     // It is accompanied by the optional arguments.
     int bsm_index = this_cp->invoke_dynamic_bootstrap_method_ref_index_at(index);
     oop bsm_oop = this_cp->resolve_possibly_cached_constant_at(bsm_index, CHECK_NULL);
@@ -991,30 +1083,142 @@
 
     // Extract the optional static arguments.
     argc = this_cp->invoke_dynamic_argument_count_at(index);
-    if (argc == 0)  return bsm_oop;
+
+    // if there are no static arguments, return the bsm by itself:
+    if (argc == 0 && UseBootstrapCallInfo < 2)  return bsm_oop;
 
     bsm = Handle(THREAD, bsm_oop);
   }
 
+  // We are going to return an ordered pair of {bsm, info}, using a 2-array.
   objArrayHandle info;
   {
-    objArrayOop info_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1+argc, CHECK_NULL);
+    objArrayOop info_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL);
     info = objArrayHandle(THREAD, info_oop);
   }
 
   info->obj_at_put(0, bsm());
-  for (int i = 0; i < argc; i++) {
-    int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i);
-    oop arg_oop = this_cp->resolve_possibly_cached_constant_at(arg_index, CHECK_NULL);
-    info->obj_at_put(1+i, arg_oop);
+
+  bool use_BSCI;
+  switch (UseBootstrapCallInfo) {
+  default: use_BSCI = true;  break;  // stress mode
+  case 0:  use_BSCI = false; break;  // stress mode
+  case 1:                            // normal mode
+    // If we were to support an alternative mode of BSM invocation,
+    // we'd convert to pull mode here if the BSM could be a candidate
+    // for that alternative mode.  We can't easily test for things
+    // like varargs here, but we can get away with approximate testing,
+    // since the JDK runtime will make up the difference either way.
+    // For now, exercise the pull-mode path if the BSM is of arity 2,
+    // or if there is a potential condy loop (see below).
+    oop mt_oop = java_lang_invoke_MethodHandle::type(bsm());
+    use_BSCI = (java_lang_invoke_MethodType::ptype_count(mt_oop) != 2);
+    break;
   }
 
+  // Here's a reason to use BSCI even if it wasn't requested:
+  // If a condy uses a condy argument, we want to avoid infinite
+  // recursion (condy loops) in the C code.  It's OK in Java,
+  // because Java has stack overflow checking, so we punt
+  // potentially cyclic cases from C to Java.
+  if (!use_BSCI && this_cp->tag_at(index).is_constant_dynamic()) {
+    bool found_unresolved_condy = false;
+    for (int i = 0; i < argc; i++) {
+      int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i);
+      if (this_cp->tag_at(arg_index).is_constant_dynamic()) {
+        // potential recursion point condy -> condy
+        bool found_it = false;
+        this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL);
+        if (!found_it) { found_unresolved_condy = true; break; }
+      }
+    }
+    if (found_unresolved_condy)
+      use_BSCI = true;
+  }
+
+  const int SMALL_ARITY = 5;
+  if (use_BSCI && argc <= SMALL_ARITY && UseBootstrapCallInfo <= 2) {
+    // If there are only a few arguments, and none of them need linking,
+    // push them, instead of asking the JDK runtime to turn around and
+    // pull them, saving a JVM/JDK transition in some simple cases.
+    bool all_resolved = true;
+    for (int i = 0; i < argc; i++) {
+      bool found_it = false;
+      int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i);
+      this_cp->find_cached_constant_at(arg_index, found_it, CHECK_NULL);
+      if (!found_it) { all_resolved = false; break; }
+    }
+    if (all_resolved)
+      use_BSCI = false;
+  }
+
+  if (!use_BSCI) {
+    // return {bsm, {arg...}}; resolution of arguments is done immediately, before JDK code is called
+    objArrayOop args_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), argc, CHECK_NULL);
+    info->obj_at_put(1, args_oop);   // may overwrite with args[0] below
+    objArrayHandle args(THREAD, args_oop);
+    copy_bootstrap_arguments_at_impl(this_cp, index, 0, argc, args, 0, true, Handle(), CHECK_NULL);
+    if (argc == 1) {
+      // try to discard the singleton array
+      oop arg_oop = args->obj_at(0);
+      if (arg_oop != NULL && !arg_oop->is_array()) {
+        // JVM treats arrays and nulls specially in this position,
+        // but other things are just single arguments
+        info->obj_at_put(1, arg_oop);
+      }
+    }
+  } else {
+    // return {bsm, {arg_count, pool_index}}; JDK code must pull the arguments as needed
+    typeArrayOop ints_oop = oopFactory::new_typeArray(T_INT, 2, CHECK_NULL);
+    ints_oop->int_at_put(0, argc);
+    ints_oop->int_at_put(1, index);
+    info->obj_at_put(1, ints_oop);
+  }
   return info();
 }
 
+void ConstantPool::copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index,
+                                                    int start_arg, int end_arg,
+                                                    objArrayHandle info, int pos,
+                                                    bool must_resolve, Handle if_not_available,
+                                                    TRAPS) {
+  int argc;
+  int limit = java_add(pos, end_arg - start_arg);
+  // checks: index in range [0..this_cp->length),
+  // tag at index, start..end in range [0..argc],
+  // info array non-null, pos..limit in [0..info.length]
+  if ((0 >= index    || index >= this_cp->length())  ||
+      !(this_cp->tag_at(index).is_invoke_dynamic()    ||
+        this_cp->tag_at(index).is_constant_dynamic()) ||
+      (0 > start_arg || start_arg > end_arg) ||
+      (end_arg > (argc = this_cp->invoke_dynamic_argument_count_at(index))) ||
+      (0 > pos       || pos > limit)         ||
+      (info.is_null() || limit > info->length())) {
+    // An index or something else went wrong; throw an error.
+    // Since this is an internal API, we don't expect this,
+    // so we don't bother to craft a nice message.
+    THROW_MSG(vmSymbols::java_lang_LinkageError(), "bad BSM argument access");
+  }
+  // now we can loop safely
+  int info_i = pos;
+  for (int i = start_arg; i < end_arg; i++) {
+    int arg_index = this_cp->invoke_dynamic_argument_index_at(index, i);
+    oop arg_oop;
+    if (must_resolve) {
+      arg_oop = this_cp->resolve_possibly_cached_constant_at(arg_index, CHECK);
+    } else {
+      bool found_it = false;
+      arg_oop = this_cp->find_cached_constant_at(arg_index, found_it, CHECK);
+      if (!found_it)  arg_oop = if_not_available();
+    }
+    info->obj_at_put(info_i++, arg_oop);
+  }
+}
+
 oop ConstantPool::string_at_impl(const constantPoolHandle& this_cp, int which, int obj_index, TRAPS) {
   // If the string has already been interned, this entry will be non-null
   oop str = this_cp->resolved_references()->obj_at(obj_index);
+  assert(str != Universe::the_null_sentinel(), "");
   if (str != NULL) return str;
   Symbol* sym = this_cp->unresolved_string_at(which);
   str = StringTable::intern(sym, CHECK_(NULL));
@@ -1195,6 +1399,18 @@
     }
   } break;
 
+  case JVM_CONSTANT_ConstantDynamic:
+  {
+    int k1 = invoke_dynamic_name_and_type_ref_index_at(index1);
+    int k2 = cp2->invoke_dynamic_name_and_type_ref_index_at(index2);
+    int i1 = invoke_dynamic_bootstrap_specifier_index(index1);
+    int i2 = cp2->invoke_dynamic_bootstrap_specifier_index(index2);
+    // separate statements and variables because CHECK_false is used
+    bool match_entry = compare_entry_to(k1, cp2, k2, CHECK_false);
+    bool match_operand = compare_operand_to(i1, cp2, i2, CHECK_false);
+    return (match_entry && match_operand);
+  } break;
+
   case JVM_CONSTANT_InvokeDynamic:
   {
     int k1 = invoke_dynamic_name_and_type_ref_index_at(index1);
@@ -1521,6 +1737,14 @@
     to_cp->method_handle_index_at_put(to_i, k1, k2);
   } break;
 
+  case JVM_CONSTANT_ConstantDynamic:
+  {
+    int k1 = from_cp->invoke_dynamic_bootstrap_specifier_index(from_i);
+    int k2 = from_cp->invoke_dynamic_name_and_type_ref_index_at(from_i);
+    k1 += operand_array_length(to_cp->operands());  // to_cp might already have operands
+    to_cp->constant_dynamic_at_put(to_i, k1, k2);
+  } break;
+
   case JVM_CONSTANT_InvokeDynamic:
   {
     int k1 = from_cp->invoke_dynamic_bootstrap_specifier_index(from_i);
@@ -1782,6 +2006,7 @@
     case JVM_CONSTANT_NameAndType:
       return 5;
 
+    case JVM_CONSTANT_ConstantDynamic:
     case JVM_CONSTANT_InvokeDynamic:
       // u1 tag, u2 bsm, u2 nt
       return 5;
@@ -1967,6 +2192,16 @@
         DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1));
         break;
       }
+      case JVM_CONSTANT_ConstantDynamic: {
+        *bytes = tag;
+        idx1 = extract_low_short_from_int(*int_at_addr(idx));
+        idx2 = extract_high_short_from_int(*int_at_addr(idx));
+        assert(idx2 == invoke_dynamic_name_and_type_ref_index_at(idx), "correct half of u4");
+        Bytes::put_Java_u2((address) (bytes+1), idx1);
+        Bytes::put_Java_u2((address) (bytes+3), idx2);
+        DBG(printf("JVM_CONSTANT_ConstantDynamic: %hd %hd", idx1, idx2));
+        break;
+      }
       case JVM_CONSTANT_InvokeDynamic: {
         *bytes = tag;
         idx1 = extract_low_short_from_int(*int_at_addr(idx));
@@ -2172,6 +2407,20 @@
     case JVM_CONSTANT_MethodTypeInError :
       st->print("signature_index=%d", method_type_index_at(index));
       break;
+    case JVM_CONSTANT_ConstantDynamic :
+      {
+        st->print("bootstrap_method_index=%d", invoke_dynamic_bootstrap_method_ref_index_at(index));
+        st->print(" type_index=%d", invoke_dynamic_name_and_type_ref_index_at(index));
+        int argc = invoke_dynamic_argument_count_at(index);
+        if (argc > 0) {
+          for (int arg_i = 0; arg_i < argc; arg_i++) {
+            int arg = invoke_dynamic_argument_index_at(index, arg_i);
+            st->print((arg_i == 0 ? " arguments={%d" : ", %d"), arg);
+          }
+          st->print("}");
+        }
+      }
+      break;
     case JVM_CONSTANT_InvokeDynamic :
       {
         st->print("bootstrap_method_index=%d", invoke_dynamic_bootstrap_method_ref_index_at(index));
--- a/src/hotspot/share/oops/constantPool.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/oops/constantPool.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -295,6 +295,11 @@
     *int_at_addr(which) = ref_index;
   }
 
+  void constant_dynamic_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) {
+    tag_at_put(which, JVM_CONSTANT_ConstantDynamic);
+    *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
+  }
+
   void invoke_dynamic_at_put(int which, int bootstrap_specifier_index, int name_and_type_index) {
     tag_at_put(which, JVM_CONSTANT_InvokeDynamic);
     *int_at_addr(which) = ((jint) name_and_type_index<<16) | bootstrap_specifier_index;
@@ -552,11 +557,13 @@
   }
 
   int invoke_dynamic_name_and_type_ref_index_at(int which) {
-    assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+    assert(tag_at(which).is_invoke_dynamic() ||
+           tag_at(which).is_constant_dynamic(), "Corrupted constant pool");
     return extract_high_short_from_int(*int_at_addr(which));
   }
   int invoke_dynamic_bootstrap_specifier_index(int which) {
-    assert(tag_at(which).value() == JVM_CONSTANT_InvokeDynamic, "Corrupted constant pool");
+    assert(tag_at(which).is_invoke_dynamic() ||
+           tag_at(which).is_constant_dynamic(), "Corrupted constant pool");
     return extract_low_short_from_int(*int_at_addr(which));
   }
   int invoke_dynamic_operand_base(int which) {
@@ -606,7 +613,7 @@
   }
 #endif //ASSERT
 
-  // layout of InvokeDynamic bootstrap method specifier (in second part of operands array):
+  // layout of InvokeDynamic and ConstantDynamic bootstrap method specifier (in second part of operands array):
   enum {
          _indy_bsm_offset  = 0,  // CONSTANT_MethodHandle bsm
          _indy_argc_offset = 1,  // u2 argc
@@ -652,14 +659,15 @@
   // Shrink the operands array to a smaller array with new_len length
   void shrink_operands(int new_len, TRAPS);
 
-
   int invoke_dynamic_bootstrap_method_ref_index_at(int which) {
-    assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+    assert(tag_at(which).is_invoke_dynamic() ||
+           tag_at(which).is_constant_dynamic(), "Corrupted constant pool");
     int op_base = invoke_dynamic_operand_base(which);
     return operands()->at(op_base + _indy_bsm_offset);
   }
   int invoke_dynamic_argument_count_at(int which) {
-    assert(tag_at(which).is_invoke_dynamic(), "Corrupted constant pool");
+    assert(tag_at(which).is_invoke_dynamic() ||
+           tag_at(which).is_constant_dynamic(), "Corrupted constant pool");
     int op_base = invoke_dynamic_operand_base(which);
     int argc = operands()->at(op_base + _indy_argc_offset);
     DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc;
@@ -729,20 +737,27 @@
   enum { _no_index_sentinel = -1, _possible_index_sentinel = -2 };
  public:
 
+  BasicType basic_type_for_constant_at(int which);
+
   // Resolve late bound constants.
   oop resolve_constant_at(int index, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
-    return resolve_constant_at_impl(h_this, index, _no_index_sentinel, THREAD);
+    return resolve_constant_at_impl(h_this, index, _no_index_sentinel, NULL, THREAD);
   }
 
   oop resolve_cached_constant_at(int cache_index, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
-    return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, THREAD);
+    return resolve_constant_at_impl(h_this, _no_index_sentinel, cache_index, NULL, THREAD);
   }
 
   oop resolve_possibly_cached_constant_at(int pool_index, TRAPS) {
     constantPoolHandle h_this(THREAD, this);
-    return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, THREAD);
+    return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, NULL, THREAD);
+  }
+
+  oop find_cached_constant_at(int pool_index, bool& found_it, TRAPS) {
+    constantPoolHandle h_this(THREAD, this);
+    return resolve_constant_at_impl(h_this, pool_index, _possible_index_sentinel, &found_it, THREAD);
   }
 
   oop resolve_bootstrap_specifier_at(int index, TRAPS) {
@@ -750,6 +765,15 @@
     return resolve_bootstrap_specifier_at_impl(h_this, index, THREAD);
   }
 
+  void copy_bootstrap_arguments_at(int index,
+                                   int start_arg, int end_arg,
+                                   objArrayHandle info, int pos,
+                                   bool must_resolve, Handle if_not_available, TRAPS) {
+    constantPoolHandle h_this(THREAD, this);
+    copy_bootstrap_arguments_at_impl(h_this, index, start_arg, end_arg,
+                                     info, pos, must_resolve, if_not_available, THREAD);
+  }
+
   // Klass name matches name at offset
   bool klass_name_at_matches(const InstanceKlass* k, int which);
 
@@ -831,6 +855,7 @@
 
   Symbol* impl_name_ref_at(int which, bool uncached);
   Symbol* impl_signature_ref_at(int which, bool uncached);
+
   int       impl_klass_ref_index_at(int which, bool uncached);
   int       impl_name_and_type_ref_index_at(int which, bool uncached);
   constantTag impl_tag_ref_at(int which, bool uncached);
@@ -860,8 +885,13 @@
   // Resolve string constants (to prevent allocation during compilation)
   static void resolve_string_constants_impl(const constantPoolHandle& this_cp, TRAPS);
 
-  static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index, TRAPS);
+  static oop resolve_constant_at_impl(const constantPoolHandle& this_cp, int index, int cache_index,
+                                      bool* status_return, TRAPS);
   static oop resolve_bootstrap_specifier_at_impl(const constantPoolHandle& this_cp, int index, TRAPS);
+  static void copy_bootstrap_arguments_at_impl(const constantPoolHandle& this_cp, int index,
+                                               int start_arg, int end_arg,
+                                               objArrayHandle info, int pos,
+                                               bool must_resolve, Handle if_not_available, TRAPS);
 
   // Exception handling
   static void throw_resolution_error(const constantPoolHandle& this_cp, int which, TRAPS);
--- a/src/hotspot/share/oops/generateOopMap.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/oops/generateOopMap.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -1871,13 +1871,15 @@
   ConstantPool* cp  = method()->constants();
   constantTag tag = cp->tag_at(ldc.pool_index()); // idx is index in resolved_references
   BasicType       bt  = ldc.result_type();
+#ifdef ASSERT
+  BasicType   tag_bt = tag.is_constant_dynamic() ? bt : tag.basic_type();
+  assert(bt == tag_bt, "same result");
+#endif
   CellTypeState   cts;
-  if (tag.basic_type() == T_OBJECT) {
+  if (is_reference_type(bt)) {  // could be T_ARRAY with condy
     assert(!tag.is_string_index() && !tag.is_klass_index(), "Unexpected index tag");
-    assert(bt == T_OBJECT, "Guard is incorrect");
     cts = CellTypeState::make_line_ref(bci);
   } else {
-    assert(bt != T_OBJECT, "Guard is incorrect");
     cts = valCTS;
   }
   ppush1(cts);
--- a/src/hotspot/share/opto/parse2.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/opto/parse2.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -1483,8 +1483,9 @@
     // If the constant is unresolved, run this BC once in the interpreter.
     {
       ciConstant constant = iter().get_constant();
-      if (constant.basic_type() == T_OBJECT &&
-          !constant.as_object()->is_loaded()) {
+      if (!constant.is_valid() ||
+          (constant.basic_type() == T_OBJECT &&
+           !constant.as_object()->is_loaded())) {
         int index = iter().get_constant_pool_index();
         constantTag tag = iter().get_constant_pool_tag(index);
         uncommon_trap(Deoptimization::make_trap_request
--- a/src/hotspot/share/prims/jvm.h	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/prims/jvm.h	Mon Sep 25 15:37:25 2017 +0100
@@ -1007,7 +1007,7 @@
     JVM_CONSTANT_NameAndType,
     JVM_CONSTANT_MethodHandle           = 15,  // JSR 292
     JVM_CONSTANT_MethodType             = 16,  // JSR 292
-    //JVM_CONSTANT_(unused)             = 17,  // JSR 292 early drafts only
+    JVM_CONSTANT_ConstantDynamic        = 17,  // JSR 292 early drafts only
     JVM_CONSTANT_InvokeDynamic          = 18,  // JSR 292
     JVM_CONSTANT_ExternalMax            = 18   // Last tag found in classfiles
 };
--- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -491,6 +491,7 @@
     } break;
 
     // this is an indirect CP entry so it needs special handling
+    case JVM_CONSTANT_ConstantDynamic:  // fall through
     case JVM_CONSTANT_InvokeDynamic:
     {
       // Index of the bootstrap specifier in the operands array
@@ -503,15 +504,18 @@
                                                     merge_cp_length_p, THREAD);
       if (new_bs_i != old_bs_i) {
         log_trace(redefine, class, constantpool)
-          ("InvokeDynamic entry@%d bootstrap_method_attr_index change: %d to %d",
+          ("Dynamic entry@%d bootstrap_method_attr_index change: %d to %d",
            *merge_cp_length_p, old_bs_i, new_bs_i);
       }
       if (new_ref_i != old_ref_i) {
         log_trace(redefine, class, constantpool)
-          ("InvokeDynamic entry@%d name_and_type_index change: %d to %d", *merge_cp_length_p, old_ref_i, new_ref_i);
+          ("Dynamic entry@%d name_and_type_index change: %d to %d", *merge_cp_length_p, old_ref_i, new_ref_i);
       }
 
-      (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i);
+      if (scratch_cp->tag_at(scratch_i).is_constant_dynamic())
+        (*merge_cp_p)->constant_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i);
+      else
+        (*merge_cp_p)->invoke_dynamic_at_put(*merge_cp_length_p, new_bs_i, new_ref_i);
       if (scratch_i != *merge_cp_length_p) {
         // The new entry in *merge_cp_p is at a different index than
         // the new entry in scratch_cp so we need to map the index values.
--- a/src/hotspot/share/prims/methodHandles.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/prims/methodHandles.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -1297,6 +1297,88 @@
 }
 JVM_END
 
+JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls,
+                                              jobject caller_jh, jintArray index_info_jh,
+                                              jint start, jint end,
+                                              jobjectArray buf_jh, jint pos,
+                                              jboolean resolve, jobject ifna_jh)) {
+  Klass* caller_k = java_lang_Class::as_Klass(JNIHandles::resolve(caller_jh));
+  if (caller_k == NULL || !caller_k->is_instance_klass()) {
+      THROW_MSG(vmSymbols::java_lang_InternalError(), "bad caller");
+  }
+  InstanceKlass* caller = InstanceKlass::cast(caller_k);
+  typeArrayOop index_info_oop = (typeArrayOop) JNIHandles::resolve(index_info_jh);
+  if (index_info_oop == NULL ||
+      index_info_oop->klass() != Universe::intArrayKlassObj() ||
+      typeArrayOop(index_info_oop)->length() < 2) {
+      THROW_MSG(vmSymbols::java_lang_InternalError(), "bad index info (0)");
+  }
+  typeArrayHandle index_info(THREAD, index_info_oop);
+  int bss_index_in_pool = index_info->int_at(1);
+  // While we are here, take a quick look at the index info:
+  if (bss_index_in_pool <= 0 ||
+      bss_index_in_pool >= caller->constants()->length() ||
+      index_info->int_at(0)
+      != caller->constants()->invoke_dynamic_argument_count_at(bss_index_in_pool)) {
+      THROW_MSG(vmSymbols::java_lang_InternalError(), "bad index info (1)");
+  }
+  objArrayHandle buf(THREAD, (objArrayOop) JNIHandles::resolve(buf_jh));
+  if (start < 0) {
+    for (int pseudo_index = -4; pseudo_index < 0; pseudo_index++) {
+      if (start == pseudo_index) {
+        if (start >= end || 0 > pos || pos >= buf->length())  break;
+        oop pseudo_arg = NULL;
+        switch (pseudo_index) {
+        case -4:  // bootstrap method
+          {
+            int bsm_index = caller->constants()->invoke_dynamic_bootstrap_method_ref_index_at(bss_index_in_pool);
+            pseudo_arg = caller->constants()->resolve_possibly_cached_constant_at(bsm_index, CHECK);
+            break;
+          }
+        case -3:  // name
+          {
+            Symbol* name = caller->constants()->name_ref_at(bss_index_in_pool);
+            Handle str = java_lang_String::create_from_symbol(name, CHECK);
+            pseudo_arg = str();
+            break;
+          }
+        case -2:  // type
+          {
+            Symbol* type = caller->constants()->signature_ref_at(bss_index_in_pool);
+            Handle th;
+            if (type->byte_at(0) == '(') {
+              th = SystemDictionary::find_method_handle_type(type, caller, CHECK);
+              
+            } else {
+              th = SystemDictionary::find_java_mirror_for_type(type, caller, SignatureStream::NCDFError, CHECK);
+            }
+            pseudo_arg = th();
+            break;
+          }
+        case -1:  // argument count
+          {
+            int argc = caller->constants()->invoke_dynamic_argument_count_at(bss_index_in_pool);
+            jvalue argc_value; argc_value.i = (jint)argc;
+            pseudo_arg = java_lang_boxing_object::create(T_INT, &argc_value, CHECK);
+            break;
+          }
+        }
+
+        // Store the pseudo-argument, and advance the pointers.
+        buf->obj_at_put(pos++, pseudo_arg);
+        ++start;
+      }
+    }
+    // When we are done with this there may be regular arguments to process too.
+  }
+  Handle ifna(THREAD, JNIHandles::resolve(ifna_jh));
+  caller->constants()->
+    copy_bootstrap_arguments_at(bss_index_in_pool,
+                                start, end, buf, pos,
+                                resolve, ifna, CHECK);
+}
+JVM_END
+
 // It is called by a Cleaner object which ensures that dropped CallSites properly
 // deallocate their dependency information.
 JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
@@ -1376,6 +1458,7 @@
   {CC "objectFieldOffset",         CC "(" MEM ")J",                          FN_PTR(MHN_objectFieldOffset)},
   {CC "setCallSiteTargetNormal",   CC "(" CS "" MH ")V",                     FN_PTR(MHN_setCallSiteTargetNormal)},
   {CC "setCallSiteTargetVolatile", CC "(" CS "" MH ")V",                     FN_PTR(MHN_setCallSiteTargetVolatile)},
+  {CC "copyOutBootstrapArguments", CC "(" CLS "[III[" OBJ "IZ" OBJ ")V",     FN_PTR(MHN_copyOutBootstrapArguments)},
   {CC "clearCallSiteContext",      CC "(" CTX ")V",                          FN_PTR(MHN_clearCallSiteContext)},
   {CC "staticFieldOffset",         CC "(" MEM ")J",                          FN_PTR(MHN_staticFieldOffset)},
   {CC "staticFieldBase",           CC "(" MEM ")" OBJ,                        FN_PTR(MHN_staticFieldBase)},
--- a/src/hotspot/share/runtime/globals.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/runtime/globals.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -3959,6 +3959,17 @@
   develop(bool, TraceInvokeDynamic, false,                                  \
           "trace internal invoke dynamic operations")                       \
                                                                             \
+  develop(bool, TraceConstantDynamic, false,                                \
+          "trace internal constant dynamic operations")                     \
+                                                                            \
+  diagnostic(int, UseBootstrapCallInfo, 1,                                  \
+          "0: when resolving InDy or ConDy, force all BSM arguments to be " \
+          "resolved before the bootstrap method is called; 1: when a BSM "  \
+          "that may accept a BootstrapCallInfo is detected, use that API "  \
+          "to pass BSM arguments, which allows the BSM to delay their "     \
+          "resolution; 2+: stress test the BCI API by calling more BSMs "   \
+          "via that API, instead of with the eagerly-resolved array.")      \
+                                                                            \
   diagnostic(bool, PauseAtStartup,      false,                              \
           "Causes the VM to pause at startup time and wait for the pause "  \
           "file to be removed (default: ./vm.paused.<pid>)")                \
--- a/src/hotspot/share/runtime/reflection.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/runtime/reflection.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -765,27 +765,22 @@
 static oop get_mirror_from_signature(const methodHandle& method,
                                      SignatureStream* ss,
                                      TRAPS) {
+  oop mirror_oop = ss->as_java_mirror(method->method_holder(), SignatureStream::NCDFError, CHECK_NULL);
 
-
-  if (T_OBJECT == ss->type() || T_ARRAY == ss->type()) {
-    Symbol* name = ss->as_symbol(CHECK_NULL);
-    oop loader = method->method_holder()->class_loader();
-    oop protection_domain = method->method_holder()->protection_domain();
-    const Klass* k = SystemDictionary::resolve_or_fail(name,
-                                                       Handle(THREAD, loader),
-                                                       Handle(THREAD, protection_domain),
-                                                       true,
-                                                       CHECK_NULL);
-    if (log_is_enabled(Debug, class, resolve)) {
+  // Special tracing logic for resolution of class names during reflection.
+  if (log_is_enabled(Debug, class, resolve)) {
+    Klass* k = java_lang_Class::as_Klass(mirror_oop);
+    if (k != NULL)  {
+      mirror_oop = NULL;
       trace_class_resolution(k);
+      mirror_oop = k->java_mirror();
     }
-    return k->java_mirror();
   }
 
   assert(ss->type() != T_VOID || ss->at_return_type(),
     "T_VOID should only appear as return type");
 
-  return java_lang_Class::primitive_mirror(ss->type());
+  return mirror_oop;
 }
 
 static objArrayHandle get_parameter_types(const methodHandle& method,
@@ -819,24 +814,17 @@
 }
 
 static Handle new_type(Symbol* signature, Klass* k, TRAPS) {
-  // Basic types
-  BasicType type = vmSymbols::signature_type(signature);
-  if (type != T_OBJECT) {
-    return Handle(THREAD, Universe::java_mirror(type));
+  Handle mirror = SystemDictionary::find_java_mirror_for_type(signature, k, SignatureStream::NCDFError, CHECK_(Handle()));
+
+  // Special tracing logic for resolution of class names during reflection.
+  if (log_is_enabled(Debug, class, resolve)) {
+    Klass* result = java_lang_Class::as_Klass(mirror());
+    if (result != NULL) {
+      trace_class_resolution(result);
+    }
   }
 
-  Klass* result =
-    SystemDictionary::resolve_or_fail(signature,
-                                      Handle(THREAD, k->class_loader()),
-                                      Handle(THREAD, k->protection_domain()),
-                                      true, CHECK_(Handle()));
-
-  if (log_is_enabled(Debug, class, resolve)) {
-    trace_class_resolution(result);
-  }
-
-  oop nt = result->java_mirror();
-  return Handle(THREAD, nt);
+  return mirror;
 }
 
 
--- a/src/hotspot/share/runtime/signature.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/runtime/signature.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -392,11 +392,19 @@
 
 oop SignatureStream::as_java_mirror(Handle class_loader, Handle protection_domain,
                                     FailureMode failure_mode, TRAPS) {
-  if (!is_object())
-    return Universe::java_mirror(type());
-  Klass* klass = as_klass(class_loader, protection_domain, failure_mode, CHECK_NULL);
-  if (klass == NULL)  return NULL;
-  return klass->java_mirror();
+  if (raw_length() == 1) {
+    // short-cut in a common case
+    return SystemDictionary::find_java_mirror_for_type((char) raw_byte_at(0));
+  }
+  TempNewSymbol signature = SymbolTable::new_symbol(_signature, _begin, _end, CHECK_NULL);
+  Klass* no_accessing_klass = NULL;
+  Handle mirror = SystemDictionary::find_java_mirror_for_type(signature,
+                                                              no_accessing_klass,
+                                                              class_loader,
+                                                              protection_domain,
+                                                              failure_mode,
+                                                              CHECK_NULL);
+  return mirror();
 }
 
 Symbol* SignatureStream::as_symbol_or_null() {
--- a/src/hotspot/share/runtime/signature.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/runtime/signature.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -406,9 +406,23 @@
   enum FailureMode { ReturnNull, CNFException, NCDFError };
   Klass* as_klass(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
   oop as_java_mirror(Handle class_loader, Handle protection_domain, FailureMode failure_mode, TRAPS);
+  oop as_java_mirror(Klass* accessing_klass, FailureMode failure_mode, TRAPS) {
+    Handle class_loader;
+    Handle protection_domain;
+    if (accessing_klass != NULL) {
+      class_loader      = Handle(THREAD, accessing_klass->class_loader());
+      protection_domain = Handle(THREAD, accessing_klass->protection_domain());
+    }
+    return as_java_mirror(class_loader, protection_domain, failure_mode, THREAD);
+  }
   const jbyte* raw_bytes()  { return _signature->bytes() + _begin; }
   int          raw_length() { return _end - _begin; }
 
+  jbyte raw_byte_at(int index) {
+    assert(index >= 0 && index < raw_length(), "index overflow");
+    return _signature->byte_at(_begin + index);
+  }
+
   // return same as_symbol except allocation of new symbols is avoided.
   Symbol* as_symbol_or_null();
 
--- a/src/hotspot/share/runtime/vmStructs.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -2320,6 +2320,7 @@
   declare_constant(JVM_CONSTANT_NameAndType)                              \
   declare_constant(JVM_CONSTANT_MethodHandle)                             \
   declare_constant(JVM_CONSTANT_MethodType)                               \
+  declare_constant(JVM_CONSTANT_ConstantDynamic)                          \
   declare_constant(JVM_CONSTANT_InvokeDynamic)                            \
   declare_constant(JVM_CONSTANT_ExternalMax)                              \
                                                                           \
--- a/src/hotspot/share/utilities/constantTag.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/utilities/constantTag.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -56,6 +56,10 @@
     case JVM_CONSTANT_MethodType :
     case JVM_CONSTANT_MethodTypeInError :
       return T_OBJECT;
+
+    case JVM_CONSTANT_ConstantDynamic :
+      assert(false, "ConstantDynamic has no fixed basic type");
+
     default:
       ShouldNotReachHere();
       return T_ILLEGAL;
@@ -123,6 +127,8 @@
       return "MethodType";
     case JVM_CONSTANT_MethodTypeInError :
       return "MethodType Error";
+    case JVM_CONSTANT_ConstantDynamic :
+      return "ConstantDynamic";
     case JVM_CONSTANT_InvokeDynamic :
       return "InvokeDynamic";
     case JVM_CONSTANT_Utf8 :
--- a/src/hotspot/share/utilities/constantTag.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/utilities/constantTag.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -90,11 +90,12 @@
 
   bool is_method_type() const              { return _tag == JVM_CONSTANT_MethodType; }
   bool is_method_handle() const            { return _tag == JVM_CONSTANT_MethodHandle; }
+  bool is_constant_dynamic() const         { return _tag == JVM_CONSTANT_ConstantDynamic; }
   bool is_invoke_dynamic() const           { return _tag == JVM_CONSTANT_InvokeDynamic; }
 
   bool is_loadable_constant() const {
     return ((_tag >= JVM_CONSTANT_Integer && _tag <= JVM_CONSTANT_String) ||
-            is_method_type() || is_method_handle() ||
+            is_method_type() || is_method_handle() || is_constant_dynamic() ||
             is_unresolved_klass());
   }
 
@@ -108,6 +109,20 @@
     _tag = tag;
   }
 
+  static constantTag ofBasicType(BasicType bt) {
+    if (is_subword_type(bt))  bt = T_INT;
+    switch (bt) {
+      case T_OBJECT: return constantTag(JVM_CONSTANT_String);
+      case T_INT:    return constantTag(JVM_CONSTANT_Integer);
+      case T_LONG:   return constantTag(JVM_CONSTANT_Long);
+      case T_FLOAT:  return constantTag(JVM_CONSTANT_Float);
+      case T_DOUBLE: return constantTag(JVM_CONSTANT_Double);
+      default:       break;
+    }
+    assert(false, "bad basic type for tag");
+    return constantTag();
+  }
+
   jbyte value() const                { return _tag; }
   jbyte error_value() const;
   jbyte non_error_value() const;
--- a/src/hotspot/share/utilities/exceptions.cpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/utilities/exceptions.cpp	Mon Sep 25 15:37:25 2017 +0100
@@ -402,6 +402,37 @@
                                    h_prot, to_utf8_safe);
 }
 
+// invokedynamic uses wrap_dynamic_exception for:
+//    - bootstrap method resolution
+//    - post call to MethodHandleNatives::linkCallSite
+// constantdynamic uses wrap_dynamic_exception for:
+//    - bootstrap method resolution
+//    - post call to MethodHandleNatives::linkConstantDynamic
+void Exceptions::wrap_dynamic_exception(Thread* THREAD) {
+  if (THREAD->has_pending_exception()) {
+    oop exception = THREAD->pending_exception();
+    // See the "Linking Exceptions" section for the invokedynamic instruction
+    // in JVMS 6.5.
+    if (exception->is_a(SystemDictionary::Error_klass())) {
+      // Pass through an Error, including BootstrapMethodError, any other form
+      // of linkage error, or say ThreadDeath/OutOfMemoryError
+      if (TraceMethodHandles) {
+        tty->print_cr("[constant/invoke]dynamic passes through an Error for " INTPTR_FORMAT, p2i((void *)exception));
+        exception->print();
+      }
+      return;
+    }
+
+    // Otherwise wrap the exception in a BootstrapMethodError
+    if (TraceMethodHandles) {
+      tty->print_cr("[constant/invoke]dynamic throws BSME for " INTPTR_FORMAT, p2i((void *)exception));
+      exception->print();
+    }
+    Handle nested_exception(THREAD, exception);
+    THREAD->clear_pending_exception();
+    THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
+  }
+}
 
 // Exception counting for hs_err file
 volatile int Exceptions::_stack_overflow_errors = 0;
--- a/src/hotspot/share/utilities/exceptions.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/utilities/exceptions.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -166,6 +166,8 @@
 
   static void throw_stack_overflow_exception(Thread* thread, const char* file, int line, const methodHandle& method);
 
+  static void wrap_dynamic_exception(Thread* thread);
+
   // Exception counting for error files of interesting exceptions that may have
   // caused a problem for the jvm
   static volatile int _stack_overflow_errors;
--- a/src/hotspot/share/utilities/globalDefinitions.hpp	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/hotspot/share/utilities/globalDefinitions.hpp	Mon Sep 25 15:37:25 2017 +0100
@@ -596,6 +596,10 @@
   return (t == T_BYTE || t == T_SHORT);
 }
 
+inline bool is_reference_type(BasicType t) {
+  return (t == T_OBJECT || t == T_ARRAY);
+}
+
 // Convert a char from a classfile signature to a BasicType
 inline BasicType char2type(char c) {
   switch( c ) {
--- a/src/java.base/share/classes/java/lang/invoke/CallSite.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/CallSite.java	Mon Sep 25 15:37:25 2017 +0100
@@ -302,65 +302,10 @@
                              Object info,
                              // Caller information:
                              Class<?> callerClass) {
-        MethodHandles.Lookup caller = IMPL_LOOKUP.in(callerClass);
         CallSite site;
         try {
-            Object binding;
-            info = maybeReBox(info);
-            if (info == null) {
-                binding = bootstrapMethod.invoke(caller, name, type);
-            } else if (!info.getClass().isArray()) {
-                binding = bootstrapMethod.invoke(caller, name, type, info);
-            } else {
-                Object[] argv = (Object[]) info;
-                maybeReBoxElements(argv);
-                switch (argv.length) {
-                    case 0:
-                        binding = bootstrapMethod.invoke(caller, name, type);
-                        break;
-                    case 1:
-                        binding = bootstrapMethod.invoke(caller, name, type,
-                                                         argv[0]);
-                        break;
-                    case 2:
-                        binding = bootstrapMethod.invoke(caller, name, type,
-                                                         argv[0], argv[1]);
-                        break;
-                    case 3:
-                        binding = bootstrapMethod.invoke(caller, name, type,
-                                                         argv[0], argv[1], argv[2]);
-                        break;
-                    case 4:
-                        binding = bootstrapMethod.invoke(caller, name, type,
-                                                         argv[0], argv[1], argv[2], argv[3]);
-                        break;
-                    case 5:
-                        binding = bootstrapMethod.invoke(caller, name, type,
-                                                         argv[0], argv[1], argv[2], argv[3], argv[4]);
-                        break;
-                    case 6:
-                        binding = bootstrapMethod.invoke(caller, name, type,
-                                                         argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
-                        break;
-                    default:
-                        final int NON_SPREAD_ARG_COUNT = 3;  // (caller, name, type)
-                        final int MAX_SAFE_SIZE = MethodType.MAX_MH_ARITY / 2 - NON_SPREAD_ARG_COUNT;
-                        if (argv.length >= MAX_SAFE_SIZE) {
-                            // to be on the safe side, use invokeWithArguments which handles jumbo lists
-                            Object[] newargv = new Object[NON_SPREAD_ARG_COUNT + argv.length];
-                            newargv[0] = caller;
-                            newargv[1] = name;
-                            newargv[2] = type;
-                            System.arraycopy(argv, 0, newargv, NON_SPREAD_ARG_COUNT, argv.length);
-                            binding = bootstrapMethod.invokeWithArguments(newargv);
-                        } else {
-                            MethodType invocationType = MethodType.genericMethodType(NON_SPREAD_ARG_COUNT + argv.length);
-                            MethodHandle typedBSM = bootstrapMethod.asType(invocationType);
-                            MethodHandle spreader = invocationType.invokers().spreadInvoker(NON_SPREAD_ARG_COUNT);
-                            binding = spreader.invokeExact(typedBSM, (Object) caller, (Object) name, (Object) type, argv);
-                        }
-                }
-            }
+            Object binding = BootstrapMethodInvoker.invoke(
+                    CallSite.class, bootstrapMethod, name, type, info, callerClass);
             if (binding instanceof CallSite) {
                 site = (CallSite) binding;
             } else {
@@ -369,7 +314,7 @@
                 // Throws a runtime exception defining the cause that is then
                 // in the "catch (Throwable ex)" a few lines below wrapped in
                 // BootstrapMethodError
-                throw new ClassCastException("bootstrap method failed to produce a CallSite");
+                throw new ClassCastException("CallSite bootstrap method failed to produce an instance of CallSite");
             }
             if (!site.getTarget().type().equals(type)) {
                 // See the "Linking Exceptions" section for the invokedynamic
@@ -388,22 +333,8 @@
             throw e;
         } catch (Throwable ex) {
             // Wrap anything else in BootstrapMethodError
-            throw new BootstrapMethodError("call site initialization exception", ex);
+            throw new BootstrapMethodError("CallSite bootstrap method initialization exception", ex);
         }
         return site;
     }
-
-    private static Object maybeReBox(Object x) {
-        if (x instanceof Integer) {
-            int xi = (int) x;
-            if (xi == (byte) xi)
-                x = xi;  // must rebox; see JLS 5.1.7
-        }
-        return x;
-    }
-    private static void maybeReBoxElements(Object[] xa) {
-        for (int i = 0; i < xa.length; i++) {
-            xa[i] = maybeReBox(xa[i]);
-        }
-    }
 }
--- a/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaMetafactory.java	Mon Sep 25 15:37:25 2017 +0100
@@ -313,6 +313,73 @@
     }
 
     /**
+     * Special-case case version of {@link LambdaMetafactory#metafactory(MethodHandles.Lookup, String, Class, MethodType, MethodHandle, MethodType)}
+     * that is restricted to non-capturing lambdas.  Rather than returning a
+     * {@link CallSite}, the function object itself is returned.
+     * Typically used as a <em>bootstrap method</em> for {@code constantdynamic}
+     * constants, to support the <em>lambda expression</em> and <em>method
+     * reference expression</em> features of the Java Programming Language.
+     *
+     * <p>The function object returned is an instance of a class which
+     * implements the interface named by {@code functionalInterface},
+     * declares a method with the name given by {@code invokedName} and the
+     * signature given by {@code samMethodType}.  It may also override additional
+     * methods from {@code Object}.
+     *
+     * @param caller Represents a lookup context with the accessibility
+     *               privileges of the caller.  When used with {@code invokedynamic},
+     *               this is stacked automatically by the VM.
+     * @param invokedName The name of the method to implement.  When used with
+     *                    {@code constantdynamic}, this is provided by the
+     *                    {@code NameAndType} of the {@code InvokeDynamic}
+     *                    structure and is stacked automatically by the VM.
+     * @param functionalInterface The functional interface the function object
+     *                            should implement.  When used with {@code invokedynamic},
+     *                            this is provided by the {@code NameAndType} of
+     *                            the {@code InvokeDynamic} structure and is
+     *                            stacked automatically by the VM. In the event
+     *                            that the implementation method is an instance
+     *                            method and this signature has any parameters,
+     *                            the first parameter in the invocation signature
+     *                            must correspond to the receiver.
+     * @param samMethodType Signature and return type of method to be implemented
+     *                      by the function object.
+     * @param implMethod A direct method handle describing the implementation
+     *                   method which should be called (with suitable adaptation
+     *                   of argument types, return types, and with captured
+     *                   arguments prepended to the invocation arguments) at
+     *                   invocation time.
+     * @param instantiatedMethodType The signature and return type that should
+     *                               be enforced dynamically at invocation time.
+     *                               This may be the same as {@code samMethodType},
+     *                               or may be a specialization of it.
+     * @return a CallSite whose target can be used to perform capture, generating
+     *         instances of the interface named by {@code invokedType}
+     * @throws LambdaConversionException If any of the linkage invariants
+     *                                   described {@link LambdaMetafactory above}
+     *                                   are violated
+     */
+    public static Object metafactory(MethodHandles.Lookup caller,
+                                     String invokedName,
+                                     Class<?> functionalInterface,
+                                     MethodType samMethodType,
+                                     MethodHandle implMethod,
+                                     MethodType instantiatedMethodType)
+            throws LambdaConversionException {
+        try {
+            return metafactory(caller, invokedName, MethodType.methodType(functionalInterface),
+                               samMethodType, implMethod, instantiatedMethodType).getTarget().invoke();
+        }
+        catch (LambdaConversionException | LinkageError e) {
+            throw e;
+        }
+        catch (Throwable e) {
+            throw new LambdaConversionException("Exception invoking lambda metafactory", e);
+        }
+    }
+
+
+    /**
      * Facilitates the creation of simple "function objects" that implement one
      * or more interfaces by delegation to a provided {@link MethodHandle},
      * after appropriate type adaptation and partial evaluation of arguments.
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java	Mon Sep 25 15:37:25 2017 +0100
@@ -65,6 +65,12 @@
     static native void setCallSiteTargetNormal(CallSite site, MethodHandle target);
     static native void setCallSiteTargetVolatile(CallSite site, MethodHandle target);
 
+    static native void copyOutBootstrapArguments(Class<?> caller, int[] indexInfo,
+                                                 int start, int end,
+                                                 Object[] buf, int pos,
+                                                 boolean resolve,
+                                                 Object ifNotAvailable);
+
     /** Represents a context to track nmethod dependencies on CallSite instance target. */
     static class CallSiteContext implements Runnable {
         //@Injected JVM_nmethodBucket* vmdependencies;
@@ -228,6 +234,7 @@
      * The JVM is linking an invokedynamic instruction.  Create a reified call site for it.
      */
     static MemberName linkCallSite(Object callerObj,
+                                   int indexInCP,
                                    Object bootstrapMethodObj,
                                    Object nameObj, Object typeObj,
                                    Object staticArguments,
@@ -268,9 +275,7 @@
                                           Object[] appendixResult) {
         Object bsmReference = bootstrapMethod.internalMemberName();
         if (bsmReference == null)  bsmReference = bootstrapMethod;
-        Object staticArglist = (staticArguments instanceof Object[] ?
-                                java.util.Arrays.asList((Object[]) staticArguments) :
-                                staticArguments);
+        String staticArglist = staticArglistForTrace(staticArguments);
         System.out.println("linkCallSite "+caller.getName()+" "+
                            bsmReference+" "+
                            name+type+"/"+staticArglist);
@@ -280,11 +285,84 @@
             System.out.println("linkCallSite => "+res+" + "+appendixResult[0]);
             return res;
         } catch (Throwable ex) {
+            ex.printStackTrace(); // print now in case exception is swallowed
             System.out.println("linkCallSite => throw "+ex);
             throw ex;
         }
     }
 
+    // this implements the upcall from the JVM, MethodHandleNatives.linkConstantDynamic:
+    static Object linkConstantDynamic(Object callerObj,
+                                      int indexInCP,
+                                      Object bootstrapMethodObj,
+                                      Object nameObj, Object typeObj,
+                                      Object staticArguments) {
+        MethodHandle bootstrapMethod = (MethodHandle)bootstrapMethodObj;
+        Class<?> caller = (Class<?>)callerObj;
+        String name = nameObj.toString().intern();
+        Class<?> type = (Class<?>)typeObj;
+        if (!TRACE_METHOD_LINKAGE)
+            return linkConstantDynamicImpl(caller, bootstrapMethod, name, type, staticArguments);
+        return linkConstantDynamicTracing(caller, bootstrapMethod, name, type, staticArguments);
+    }
+
+    static Object linkConstantDynamicImpl(Class<?> caller,
+                                          MethodHandle bootstrapMethod,
+                                          String name, Class<?> type,
+                                          Object staticArguments) {
+        return ConstantDynamic.makeConstant(bootstrapMethod, name, type, staticArguments, caller);
+    }
+
+    private static String staticArglistForTrace(Object staticArguments) {
+        if (staticArguments instanceof Object[])
+            return "BSA="+java.util.Arrays.asList((Object[]) staticArguments);
+        if (staticArguments instanceof int[])
+            return "BSA@"+java.util.Arrays.toString((int[]) staticArguments);
+        if (staticArguments == null)
+            return "BSA0=null";
+        return "BSA1="+staticArguments;
+    }
+
+    // Tracing logic:
+    static Object linkConstantDynamicTracing(Class<?> caller,
+                                             MethodHandle bootstrapMethod,
+                                             String name, Class<?> type,
+                                             Object staticArguments) {
+        Object bsmReference = bootstrapMethod.internalMemberName();
+        if (bsmReference == null)  bsmReference = bootstrapMethod;
+        String staticArglist = staticArglistForTrace(staticArguments);
+        System.out.println("linkConstantDynamic "+caller.getName()+" "+
+                           bsmReference+" "+
+                           name+type+"/"+staticArglist);
+        try {
+            Object res = linkConstantDynamicImpl(caller, bootstrapMethod, name, type, staticArguments);
+            System.out.println("linkConstantDynamicImpl => "+res);
+            return res;
+        } catch (Throwable ex) {
+            ex.printStackTrace(); // print now in case exception is swallowed
+            System.out.println("linkConstantDynamic => throw "+ex);
+            throw ex;
+        }
+    }
+
+    /** The JVM is requesting pull-mode bootstrap when it provides
+     *  a tuple of the form int[]{ argc, vmindex }.
+     *  The BSM is expected to call back to the JVM using the caller
+     *  class and vmindex to resolve the static arguments.
+     */
+    static boolean staticArgumentsPulled(Object staticArguments) {
+        return staticArguments instanceof int[];
+    }
+
+    /** A BSM runs in pull-mode if and only if its sole arguments
+     * are (Lookup, BootstrapCallInfo), or can be converted pairwise
+     * to those types, and it is not of variable arity.
+     * Excluding error cases, we can just test that the arity is a constant 2.
+     */
+    static boolean isPullModeBSM(MethodHandle bsm) {
+        return bsm.type().parameterCount() == 2 && !bsm.isVarargsCollector();
+    }
+
     /**
      * The JVM wants a pointer to a MethodType.  Oblige it by finding or creating one.
      */
@@ -506,34 +584,43 @@
             Lookup lookup = IMPL_LOOKUP.in(callerClass);
             assert(refKindIsValid(refKind));
             return lookup.linkMethodHandleConstant((byte) refKind, defc, name, type);
-        } catch (IllegalAccessException ex) {
+        } catch (ReflectiveOperationException ex) {
+            throw mapLookupExceptionToError(ex);
+        }
+    }
+
+    /**
+     * Map a reflective exception to a linkage error.
+     */
+    static LinkageError mapLookupExceptionToError(ReflectiveOperationException ex) {
+        LinkageError err;
+        if (ex instanceof IllegalAccessException) {
             Throwable cause = ex.getCause();
             if (cause instanceof AbstractMethodError) {
-                throw (AbstractMethodError) cause;
+                return (AbstractMethodError) cause;
             } else {
-                Error err = new IllegalAccessError(ex.getMessage());
-                throw initCauseFrom(err, ex);
+                err = new IllegalAccessError(ex.getMessage());
             }
-        } catch (NoSuchMethodException ex) {
-            Error err = new NoSuchMethodError(ex.getMessage());
-            throw initCauseFrom(err, ex);
-        } catch (NoSuchFieldException ex) {
-            Error err = new NoSuchFieldError(ex.getMessage());
-            throw initCauseFrom(err, ex);
-        } catch (ReflectiveOperationException ex) {
-            Error err = new IncompatibleClassChangeError();
-            throw initCauseFrom(err, ex);
+        } else if (ex instanceof NoSuchMethodException) {
+            err = new NoSuchMethodError(ex.getMessage());
+        } else if (ex instanceof NoSuchFieldException) {
+            err = new NoSuchFieldError(ex.getMessage());
+        } else {
+            err = new IncompatibleClassChangeError();
         }
+        return initCauseFrom(err, ex);
     }
 
     /**
      * Use best possible cause for err.initCause(), substituting the
      * cause for err itself if the cause has the same (or better) type.
      */
-    private static Error initCauseFrom(Error err, Exception ex) {
+    static <E extends Error> E initCauseFrom(E err, Exception ex) {
         Throwable th = ex.getCause();
-        if (err.getClass().isInstance(th))
-           return (Error) th;
+        @SuppressWarnings("unchecked")
+        final Class<E> Eclass = (Class<E>) err.getClass();
+        if (Eclass.isInstance(th))
+           return Eclass.cast(th);
         err.initCause(th == null ? ex : th);
         return err;
     }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java	Mon Sep 25 15:37:25 2017 +0100
@@ -142,4 +142,13 @@
         if (obj != null || obj2 != null)  message = message + ": " + obj + ", " + obj2;
         return message;
     }
+    /*non-public*/ static void rangeCheck2(int start, int end, int size) {
+        if (0 > start || start > end || end > size)
+            throw new IndexOutOfBoundsException(start+".."+end);
+    }
+    /*non-public*/ static int rangeCheck1(int index, int size) {
+        if (0 > index || index >= size)
+            throw new IndexOutOfBoundsException(index);
+        return index;
+    }
 }
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Mon Sep 25 15:37:25 2017 +0100
@@ -101,8 +101,10 @@
      * <p>
      * For any given caller class {@code C}, the lookup object returned by this call
      * has equivalent capabilities to any lookup object
-     * supplied by the JVM to the bootstrap method of an
-     * <a href="package-summary.html#indyinsn">invokedynamic instruction</a>
+     * supplied by the JVM to the
+     * <a href="package-summary.html#bsm">bootstrap method</a> of an
+     * <a href="package-summary.html#indyinsn">invokedynamic instruction</a> or
+     * <a href="package-summary.html#condycon">dynamic constant</a>
      * executing in the same caller class {@code C}.
      * @return a lookup object for the caller of this method, with private access
      */
--- a/src/java.base/share/classes/java/lang/invoke/package-info.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/java/lang/invoke/package-info.java	Mon Sep 25 15:37:25 2017 +0100
@@ -50,7 +50,11 @@
  * current version of that specification.
  *
  * Each occurrence of an {@code invokedynamic} instruction is called a <em>dynamic call site</em>.
+ * Each occurrence of an {@code CONSTANT_ConstantDynamic} constant pool entry is called a <em>dynamic constant</em>.
+ *
  * <h2><a id="indyinsn"></a>{@code invokedynamic} instructions</h2>
+ * Bytecode may contain <em>dynamic call sites</em> equipped with
+ * bootstrap methods which perform their resolution.
  * A dynamic call site is originally in an unlinked state.  In this state, there is
  * no target method for the call site to invoke.
  * <p>
@@ -63,25 +67,72 @@
  * <p>
  * Each {@code invokedynamic} instruction statically specifies its own
  * bootstrap method as a constant pool reference.
- * The constant pool reference also specifies the call site's name and type descriptor,
- * just like {@code invokevirtual} and the other invoke instructions.
+ * The constant pool reference also specifies the call site's name and method type descriptor,
+ * just like {@code invokestatic} and the other invoke instructions.
+ *
+ * <h2><a id="condycon"></a>constants with tag {@code CONSTANT_ConstantDynamic}</h2>
+ * The constant pool may contain constants tagged {@code CONSTANT_ConstantDynamic},
+ * equipped with bootstrap methods which perform their resolution.
+ * Such a <em>dynamic constant</em> is originally in an unresolved state.
+ * Before the JVM can evaluate a dynamic constant, it must first be <em>resolved</em>.
+ * Dynamic constant resolution is accomplished by calling a <em>bootstrap method</em>
+ * which is given the static information content of the constant,
+ * and which must produce a value of the constant's statically declared type.
  * <p>
- * Linking starts with resolving the constant pool entry for the
- * bootstrap method, and resolving a {@link java.lang.invoke.MethodType MethodType} object for
- * the type descriptor of the dynamic call site.
+ * Each {@code CONSTANT_ConstantDynamic} constant statically specifies its own
+ * bootstrap method as a constant pool reference.
+ * The constant pool reference also specifies the constant's name and field type descriptor,
+ * just like {@code getstatic} and the other field reference instructions.
+ * (Roughly speaking, a dynamic constant is to a dynamic call descriptor
+ * as a {@code CONSTANT_Fieldref} is to a {@code CONSTANT_Methodref}.)
+ *
+ * <h2><a id="bsm"></a>execution of bootstrap methods</h2>
+ * Linking a dynamic call site or dynamic constant
+ * starts with resolving constants from the constant pool for the
+ * following items:
+ * <ul>
+ * <li>the bootstrap method, either a {@code CONSTANT_MethodHandle}
+ * or a {@code CONSTANT_ConstantDynamic} entry</li>
+ * <li>if linking a dynamic call site, the {@code MethodType} derived from
+ * type component of the {@code CONSTANT_NameAndType} descriptor of the call</li>
+ * <li>if linking a dynamic constant, the {@code Class} derived from
+ * type component of the {@code CONSTANT_NameAndType} descriptor of the constant</li>
+ * </ul>
  * This resolution process may trigger class loading.
  * It may therefore throw an error if a class fails to load.
  * This error becomes the abnormal termination of the dynamic
- * call site execution.
+ * call site execution or dynamic constant evaluation.
  * Linkage does not trigger class initialization.
+ * Static arguments, if any, are resolved in the following phase.
+ * (Note that static arguments can themselves be dynamic constants.)
  * <p>
- * The bootstrap method is invoked on at least three values:
+ * The arity of the bootstrap method determines its invocation for linkage.
+ * If the bootstrap method accepts at least three parameters, or if it
+ * is a variable-arity method handle, the linkage information is <em>pushed</em>
+ * into the bootstrap method, by invoking it on these values:
+ * <ul>
+ * <li>a {@code MethodHandles.Lookup}, which is a lookup object on the <em>caller class</em>
+ * in which dynamic call site or constant occurs </li>
+ * <li>a {@code String}, the method or constant name mentioned in the call site or constant </li>
+ * <li>a {@code MethodType}, the resolved type descriptor of the call site, if it is a dynamic call site </li>
+ * <li>a {@code Class}, the resolved type descriptor of the constant, if it is a dynamic constant </li>
+ * <li>optionally, any number of additional static arguments taken from the constant pool </li>
+ * </ul>
+ * In this case the static arguments are resolved before the bootstrap method
+ * is invoked.  If this resolution causes exceptions they are processed without
+ * calling the bootstrap method.
+ * <p>
+ * If the bootstrap method accepts two parameters, and it is <em>not</em>
+ * a variable-arity method handle, then the linkage information is presented
+ * to the bootstrap method by a API which allows it to <em>pull</em> the static arguments.
+ * This allows the bootstrap logic the ability to order the resolution of constants and catch
+ * linkage exceptions.  For this mode of linkage, the bootstrap method is
+ * is invoked on just two values:
  * <ul>
  * <li>a {@code MethodHandles.Lookup}, a lookup object on the <em>caller class</em>
- *     in which dynamic call site occurs </li>
- * <li>a {@code String}, the method name mentioned in the call site </li>
- * <li>a {@code MethodType}, the resolved type descriptor of the call </li>
- * <li>optionally, any number of additional static arguments taken from the constant pool </li>
+ * (as in the "push" mode) </li>
+ * <li>a {@link java.lang.invoke.BootstrapCallInfo BootstrapCallInfo} object
+ * describing the linkage parameters of the dynamic call site or constant </li>
  * </ul>
  * <p>
  * In all cases, bootstrap method invocation is as if by
@@ -101,16 +152,25 @@
  * On success the call site then becomes permanently linked to the dynamic call
  * site.
  * <p>
- * If an exception, {@code E} say, occurs when linking the call site then the
+ * For a {@code ConstantDynamic} constant, the result returned from the
+ * bootstrap method must be convertible (by the same conversions as
+ * {@linkplain java.lang.invoke.MethodHandle#asType a method handle transformed by {@code asType}})
+ * to the statically declared type of the {@code ConstantDynamic} constant.
+ * On success the constant then becomes permanently linked to the
+ * converted result of the bootstrap method.
+ * <p>
+ * If an exception, {@code E} say, occurs when linking the call site or constant then the
  * linkage fails and terminates abnormally. {@code E} is rethrown if the type of
  * {@code E} is {@code Error} or a subclass, otherwise a
  * {@code BootstrapMethodError} that wraps {@code E} is thrown.
  * If this happens, the same {@code Error} or subclass will the thrown for all
- * subsequent attempts to execute the dynamic call site.
+ * subsequent attempts to execute the dynamic call site or load the dynamic constant.
  * <h2>timing of linkage</h2>
  * A dynamic call site is linked just before its first execution.
+ * A dynamic constant is linked just before the first time it is used
+ * (by pushing on the stack or linking it as a bootstrap method parameter).
  * The bootstrap method call implementing the linkage occurs within
- * a thread that is attempting a first execution.
+ * a thread that is attempting a first execution or first use.
  * <p>
  * If there are several such threads, the bootstrap method may be
  * invoked in several threads concurrently.
@@ -128,9 +188,10 @@
  * the instructions.
  * <p>
  * If several threads simultaneously execute a bootstrap method for a single dynamic
- * call site, the JVM must choose one {@code CallSite} object and install it visibly to
+ * call site or constant, the JVM must choose one bootstrap method result and install it visibly to
  * all threads.  Any other bootstrap method calls are allowed to complete, but their
- * results are ignored, and their dynamic call site invocations proceed with the originally
+ * results are ignored, and their dynamic call site invocations
+ * or constant loads proceed with the originally
  * chosen target object.
 
  * <p style="font-size:smaller;">
@@ -186,6 +247,7 @@
  *     <li><code>CallSite bootstrap(Lookup caller, String name, MethodType type, Object... args)</code>
  *     <li><code>CallSite bootstrap(Object... args)</code>
  *     <li><code>CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)</code>
+ *     <li><code>CallSite bootstrap(Lookup caller, BootstrapCallInfo bsci)</code>
  *     </ul></td></tr>
  * <tr><th scope="row" style="font-weight:normal; vertical-align:top">0</th><td>
  *     <ul style="list-style:none; padding-left: 0; margin:0">
@@ -203,11 +265,21 @@
  * </tbody>
  * </table>
  * The last example assumes that the extra arguments are of type
- * {@code String} and {@code Integer} (or {@code int}), respectively.
+ * {@code CONSTANT_String} and {@code CONSTANT_Integer}, respectively.
  * The second-to-last example assumes that all extra arguments are of type
- * {@code String}.
+ * {@code CONSTANT_String}.
  * The other examples work with all types of extra arguments.
  * <p>
+ * The fourth example (which is the only example that does
+ * <em>not</em> use variable arity <em>and</em> takes two arguments)
+ * is the normal signature under which a "pull" mode bootstrap method
+ * is invoked.  For such a bootstrap method, the two parameters may
+ * also be {@code Object}, since that is a supertype of {@code Lookup}
+ * and {@link java.lang.invoke.BootstrapCallInfo BootstrapCallInfo}.
+ * See {@linkplain java.lang.invoke.BootstrapCallInfo BootstrapCallInfo}
+ * the documentation for that interface} for further notes about the
+ * relation between the two modes of bootstrap method invocation.
+ * <p>
  * As noted above, the actual method type of the bootstrap method can vary.
  * For example, the fourth argument could be {@code MethodHandle},
  * if that is the type of the corresponding constant in
@@ -218,13 +290,28 @@
  * (If a string constant were passed instead, by badly generated code, that cast would then fail,
  * resulting in a {@code BootstrapMethodError}.)
  * <p>
- * Note that, as a consequence of the above rules, the bootstrap method may accept a primitive
- * argument, if it can be represented by a constant pool entry.
+ * Since dynamic constants can be provided as static arguments to bootstrap
+ * methods, there are no limitations on the types of bootstrap arguments.
  * However, arguments of type {@code boolean}, {@code byte}, {@code short}, or {@code char}
- * cannot be created for bootstrap methods, since such constants cannot be directly
- * represented in the constant pool, and the invocation of the bootstrap method will
+ * cannot be <em>directly</em> supplied by {@code CONSTANT_Integer}
+ * constant pool entries, since the {@code asType} conversions do
  * not perform the necessary narrowing primitive conversions.
  * <p>
+ * In the above examples, the return type is always {@code CallSite},
+ * but that is not a necessary feature of bootstrap methods.
+ * In the case of a dynamic call site, the only requirement is that
+ * the value returned by the bootstrap method must be convertible
+ * (using the {@code asType} conversions) to {@code CallSite}, which
+ * means the bootstrap method return type might be {@code Object} or
+ * {@code ConstantCallSite}
+ * In the case of a dynamic constant, the result of the bootstrap
+ * method must be convertible to the type of the constant, as
+ * represented by its field type descriptor.  For example, if the
+ * dynamic constant has a field type descriptor of {@code "C"}
+ * ({@code char}) then the bootstrap method return type could be
+ * {@code Object}, {@code Character}, or {@code char}, but not
+ * {@code int} or {@code Integer}.
+ * <p>
  * Extra bootstrap method arguments are intended to allow language implementors
  * to safely and compactly encode metadata.
  * In principle, the name and extra arguments are redundant,
--- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java	Mon Sep 25 15:37:25 2017 +0100
@@ -215,6 +215,10 @@
             case ClassWriter.FLOAT:
             case ClassWriter.NAME_TYPE:
             case ClassWriter.INDY:
+            // @@@ ClassWriter.CONDY
+            // Enables MethodHandles.lookup().defineClass to function correctly
+            // when it reads the class name
+            case 17:
                 size = 5;
                 break;
             case ClassWriter.LONG:
--- a/src/java.base/share/native/libjli/java.c	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/java.base/share/native/libjli/java.c	Mon Sep 25 15:37:25 2017 +0100
@@ -1517,7 +1517,6 @@
             }
             str = (*env)->CallStaticObjectMethod(env, cls,
                     makePlatformStringMID, USE_STDERR, ary);
-            CHECK_EXCEPTION_RETURN_VALUE(0);
             (*env)->DeleteLocalRef(env, ary);
             return str;
         }
@@ -1586,16 +1585,13 @@
 GetApplicationClass(JNIEnv *env)
 {
     jmethodID mid;
-    jclass appClass;
     jclass cls = GetLauncherHelperClass(env);
     NULL_CHECK0(cls);
     NULL_CHECK0(mid = (*env)->GetStaticMethodID(env, cls,
                 "getApplicationClass",
                 "()Ljava/lang/Class;"));
 
-    appClass = (*env)->CallStaticObjectMethod(env, cls, mid);
-    CHECK_EXCEPTION_RETURN_VALUE(0);
-    return appClass;
+    return (*env)->CallStaticObjectMethod(env, cls, mid);
 }
 
 static char* expandWildcardOnLongOpt(char* arg) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java	Mon Sep 25 15:37:25 2017 +0100
@@ -84,6 +84,7 @@
     public final static int CONSTANT_NameandType = 12;
     public final static int CONSTANT_MethodHandle = 15;
     public final static int CONSTANT_MethodType = 16;
+    public final static int CONSTANT_ConstantDynamic = 17;
     public final static int CONSTANT_InvokeDynamic = 18;
     public final static int CONSTANT_Module = 19;
     public final static int CONSTANT_Package = 20;
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java	Mon Sep 25 15:37:25 2017 +0100
@@ -405,6 +405,7 @@
             case CONSTANT_NameandType:
             case CONSTANT_Integer:
             case CONSTANT_Float:
+            case CONSTANT_ConstantDynamic:
             case CONSTANT_InvokeDynamic:
                 bp = bp + 4;
                 break;
@@ -480,6 +481,7 @@
         case CONSTANT_MethodType:
             skipBytes(3);
             break;
+        case CONSTANT_ConstantDynamic:
         case CONSTANT_InvokeDynamic:
             skipBytes(5);
             break;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java	Mon Sep 25 15:37:25 2017 +0100
@@ -297,7 +297,7 @@
       // change byte-ordering and go via cache
       i = remapInstructionOperandFromCache(which);
     } else {
-      if (getTagAt(which).isInvokeDynamic()) {
+      if (getTagAt(which).isInvokeDynamic() || getTagAt(which).isConstantDynamic()) {
         int poolIndex = invokeDynamicNameAndTypeRefIndexAt(which);
         Assert.that(getTagAt(poolIndex).isNameAndType(), "");
         return poolIndex;
@@ -433,7 +433,7 @@
   /** Lookup for multi-operand (InvokeDynamic) entries. */
   public short[] getBootstrapSpecifierAt(int i) {
     if (Assert.ASSERTS_ENABLED) {
-      Assert.that(getTagAt(i).isInvokeDynamic(), "Corrupted constant pool");
+      Assert.that(getTagAt(i).isInvokeDynamic() || getTagAt(i).isConstantDynamic(), "Corrupted constant pool");
     }
     int bsmSpec = extractLowShortFromInt(this.getIntAt(i));
     U2Array operands = getOperands();
@@ -469,6 +469,7 @@
     case JVM_CONSTANT_NameAndType:        return "JVM_CONSTANT_NameAndType";
     case JVM_CONSTANT_MethodHandle:       return "JVM_CONSTANT_MethodHandle";
     case JVM_CONSTANT_MethodType:         return "JVM_CONSTANT_MethodType";
+    case JVM_CONSTANT_ConstantDynamic:    return "JVM_CONSTANT_ConstantDynamic";
     case JVM_CONSTANT_InvokeDynamic:      return "JVM_CONSTANT_InvokeDynamic";
     case JVM_CONSTANT_Invalid:            return "JVM_CONSTANT_Invalid";
     case JVM_CONSTANT_UnresolvedClass:    return "JVM_CONSTANT_UnresolvedClass";
@@ -525,6 +526,7 @@
         case JVM_CONSTANT_NameAndType:
         case JVM_CONSTANT_MethodHandle:
         case JVM_CONSTANT_MethodType:
+        case JVM_CONSTANT_ConstantDynamic:
         case JVM_CONSTANT_InvokeDynamic:
           visitor.doInt(new IntField(new NamedFieldIdentifier(nameForTag(ctag)), indexOffset(index), true), true);
           break;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java	Mon Sep 25 15:37:25 2017 +0100
@@ -42,7 +42,7 @@
     public static final int JVM_CONSTANT_NameAndType        = 12;
     public static final int JVM_CONSTANT_MethodHandle       = 15;
     public static final int JVM_CONSTANT_MethodType         = 16;
-    //     static final int JVM_CONSTANT_(unused)           = 17;
+    public static final int JVM_CONSTANT_ConstantDynamic    = 17;
     public static final int JVM_CONSTANT_InvokeDynamic      = 18;
 
     // JVM_CONSTANT_MethodHandle subtypes
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/jcore/ClassWriter.java	Mon Sep 25 15:37:25 2017 +0100
@@ -296,6 +296,18 @@
                      break;
                 }
 
+                case JVM_CONSTANT_ConstantDynamic: {
+                    dos.writeByte(cpConstType);
+                    int value = cpool.getIntAt(ci);
+                    short bsmIndex = (short) extractLowShortFromInt(value);
+                    short nameAndTypeIndex = (short) extractHighShortFromInt(value);
+                    dos.writeShort(bsmIndex);
+                    dos.writeShort(nameAndTypeIndex);
+                    if (DEBUG) debugMessage("CP[" + ci + "] = CONDY bsm = " +
+                                            bsmIndex + ", N&T = " + nameAndTypeIndex);
+                    break;
+                }
+
                 case JVM_CONSTANT_InvokeDynamic: {
                      dos.writeByte(cpConstType);
                      int value = cpool.getIntAt(ci);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/ui/classbrowser/HTMLGenerator.java	Mon Sep 25 15:37:25 2017 +0100
@@ -557,6 +557,12 @@
                buf.cell(Integer.toString(cpool.getIntAt(index)));
                break;
 
+           case JVM_CONSTANT_ConstantDynamic:
+               buf.cell("JVM_CONSTANT_ConstantDynamic");
+               buf.cell(genLowHighShort(cpool.getIntAt(index)) +
+                        genListOfShort(cpool.getBootstrapSpecifierAt(index)));
+             break;
+
             case JVM_CONSTANT_InvokeDynamic:
                buf.cell("JVM_CONSTANT_InvokeDynamic");
                buf.cell(genLowHighShort(cpool.getIntAt(index)) +
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/utilities/ConstantTag.java	Mon Sep 25 15:37:25 2017 +0100
@@ -42,7 +42,7 @@
   private static final int JVM_CONSTANT_NameAndType             = 12;
   private static final int JVM_CONSTANT_MethodHandle            = 15;  // JSR 292
   private static final int JVM_CONSTANT_MethodType              = 16;  // JSR 292
-  //      static final int JVM_CONSTANT_(unused)                = 17;  // JSR 292 early drafts only
+  private static final int JVM_CONSTANT_ConstantDynamic         = 17;  // JSR 292 early drafts only
   private static final int JVM_CONSTANT_InvokeDynamic           = 18;  // JSR 292
   private static final int JVM_CONSTANT_Invalid                 = 0;   // For bad value initialization
   private static final int JVM_CONSTANT_UnresolvedClass         = 100; // Temporary tag until actual use
@@ -84,6 +84,7 @@
   public boolean isUtf8()             { return tag == JVM_CONSTANT_Utf8; }
   public boolean isMethodHandle()     { return tag == JVM_CONSTANT_MethodHandle; }
   public boolean isMethodType()       { return tag == JVM_CONSTANT_MethodType; }
+  public boolean isConstantDynamic()  { return tag == JVM_CONSTANT_ConstantDynamic; }
   public boolean isInvokeDynamic()    { return tag == JVM_CONSTANT_InvokeDynamic; }
 
   public boolean isInvalid()          { return tag == JVM_CONSTANT_Invalid; }
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/CompilerToVM.java	Mon Sep 25 15:37:25 2017 +0100
@@ -237,6 +237,8 @@
      */
     native HotSpotResolvedJavaMethodImpl lookupMethodInPool(HotSpotConstantPool constantPool, int cpi, byte opcode);
 
+    // TODO resolving ConstantDynamic
+
     /**
      * Ensures that the type referenced by the specified {@code JVM_CONSTANT_InvokeDynamic} entry at
      * index {@code cpi} in {@code constantPool} is loaded and initialized.
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassTranslator.java	Mon Sep 25 15:37:25 2017 +0100
@@ -28,6 +28,7 @@
 import java.util.Map;
 
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Class_info;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_ConstantDynamic_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Double_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Fieldref_info;
 import com.sun.tools.classfile.ConstantPool.CONSTANT_Float_info;
@@ -331,6 +332,20 @@
         return info;
     }
 
+    public CPInfo visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Map<Object, Object> translations) {
+        CONSTANT_ConstantDynamic_info info2 = (CONSTANT_ConstantDynamic_info) translations.get(info);
+        if (info2 == null) {
+            ConstantPool cp2 = translate(info.cp, translations);
+            if (cp2 == info.cp) {
+                info2 = info;
+            } else {
+                info2 = new CONSTANT_ConstantDynamic_info(cp2, info.bootstrap_method_attr_index, info.name_and_type_index);
+            }
+            translations.put(info, info2);
+        }
+        return info;
+    }
+
     @Override
     public CPInfo visitLong(CONSTANT_Long_info info, Map<Object, Object> translations) {
         CONSTANT_Long_info info2 = (CONSTANT_Long_info) translations.get(info);
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ClassWriter.java	Mon Sep 25 15:37:25 2017 +0100
@@ -283,6 +283,12 @@
             return 1;
         }
 
+        public Integer visitConstantDynamic(CONSTANT_ConstantDynamic_info info, ClassOutputStream out) {
+            out.writeShort(info.bootstrap_method_attr_index);
+            out.writeShort(info.name_and_type_index);
+            return 1;
+        }
+
         @Override
         public Integer visitLong(CONSTANT_Long_info info, ClassOutputStream out) {
             out.writeLong(info.value);
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ConstantPool.java	Mon Sep 25 15:37:25 2017 +0100
@@ -116,6 +116,7 @@
     public static final int CONSTANT_NameAndType = 12;
     public static final int CONSTANT_MethodHandle = 15;
     public static final int CONSTANT_MethodType = 16;
+    public static final int CONSTANT_ConstantDynamic = 17;
     public static final int CONSTANT_InvokeDynamic = 18;
     public static final int CONSTANT_Module = 19;
     public static final int CONSTANT_Package = 20;
@@ -198,6 +199,10 @@
                 pool[i] = new CONSTANT_InvokeDynamic_info(this, cr);
                 break;
 
+            case CONSTANT_ConstantDynamic:
+                pool[i] = new CONSTANT_ConstantDynamic_info(this, cr);
+                break;
+
             case CONSTANT_Long:
                 pool[i] = new CONSTANT_Long_info(cr);
                 i++;
@@ -352,6 +357,7 @@
         R visitInteger(CONSTANT_Integer_info info, P p);
         R visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, P p);
         R visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, P p);
+        R visitConstantDynamic(CONSTANT_ConstantDynamic_info info, P p);
         R visitLong(CONSTANT_Long_info info, P p);
         R visitMethodref(CONSTANT_Methodref_info info, P p);
         R visitMethodHandle(CONSTANT_MethodHandle_info info, P p);
@@ -879,6 +885,44 @@
         public final int type_index;
     }
 
+    public static class CONSTANT_ConstantDynamic_info extends CPInfo {
+        CONSTANT_ConstantDynamic_info(ConstantPool cp, ClassReader cr) throws IOException {
+            super(cp);
+            bootstrap_method_attr_index = cr.readUnsignedShort();
+            name_and_type_index = cr.readUnsignedShort();
+        }
+
+        public CONSTANT_ConstantDynamic_info(ConstantPool cp, int bootstrap_method_index, int name_and_type_index) {
+            super(cp);
+            this.bootstrap_method_attr_index = bootstrap_method_index;
+            this.name_and_type_index = name_and_type_index;
+        }
+
+        public int getTag() {
+            return CONSTANT_ConstantDynamic;
+        }
+
+        public int byteLength() {
+            return 5;
+        }
+
+        @Override
+        public String toString() {
+            return "CONSTANT_ConstantDynamic_info[bootstrap_method_index: " + bootstrap_method_attr_index + ", name_and_type_index: " + name_and_type_index + "]";
+        }
+
+        public <R, D> R accept(Visitor<R, D> visitor, D data) {
+            return visitor.visitConstantDynamic(this, data);
+        }
+
+        public CONSTANT_NameAndType_info getNameAndTypeInfo() throws ConstantPoolException {
+            return cp.getNameAndTypeInfo(name_and_type_index);
+        }
+
+        public final int bootstrap_method_attr_index;
+        public final int name_and_type_index;
+    }
+
     public static class CONSTANT_Package_info extends CPInfo {
         CONSTANT_Package_info(ConstantPool cp, ClassReader cr) throws IOException {
             super(cp);
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/Dependencies.java	Mon Sep 25 15:37:25 2017 +0100
@@ -688,6 +688,11 @@
                 return null;
             }
 
+            @Override
+            public Void visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Void aVoid) {
+                return null;
+            }
+
             public Void visitLong(CONSTANT_Long_info info, Void p) {
                 return null;
             }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java	Mon Sep 25 15:37:25 2017 +0100
@@ -160,6 +160,11 @@
             return false;
         }
 
+        @Override
+        public Boolean visitConstantDynamic(CONSTANT_ConstantDynamic_info info, ConstantPool constantPool) {
+            return false;
+        }
+
         public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) {
             return false;
         }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/ConstantWriter.java	Mon Sep 25 15:37:25 2017 +0100
@@ -104,6 +104,13 @@
                 return 1;
             }
 
+            public Integer visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Void p) {
+                print("#" + info.bootstrap_method_attr_index + ":#" + info.name_and_type_index);
+                tab();
+                println("// " + stringValue(info));
+                return 1;
+            }
+
             public Integer visitLong(CONSTANT_Long_info info, Void p) {
                 println(stringValue(info));
                 return 2;
@@ -246,6 +253,8 @@
                 return "InterfaceMethod";
             case CONSTANT_InvokeDynamic:
                 return "InvokeDynamic";
+            case CONSTANT_ConstantDynamic:
+                return "ConstantDynamic";
             case CONSTANT_NameAndType:
                 return "NameAndType";
             default:
@@ -314,6 +323,15 @@
             }
         }
 
+        public String visitConstantDynamic(CONSTANT_ConstantDynamic_info info, Void p) {
+            try {
+                String callee = stringValue(info.getNameAndTypeInfo());
+                return "#" + info.bootstrap_method_attr_index + ":" + callee;
+            } catch (ConstantPoolException e) {
+                return report(e);
+            }
+        }
+
         public String visitLong(CONSTANT_Long_info info, Void p) {
             return info.value + "l";
         }
--- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/CPSelector.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeprscan/scan/CPSelector.java	Mon Sep 25 15:37:25 2017 +0100
@@ -26,6 +26,7 @@
 package com.sun.tools.jdeprscan.scan;
 
 import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPool.CONSTANT_ConstantDynamic_info;
 
 /**
  * A visitor that selects constant pool entries by type and adds
@@ -70,6 +71,10 @@
         return null;
     }
 
+    public Void visitConstantDynamic(CONSTANT_ConstantDynamic_info info, CPEntries p) {
+        return null;
+    }
+
     @Override
     public Void visitLong(ConstantPool.CONSTANT_Long_info info, CPEntries p) {
         return null;
--- a/src/sample/nashorn/java_completion.js	Mon Sep 25 16:29:23 2017 +0200
+++ b/src/sample/nashorn/java_completion.js	Mon Sep 25 15:37:25 2017 +0100
@@ -38,4 +38,4 @@
 var analysis = repl.sourceCodeAnalysis()
 var code = "System."
 var suggestions = analysis.completionSuggestions(code, code.length, [0])
-suggestions.forEach(function(s) print(s.continuation()))
+suggestions.forEach(function(s) print(s.continuation))
--- a/test/jdk/java/lang/invoke/CallSiteTest.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/test/jdk/java/lang/invoke/CallSiteTest.java	Mon Sep 25 15:37:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -24,39 +24,48 @@
 /**
  * @test
  * @summary smoke tests for CallSite
- *
- * @build indify.Indify
- * @compile CallSiteTest.java
- * @run main/othervm/timeout=3600 -XX:+IgnoreUnrecognizedVMOptions -XX:-VerifyDependencies
- *      indify.Indify
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.lang.invoke.CallSiteTest
+ * @library /lib/testlibrary/bytecode /java/lang/invoke/common
+ * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
+ * @run main test.java.lang.invoke.CallSiteTest
  */
 
 package test.java.lang.invoke;
 
-import java.io.*;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.lang.invoke.VolatileCallSite;
 
-import java.lang.invoke.*;
-import static java.lang.invoke.MethodHandles.*;
-import static java.lang.invoke.MethodType.*;
+import static java.lang.invoke.MethodHandles.Lookup;
+import static java.lang.invoke.MethodHandles.lookup;
+import static java.lang.invoke.MethodType.methodType;
+import static test.java.lang.invoke.lib.InstructionHelper.invokedynamic;
 
 public class CallSiteTest {
     private static final Class<?> CLASS = CallSiteTest.class;
 
-    private static CallSite mcs;
-    private static CallSite vcs;
-    private static MethodHandle mh_foo;
-    private static MethodHandle mh_bar;
+    private static final CallSite mcs;
+    private static final CallSite vcs;
+    private static final MethodHandle mh_foo;
+    private static final MethodHandle mh_bar;
 
+    private static final MethodHandle indy_mcs;
+    private static final MethodHandle indy_vcs;
     static {
         try {
-            mh_foo = lookup().findStatic(CLASS, "foo", methodType(int.class, int.class, int.class));
-            mh_bar = lookup().findStatic(CLASS, "bar", methodType(int.class, int.class, int.class));
+            MethodHandles.Lookup l = lookup();
+            mh_foo = l.findStatic(CLASS, "foo", methodType(int.class, int.class, int.class));
+            mh_bar = l.findStatic(CLASS, "bar", methodType(int.class, int.class, int.class));
             mcs = new MutableCallSite(mh_foo);
             vcs = new VolatileCallSite(mh_foo);
+
+            MethodType bsmType = methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+            indy_mcs = invokedynamic(l, "mcs", methodType(int.class, int.class, int.class), "bsm_mcs", bsmType, S -> {});
+            indy_vcs = invokedynamic(l, "vcs", methodType(int.class, int.class, int.class), "bsm_vcs", bsmType, S -> {});
         } catch (Exception e) {
-            e.printStackTrace();
+            throw new Error(e);
         }
     }
 
@@ -112,14 +121,14 @@
     private static int runMutableCallSite() throws Throwable {
         int sum = 0;
         for (int i = 0; i < N; i++) {
-            sum += (int) INDY_mcs().invokeExact(i, i+1);
+            sum += (int) indy_mcs.invokeExact(i, i+1);
         }
         return sum;
     }
     private static int runVolatileCallSite() throws Throwable {
         int sum = 0;
         for (int i = 0; i < N; i++) {
-            sum += (int) INDY_vcs().invokeExact(i, i+1);
+            sum += (int) indy_vcs.invokeExact(i, i+1);
         }
         return sum;
     }
@@ -127,37 +136,11 @@
     static int foo(int a, int b) { return a + b; }
     static int bar(int a, int b) { return a - b; }
 
-    private static MethodType MT_bsm() {
-        shouldNotCallThis();
-        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
+    static CallSite bsm_mcs(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
+        return mcs;
     }
 
-    private static CallSite bsm_mcs(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
-        return mcs;
-    }
-    private static MethodHandle MH_bsm_mcs() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm_mcs", MT_bsm());
-    }
-    private static MethodHandle INDY_mcs() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm_mcs().invoke(lookup(), "foo", methodType(int.class, int.class, int.class))).dynamicInvoker();
-    }
-
-    private static CallSite bsm_vcs(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
+    static CallSite bsm_vcs(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
         return vcs;
     }
-    private static MethodHandle MH_bsm_vcs() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm_vcs", MT_bsm());
-    }
-    private static MethodHandle INDY_vcs() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm_vcs().invoke(lookup(), "foo", methodType(int.class, int.class, int.class))).dynamicInvoker();
-    }
-
-    private static void shouldNotCallThis() {
-        // if this gets called, the transformation has not taken place
-        throw new AssertionError("this code should be statically transformed away by Indify");
-    }
 }
--- a/test/jdk/java/lang/invoke/CallStaticInitOrder.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/test/jdk/java/lang/invoke/CallStaticInitOrder.java	Mon Sep 25 15:37:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -24,22 +24,18 @@
 /**
  * @test
  * @summary static initializer invocation order
- *
- * @build indify.Indify
- * @compile CallStaticInitOrder.java
- * @run main/othervm
- *      indify.Indify
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.lang.invoke.CallStaticInitOrder
+ * @library /lib/testlibrary/bytecode /java/lang/invoke/common
+ * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
+ * @run main test.java.lang.invoke.CallStaticInitOrder
  */
 
 package test.java.lang.invoke;
 
-import java.io.*;
+import java.lang.invoke.*;
 
-import java.lang.invoke.*;
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
+import static test.java.lang.invoke.lib.InstructionHelper.invokedynamic;
 
 public class CallStaticInitOrder {
     private static int TICK;
@@ -96,19 +92,35 @@
     private static final MethodHandle CONSTANT_MH_bat;
     private static final MethodHandle CONSTANT_MH_bangGetter;
     private static final MethodHandle CONSTANT_MH_pongSetter;
+
+    private static final MethodHandle INDY_foo;
+    private static final MethodHandle INDY_bar;
+    private static final MethodHandle INDY_baz;
+    private static final MethodHandle INDY_bat;
+    private static final MethodHandle INDY_bang;
+    private static final MethodHandle INDY_pong;
     static {
         try {
             int t1 = tick("CallStaticInitOrder.<clinit>");
             {
+                MethodHandles.Lookup l = lookup();
                 CONSTANT_CS_baz = new MutableCallSite(methodType(int.class));
                 // MH_foo() := lookup().findStatic(Init1.class, "foo", methodType(int.class));
-                CONSTANT_MH_bar = lookup().findStatic(Init2.class, "bar", methodType(int.class));
+                CONSTANT_MH_bar = l.findStatic(Init2.class, "bar", methodType(int.class));
                 // MH_baz() := lookup().findStatic(Init3.class, "baz", methodType(int.class));
-                CONSTANT_MH_bat = lookup().unreflect(Init4.class.getDeclaredMethod("bat"));
-                CONSTANT_MH_bangGetter = lookup().findStaticGetter(Init5.class, "bang", int.class);
-                MethodHandle pongSetter = lookup().findStaticSetter(Init6.class, "pong", int.class);
-                MethodHandle tickGetter = lookup().findStaticGetter(CallStaticInitOrder.class, "Init6Tick", int.class);
+                CONSTANT_MH_bat = l.unreflect(Init4.class.getDeclaredMethod("bat"));
+                CONSTANT_MH_bangGetter = l.findStaticGetter(Init5.class, "bang", int.class);
+                MethodHandle pongSetter = l.findStaticSetter(Init6.class, "pong", int.class);
+                MethodHandle tickGetter = l.findStaticGetter(CallStaticInitOrder.class, "Init6Tick", int.class);
                 CONSTANT_MH_pongSetter = filterReturnValue(insertArguments(pongSetter, 0, -99), tickGetter);
+
+                MethodType bsmType = methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+                INDY_foo = invokedynamic(l, "foo", methodType(int.class), "bsm", bsmType, S -> {});
+                INDY_bar = invokedynamic(l, "bar", methodType(int.class), "bsm", bsmType, S -> {});
+                INDY_baz = invokedynamic(l, "baz", methodType(int.class), "bsm", bsmType, S -> {});
+                INDY_bat = invokedynamic(l, "bat", methodType(int.class), "bsm", bsmType, S -> {});
+                INDY_bang = invokedynamic(l, "bang", methodType(int.class), "bsm", bsmType, S -> {});
+                INDY_pong = invokedynamic(l, "pong", methodType(int.class), "bsm", bsmType, S -> {});
             }
             int t2 = tick("CallStaticInitOrder.<clinit> done");
             assertEquals(t1+1, t2);  // no ticks in between
@@ -151,94 +163,70 @@
     private static int runFoo() throws Throwable {
         assertEquals(Init1Tick, 0);  // Init1 not initialized yet
         int t1 = tick("runFoo");
-        int t2 = (int) INDY_foo().invokeExact();
+        int t2 = (int) INDY_foo.invokeExact();
         int t3 = tick("runFoo done");
         assertEquals(Init1Tick, t2);  // when Init1 was initialized
         assertEquals(t1+2, t3);  // exactly two ticks in between
         assertEquals(t1+1, t2);  // init happened inside
         return t2;
     }
-    private static MethodHandle INDY_foo() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(), "foo", methodType(int.class))).dynamicInvoker();
-    }
 
     private static int runBar() throws Throwable {
         assertEquals(Init2Tick, 0);  // Init2 not initialized yet
         int t1 = tick("runBar");
-        int t2 = (int) INDY_bar().invokeExact();
+        int t2 = (int) INDY_bar.invokeExact();
         int t3 = tick("runBar done");
         assertEquals(Init2Tick, t2);  // when Init2 was initialized
         assertEquals(t1+2, t3);  // exactly two ticks in between
         assertEquals(t1+1, t2);  // init happened inside
         return t2;
     }
-    private static MethodHandle INDY_bar() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(), "bar", methodType(int.class))).dynamicInvoker();
-    }
 
     private static int runBaz() throws Throwable {
         assertEquals(Init3Tick, 0);  // Init3 not initialized yet
         int t1 = tick("runBaz");
-        int t2 = (int) INDY_baz().invokeExact();
+        int t2 = (int) INDY_baz.invokeExact();
         int t3 = tick("runBaz done");
         assertEquals(Init3Tick, t2);  // when Init3 was initialized
         assertEquals(t1+2, t3);  // exactly two ticks in between
         assertEquals(t1+1, t2);  // init happened inside
         return t2;
     }
-    private static MethodHandle INDY_baz() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(), "baz", methodType(int.class))).dynamicInvoker();
-    }
 
     private static int runBat() throws Throwable {
         assertEquals(Init4Tick, 0);  // Init4 not initialized yet
         int t1 = tick("runBat");
-        int t2 = (int) INDY_bat().invokeExact();
+        int t2 = (int) INDY_bat.invokeExact();
         int t3 = tick("runBat done");
         assertEquals(Init4Tick, t2);  // when Init4 was initialized
         assertEquals(t1+2, t3);  // exactly two ticks in between
         assertEquals(t1+1, t2);  // init happened inside
         return t2;
     }
-    private static MethodHandle INDY_bat() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(), "bat", methodType(int.class))).dynamicInvoker();
-    }
 
     private static int runBang() throws Throwable {
         assertEquals(Init5Tick, 0);  // Init5 not initialized yet
         int t1 = tick("runBang");
-        int t2 = (int) INDY_bang().invokeExact();
+        int t2 = (int) INDY_bang.invokeExact();
         int t3 = tick("runBang done");
         assertEquals(Init5Tick, t2);  // when Init5 was initialized
         assertEquals(t1+2, t3);  // exactly two ticks in between
         assertEquals(t1+1, t2);  // init happened inside
         return t2;
     }
-    private static MethodHandle INDY_bang() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(), "bang", methodType(int.class))).dynamicInvoker();
-    }
 
     private static int runPong() throws Throwable {
         assertEquals(Init6Tick, 0);  // Init6 not initialized yet
         int t1 = tick("runPong");
-        int t2 = (int) INDY_pong().invokeExact();
+        int t2 = (int) INDY_pong.invokeExact();
         int t3 = tick("runPong done");
         assertEquals(Init6Tick, t2);  // when Init6 was initialized
         assertEquals(t1+2, t3);  // exactly two ticks in between
         assertEquals(t1+1, t2);  // init happened inside
         return t2;
     }
-    private static MethodHandle INDY_pong() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(), "pong", methodType(int.class))).dynamicInvoker();
-    }
 
-    private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
+    static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
         System.out.println("bsm "+name+type);
         CallSite res;
         switch (name) {
@@ -262,13 +250,4 @@
         }
         return res;
     }
-    private static MethodHandle MH_bsm() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm",
-                                   methodType(CallSite.class, Lookup.class, String.class, MethodType.class));
-    }
-    private static void shouldNotCallThis() {
-        // if this gets called, the transformation has not taken place
-        throw new AssertionError("this code should be statically transformed away by Indify");
-    }
 }
--- a/test/jdk/java/lang/invoke/InvokeDynamicPrintArgs.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/test/jdk/java/lang/invoke/InvokeDynamicPrintArgs.java	Mon Sep 25 15:37:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -24,51 +24,96 @@
 /* @test
  * @bug 7050328 8007035
  * @summary smoke test for invokedynamic instructions
- * @build indify.Indify
- * @compile InvokeDynamicPrintArgs.java
- * @run main/othervm
- *      indify.Indify
- *      --verify-specifier-count=8
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.lang.invoke.InvokeDynamicPrintArgs --check-output
- * @run main/othervm
- *      indify.Indify
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.lang.invoke.InvokeDynamicPrintArgs --security-manager
+ * @library /lib/testlibrary/bytecode /java/lang/invoke/common
+ * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
+ * @run main test.java.lang.invoke.InvokeDynamicPrintArgs --check-output
+ * @run main/othervm test.java.lang.invoke.InvokeDynamicPrintArgs --security-manager
  */
 
 package test.java.lang.invoke;
 
-import java.util.*;
-import java.io.*;
+import jdk.experimental.bytecode.PoolHelper;
 
-import java.lang.invoke.*;
-import java.security.*;
-import static java.lang.invoke.MethodHandles.*;
-import static java.lang.invoke.MethodType.*;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+import static java.lang.invoke.MethodHandles.Lookup;
+import static java.lang.invoke.MethodHandles.lookup;
+import static java.lang.invoke.MethodType.genericMethodType;
+import static java.lang.invoke.MethodType.methodType;
+import static test.java.lang.invoke.lib.InstructionHelper.invokedynamic;
 
 public class InvokeDynamicPrintArgs {
+
+    private static final MethodHandle INDY_nothing;
+    private static final MethodHandle INDY_foo;
+    private static final MethodHandle INDY_bar;
+    private static final MethodHandle INDY_bar2;
+    private static final MethodHandle INDY_baz;
+    static {
+        try {
+            MethodHandles.Lookup l = lookup();
+            MethodType bsmType = methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+            INDY_nothing = invokedynamic(l, "nothing", methodType(void.class), "bsm", bsmType, S -> { });
+            INDY_foo = invokedynamic(l, "foo", methodType(void.class, String.class), "bsm", bsmType, S -> { });
+
+            MethodType bsm2Type = methodType(CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, Object[].class);
+            INDY_bar = invokedynamic(l, "bar", methodType(void.class, String.class, int.class), "bsm2", bsm2Type,
+                                     S -> {
+                                         S.add("java/lang/Void", PoolHelper::putClass);
+                                         S.add("void type!", PoolHelper::putString);
+                                         S.add(1);
+                                         S.add(234.5F);
+                                         S.add(67.5);
+                                         S.add(89L);
+                                     });
+            INDY_bar2 = invokedynamic(l, "bar2", methodType(void.class, String.class, int.class), "bsm2", bsm2Type,
+                                      S -> {
+                                          S.add("java/lang/Void", PoolHelper::putClass);
+                                          S.add("void type!", PoolHelper::putString);
+                                          S.add(1);
+                                          S.add(234.5F);
+                                          S.add(67.5);
+                                          S.add(89L);
+                                      });
+            INDY_baz = invokedynamic(l, "baz", methodType(void.class, String.class, int.class, double.class), "bsm2", bsm2Type,
+                                     S -> {
+                                         S.add(1234.5);
+                                     });
+        } catch (Exception ex) {
+            throw new InternalError(ex);
+        }
+    }
+
     public static void main(String... av) throws Throwable {
         if (av.length > 0 && av[0].equals("--check-output"))  openBuf();
         if (av.length > 0 && av[0].equals("--security-manager"))  setSM();
         System.out.println("Printing some argument lists, starting with a empty one:");
-        INDY_nothing().invokeExact();                 // BSM specifier #0 = {bsm}
-        INDY_bar().invokeExact("bar arg", 1);         // BSM specifier #1 = {bsm2, Void.class, "void type"}
-        INDY_bar2().invokeExact("bar2 arg", 222);     // BSM specifier #1 = (same)
-        INDY_baz().invokeExact("baz arg", 2, 3.14);   // BSM specifier #2 = {bsm2, 1234.5}
-        INDY_foo().invokeExact("foo arg");            // BSM specifier #0 = (same)
+        INDY_nothing.invokeExact();                 // BSM specifier #0 = {bsm}
+        INDY_bar.invokeExact("bar arg", 1);         // BSM specifier #1 = {bsm2, Void.class, "void type"}
+        INDY_bar2.invokeExact("bar2 arg", 222);     // BSM specifier #1 = (same)
+        INDY_baz.invokeExact("baz arg", 2, 3.14);   // BSM specifier #2 = {bsm2, 1234.5}
+        INDY_foo.invokeExact("foo arg");            // BSM specifier #0 = (same)
         // Hence, BSM specifier count should be 3.  See "--verify-specifier-count=3" above.
         System.out.println("Done printing argument lists.");
         closeBuf();
-        checkConstantRefs();
     }
 
-    private static void checkConstantRefs() throws Throwable {
-        // check some constant references to its self class
-        assertEquals(MT_bsm(), MH_bsm().type());
-        assertEquals(MT_bsm2(), MH_bsm2().type());
-        assertEquals(MT_bsm(), non_MH_bsm().type());
-    }
     private static void assertEquals(Object exp, Object act) {
         if (exp == act || (exp != null && exp.equals(act)))  return;
         throw new AssertionError("not equal: "+exp+", "+act);
@@ -119,26 +164,22 @@
         if (doPrint)  System.out.println(message);
     }
     private static MethodHandle MH_printArgs() throws ReflectiveOperationException {
-        shouldNotCallThis();
         return lookup().findStatic(lookup().lookupClass(),
                                    "printArgs", methodType(void.class, Object.class, Object[].class));
     }
 
-    private static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
+    static CallSite bsm(Lookup caller, String name, MethodType type) throws ReflectiveOperationException {
         // ignore caller and name, but match the type:
-        Object bsmInfo = Arrays.asList(caller, name, type);
+
+        Object bsmInfo = Arrays.asList(forName(caller.lookupClass()), name, type);
         return new ConstantCallSite(MH_printArgs().bindTo(bsmInfo).asCollector(Object[].class, type.parameterCount()).asType(type));
     }
-    private static MethodType MT_bsm() {
-        shouldNotCallThis();
-        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class);
-    }
-    private static MethodHandle MH_bsm() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
-    }
-    private static MethodHandle non_MH_bsm() throws ReflectiveOperationException {
-        return lookup().findStatic(lookup().lookupClass(), "bsm", MT_bsm());
+
+    static String forName(Class<?> c) {
+        String s = c.getCanonicalName();
+        int i = s.indexOf('$');
+        if (i > 0) s = s.substring(0, i);
+        return s;
     }
 
     /* Example of a constant call site with user-data.
@@ -169,69 +210,20 @@
         }
 
         public Object runTarget(Object... dynamicArgs) {
-            List<Object> bsmInfo = new ArrayList<>(Arrays.asList(caller, name, type()));
+            List<Object> bsmInfo = new ArrayList<>(Arrays.asList(forName(caller.lookupClass()), name, type()));
             bsmInfo.addAll(Arrays.asList(staticArgs));
             printArgs(bsmInfo, dynamicArgs);
             return null;
         }
 
         private static MethodHandle MH_createTarget() throws ReflectiveOperationException {
-            shouldNotCallThis();
             return lookup().findVirtual(lookup().lookupClass(), "createTarget", methodType(MethodHandle.class));
         }
     }
-    private static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws Throwable {
+    static CallSite bsm2(Lookup caller, String name, MethodType type, Object... arg) throws Throwable {
         // ignore caller and name, but match the type:
         return new PrintingCallSite(caller, name, type, arg);
     }
-    private static MethodType MT_bsm2() {
-        shouldNotCallThis();
-        return methodType(CallSite.class, Lookup.class, String.class, MethodType.class, Object[].class);
-    }
-    private static MethodHandle MH_bsm2() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(lookup().lookupClass(), "bsm2", MT_bsm2());
-    }
-
-    private static MethodHandle INDY_nothing() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(),
-                                                  "nothing", methodType(void.class)
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_foo() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm().invoke(lookup(),
-                                                  "foo", methodType(void.class, String.class)
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_bar() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm2().invoke(lookup(),
-                                                  "bar", methodType(void.class, String.class, int.class)
-                                                  , Void.class, "void type!", 1, 234.5F, 67.5, (long)89
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_bar2() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm2().invoke(lookup(),
-                                                  "bar2", methodType(void.class, String.class, int.class)
-                                                  , Void.class, "void type!", 1, 234.5F, 67.5, (long)89
-                                                  )).dynamicInvoker();
-    }
-    private static MethodHandle INDY_baz() throws Throwable {
-        shouldNotCallThis();
-        return ((CallSite) MH_bsm2().invoke(lookup(),
-                                                  "baz", methodType(void.class, String.class, int.class, double.class)
-                                                  , 1234.5
-                                                  )).dynamicInvoker();
-    }
-
-    private static void shouldNotCallThis() {
-        // if this gets called, the transformation has not taken place
-        if (System.getProperty("InvokeDynamicPrintArgs.allow-untransformed") != null)  return;
-        throw new AssertionError("this code should be statically transformed away by Indify");
-    }
 
     static class TestPolicy extends Policy {
         final PermissionCollection permissions = new Permissions();
--- a/test/jdk/java/lang/invoke/MethodHandleConstants.java	Mon Sep 25 16:29:23 2017 +0200
+++ b/test/jdk/java/lang/invoke/MethodHandleConstants.java	Mon Sep 25 15:37:25 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 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
@@ -24,39 +24,74 @@
 /* @test
  * @bug 8022066
  * @summary smoke test for method handle constants
- * @build indify.Indify
- * @compile MethodHandleConstants.java
- * @run main/othervm
- *      indify.Indify
- *      --verify-specifier-count=4
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.lang.invoke.MethodHandleConstants --check-output
- * @run main/othervm
- *      indify.Indify
- *      --expand-properties --classpath ${test.classes}
- *      --java test.java.lang.invoke.MethodHandleConstants --security-manager
+ * @library /lib/testlibrary/bytecode /java/lang/invoke/common
+ * @build jdk.experimental.bytecode.BasicClassBuilder test.java.lang.invoke.lib.InstructionHelper
+ * @run main test.java.lang.invoke.MethodHandleConstants --check-output
+ * @run main/othervm test.java.lang.invoke.MethodHandleConstants --security-manager
  */
 
 package test.java.lang.invoke;
 
-import java.util.*;
-import java.io.*;
-import java.lang.invoke.*;
-import java.security.*;
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleInfo;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.Iterator;
 
-import static java.lang.invoke.MethodHandles.*;
-import static java.lang.invoke.MethodType.*;
+import static java.lang.invoke.MethodHandles.lookup;
+import static java.lang.invoke.MethodType.methodType;
+import static test.java.lang.invoke.lib.InstructionHelper.ldcMethodHandle;
 
 public class MethodHandleConstants {
+    private static final MethodHandle MH_String_replace_C2;
+    private static final MethodHandle MH_MethodHandle_invokeExact_SC2;
+    private static final MethodHandle MH_MethodHandle_invoke_SC2;
+    private static final MethodHandle MH_Class_forName_S;
+    private static final MethodHandle MH_Class_forName_SbCL;
+    static {
+        try {
+            MethodHandles.Lookup l = lookup();
+
+            MH_String_replace_C2 = ldcMethodHandle(l,
+                    MethodHandleInfo.REF_invokeVirtual, String.class, "replace",
+                    methodType(String.class, char.class, char.class));
+            MH_MethodHandle_invokeExact_SC2 = ldcMethodHandle(l,
+                    MethodHandleInfo.REF_invokeVirtual, MethodHandle.class, "invokeExact",
+                    methodType(String.class, String.class, char.class, char.class));
+            MH_MethodHandle_invoke_SC2 = ldcMethodHandle(l,
+                    MethodHandleInfo.REF_invokeVirtual, MethodHandle.class, "invoke",
+                    methodType(String.class, String.class, char.class, char.class));
+            MH_Class_forName_S = ldcMethodHandle(l,
+                    MethodHandleInfo.REF_invokeStatic, Class.class, "forName",
+                    methodType(Class.class, String.class));
+            MH_Class_forName_SbCL = ldcMethodHandle(l,
+                    MethodHandleInfo.REF_invokeStatic, Class.class, "forName",
+                    methodType(Class.class, String.class, boolean.class, ClassLoader.class));
+        }
+        catch (Exception ex) {
+            ex.printStackTrace();
+            throw new InternalError(ex);
+        }
+    }
+
     public static void main(String... av) throws Throwable {
         if (av.length > 0 && av[0].equals("--check-output"))  openBuf();
         if (av.length > 0 && av[0].equals("--security-manager"))  setSM();
         System.out.println("Obtaining method handle constants:");
-        testCase(MH_String_replace_C2(), String.class, "replace", String.class, String.class, char.class, char.class);
-        testCase(MH_MethodHandle_invokeExact_SC2(), MethodHandle.class, "invokeExact", String.class, MethodHandle.class, String.class, char.class, char.class);
-        testCase(MH_MethodHandle_invoke_SC2(), MethodHandle.class, "invoke", String.class, MethodHandle.class, String.class, char.class, char.class);
-        testCase(MH_Class_forName_S(), Class.class, "forName", Class.class, String.class);
-        testCase(MH_Class_forName_SbCL(), Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class);
+        testCase((MethodHandle) MH_String_replace_C2.invokeExact(), String.class, "replace", String.class, String.class, char.class, char.class);
+        testCase((MethodHandle) MH_MethodHandle_invokeExact_SC2.invokeExact(), MethodHandle.class, "invokeExact", String.class, MethodHandle.class, String.class, char.class, char.class);
+        testCase((MethodHandle) MH_MethodHandle_invoke_SC2.invokeExact(), MethodHandle.class, "invoke", String.class, MethodHandle.class, String.class, char.class, char.class);
+        testCase((MethodHandle) MH_Class_forName_S.invokeExact(), Class.class, "forName", Class.class, String.class);
+        testCase((MethodHandle) MH_Class_forName_SbCL.invokeExact(), Class.class, "forName", Class.class, String.class, boolean.class, ClassLoader.class);
         System.out.println("Done.");
         closeBuf();
     }
@@ -112,62 +147,6 @@
         "Done."
     };
 
-    // String.replace(String, char, char)
-    private static MethodType MT_String_replace_C2() {
-        shouldNotCallThis();
-        return methodType(String.class, char.class, char.class);
-    }
-    private static MethodHandle MH_String_replace_C2() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findVirtual(String.class, "replace", MT_String_replace_C2());
-    }
-
-    // MethodHandle.invokeExact(...)
-    private static MethodType MT_MethodHandle_invokeExact_SC2() {
-        shouldNotCallThis();
-        return methodType(String.class, String.class, char.class, char.class);
-    }
-    private static MethodHandle MH_MethodHandle_invokeExact_SC2() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findVirtual(MethodHandle.class, "invokeExact", MT_MethodHandle_invokeExact_SC2());
-    }
-
-    // MethodHandle.invoke(...)
-    private static MethodType MT_MethodHandle_invoke_SC2() {
-        shouldNotCallThis();
-        return methodType(String.class, String.class, char.class, char.class);
-    }
-    private static MethodHandle MH_MethodHandle_invoke_SC2() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findVirtual(MethodHandle.class, "invoke", MT_MethodHandle_invoke_SC2());
-    }
-
-    // Class.forName(String)
-    private static MethodType MT_Class_forName_S() {
-        shouldNotCallThis();
-        return methodType(Class.class, String.class);
-    }
-    private static MethodHandle MH_Class_forName_S() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(Class.class, "forName", MT_Class_forName_S());
-    }
-
-    // Class.forName(String, boolean, ClassLoader)
-    private static MethodType MT_Class_forName_SbCL() {
-        shouldNotCallThis();
-        return methodType(Class.class, String.class, boolean.class, ClassLoader.class);
-    }
-    private static MethodHandle MH_Class_forName_SbCL() throws ReflectiveOperationException {
-        shouldNotCallThis();
-        return lookup().findStatic(Class.class, "forName", MT_Class_forName_SbCL());
-    }
-
-    private static void shouldNotCallThis() {
-        // if this gets called, the transformation has not taken place
-        if (System.getProperty("MethodHandleConstants.allow-untransformed") != null)  return;
-        throw new AssertionError("this code should be statically transformed away by Indify");
-    }
-
     static class TestPolicy extends Policy {
         final PermissionCollection permissions = new Permissions();
         TestPolicy() {