Merge
authorprr
Wed, 29 Nov 2017 09:07:01 -0800
changeset 47981 444dbe37e451
parent 47980 519f8bc59a1f (current diff)
parent 47957 7175a92b6fd7 (diff)
child 47982 44371ff1ee9a
Merge
--- a/make/InitSupport.gmk	Tue Nov 28 15:01:00 2017 -0800
+++ b/make/InitSupport.gmk	Wed Nov 29 09:07:01 2017 -0800
@@ -47,7 +47,7 @@
 
   # Make control variables, handled by Init.gmk
   INIT_CONTROL_VARIABLES += LOG CONF CONF_NAME SPEC JOBS TEST_JOBS CONF_CHECK \
-      COMPARE_BUILD JTREG GTEST
+      COMPARE_BUILD JTREG GTEST TEST_OPTS TEST_VM_OPTS
 
   # All known make control variables
   MAKE_CONTROL_VARIABLES := $(INIT_CONTROL_VARIABLES) TEST JDK_FILTER
--- a/make/RunTests.gmk	Tue Nov 28 15:01:00 2017 -0800
+++ b/make/RunTests.gmk	Wed Nov 29 09:07:01 2017 -0800
@@ -32,11 +32,42 @@
 # We will always run multiple tests serially
 .NOTPARALLEL:
 
+################################################################################
+# Parse global control variables
+################################################################################
+
+ifneq ($(TEST_VM_OPTS), )
+  ifneq ($(TEST_OPTS), )
+    TEST_OPTS := $(TEST_OPTS);VM_OPTIONS=$(TEST_VM_OPTS)
+  else
+    TEST_OPTS := VM_OPTIONS=$(TEST_VM_OPTS)
+  endif
+endif
+
+$(eval $(call ParseKeywordVariable, TEST_OPTS, \
+    KEYWORDS := JOBS TIMEOUT, \
+    STRING_KEYWORDS := VM_OPTIONS, \
+))
+
+# Helper function to propagate TEST_OPTS values.
+#
+# Note: No spaces are allowed around the arguments.
+# Arg $1 The variable in TEST_OPTS to propagate
+# Arg $2 The control variable to propagate it to
+define SetTestOpt
+  ifneq ($$(TEST_OPTS_$1), )
+    $2_$1 := $$(TEST_OPTS_$1)
+  endif
+endef
+
+################################################################################
 # 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_SUMMARY := $(TEST_RESULTS_DIR)/test-summary.txt
 
 ifeq ($(CUSTOM_ROOT), )
   JTREG_TOPDIR := $(TOPDIR)
@@ -48,6 +79,17 @@
 # Parse control variables
 ################################################################################
 
+ifneq ($(TEST_OPTS), )
+  # Inform the user
+  $(info Running tests using TEST_OPTS control variable '$(TEST_OPTS)')
+
+  $(eval $(call SetTestOpt,VM_OPTIONS,JTREG))
+  $(eval $(call SetTestOpt,VM_OPTIONS,GTEST))
+
+  $(eval $(call SetTestOpt,JOBS,JTREG))
+  $(eval $(call SetTestOpt,TIMEOUT,JTREG))
+endif
+
 $(eval $(call ParseKeywordVariable, JTREG, \
     KEYWORDS := JOBS TIMEOUT TEST_MODE ASSERT VERBOSE RETAIN MAX_MEM, \
     STRING_KEYWORDS := OPTIONS JAVA_OPTIONS VM_OPTIONS, \
@@ -60,7 +102,7 @@
 
 $(eval $(call ParseKeywordVariable, GTEST, \
     KEYWORDS := REPEAT, \
-    STRING_KEYWORDS := OPTIONS, \
+    STRING_KEYWORDS := OPTIONS VM_OPTIONS, \
 ))
 
 ifneq ($(GTEST), )
@@ -280,7 +322,7 @@
 	    $$(FIXPATH) $$(TEST_IMAGE_DIR)/hotspot/gtest/server/gtestLauncher \
 	    -jdk $(JDK_IMAGE_DIR) $$($1_GTEST_FILTER) \
 	    --gtest_output=xml:$$($1_TEST_RESULTS_DIR)/gtest.xml \
-	    $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) \
+	    $$($1_GTEST_REPEAT) $$(GTEST_OPTIONS) $$(GTEST_VM_OPTIONS) \
 	    > >($(TEE) $$($1_TEST_RESULTS_DIR)/gtest.txt) || true )
 
   $1_RESULT_FILE := $$($1_TEST_RESULTS_DIR)/gtest.txt
@@ -289,15 +331,24 @@
 	$$(call LogWarn, Finished running test '$$($1_TEST)')
 	$$(call LogWarn, Test report is stored in $$(strip \
 	    $$(subst $$(TOPDIR)/, , $$($1_TEST_RESULTS_DIR))))
-	$$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
-	    test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE)))
-	$$(eval $1_PASSED := $$(shell $$(AWK) '/\[  PASSED  \] .* tests?./ \
-	    { print $$$$4 }' $$($1_RESULT_FILE)))
-	$$(eval $1_FAILED := $$(shell $$(AWK) '/\[  FAILED  \] .* tests?, \
-	    listed below/ { print $$$$4 }' $$($1_RESULT_FILE)))
-	$$(if $$($1_FAILED), , $$(eval $1_FAILED := 0))
-	$$(eval $1_ERROR := $$(shell \
-	    $$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED)))
+	$$(if  $$(wildcard $$($1_RESULT_FILE)), \
+	  $$(eval $1_TOTAL := $$(shell $$(AWK) '/==========.* tests? from .* \
+	      test cases? ran/ { print $$$$2 }' $$($1_RESULT_FILE))) \
+	  $$(if $$($1_TOTAL), , $$(eval $1_TOTAL := 0)) \
+	  $$(eval $1_PASSED := $$(shell $$(AWK) '/\[  PASSED  \] .* tests?./ \
+	      { print $$$$4 }' $$($1_RESULT_FILE))) \
+	  $$(if $$($1_PASSED), , $$(eval $1_PASSED := 0)) \
+	  $$(eval $1_FAILED := $$(shell $$(AWK) '/\[  FAILED  \] .* tests?, \
+	      listed below/ { print $$$$4 }' $$($1_RESULT_FILE))) \
+	  $$(if $$($1_FAILED), , $$(eval $1_FAILED := 0)) \
+	  $$(eval $1_ERROR := $$(shell \
+	      $$(EXPR) $$($1_TOTAL) - $$($1_PASSED) - $$($1_FAILED))) \
+	, \
+	  $$(eval $1_PASSED := 0) \
+	  $$(eval $1_FAILED := 0) \
+	  $$(eval $1_ERROR := 1) \
+	  $$(eval $1_TOTAL := 1) \
+	)
 
   $1: run-test-$1 parse-test-$1
 
@@ -521,42 +572,46 @@
 TEST_FAILURE := false
 
 run-test: $(TARGETS)
-        # Print a table of the result of all tests run and their result
-	$(ECHO)
-	$(ECHO) ==============================
-	$(ECHO) Test summary
-	$(ECHO) ==============================
-	$(PRINTF) "%2s %-49s %5s %5s %5s %5s %2s\n" "  " TEST \
-	    TOTAL PASS FAIL ERROR " "
+        # Create and print a table of the result of all tests run
+	$(RM) $(TEST_SUMMARY).old 2> /dev/null
+	$(MV) $(TEST_SUMMARY) $(TEST_SUMMARY).old 2> /dev/null || true
+	$(ECHO) >> $(TEST_SUMMARY) ==============================
+	$(ECHO) >> $(TEST_SUMMARY) Test summary
+	$(ECHO) >> $(TEST_SUMMARY) ==============================
+	$(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5s %5s %5s %5s %2s\n" "  " \
+	    TEST TOTAL PASS FAIL ERROR " "
 	$(foreach test, $(TESTS_TO_RUN), \
 	  $(eval TEST_ID := $(shell $(ECHO) $(strip $(test)) | \
 	      $(TR) -cs '[a-z][A-Z][0-9]\n' '_')) \
 	  $(eval NAME_PATTERN := $(shell $(ECHO) $(test) | $(TR) -c \\n _)) \
 	  $(if $(filter __________________________________________________%, $(NAME_PATTERN)), \
 	    $(eval TEST_NAME := ) \
-	    $(PRINTF) "%2s %-49s\n" "  " "$(test)"  $(NEWLINE) \
+	    $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s\n" "  " "$(test)"  $(NEWLINE) \
 	  , \
 	    $(eval TEST_NAME := $(test)) \
 	  ) \
 	  $(if $(filter $($(TEST_ID)_PASSED), $($(TEST_ID)_TOTAL)), \
-	    $(PRINTF) "%2s %-49s %5d %5d %5d %5d %2s\n" "  " "$(TEST_NAME)" \
-	        $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) $($(TEST_ID)_FAILED) \
-	        $($(TEST_ID)_ERROR) "  " $(NEWLINE) \
+	    $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %2s\n" \
+	        "  " "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \
+	        $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) "  " $(NEWLINE) \
 	  , \
-	    $(PRINTF) "%2s %-49s %5d %5d %5d %5d %2s\n" ">>" "$(TEST_NAME)" \
-	        $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) $($(TEST_ID)_FAILED) \
-	        $($(TEST_ID)_ERROR) "<<" $(NEWLINE) \
+	    $(PRINTF) >> $(TEST_SUMMARY) "%2s %-49s %5d %5d %5d %5d %2s\n" \
+	         ">>" "$(TEST_NAME)" $($(TEST_ID)_TOTAL) $($(TEST_ID)_PASSED) \
+	        $($(TEST_ID)_FAILED) $($(TEST_ID)_ERROR) "<<" $(NEWLINE) \
 	    $(eval TEST_FAILURE := true) \
 	  ) \
 	)
-	$(ECHO) ==============================
+	$(ECHO) >> $(TEST_SUMMARY) ==============================
 	$(if $(filter true, $(TEST_FAILURE)), \
-	  $(ECHO) TEST FAILURE $(NEWLINE) \
+	  $(ECHO) >> $(TEST_SUMMARY) TEST FAILURE $(NEWLINE) \
+	  $(MKDIR) -p $(MAKESUPPORT_OUTPUTDIR) $(NEWLINE) \
 	  $(TOUCH) $(MAKESUPPORT_OUTPUTDIR)/exit-with-error \
 	, \
-	  $(ECHO) TEST SUCCESS \
+	  $(ECHO) >> $(TEST_SUMMARY) TEST SUCCESS \
 	)
 	$(ECHO)
+	$(CAT) $(TEST_SUMMARY)
+	$(ECHO)
 
 ################################################################################
 
--- a/make/nashorn/build.xml	Tue Nov 28 15:01:00 2017 -0800
+++ b/make/nashorn/build.xml	Wed Nov 29 09:07:01 2017 -0800
@@ -115,11 +115,11 @@
    </target>
   
 
-  <!-- check minimum ant version required to be 1.8.4 -->
+  <!-- check minimum ant version required to be 1.9.5 -->
   <target name="check-ant-version">
-    <property name="ant.version.required" value="1.8.4"/>
+    <property name="ant.version.required" value="1.9.5"/>
     <antversion property="ant.current.version" />
-    <fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.8.4 or above.">
+    <fail message="The current ant version, ${ant.current.version}, is too old. Please use 1.9.5 or above.">
         <condition>
             <not>
                 <antversion atleast="${ant.version.required}"/>
--- a/src/java.base/share/classes/java/lang/ClassLoader.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/java.base/share/classes/java/lang/ClassLoader.java	Wed Nov 29 09:07:01 2017 -0800
@@ -1813,7 +1813,7 @@
     }
 
     /**
-     * Returns the platform class loader for delegation.  All
+     * Returns the platform class loader.  All
      * <a href="#builtinLoaders">platform classes</a> are visible to
      * the platform class loader.
      *
@@ -1843,7 +1843,7 @@
     }
 
     /**
-     * Returns the system class loader for delegation.  This is the default
+     * Returns the system class loader.  This is the default
      * delegation parent for new {@code ClassLoader} instances, and is
      * typically the class loader used to start the application.
      *
@@ -1884,7 +1884,7 @@
      * the application module path then the class path defaults to
      * the current working directory.
      *
-     * @return  The system {@code ClassLoader} for delegation
+     * @return  The system {@code ClassLoader}
      *
      * @throws  SecurityException
      *          If a security manager is present, and the caller's class loader
--- a/src/java.base/share/classes/java/security/interfaces/DSAKeyPairGenerator.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/java.base/share/classes/java/security/interfaces/DSAKeyPairGenerator.java	Wed Nov 29 09:07:01 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -32,9 +32,12 @@
  *
  * <p>The {@code initialize} methods may each be called any number
  * of times. If no {@code initialize} method is called on a
- * DSAKeyPairGenerator, the default is to generate 1024-bit keys, using
- * precomputed p, q and g parameters and an instance of SecureRandom as
- * the random bit source.
+ * DSAKeyPairGenerator, each provider that implements this interface
+ * should supply (and document) a default initialization. Note that
+ * defaults may vary across different providers. Additionally, the default
+ * value for a provider may change in a future version. Therefore, it is
+ * recommended to explicitly initialize the DSAKeyPairGenerator instead
+ * of relying on provider-specific defaults.
  *
  * <p>Users wishing to indicate DSA-specific parameters, and to generate a key
  * pair suitable for use with the DSA algorithm typically
@@ -45,12 +48,13 @@
  * KeyPairGenerator {@code getInstance} method with "DSA"
  * as its argument.
  *
- * <li>Initialize the generator by casting the result to a DSAKeyPairGenerator
- * and calling one of the
- * {@code initialize} methods from this DSAKeyPairGenerator interface.
+ * <li>Check if the returned key pair generator is an instance of
+ * DSAKeyPairGenerator before casting the result to a DSAKeyPairGenerator
+ * and calling one of the {@code initialize} methods from this
+ * DSAKeyPairGenerator interface.
  *
  * <li>Generate a key pair by calling the {@code generateKeyPair}
- * method from the KeyPairGenerator class.
+ * method of the KeyPairGenerator class.
  *
  * </ol>
  *
@@ -63,7 +67,7 @@
  * parameters.
  *
  * <p>Note: Some earlier implementations of this interface may not support
- * larger sizes of DSA parameters such as 2048 and 3072-bit.
+ * larger values of DSA parameters such as 3072-bit.
  *
  * @since 1.1
  * @see java.security.KeyPairGenerator
@@ -97,8 +101,7 @@
      * p, q and g parameters. If it is false, the method uses precomputed
      * parameters for the modulus length requested. If there are no
      * precomputed parameters for that modulus length, an exception will be
-     * thrown. It is guaranteed that there will always be
-     * default parameters for modulus lengths of 512 and 1024 bits.
+     * thrown.
      *
      * @param modlen the modulus length in bits. Valid values are any
      * multiple of 64 between 512 and 1024, inclusive, 2048, and 3072.
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor6.java	Wed Nov 29 09:07:01 2017 -0800
@@ -257,7 +257,7 @@
      *
      * @implSpec This implementation dispatches to the visit method for
      * the specific {@linkplain TypeKind kind} of pseudo-type:
-     * {@code VOID}, {@code PACKAGE}, or {@code NONE}.
+     * {@code VOID}, {@code PACKAGE}, {@code MODULE}, or {@code NONE}.
      *
      * @param t {@inheritDoc}
      * @param p {@inheritDoc}
@@ -273,6 +273,9 @@
         case PACKAGE:
             return visitNoTypeAsPackage(t, p);
 
+        case MODULE:
+            return visitNoTypeAsModule(t, p);
+
         case NONE:
             return visitNoTypeAsNone(t, p);
 
@@ -308,6 +311,21 @@
     }
 
     /**
+     * Visits a {@link TypeKind#MODULE MODULE} pseudo-type.
+     *
+     * @implSpec This implementation calls {@code visitUnknown}.
+     *
+     * @param t the type to visit
+     * @param p a visitor-specified parameter
+     * @return  the result of {@code visitUnknown}
+     *
+     * @since 10
+     */
+    public R visitNoTypeAsModule(NoType t, P p) {
+        return visitUnknown(t, p);
+    }
+
+    /**
      * Visits a {@link TypeKind#NONE NONE} pseudo-type.
      *
      * @implSpec This implementation calls {@code defaultAction}.
--- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor9.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor9.java	Wed Nov 29 09:07:01 2017 -0800
@@ -93,4 +93,20 @@
     protected TypeKindVisitor9(R defaultValue) {
         super(defaultValue);
     }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @implSpec This implementation calls {@code defaultAction}.
+     *
+     * @param t {@inheritDoc}
+     * @param p {@inheritDoc}
+     * @return  the result of {@code defaultAction}
+     *
+     * @since 10
+     */
+    @Override
+    public R visitNoTypeAsModule(NoType t, P p) {
+        return defaultAction(t, p);
+    }
 }
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Analyzer.java	Wed Nov 29 09:07:01 2017 -0800
@@ -63,6 +63,7 @@
 import com.sun.tools.javac.util.ListBuffer;
 import com.sun.tools.javac.util.Log;
 import com.sun.tools.javac.util.Options;
+import com.sun.tools.javac.util.Position;
 
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -305,7 +306,7 @@
             JCMethodDecl md = (JCMethodDecl)decls(oldTree.def).head;
             List<JCVariableDecl> params = md.params;
             JCBlock body = md.body;
-            JCLambda newTree = make.Lambda(params, body);
+            JCLambda newTree = make.at(oldTree).Lambda(params, body);
             return List.of(newTree);
         }
 
@@ -418,7 +419,7 @@
         List<JCEnhancedForLoop> rewrite(JCEnhancedForLoop oldTree) {
             JCEnhancedForLoop newTree = copier.copy(oldTree);
             newTree.var = rewriteVarType(oldTree.var);
-            newTree.body = make.Block(0, List.nil());
+            newTree.body = make.at(oldTree.body).Block(0, List.nil());
             return List.of(newTree);
         }
         @Override
@@ -551,7 +552,8 @@
             JCStatement treeToAnalyze = (JCStatement)rewriting.originalTree;
             if (rewriting.env.info.scope.owner.kind == Kind.TYP) {
                 //add a block to hoist potential dangling variable declarations
-                treeToAnalyze = make.Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
+                treeToAnalyze = make.at(Position.NOPOS)
+                                    .Block(Flags.SYNTHETIC, List.of((JCStatement)rewriting.originalTree));
             }
 
             //TODO: to further refine the analysis, try all rewriting combinations
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ArgumentAttr.java	Wed Nov 29 09:07:01 2017 -0800
@@ -57,6 +57,7 @@
 import com.sun.tools.javac.util.Assert;
 import com.sun.tools.javac.util.Context;
 import com.sun.tools.javac.util.DiagnosticSource;
+import com.sun.tools.javac.util.JCDiagnostic;
 import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
 import com.sun.tools.javac.util.List;
 import com.sun.tools.javac.util.ListBuffer;
@@ -98,6 +99,7 @@
     protected static final Context.Key<ArgumentAttr> methodAttrKey = new Context.Key<>();
 
     private final DeferredAttr deferredAttr;
+    private final JCDiagnostic.Factory diags;
     private final Attr attr;
     private final Symtab syms;
     private final Log log;
@@ -121,6 +123,7 @@
     protected ArgumentAttr(Context context) {
         context.put(methodAttrKey, this);
         deferredAttr = DeferredAttr.instance(context);
+        diags = JCDiagnostic.Factory.instance(context);
         attr = Attr.instance(context);
         syms = Symtab.instance(context);
         log = Log.instance(context);
@@ -482,18 +485,14 @@
         List<JCReturn> returnExpressions() {
             return returnExpressions.orElseGet(() -> {
                 final List<JCReturn> res;
-                if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION) {
-                    res = List.of(attr.make.Return((JCExpression)speculativeTree.body));
-                } else {
-                    ListBuffer<JCReturn> returnExpressions = new ListBuffer<>();
-                    new LambdaReturnScanner() {
-                        @Override
-                        public void visitReturn(JCReturn tree) {
-                            returnExpressions.add(tree);
-                        }
-                    }.scan(speculativeTree.body);
-                    res = returnExpressions.toList();
-                }
+                ListBuffer<JCReturn> buf = new ListBuffer<>();
+                new LambdaReturnScanner() {
+                    @Override
+                    public void visitReturn(JCReturn tree) {
+                        buf.add(tree);
+                    }
+                }.scan(speculativeTree.body);
+                res = buf.toList();
                 returnExpressions = Optional.of(res);
                 return res;
             });
@@ -519,16 +518,38 @@
         private void checkLambdaCompatible(Type descriptor, ResultInfo resultInfo) {
             CheckContext checkContext = resultInfo.checkContext;
             ResultInfo bodyResultInfo = attr.lambdaBodyResult(speculativeTree, descriptor, resultInfo);
-            for (JCReturn ret : returnExpressions()) {
-                Type t = getReturnType(ret);
-                if (speculativeTree.getBodyKind() == BodyKind.EXPRESSION || !t.hasTag(VOID)) {
-                    checkSpeculative(ret.expr, t, bodyResultInfo);
-                }
+            switch (speculativeTree.getBodyKind()) {
+                case EXPRESSION:
+                    checkSpeculative(speculativeTree.body, speculativeTree.body.type, bodyResultInfo);
+                    break;
+                case STATEMENT:
+                    for (JCReturn ret : returnExpressions()) {
+                        checkReturnInStatementLambda(ret, bodyResultInfo);
+                    }
+                    break;
             }
 
             attr.checkLambdaCompatible(speculativeTree, descriptor, checkContext);
         }
 
+        /**
+         * This is an inlined version of {@link Attr#visitReturn(JCReturn)}.
+         */
+        void checkReturnInStatementLambda(JCReturn ret, ResultInfo resultInfo) {
+            if (resultInfo.pt.hasTag(VOID) && ret.expr != null) {
+                //fail - if the function type's result is void, the lambda body must be a void-compatible block.
+                resultInfo.checkContext.report(speculativeTree.pos(),
+                        diags.fragment("unexpected.ret.val"));
+            } else if (!resultInfo.pt.hasTag(VOID)) {
+                if (ret.expr == null) {
+                    //fail - if the function type's result is non-void, the lambda body must be a value-compatible block.
+                    resultInfo.checkContext.report(speculativeTree.pos(),
+                            diags.fragment("missing.ret.val"));
+                }
+                checkSpeculative(ret.expr, ret.expr.type, resultInfo);
+            }
+        }
+
         /** Get the type associated with given return expression. */
         Type getReturnType(JCReturn ret) {
             if (ret.expr == null) {
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Wed Nov 29 09:07:01 2017 -0800
@@ -3557,18 +3557,19 @@
                                       Scope staticallyImportedSoFar, Scope topLevelScope,
                                       Symbol sym, boolean staticImport) {
         Filter<Symbol> duplicates = candidate -> candidate != sym && !candidate.type.isErroneous();
-        Symbol clashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
-        if (clashing == null && !staticImport) {
-            clashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
+        Symbol ordinaryClashing = ordinallyImportedSoFar.findFirst(sym.name, duplicates);
+        Symbol staticClashing = null;
+        if (ordinaryClashing == null && !staticImport) {
+            staticClashing = staticallyImportedSoFar.findFirst(sym.name, duplicates);
         }
-        if (clashing != null) {
-            if (staticImport)
-                log.error(pos, Errors.AlreadyDefinedStaticSingleImport(clashing));
+        if (ordinaryClashing != null || staticClashing != null) {
+            if (ordinaryClashing != null)
+                log.error(pos, Errors.AlreadyDefinedSingleImport(ordinaryClashing));
             else
-                log.error(pos, Errors.AlreadyDefinedSingleImport(clashing));
+                log.error(pos, Errors.AlreadyDefinedStaticSingleImport(staticClashing));
             return false;
         }
-        clashing = topLevelScope.findFirst(sym.name, duplicates);
+        Symbol clashing = topLevelScope.findFirst(sym.name, duplicates);
         if (clashing != null) {
             log.error(pos, Errors.AlreadyDefinedThisUnit(clashing));
             return false;
--- a/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.dynalink/share/classes/jdk/dynalink/beans/BeanLinker.java	Wed Nov 29 09:07:01 2017 -0800
@@ -91,6 +91,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.function.Function;
 import jdk.dynalink.CallSiteDescriptor;
 import jdk.dynalink.Namespace;
 import jdk.dynalink.Operation;
@@ -189,85 +190,126 @@
         assertParameterCount(callSiteDescriptor, isFixedKey ? 1 : 2);
         final LinkerServices linkerServices = req.linkerServices;
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
-        final Class<?> declaredType = callSiteType.parameterType(0);
         final GuardedInvocationComponent nextComponent = getNextComponent(req);
 
+        final GuardedInvocationComponentAndCollectionType gicact = guardedInvocationComponentAndCollectionType(
+                callSiteType, linkerServices, MethodHandles::arrayElementGetter, GET_LIST_ELEMENT, GET_MAP_ELEMENT);
+
+        if (gicact == null) {
+            // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
+            return nextComponent;
+        }
+
+        final Object typedName = getTypedName(name, gicact.collectionType == CollectionType.MAP, linkerServices);
+        if (typedName == INVALID_NAME) {
+            return nextComponent;
+        }
+
+        return guardComponentWithRangeCheck(gicact, linkerServices,
+                callSiteDescriptor, nextComponent, new Binder(linkerServices, callSiteType, typedName),
+                isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2);
+    }
+
+    private static class GuardedInvocationComponentAndCollectionType {
+        final GuardedInvocationComponent gic;
+        final CollectionType collectionType;
+
+        GuardedInvocationComponentAndCollectionType(final GuardedInvocationComponent gic, final CollectionType collectionType) {
+            this.gic = gic;
+            this.collectionType = collectionType;
+        }
+    }
+
+    private GuardedInvocationComponentAndCollectionType guardedInvocationComponentAndCollectionType(
+            final MethodType callSiteType, final LinkerServices linkerServices,
+            final Function<Class<?>, MethodHandle> arrayMethod, final MethodHandle listMethod, final MethodHandle mapMethod) {
+        final Class<?> declaredType = callSiteType.parameterType(0);
         // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
         // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
         // dealing with an array, or a list or map, but hey...
         // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
         // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
-        final GuardedInvocationComponent gic;
-        final CollectionType collectionType;
         if(declaredType.isArray()) {
-            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementGetter(declaredType), linkerServices);
-            collectionType = CollectionType.ARRAY;
+            return new GuardedInvocationComponentAndCollectionType(
+                    createInternalFilteredGuardedInvocationComponent(arrayMethod.apply(declaredType), linkerServices),
+                    CollectionType.ARRAY);
         } else if(List.class.isAssignableFrom(declaredType)) {
-            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, linkerServices);
-            collectionType = CollectionType.LIST;
+            return new GuardedInvocationComponentAndCollectionType(
+                    createInternalFilteredGuardedInvocationComponent(listMethod, linkerServices),
+                    CollectionType.LIST);
         } else if(Map.class.isAssignableFrom(declaredType)) {
-            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, linkerServices);
-            collectionType = CollectionType.MAP;
+            return new GuardedInvocationComponentAndCollectionType(
+                    createInternalFilteredGuardedInvocationComponent(mapMethod, linkerServices),
+                    CollectionType.MAP);
         } else if(clazz.isArray()) {
-            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(MethodHandles.arrayElementGetter(clazz)), callSiteType);
-            collectionType = CollectionType.ARRAY;
+            return new GuardedInvocationComponentAndCollectionType(
+                    getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(arrayMethod.apply(clazz)), callSiteType),
+                    CollectionType.ARRAY);
         } else if(List.class.isAssignableFrom(clazz)) {
-            gic = createInternalFilteredGuardedInvocationComponent(GET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
-                    linkerServices);
-            collectionType = CollectionType.LIST;
+            return new GuardedInvocationComponentAndCollectionType(
+                    createInternalFilteredGuardedInvocationComponent(listMethod, Guards.asType(LIST_GUARD, callSiteType),
+                            List.class, ValidationType.INSTANCE_OF, linkerServices),
+                    CollectionType.LIST);
         } else if(Map.class.isAssignableFrom(clazz)) {
-            gic = createInternalFilteredGuardedInvocationComponent(GET_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType), Map.class, ValidationType.INSTANCE_OF,
-                    linkerServices);
-            collectionType = CollectionType.MAP;
-        } else {
-            // Can't retrieve elements for objects that are neither arrays, nor list, nor maps.
-            return nextComponent;
+            return new GuardedInvocationComponentAndCollectionType(
+                    createInternalFilteredGuardedInvocationComponent(mapMethod, Guards.asType(MAP_GUARD, callSiteType),
+                            Map.class, ValidationType.INSTANCE_OF, linkerServices),
+                    CollectionType.MAP);
         }
+        return null;
+    }
 
+    private static final Object INVALID_NAME = new Object();
+
+    private static Object getTypedName(final Object name, final boolean isMap, final LinkerServices linkerServices) throws Exception {
         // Convert the key to a number if we're working with a list or array
-        final Object typedName;
-        if (collectionType != CollectionType.MAP && isFixedKey) {
+        if (!isMap && name != null) {
             final Integer integer = convertKeyToInteger(name, linkerServices);
             if (integer == null || integer.intValue() < 0) {
                 // key is not a non-negative integer, it can never address an
                 // array or list element
-                return nextComponent;
+                return INVALID_NAME;
             }
-            typedName = integer;
-        } else {
-            typedName = name;
+            return integer;
         }
+        return name;
+    }
 
-        final GuardedInvocation gi = gic.getGuardedInvocation();
-        final Binder binder = new Binder(linkerServices, callSiteType, typedName);
-        final MethodHandle invocation = gi.getInvocation();
+    private static GuardedInvocationComponent guardComponentWithRangeCheck(
+            final GuardedInvocationComponentAndCollectionType gicact, final LinkerServices linkerServices,
+            final CallSiteDescriptor callSiteDescriptor, final GuardedInvocationComponent nextComponent, final Binder binder,
+            final MethodHandle noOp) {
+        final MethodType callSiteType = callSiteDescriptor.getMethodType();
 
         final MethodHandle checkGuard;
-        switch(collectionType) {
-        case LIST:
-            checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
-            break;
-        case MAP:
-            checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
-            break;
-        case ARRAY:
-            checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
-            break;
-        default:
-            throw new AssertionError();
+        switch(gicact.collectionType) {
+            case LIST:
+                checkGuard = convertArgToNumber(RANGE_CHECK_LIST, linkerServices, callSiteDescriptor);
+                break;
+            case MAP:
+                checkGuard = linkerServices.filterInternalObjects(CONTAINS_MAP);
+                break;
+            case ARRAY:
+                checkGuard = convertArgToNumber(RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
+                break;
+            default:
+                throw new AssertionError();
         }
 
-        // If there's no next component, produce a fixed null-returning one
+        // If there's no next component, produce a fixed no-op one
         final GuardedInvocationComponent finalNextComponent;
         if (nextComponent != null) {
             finalNextComponent = nextComponent;
         } else {
-            final MethodHandle nullGetterHandle = isFixedKey ? NULL_GETTER_1 : NULL_GETTER_2;
-            finalNextComponent = createGuardedInvocationComponentAsType(nullGetterHandle, callSiteType, linkerServices);
+            finalNextComponent = createGuardedInvocationComponentAsType(noOp, callSiteType, linkerServices);
         }
 
-        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
+        final GuardedInvocationComponent gic = gicact.gic;
+        final GuardedInvocation gi = gic.getGuardedInvocation();
+
+        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(gi.getInvocation()),
                 finalNextComponent.getGuardedInvocation().getInvocation());
+
         return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
                 gic.getValidatorClass(), gic.getValidationType());
     }
@@ -435,90 +477,37 @@
         assertParameterCount(callSiteDescriptor, isFixedKey ? 2 : 3);
         final LinkerServices linkerServices = req.linkerServices;
         final MethodType callSiteType = callSiteDescriptor.getMethodType();
-        final Class<?> declaredType = callSiteType.parameterType(0);
+
+        final GuardedInvocationComponentAndCollectionType gicact = guardedInvocationComponentAndCollectionType(
+                callSiteType, linkerServices, MethodHandles::arrayElementSetter, SET_LIST_ELEMENT, PUT_MAP_ELEMENT);
 
-        final GuardedInvocationComponent gic;
-        // If declared type of receiver at the call site is already an array, a list or map, bind without guard. Thing
-        // is, it'd be quite stupid of a call site creator to go though invokedynamic when it knows in advance they're
-        // dealing with an array, or a list or map, but hey...
-        // Note that for arrays and lists, using LinkerServices.asType() will ensure that any language specific linkers
-        // in use will get a chance to perform any (if there's any) implicit conversion to integer for the indices.
-        final CollectionType collectionType;
-        if(declaredType.isArray()) {
-            gic = createInternalFilteredGuardedInvocationComponent(MethodHandles.arrayElementSetter(declaredType), linkerServices);
-            collectionType = CollectionType.ARRAY;
-        } else if(List.class.isAssignableFrom(declaredType)) {
-            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, linkerServices);
-            collectionType = CollectionType.LIST;
-        } else if(Map.class.isAssignableFrom(declaredType)) {
-            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, linkerServices);
-            collectionType = CollectionType.MAP;
-        } else if(clazz.isArray()) {
-            gic = getClassGuardedInvocationComponent(linkerServices.filterInternalObjects(
-                    MethodHandles.arrayElementSetter(clazz)), callSiteType);
-            collectionType = CollectionType.ARRAY;
-        } else if(List.class.isAssignableFrom(clazz)) {
-            gic = createInternalFilteredGuardedInvocationComponent(SET_LIST_ELEMENT, Guards.asType(LIST_GUARD, callSiteType), List.class, ValidationType.INSTANCE_OF,
-                    linkerServices);
-            collectionType = CollectionType.LIST;
-        } else if(Map.class.isAssignableFrom(clazz)) {
-            gic = createInternalFilteredGuardedInvocationComponent(PUT_MAP_ELEMENT, Guards.asType(MAP_GUARD, callSiteType),
-                    Map.class, ValidationType.INSTANCE_OF, linkerServices);
-            collectionType = CollectionType.MAP;
-        } else {
-            // Can't set elements for objects that are neither arrays, nor list, nor maps.
-            gic = null;
-            collectionType = null;
+        if(gicact == null) {
+            return getNextComponent(req);
         }
 
+        final boolean isMap = gicact.collectionType == CollectionType.MAP;
+
         // In contrast to, say, getElementGetter, we only compute the nextComponent if the target object is not a map,
         // as maps will always succeed in setting the element and will never need to fall back to the next component
         // operation.
-        final GuardedInvocationComponent nextComponent = collectionType == CollectionType.MAP ? null : getNextComponent(req);
-        if(gic == null) {
+        final GuardedInvocationComponent nextComponent = isMap ? null : getNextComponent(req);
+
+        final Object typedName = getTypedName(name, isMap, linkerServices);
+        if (typedName == INVALID_NAME) {
             return nextComponent;
         }
 
-        // Convert the key to a number if we're working with a list or array
-        final Object typedName;
-        if (collectionType != CollectionType.MAP && isFixedKey) {
-            final Integer integer = convertKeyToInteger(name, linkerServices);
-            if (integer == null || integer.intValue() < 0) {
-                // key is not a non-negative integer, it can never address an
-                // array or list element
-                return nextComponent;
-            }
-            typedName = integer;
-        } else {
-            typedName = name;
-        }
-
+        final GuardedInvocationComponent gic = gicact.gic;
         final GuardedInvocation gi = gic.getGuardedInvocation();
         final Binder binder = new Binder(linkerServices, callSiteType, typedName);
         final MethodHandle invocation = gi.getInvocation();
 
-        if (collectionType == CollectionType.MAP) {
-            assert nextComponent == null;
+        if (isMap) {
             return gic.replaceInvocation(binder.bind(invocation));
         }
 
-        assert collectionType == CollectionType.LIST || collectionType == CollectionType.ARRAY;
-        final MethodHandle checkGuard = convertArgToNumber(collectionType == CollectionType.LIST ? RANGE_CHECK_LIST :
-            RANGE_CHECK_ARRAY, linkerServices, callSiteDescriptor);
-
-        // If there's no next component, produce a no-op one.
-        final GuardedInvocationComponent finalNextComponent;
-        if (nextComponent != null) {
-            finalNextComponent = nextComponent;
-        } else {
-            final MethodHandle noOpSetterHandle = isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3;
-            finalNextComponent = createGuardedInvocationComponentAsType(noOpSetterHandle, callSiteType, linkerServices);
-        }
-
-        final MethodPair matchedInvocations = matchReturnTypes(binder.bind(invocation),
-                finalNextComponent.getGuardedInvocation().getInvocation());
-        return finalNextComponent.compose(matchedInvocations.guardWithTest(binder.bindTest(checkGuard)), gi.getGuard(),
-                gic.getValidatorClass(), gic.getValidationType());
+        return guardComponentWithRangeCheck(gicact, linkerServices, callSiteDescriptor,
+                nextComponent, binder, isFixedKey ? NO_OP_SETTER_2 : NO_OP_SETTER_3);
     }
 
     private static final MethodHandle GET_COLLECTION_LENGTH = Lookup.PUBLIC.findVirtual(Collection.class, "size",
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Wed Nov 29 09:07:01 2017 -0800
@@ -1,10 +1,16 @@
-/* Javadoc style sheet */
-/*
-Overall document style
-*/
+/* 
+ * Javadoc style sheet
+ */
 
 @import url('resources/fonts/dejavu.css');
 
+/*
+ * Styles for individual HTML elements.
+ *
+ * These are styles that are specific to individual HTML elements. Changing them affects the style of a particular
+ * HTML element throughout the page.
+ */
+
 body {
     background-color:#ffffff;
     color:#353833;
@@ -41,9 +47,6 @@
     padding-top:129px;
     margin-top:-129px;
 }
-.searchTagResult:before, .searchTagResult:target {
-    color:red;
-}
 pre {
     font-family:'DejaVu Sans Mono', monospace;
     font-size:14px;
@@ -91,9 +94,16 @@
 sup {
     font-size:8px;
 }
+
 /*
-Document title and Copyright styles
-*/
+ * Styles for HTML generated by javadoc.
+ *
+ * These are style classes that are used by the standard doclet to generate HTML documentation.
+ */
+
+/*
+ * Styles for document title and copyright.
+ */
 .clear {
     clear:both;
     height:0px;
@@ -124,8 +134,8 @@
     font-weight:bold;
 }
 /*
-Navigation bar styles
-*/
+ * Styles for navigation bar.
+ */
 .bar {
     background-color:#4D7A97;
     color:#FFFFFF;
@@ -233,8 +243,8 @@
     overflow:hidden;
 }
 /*
-Page header and footer styles
-*/
+ * Styles for page header and footer.
+ */
 .header, .footer {
     clear:both;
     margin:0 20px;
@@ -277,8 +287,8 @@
     font-size:13px;
 }
 /*
-Heading styles
-*/
+ * Styles for headings.
+ */
 div.details ul.blockList ul.blockList ul.blockList li.blockList h4, div.details ul.blockList ul.blockList ul.blockListLast li.blockList h4 {
     background-color:#dee3e9;
     border:1px solid #d0d9e0;
@@ -299,8 +309,8 @@
     padding:0px 0 20px 0;
 }
 /*
-Page layout container styles
-*/
+ * Styles for page layout containers.
+ */
 .contentContainer, .sourceContainer, .classUseContainer, .serializedFormContainer, .constantValuesContainer {
     clear:both;
     padding:10px 20px;
@@ -346,8 +356,8 @@
     display:inline;
 }
 /*
-List styles
-*/
+ * Styles for lists.
+ */
 li.circle {
     list-style:circle;
 }
@@ -403,8 +413,8 @@
     margin-bottom:1px;
 }
 /*
-Table styles
-*/
+ * Styles for tables.
+ */
 .overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary,
 .requiresSummary, .packagesSummary, .providesSummary, .usesSummary {
     width:100%;
@@ -529,7 +539,6 @@
     position:relative;
     background-color:#4D7A97;
     float:left;
-
 }
 .rowColor th, .altColor th {
     font-weight:normal;
@@ -601,8 +610,8 @@
     background-color:#EEEEEF;
 }
 /*
-Content styles
-*/
+ * Styles for contents.
+ */
 .description pre {
     margin-top:0;
 }
@@ -613,27 +622,22 @@
 .docSummary {
     padding:0;
 }
-
 ul.blockList ul.blockList ul.blockList li.blockList h3 {
     font-style:normal;
 }
-
 div.block {
     font-size:14px;
     font-family:'DejaVu Serif', Georgia, "Times New Roman", Times, serif;
 }
-
 td.colLast div {
     padding-top:0px;
 }
-
-
 td.colLast a {
     padding-bottom:3px;
 }
 /*
-Formatting effect styles
-*/
+ * Styles for formatting effect.
+ */
 .sourceLineNo {
     color:green;
     padding:0 30px 0 0;
@@ -668,18 +672,16 @@
     margin-right:10px;
     display:inline-block;
 }
-
 div.block div.deprecationComment, div.block div.block span.emphasizedPhrase,
 div.block div.block span.interfaceName {
     font-style:normal;
 }
-
 div.contentContainer ul.blockList li.blockList h2 {
     padding-bottom:0px;
 }
 /*
-IFRAME specific styles
-*/
+ * Styles for IFRAME.
+ */
 .mainContainer {
     margin:0 auto; 
     padding:0; 
@@ -733,11 +735,14 @@
     margin-bottom:30px;
 }
 /*
-HTML5 specific styles
-*/
+ * Styles specific to HTML5 elements.
+ */
 main, nav, header, footer, section {
     display:block;
 }
+/*
+ * Styles for javadoc search.
+ */
 .ui-autocomplete-category {
     font-weight:bold;
     font-size:15px;
@@ -802,7 +807,9 @@
     font-style:italic;
     font-size:12px;
 }
-
+.searchTagResult:before, .searchTagResult:target {
+    color:red;
+}
 .moduleGraph span {
     display:none;
     position:absolute;
@@ -838,20 +845,17 @@
     margin-top: 10px;
     margin-bottom: 10px;
 }
-
 table.borderless > caption,
 table.plain > caption,
 table.striped > caption {
     font-weight: bold;
     font-size: smaller;
 }
-
 table.borderless th, table.borderless td,
 table.plain th, table.plain td,
 table.striped th, table.striped td {
     padding: 2px 5px;
 }
-
 table.borderless,
 table.borderless > thead > tr > th, table.borderless > tbody > tr > th, table.borderless > tr > th,
 table.borderless > thead > tr > td, table.borderless > tbody > tr > td, table.borderless > tr > td {
@@ -860,7 +864,6 @@
 table.borderless > thead > tr, table.borderless > tbody > tr, table.borderless > tr {
     background-color: transparent;
 }
-
 table.plain {
     border-collapse: collapse;
     border: 1px solid black;
@@ -872,7 +875,6 @@
 table.plain > thead > tr > td, table.plain > tbody > tr > td, table.plain > tr > td {
     border: 1px solid black;
 }
-
 table.striped {
     border-collapse: collapse;
     border: 1px solid black;
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Wed Nov 29 09:07:01 2017 -0800
@@ -306,10 +306,10 @@
 
     @Override
     public boolean enterVarNode(final VarNode varNode) {
-        if (!inSplitNode()) {
+        // ES6 block scoped declarations are already placed at their proper position by splitter
+        if (!inSplitNode() || varNode.isBlockScoped()) {
             return super.enterVarNode(varNode);
         }
-        assert !varNode.isBlockScoped(); //TODO: we must handle these too, but we currently don't
 
         final Expression init = varNode.getInit();
 
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Splitter.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/Splitter.java	Wed Nov 29 09:07:01 2017 -0800
@@ -41,6 +41,7 @@
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.Splittable;
 import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.visitor.SimpleNodeVisitor;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.logging.DebugLogger;
@@ -201,8 +202,9 @@
 
         for (final Statement statement : block.getStatements()) {
             final long weight = WeighNodes.weigh(statement, weightCache);
+            final boolean isBlockScopedVarNode = isBlockScopedVarNode(statement);
 
-            if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal()) {
+            if (statementsWeight + weight >= SPLIT_THRESHOLD || statement.isTerminal() || isBlockScopedVarNode) {
                 if (!statements.isEmpty()) {
                     splits.add(createBlockSplitNode(block, function, statements, statementsWeight));
                     statements = new ArrayList<>();
@@ -210,7 +212,7 @@
                 }
             }
 
-            if (statement.isTerminal()) {
+            if (statement.isTerminal() || isBlockScopedVarNode) {
                 splits.add(statement);
             } else {
                 statements.add(statement);
@@ -243,6 +245,10 @@
         return new SplitNode(name, newBlock, compiler.findUnit(weight + WeighNodes.FUNCTION_WEIGHT));
     }
 
+    private boolean isBlockScopedVarNode(final Statement statement) {
+        return statement instanceof VarNode && ((VarNode) statement).isBlockScoped();
+    }
+
     @Override
     public boolean enterBlock(final Block block) {
         if (block.isCatchBlock()) {
--- a/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitReturn.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/SplitReturn.java	Wed Nov 29 09:07:01 2017 -0800
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.ir;
 
+import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
 /**
@@ -37,6 +38,7 @@
     private static final long serialVersionUID = 1L;
 
     /** The sole instance of this AST node. */
+    @Ignore
     public static final SplitReturn INSTANCE = new SplitReturn();
 
     private SplitReturn() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Cert.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * The certificates and corresponding private keys used by the test.
+ * All of certificates uses relative weak key size and hash algorithm, then
+ * all JDK releases can load them. Accordingly, a custom java.security file is
+ * provided to make sure such weak key sizes and algorithms are not blocked by
+ * any JDK build.
+ */
+public enum Cert {
+
+    // This certificate is generated by the below command:
+    // openssl req -x509 -newkey rsa:1024 -days 7300 \
+    //     -subj "/CN=RSA_SHA1_1024" -sha1 \
+    //     -keyout key.pem -out cert.pem
+    RSA_SHA1_1024(
+            SignatureAlgorithm.RSA,
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIIB/jCCAWegAwIBAgIJANPuKkD7/jxkMA0GCSqGSIb3DQEBBQUAMBgxFjAUBgNV\n" +
+            "BAMMDVJTQV9TSEExXzEwMjQwHhcNMTcwOTA3MDIwNTM0WhcNMzcwOTAyMDIwNTM0\n" +
+            "WjAYMRYwFAYDVQQDDA1SU0FfU0hBMV8xMDI0MIGfMA0GCSqGSIb3DQEBAQUAA4GN\n" +
+            "ADCBiQKBgQC3v7UeIxD5bdv4mqwcpah7sNxpI3IxUFzI2ao1g1jVzDPZt9Zawa3K\n" +
+            "H+m9al1Fg2X1dyNeRlbiXavcIZOQwZqNj08zJEwAdICP8iOnXQ2HUv5cpzArOPTu\n" +
+            "GY3flhf39xgiWsSdfb+cP0QsWNagNU8EtebbHndv8W+2K5JEdlpwQQIDAQABo1Aw\n" +
+            "TjAdBgNVHQ4EFgQU32KqdiGyzg39chNt/OwQzGOlUyAwHwYDVR0jBBgwFoAU32Kq\n" +
+            "diGyzg39chNt/OwQzGOlUyAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOB\n" +
+            "gQAWx8y45IIWWhy44cuQs0qcSDQihIvhXB3pvlpCNdfsSrVoaaH8lrOVjTC718ip\n" +
+            "fE1sF8I9niLHUg8WrAzdQRDsKyUhDUhEEJ7w1ffxwf8bcI9+NgWwEix0Dazzkub8\n" +
+            "2IRXuZ3dGwzoI54XtxvKMFH86nJEj4M/XQGrc9bnlhcn4g==\n" +
+            "-----END CERTIFICATE-----",
+            "30820278020100300d06092a864886f70d0101010500048202623082025e0201" +
+            "0002818100b7bfb51e2310f96ddbf89aac1ca5a87bb0dc69237231505cc8d9aa" +
+            "358358d5cc33d9b7d65ac1adca1fe9bd6a5d458365f577235e4656e25dabdc21" +
+            "9390c19a8d8f4f33244c0074808ff223a75d0d8752fe5ca7302b38f4ee198ddf" +
+            "9617f7f718225ac49d7dbf9c3f442c58d6a0354f04b5e6db1e776ff16fb62b92" +
+            "44765a7041020301000102818100b2c5afdf5c5a9d72c73b7eb0c9465b3fcc79" +
+            "0549d946255bc0861555ef2eb503f1c67757f400cfa7019996123020fb906d5b" +
+            "b66b789ffba90b16270cbd1fbfcf285a821dcdc78fd8f17f399eb231ce9724db" +
+            "af60f9dd20f3e57bb4c0f9fdc9069589b82d442dd868d48c031eb782e27f9e70" +
+            "8469f9b3d5b1b23cee5bf1b41781024100dec184ea77c2126c6bc0c01ba727b4" +
+            "642587d63811240932334dc80c7976e0f715f156e52b352a25e5c52542af2b5f" +
+            "68a29a9b68858f313c4375cc78ec03d859024100d32be8375f52cbe904002321" +
+            "6977aee83fa88bf536d4052d2ed578727d7b7e5aeef91fc52b34c1b6638c00f0" +
+            "4c6985fdaaa2d6e72adbcc7d10ed8bafff69da29024100ae8210acd6f13519b7" +
+            "38a3c7862636ce1610daa3c5d9e3526e9acad3eafc54b57d7d3a44029b7dcf7e" +
+            "b7f9beca1842806892929949b8aa2bb9f5b9202a55c0d1024100887dc0c2c9a2" +
+            "429a823374818c2207b3a631d304d443867505e884c9bbc1ae9228146e2c8b18" +
+            "b67ca52b411010d3c3ff89e366f454076dcd08bc01a5e8790ac102402321988a" +
+            "2003e19c878791d402a7c0acdd1b6dd27203ed88f86a0e3a390ee57c0cd277f3" +
+            "ea5df6440dbc8bdb4c8b3c28fc77e6991bc4ed3f4dc0619a5b953e8e"),
+
+    // This certificate is generated by the below command:
+    // openssl req -x509 -newkey rsa:1024 -days 7300 \
+    //     -subj "/CN=www.example.com" -sha1 \
+    //     -keyout key.pem -out cert.pem
+    RSA_EXAMPLE_SHA1_1024(
+            SignatureAlgorithm.RSA,
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIICAjCCAWugAwIBAgIJAK6TC9eDtZg4MA0GCSqGSIb3DQEBBQUAMBoxGDAWBgNV\n" +
+            "BAMMD3d3dy5leGFtcGxlLmNvbTAeFw0xNzExMDIwNTA5NDRaFw0zNzEwMjgwNTA5\n" +
+            "NDRaMBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEF\n" +
+            "AAOBjQAwgYkCgYEAtt5kxFTzJuoxJR2UgeXUxCw7TfL3FeK3lCrU3vruBe3XKKvF\n" +
+            "oyCxf/B5ucm22gzMfOvJBWRg6KrNTrXGI1LtlmAYNDM5J0lK2N/neKOm3Qxe0d1W\n" +
+            "AZ1lwgrMNirsWu+r4UPNMq5UohL5nqVU9WwVa12t0GF3er3k32tMTBqSclcCAwEA\n" +
+            "AaNQME4wHQYDVR0OBBYEFNc8tKGfZdFyaY0ZslwGLt1kpRYAMB8GA1UdIwQYMBaA\n" +
+            "FNc8tKGfZdFyaY0ZslwGLt1kpRYAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEF\n" +
+            "BQADgYEAc71ZO83YEw9WvhxDEng9tMYUhJnNZJss6+gfWjZ487aiEGnS+VgKsHWz\n" +
+            "DBLBrYe9Ag5L9f1HtPNheUbnhhBbQ607jOG/wfmpi4VoU3myB5uxOfeAZdXDOB5x\n" +
+            "bv3t7KcEhgmPjB/e123jrBK8qnAYmDlQVlkZScctB3I1OuA2Po4=\n" +
+            "-----END CERTIFICATE-----",
+            "30820277020100300d06092a864886f70d0101010500048202613082025d0201" +
+            "0002818100b6de64c454f326ea31251d9481e5d4c42c3b4df2f715e2b7942ad4" +
+            "defaee05edd728abc5a320b17ff079b9c9b6da0ccc7cebc9056460e8aacd4eb5" +
+            "c62352ed96601834333927494ad8dfe778a3a6dd0c5ed1dd56019d65c20acc36" +
+            "2aec5aefabe143cd32ae54a212f99ea554f56c156b5dadd061777abde4df6b4c" +
+            "4c1a927257020301000102818048af52bc1acbdededd13d4930fa28b9441c47c" +
+            "b222f5c6fc92df07676db3a815a61c9b51de0a03a347b10a609bd6459a0dd926" +
+            "38877261686a5c6bb1ca9e8ea2373870af7685e7d6cebd66faba65af2ef04bd9" +
+            "1244ae56900fcd6ce11207d8c4040176e4ba9fef3d563741a1027b229134cfe1" +
+            "c0a90d9c8eba9ce6349835e769024100e82494b6f777c784ffc29298d033e11d" +
+            "af46f0d464c4dbd950d46bcd697d0f0b49a77699f0111d408e8748f2b461ab8f" +
+            "210071c9c20d8ecee3ae229cb9c3954b024100c9a976f0011fcdc0ca7fb2f679" +
+            "974fa85d420c604ca7ff64fe4667a44f73088eef290d22195474039760e99325" +
+            "3ca45ee444588b150467d14451d3c45dab0ba5024019df39d3ca70c703c39d63" +
+            "c9342b1403c2ed1d1a0ec101df8e6a9e391e7099a4a068d187068261c8381a4b" +
+            "bf00eb81bb49ea4ac439a4592e25a1daa9acea67510241008c4640007497bdd4" +
+            "94473da26b33d06a29ecae9531dd4e2edf1cf42cfc42e53a1fac2b8183a3164c" +
+            "053999600c6fe15a4c682a3b1cb482ceb33a4416fc9ce52d024100e4f08cd10a" +
+            "5c8face0b20db86443d0a42e34dfdde236dae4f042a06dd3aff7ca159f8aa3b7" +
+            "854df41d510148096155204f2bf46c4a96e271747a4126a66ade6c"),
+
+    // This certificate is generated by the below commands:
+    // openssl dsaparam -genkey 1024 -out key.pem
+    // openssl req -x509 -new -key key.pem -days 7300 \
+    //     -subj "/CN=DSA_SHA1_1024" -sha1 -out cert.pem
+    DSA_SHA1_1024(
+            SignatureAlgorithm.DSA,
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIICuzCCAnugAwIBAgIJAMAMLRrhQWQFMAkGByqGSM44BAMwGDEWMBQGA1UEAwwN\n" +
+            "RFNBX1NIQTFfMTAyNDAeFw0xNzExMDIwNjA4MDRaFw0zNzEwMjgwNjA4MDRaMBgx\n" +
+            "FjAUBgNVBAMMDURTQV9TSEExXzEwMjQwggG2MIIBKwYHKoZIzjgEATCCAR4CgYEA\n" +
+            "8CspE1sE84pJ4YxzVHFEDNJvBaIxsbax03pDwNHr/ogP9PVwF9z1jT6hpC5WluHG\n" +
+            "g5n5gqpF2XpBhX2fKm1qqZWRxNvHKo0+zzAhUqMrvRJqcjlL4ijXndHldt67/VKS\n" +
+            "0eTKi9m64c+yJx80YYphCO5b93d2sTM29z8QZOlrbD8CFQCmttKnPAOk4uz8Z8cV\n" +
+            "uPGeGOMB9wKBgCItgPpAjW0srIwCaDysDNpydX6hB+1NTy1gFYl24n8edLGbR0mZ\n" +
+            "isteBd6LjMtgicRmtKZzKxW7igxoVvR3WHpTucFjms5NRNjPaj5wt3DxoXn4hyWk\n" +
+            "LzMvDeBvi+jKJiO0jnQ3+1NDOlAQy6ukeH59/gxZ3UmcNxDlAQ/IYHcpA4GEAAKB\n" +
+            "gEgvi72gL+zax7Y2hg4PL1PqZx2jFp0XlTIugiTrcsGytrAnn+/s2+3xVyVyvVMn\n" +
+            "0z5yL5eP9cdGA7qV1+7n6KJ8jNAhLCBSiC6x5ekd88aTlqnmt5lstk4w0Q0zSa58\n" +
+            "Hp6dCFg2Irk6Z9ERKaXJJBBS6reaFeATVROhN/LEEzzvo1AwTjAdBgNVHQ4EFgQU\n" +
+            "jb+HHABclGNR4lpf19nHFZpfwPQwHwYDVR0jBBgwFoAUjb+HHABclGNR4lpf19nH\n" +
+            "FZpfwPQwDAYDVR0TBAUwAwEB/zAJBgcqhkjOOAQDAy8AMCwCFDB3F/m6jsZdHaoy\n" +
+            "1xTp2U8uHBO+AhQYzeJuJd8/qRSDVLs8mesE8TQg2g==\n" +
+            "-----END CERTIFICATE-----",
+            "3082014a0201003082012b06072a8648ce3804013082011e02818100f02b2913" +
+            "5b04f38a49e18c735471440cd26f05a231b1b6b1d37a43c0d1ebfe880ff4f570" +
+            "17dcf58d3ea1a42e5696e1c68399f982aa45d97a41857d9f2a6d6aa99591c4db" +
+            "c72a8d3ecf302152a32bbd126a72394be228d79dd1e576debbfd5292d1e4ca8b" +
+            "d9bae1cfb2271f34618a6108ee5bf77776b13336f73f1064e96b6c3f021500a6" +
+            "b6d2a73c03a4e2ecfc67c715b8f19e18e301f7028180222d80fa408d6d2cac8c" +
+            "02683cac0cda72757ea107ed4d4f2d60158976e27f1e74b19b4749998acb5e05" +
+            "de8b8ccb6089c466b4a6732b15bb8a0c6856f477587a53b9c1639ace4d44d8cf" +
+            "6a3e70b770f1a179f88725a42f332f0de06f8be8ca2623b48e7437fb53433a50" +
+            "10cbaba4787e7dfe0c59dd499c3710e5010fc8607729041602146ef9db36045f" +
+            "bcd8c7fd82ba29c5c5057ed11c7f"),
+
+    // This certificate is generated by the below commands:
+    // openssl dsaparam -genkey 1024 -out key.pem
+    // openssl req -x509 -new -key key.pem -days 7300 \
+    //     -subj "/CN=www.example.com" -sha1 -out cert.pem
+    DSA_EXAMPLE_SHA1_1024(
+            SignatureAlgorithm.DSA,
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIICwDCCAoCgAwIBAgIJAI5mKbdK5ZqyMAkGByqGSM44BAMwGjEYMBYGA1UEAwwP\n" +
+            "d3d3LmV4YW1wbGUuY29tMB4XDTE3MTEwMjA1NDczOVoXDTM3MTAyODA1NDczOVow\n" +
+            "GjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMIIBtzCCASwGByqGSM44BAEwggEf\n" +
+            "AoGBANVGWRSlxVZQKlVrTDcU/6Mr8QFlR3kGKmkvdbTHH1EhcP7YlZ7CJ30VBDbN\n" +
+            "LS2HvN3HHNooJ7hHBheL5Yz8EZIUa95TzPukZ1TmCo9fufR5i9HWj9Z8jLhyqx3l\n" +
+            "iUZOYN9H0MSn4ftK6dr5oTz2ZGYDblXDCq6R8qZfuw1URFqrAhUArx0nmGEI/1S/\n" +
+            "qyxnV4I6ItOntxMCgYEAxZKIZ/7aOGfzaQG2wRFdD/viHBZkkcxCsgmPUroQVUIw\n" +
+            "dqmUnfYk8cb02LCevhhSwcjfocQsA3y1jufIUdWaHuIB9W3EsFJQNd/Byh9j/pRD\n" +
+            "7zH/8lnBzJh2S7y10Vg840STVo5+ekZb4E+W7KK5gUaEQ6kAtUIIB0xjNz7RWs4D\n" +
+            "gYQAAoGAPVQKWqJSlMrbU4XEsx50Ur8P84CwMnS7WcQNLnih1ScaK2BijgVj5Fny\n" +
+            "9JZxITwj7XD7FWriq3kTjbydi3iAvrgVWij79x5Z7fTRCuoBVmtnAFkVGalwbGr2\n" +
+            "ghz70y6hep2Evb1pRCrHjRkMaJFE5Y2CA7VbpKoat+j47/LkXJ2jUDBOMB0GA1Ud\n" +
+            "DgQWBBSVjWy3SpaDfnFo+37mZJqX2aybzTAfBgNVHSMEGDAWgBSVjWy3SpaDfnFo\n" +
+            "+37mZJqX2aybzTAMBgNVHRMEBTADAQH/MAkGByqGSM44BAMDLwAwLAIUd5NOlcfX\n" +
+            "5rakT9H8UzlFcFQLr0MCFGrEYvlFUf/HJOH4FwXS2jEholBB\n" +
+            "-----END CERTIFICATE-----",
+            "3082014c0201003082012c06072a8648ce3804013082011f02818100d5465914" +
+            "a5c556502a556b4c3714ffa32bf101654779062a692f75b4c71f512170fed895" +
+            "9ec2277d150436cd2d2d87bcddc71cda2827b84706178be58cfc1192146bde53" +
+            "ccfba46754e60a8f5fb9f4798bd1d68fd67c8cb872ab1de589464e60df47d0c4" +
+            "a7e1fb4ae9daf9a13cf66466036e55c30aae91f2a65fbb0d54445aab021500af" +
+            "1d27986108ff54bfab2c6757823a22d3a7b71302818100c5928867feda3867f3" +
+            "6901b6c1115d0ffbe21c166491cc42b2098f52ba1055423076a9949df624f1c6" +
+            "f4d8b09ebe1852c1c8dfa1c42c037cb58ee7c851d59a1ee201f56dc4b0525035" +
+            "dfc1ca1f63fe9443ef31fff259c1cc98764bbcb5d1583ce34493568e7e7a465b" +
+            "e04f96eca2b981468443a900b54208074c63373ed15ace0417021500abf47692" +
+            "88c6ac41e2802e7eb7addba367339318"),
+
+    // This certificate is generated by the below commands:
+    // openssl ecparam -name prime256v1 -genkey -out key.pem
+    // openssl req -new -key key.pem -x509 -nodes -days 7300 \
+    //     -subj "/CN=ECDSA_SHA1_prime256v1" -sha1 -out cert.pem
+    ECDSA_SHA1_PRIME256V1(
+            SignatureAlgorithm.ECDSA,
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIIBhDCCASygAwIBAgIJAKW4wuujp9JbMAkGByqGSM49BAEwIDEeMBwGA1UEAwwV\n" +
+            "RUNEU0FfU0hBMV9wcmltZTI1NnYxMB4XDTE3MDkwNzAyMTA0MVoXDTM3MDkwMjAy\n" +
+            "MTA0MVowIDEeMBwGA1UEAwwVRUNEU0FfU0hBMV9wcmltZTI1NnYxMFkwEwYHKoZI\n" +
+            "zj0CAQYIKoZIzj0DAQcDQgAEdbE+AMwsFBf73YXRVwsvsx2dMt1xgDxj/4pN+BfY\n" +
+            "LWnO94beeZcrCJ1/N8CHmDOce7KRDR6/9kpi20wFAVXZ3KNQME4wHQYDVR0OBBYE\n" +
+            "FA/hB2ODDNdz1JF08u2uhknhlsVoMB8GA1UdIwQYMBaAFA/hB2ODDNdz1JF08u2u\n" +
+            "hknhlsVoMAwGA1UdEwQFMAMBAf8wCQYHKoZIzj0EAQNHADBEAiBNxv2L2FW+6+w/\n" +
+            "QtDe+YSUNRj3F8QrpLkfGk7rVaOiHQIgVF2pWJ5ytg0pbCuO8Bh+UZ7zfZUD03s8\n" +
+            "ZuIYW7RtMe0=\n" +
+            "-----END CERTIFICATE-----",
+            "308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02" +
+            "010104204d901d5efd0e3def78d5307788a4c760115effce4b9e2c31ae5860b6" +
+            "c11915aca1440342000475b13e00cc2c1417fbdd85d1570b2fb31d9d32dd7180" +
+            "3c63ff8a4df817d82d69cef786de79972b089d7f37c08798339c7bb2910d1ebf" +
+            "f64a62db4c050155d9dc"),
+
+    // This certificate is generated by the below commands:
+    // openssl ecparam -name prime256v1 -genkey -out key.pem
+    // openssl req -new -key key.pem -x509 -nodes -days 7300 \
+    //     -subj "/CN=www.example.com" -sha1 -out cert.pem
+    ECDSA_EXAMPLE_SHA1_PRIME256V1(
+            SignatureAlgorithm.ECDSA,
+            "-----BEGIN CERTIFICATE-----\n" +
+            "MIIBeDCCASCgAwIBAgIJAMxOXBpiJ5mDMAkGByqGSM49BAEwGjEYMBYGA1UEAwwP\n" +
+            "d3d3LmV4YW1wbGUuY29tMB4XDTE3MTEwMjA1MTg0MVoXDTM3MTAyODA1MTg0MVow\n" +
+            "GjEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0D\n" +
+            "AQcDQgAER9IyuwyrJ7X9DmIqGC3YNTlWBt4Fo/Y3RnlcxhTVxb/ZAYVNhqe4MbSM\n" +
+            "2nsVnYMjjXXDav1plNKvmgGDf9s/saNQME4wHQYDVR0OBBYEFHNUTaIIEA89uNKH\n" +
+            "OOUgJ981Qj5HMB8GA1UdIwQYMBaAFHNUTaIIEA89uNKHOOUgJ981Qj5HMAwGA1Ud\n" +
+            "EwQFMAMBAf8wCQYHKoZIzj0EAQNHADBEAiBCW59S1nE15j8euO6/q9bM6J9Ci5xJ\n" +
+            "WWAVznGGxnS/HgIgFaFKC31uxTXoBN7QN0yW/umQgJ0nsjwj7Pnxc0wNyw8=\n" +
+            "-----END CERTIFICATE-----",
+            "308187020100301306072a8648ce3d020106082a8648ce3d030107046d306b02" +
+            "010104209aa3784cd0c1fe0553e59b3c7b8f08c8fdaffd94f34e2c1683243a79" +
+            "7b64b673a1440342000447d232bb0cab27b5fd0e622a182dd835395606de05a3" +
+            "f63746795cc614d5c5bfd901854d86a7b831b48cda7b159d83238d75c36afd69" +
+            "94d2af9a01837fdb3fb1");
+
+    public final SignatureAlgorithm signatureAlgorithm;
+    public final String certMaterials;
+    public final String privKeyMaterials;
+
+    private Cert(
+            SignatureAlgorithm signatureAlgorithm,
+            String certMaterials,
+            String privKeyMaterials) {
+        this.signatureAlgorithm = signatureAlgorithm;
+        this.certMaterials = certMaterials;
+        this.privKeyMaterials = privKeyMaterials;
+    }
+
+    // Two certificates (mainCert and exampleCert) are selected to respect the
+    // specified cipher suite. SNI-associated cases specify exampleCert as desired.
+    public static Cert[] getCerts(String cipherSuite) {
+        Cert mainCert = Cert.DSA_SHA1_1024;
+        Cert exampleCert = Cert.DSA_EXAMPLE_SHA1_1024;
+        if (cipherSuite.contains("_ECDHE_RSA_")) {
+            mainCert = Cert.RSA_SHA1_1024;
+            exampleCert = Cert.RSA_EXAMPLE_SHA1_1024;
+        } else if (cipherSuite.contains("_EC")) {
+            mainCert = Cert.ECDSA_SHA1_PRIME256V1;
+            exampleCert = Cert.ECDSA_EXAMPLE_SHA1_PRIME256V1;
+        } else if (cipherSuite.contains("_RSA")) {
+            mainCert = Cert.RSA_SHA1_1024;
+            exampleCert = Cert.RSA_EXAMPLE_SHA1_1024;
+        }
+        System.out.printf("mainCert=%s, exampleCert=%s%n",
+                mainCert, exampleCert);
+        return new Cert[] { mainCert, exampleCert };
+    }
+}
+
+enum SignatureAlgorithm {
+
+    RSA, DSA, ECDSA;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Client.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+
+/*
+ * A simple SSL socket client.
+ */
+public class Client {
+
+    private final SSLSocket socket;
+
+    public Client(SSLContext context) throws Exception {
+        SSLSocketFactory socketFactory = context.getSocketFactory();
+        socket = (SSLSocket) socketFactory.createSocket();
+        socket.setSoTimeout(Utils.TIMEOUT);
+    }
+
+    public Client(Cert... certs) throws Exception {
+        this(Utils.createSSLContext(certs));
+    }
+
+    private SSLSession getSession() {
+        return socket.getSession();
+    }
+
+    private void setEnabledCipherSuites(String... cipherSuites) {
+        socket.setEnabledCipherSuites(cipherSuites);
+    }
+
+    private void setEnabledProtocols(String... protocols) {
+        socket.setEnabledProtocols(protocols);
+    }
+
+    @SuppressWarnings(value = { "unchecked", "rawtypes" })
+    private void setServerName(String hostname) {
+        List serverNames = new ArrayList();
+        serverNames.add(createSNIHostName(hostname));
+        SSLParameters params = socket.getSSLParameters();
+        params.setServerNames(serverNames);
+        socket.setSSLParameters(params);
+    }
+
+    // Create SNIHostName via reflection due to pre-8 JDK builds don't support
+    // SNI. Those JDK builds cannot find classes SNIServerName and SNIHostName.
+    private Object createSNIHostName(String hostname) {
+        try {
+            Class<?> clazz = Class.forName("javax.net.ssl.SNIHostName");
+            return clazz.getConstructor(String.class).newInstance(hostname);
+        } catch (Exception e) {
+            throw new RuntimeException("Creates SNIHostName failed!", e);
+        }
+    }
+
+    private void setApplicationProtocols(String... protocols) {
+        SSLParameters params = socket.getSSLParameters();
+        params.setApplicationProtocols(protocols);
+        socket.setSSLParameters(params);
+    }
+
+    private String getNegotiatedApplicationProtocol() {
+        return socket.getApplicationProtocol();
+    }
+
+    private void oneTimeConnect(String host, int port) throws IOException {
+        socket.connect(new InetSocketAddress(host, port));
+
+        OutputStream out = socket.getOutputStream();
+        out.write('C');
+        out.flush();
+
+        InputStream in = socket.getInputStream();
+        in.read();
+    }
+
+    public void close() throws IOException {
+        socket.close();
+    }
+
+    public static void main(String[] args) throws IOException {
+        System.out.println("----- Client start -----");
+        int port = Integer.valueOf(System.getProperty(Utils.PROP_PORT));
+
+        String protocol = System.getProperty(Utils.PROP_PROTOCOL);
+        String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
+        String serverName = System.getProperty(Utils.PROP_SERVER_NAME);
+        String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
+        boolean supportsSNIOnServer
+                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_SERVER);
+        boolean supportsSNIOnClient
+                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_SNI_ON_CLIENT);
+        boolean supportsALPNOnServer
+                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
+        boolean supportsALPNOnClient
+                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT);
+        boolean negativeCase
+                = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_CLIENT);
+        System.out.println(Utils.join(Utils.PARAM_DELIMITER,
+                "ClientJDK=" + System.getProperty(Utils.PROP_CLIENT_JDK),
+                "Protocol=" + protocol,
+                "CipherSuite=" + cipherSuite,
+                "ServerName=" + serverName,
+                "AppProtocols=" + appProtocols));
+
+        Status status = Status.SUCCESS;
+        Client client = null;
+        try {
+            client = new Client(Cert.getCerts(cipherSuite));
+            client.setEnabledProtocols(protocol);
+            client.setEnabledCipherSuites(cipherSuite);
+
+            if (serverName != null) {
+                if (supportsSNIOnClient) {
+                    client.setServerName(serverName);
+                } else {
+                    System.out.println(
+                            "Ignored due to client doesn't support SNI.");
+                }
+            }
+
+            if (appProtocols != null) {
+                if (supportsALPNOnClient) {
+                    client.setApplicationProtocols(
+                            Utils.split(appProtocols, Utils.VALUE_DELIMITER));
+                } else {
+                    System.out.println(
+                            "Ignored due to client doesn't support ALPN.");
+                }
+            }
+
+            client.oneTimeConnect("localhost", port);
+
+            if (serverName != null && supportsSNIOnServer
+                    && supportsSNIOnClient) {
+                X509Certificate cert
+                        = (X509Certificate) client.getSession().getPeerCertificates()[0];
+                String subject
+                        = cert.getSubjectX500Principal().getName();
+                if (!subject.contains(serverName)) {
+                    System.out.println("Unexpected server: " + subject);
+                    status = Status.FAIL;
+                }
+            }
+
+            if (appProtocols != null && supportsALPNOnServer
+                    && supportsALPNOnClient) {
+                String negoAppProtocol
+                        = client.getNegotiatedApplicationProtocol();
+                String expectedNegoAppProtocol
+                        = System.getProperty(Utils.PROP_NEGO_APP_PROTOCOL);
+                if (!expectedNegoAppProtocol.equals(negoAppProtocol)) {
+                    System.out.println("Unexpected negotiated app protocol: "
+                            + negoAppProtocol);
+                    status = Status.FAIL;
+                }
+            }
+
+            if (status != Status.FAIL) {
+                status = negativeCase
+                       ? Status.UNEXPECTED_SUCCESS
+                       : Status.SUCCESS;
+            }
+        } catch (Exception exception) {
+            status = Utils.handleException(exception, negativeCase);
+        } finally {
+            if (client != null) {
+                client.close();
+            }
+        }
+
+        System.out.println("STATUS: " + status);
+        System.out.println("----- Client end -----");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Compatibility.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,338 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @summary This test is used to check the interop compatibility on JSSE among
+ *     different JDK releases.
+ *     Note that, this is a manual test. For more details about the test and
+ *     its usages, please look through README.
+ *
+ * @library /test/lib
+ * @compile -source 1.6 -target 1.6 JdkUtils.java Parameter.java Server.java Client.java
+ * @run main/manual Compatibility
+ */
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class Compatibility {
+
+    public static void main(String[] args) throws Throwable {
+        String javaSecurityFile
+                = System.getProperty("test.src") + "/java.security";
+        boolean debug = Utils.getBoolProperty("debug");
+
+        Set<JdkInfo> jdkInfos = jdkInfoList();
+
+        System.out.println("Test start");
+
+        List<TestCase> testCases = new ArrayList<>();
+        ExecutorService executor = Executors.newCachedThreadPool();
+        PrintStream origStdOut = System.out;
+        PrintStream origStdErr = System.err;
+
+        try (PrintStream printStream = new PrintStream(
+                new FileOutputStream(Utils.TEST_LOG, true))) {
+            System.setOut(printStream);
+            System.setErr(printStream);
+
+            System.out.println(Utils.startHtml());
+            System.out.println(Utils.startPre());
+
+            for (UseCase useCase : UseCase.getAllUseCases()) {
+                for (JdkInfo serverJdk : jdkInfos) {
+                    if (useCase.ignoredByJdk(serverJdk)) {
+                        continue;
+                    }
+
+                    Map<String, String> props = new LinkedHashMap<>();
+                    if (debug) {
+                        props.put("javax.net.debug", "ssl");
+                    }
+                    props.put("java.security.properties", javaSecurityFile);
+
+                    props.put(Utils.PROP_PROTOCOL, useCase.protocol.version);
+                    props.put(Utils.PROP_CIPHER_SUITE, useCase.cipherSuite.name());
+                    props.put(Utils.PROP_CLIENT_AUTH, useCase.clientAuth.name());
+                    if (useCase.appProtocol != AppProtocol.NONE) {
+                        props.put(Utils.PROP_APP_PROTOCOLS,
+                                Utils.join(Utils.VALUE_DELIMITER,
+                                        useCase.appProtocol.appProtocols));
+                        props.put(Utils.PROP_NEGO_APP_PROTOCOL,
+                                useCase.appProtocol.negoAppProtocol);
+                    }
+                    props.put(Utils.PROP_SERVER_JDK, serverJdk.version);
+
+                    props.put(Utils.PROP_SUPPORTS_SNI_ON_SERVER,
+                            serverJdk.supportsSNI + "");
+                    props.put(Utils.PROP_SUPPORTS_ALPN_ON_SERVER,
+                            serverJdk.supportsALPN + "");
+
+                    for (JdkInfo clientJdk : jdkInfos) {
+                        if (useCase.ignoredByJdk(clientJdk)) {
+                            continue;
+                        }
+
+                        TestCase testCase = new TestCase(serverJdk, clientJdk,
+                                useCase);
+                        System.out.println(Utils.anchorName(testCase.toString(),
+                                "----- Case start -----"));
+                        System.out.println(testCase.toString());
+
+                        props.put(Utils.PROP_NEGATIVE_CASE_ON_SERVER,
+                                testCase.negativeCaseOnServer + "");
+                        props.put(Utils.PROP_NEGATIVE_CASE_ON_CLIENT,
+                                testCase.negativeCaseOnClient + "");
+
+                        Future<OutputAnalyzer> serverFuture = executor.submit(() -> {
+                            return runServer(serverJdk.jdkPath, props);
+                        });
+                        int port = waitForServerStarted();
+                        System.out.println("port=" + port);
+
+                        props.put(Utils.PROP_PORT, port + "");
+
+                        props.put(Utils.PROP_CLIENT_JDK, clientJdk.version);
+
+                        props.put(Utils.PROP_SUPPORTS_SNI_ON_CLIENT,
+                                clientJdk.supportsSNI + "");
+                        props.put(Utils.PROP_SUPPORTS_ALPN_ON_CLIENT,
+                                clientJdk.supportsALPN + "");
+                        if (useCase.serverName != ServerName.NONE) {
+                            props.put(Utils.PROP_SERVER_NAME,
+                                    useCase.serverName.name);
+                        }
+
+                        Status clientStatus = null;
+                        if (port != -1) {
+                            String clientOutput = runClient(clientJdk.jdkPath,
+                                    props).getOutput();
+                            clientStatus = getStatus(clientOutput);
+                        }
+
+                        String serverOutput = serverFuture.get().getOutput();
+                        Status serverStatus = getStatus(serverOutput);
+                        testCase.setStatus(caseStatus(serverStatus, clientStatus));
+                        testCases.add(testCase);
+                        System.out.printf(
+                                "ServerStatus=%s, ClientStatus=%s, CaseStatus=%s%n",
+                                serverStatus, clientStatus, testCase.getStatus());
+
+                        // Confirm the server has stopped.
+                        if(new File(Utils.PORT_LOG).exists()) {
+                            throw new RuntimeException("Server doesn't stop.");
+                        }
+                        System.out.println("----- Case end -----");
+                    }
+                }
+            }
+
+            System.out.println(Utils.endPre());
+            System.out.println(Utils.endHtml());
+        }
+        System.setOut(origStdOut);
+        System.setErr(origStdErr);
+        executor.shutdown();
+
+        System.out.println("Test end");
+        System.out.println("Report is being generated...");
+        boolean failed = generateReport(testCases);
+        System.out.println("Report is generated.");
+        if (failed) {
+            throw new RuntimeException("At least one case failed. "
+                    + "Please check logs for more details.");
+        }
+    }
+
+    private static Status getStatus(String log) {
+        if (log.contains(Status.UNEXPECTED_SUCCESS.name())) {
+            return Status.UNEXPECTED_SUCCESS;
+        } else if (log.contains(Status.SUCCESS.name())) {
+            return Status.SUCCESS;
+        } else if (log.contains(Status.EXPECTED_FAIL.name())) {
+            return Status.EXPECTED_FAIL;
+        } else if (log.contains(Status.TIMEOUT.name())) {
+            return Status.TIMEOUT;
+        } else {
+            return Status.FAIL;
+        }
+    }
+
+    private static Status caseStatus(Status serverStatus, Status clientStatus) {
+        if (clientStatus == null || clientStatus == Status.TIMEOUT) {
+            return serverStatus == Status.EXPECTED_FAIL
+                   ? Status.EXPECTED_FAIL
+                   : Status.FAIL;
+        } else if (serverStatus == Status.TIMEOUT) {
+            return clientStatus == Status.EXPECTED_FAIL
+                   ? Status.EXPECTED_FAIL
+                   : Status.FAIL;
+        } else {
+            return serverStatus == clientStatus
+                   ? serverStatus
+                   : Status.FAIL;
+        }
+    }
+
+    // Retrieves JDK info from the file which is specified by jdkListFile.
+    // If no such file or no JDK is specified by the file, the current testing
+    // JDK will be used.
+    private static Set<JdkInfo> jdkInfoList() throws Throwable {
+        List<String> jdkList = jdkList("jdkListFile");
+        if (jdkList.size() == 0) {
+            jdkList.add(System.getProperty("test.jdk"));
+        }
+
+        Set<JdkInfo> jdkInfoList = new LinkedHashSet<>();
+        for (String jdkPath : jdkList) {
+            JdkInfo jdkInfo = new JdkInfo(jdkPath);
+            // JDK version must be unique.
+            if (!jdkInfoList.add(jdkInfo)) {
+                System.out.println("The JDK version is duplicate: " + jdkPath);
+            }
+        }
+        return jdkInfoList;
+    }
+
+    private static List<String> jdkList(String listFileProp) throws IOException {
+        String listFile = System.getProperty(listFileProp);
+        System.out.println(listFileProp + "=" + listFile);
+        if (listFile != null && new File(listFile).exists()) {
+            return Files.lines(Paths.get(listFile))
+                        .filter(line -> { return !line.trim().isEmpty(); })
+                        .collect(Collectors.toList());
+        } else {
+            return new ArrayList<>();
+        }
+    }
+
+    // Checks if server is already launched, and returns server port.
+    private static int waitForServerStarted()
+            throws IOException, InterruptedException {
+        System.out.print("Waiting for server");
+        long deadline = System.currentTimeMillis() + Utils.TIMEOUT;
+        int port;
+        while ((port = getServerPort()) == -1
+                && System.currentTimeMillis() < deadline) {
+            System.out.print(".");
+            TimeUnit.SECONDS.sleep(1);
+        }
+        System.out.println();
+
+        return port;
+    }
+
+    // Retrieves the latest server port from port.log.
+    private static int getServerPort() throws IOException {
+        if (!new File(Utils.PORT_LOG).exists()) {
+            return -1;
+        }
+
+        return Integer.valueOf(
+                Files.lines(Paths.get(Utils.PORT_LOG)).findFirst().get());
+    }
+
+    private static OutputAnalyzer runServer(String jdkPath,
+            Map<String, String> props) {
+        return ProcessUtils.java(jdkPath, props, Server.class);
+    }
+
+    private static OutputAnalyzer runClient(String jdkPath,
+            Map<String, String> props) {
+        return ProcessUtils.java(jdkPath, props, Client.class);
+    }
+
+    // Generates the test result report.
+    private static boolean generateReport(List<TestCase> testCases)
+            throws IOException {
+        boolean failed = false;
+        StringBuilder report = new StringBuilder();
+        report.append(Utils.startHtml());
+        report.append(Utils.tableStyle());
+        report.append(Utils.startTable());
+        report.append(Utils.row(
+                "No.",
+                "ServerJDK",
+                "ClientJDK",
+                "Protocol",
+                "CipherSuite",
+                "ClientAuth",
+                "SNI",
+                "ALPN",
+                "Status"));
+        for (int i = 0, size = testCases.size(); i < size; i++) {
+            TestCase testCase = testCases.get(i);
+
+            report.append(Utils.row(
+                    Utils.anchorLink(
+                            Utils.TEST_LOG,
+                            testCase.toString(),
+                            i + ""),
+                    testCase.serverJdk.version,
+                    testCase.clientJdk.version,
+                    testCase.useCase.protocol.version,
+                    testCase.useCase.cipherSuite,
+                    Utils.boolToStr(
+                            testCase.useCase.clientAuth == ClientAuth.TRUE),
+                    Utils.boolToStr(
+                            testCase.useCase.serverName == ServerName.EXAMPLE),
+                    Utils.boolToStr(
+                            testCase.useCase.appProtocol == AppProtocol.EXAMPLE),
+                    testCase.getStatus()));
+            failed = failed
+                    || testCase.getStatus() == Status.FAIL
+                    || testCase.getStatus() == Status.UNEXPECTED_SUCCESS;
+        }
+        report.append(Utils.endTable());
+        report.append(Utils.endHtml());
+
+        generateFile("report.html", report.toString());
+        return failed;
+    }
+
+    private static void generateFile(String path, String content)
+            throws IOException {
+        try(FileWriter writer = new FileWriter(new File(path))) {
+            writer.write(content);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/JdkInfo.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * It represents a JDK with some specific attributes.
+ * If two JdkInfo instances have the same version value, the instances are
+ * regarded as equivalent.
+ */
+public class JdkInfo {
+
+    public final String jdkPath;
+
+    public final String version;
+    public final boolean supportsECKey;
+    public final boolean supportsSNI;
+    public final boolean supportsALPN;
+
+    public JdkInfo(String jdkPath) throws Throwable {
+        this.jdkPath = jdkPath;
+
+        String output = jdkAttributes(jdkPath);
+        if (output == null || output.trim().isEmpty()) {
+            throw new RuntimeException(
+                    "Cannot determine the JDK attributes: " + jdkPath);
+        }
+
+        String[] attributes = Utils.split(output, Utils.PARAM_DELIMITER);
+        version = attributes[0].replaceAll(".*=", "");
+        supportsECKey = Boolean.valueOf(attributes[1].replaceAll(".*=", ""));
+        supportsSNI = Boolean.valueOf(attributes[2].replaceAll(".*=", ""));
+        supportsALPN = Boolean.valueOf(attributes[3].replaceAll(".*=", ""));
+    }
+
+    // Determines the specific attributes for the specified JDK.
+    private static String jdkAttributes(String jdkPath) throws Throwable {
+        return ProcessUtils.java(jdkPath, null, JdkUtils.class).getOutput();
+    }
+
+    @Override
+    public int hashCode() {
+        return version == null ? 0 : version.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        JdkInfo other = (JdkInfo) obj;
+        if (version == null) {
+            if (other.version != null) {
+                return false;
+            }
+        } else if (!version.equals(other.version)) {
+            return false;
+        }
+        return true;
+    }
+
+    public boolean supportsCipherSuite(CipherSuite cipherSuite) {
+        JdkRelease jdkRelease = JdkRelease.getRelease(version);
+        return cipherSuite.startJdk.sequence <= jdkRelease.sequence
+                && (cipherSuite.endJdk == null
+                        || cipherSuite.endJdk.sequence >= jdkRelease.sequence);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/JdkRelease.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * JDK major versions.
+ */
+public enum JdkRelease {
+
+    JDK6(6, "1.6"),
+    JDK7(7, "1.7"),
+    JDK8(8, "1.8"),
+    JDK9(9, "9"),
+    JDK10(10, "10");
+
+    public final int sequence;
+    public final String release;
+
+    private JdkRelease(int sequence, String release) {
+        this.sequence = sequence;
+        this.release = release;
+    }
+
+    public static JdkRelease getRelease(String jdkVersion) {
+        if (jdkVersion.startsWith(JDK6.release)) {
+            return JDK6;
+        } else if (jdkVersion.startsWith(JDK7.release)) {
+            return JDK7;
+        } else if (jdkVersion.startsWith(JDK8.release)) {
+            return JDK8;
+        } else if (jdkVersion.startsWith(JDK9.release)) {
+            return JDK9;
+        } else if (jdkVersion.startsWith(JDK10.release)) {
+            return JDK10;
+        }
+
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/JdkUtils.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+
+import javax.net.ssl.SSLParameters;
+
+/*
+ * This class is used for returning some specific JDK information.
+ */
+public class JdkUtils {
+
+    public static final String JAVA_RUNTIME_VERSION = "javaRuntimeVersion";
+    public static final String SUPPORTS_EC_KEY = "supportsECKey";
+    public static final String SUPPORTS_SNI = "supportsSNI";
+    public static final String SUPPORTS_ALPN = "supportsALPN";
+
+    // Returns the JDK build version.
+    public static String javaRuntimeVersion() {
+        return System.getProperty("java.runtime.version");
+    }
+
+    // Checks if EC key algorithm is supported by the JDK build.
+    private static boolean supportsECKey() {
+        boolean isSupported = true;
+        try {
+            KeyFactory.getInstance("EC");
+        } catch (NoSuchAlgorithmException e) {
+            isSupported = false;
+        }
+        return isSupported;
+    }
+
+    // Checks if SNI is supported by the JDK build.
+    private static boolean supportsSNI() {
+        boolean isSupported = true;
+        try {
+            SSLParameters.class.getMethod("getServerNames");
+        } catch (NoSuchMethodException e) {
+            isSupported = false;
+        }
+        return isSupported;
+    }
+
+    // Checks if ALPN is supported by the JDK build.
+    private static boolean supportsALPN() {
+        boolean isSupported = true;
+        try {
+            SSLParameters.class.getMethod("getApplicationProtocols");
+        } catch (NoSuchMethodException e) {
+            isSupported = false;
+        }
+        return isSupported;
+    }
+
+    public static void main(String[] args) {
+        System.out.print(Utils.join(Utils.PARAM_DELIMITER,
+                attr(JAVA_RUNTIME_VERSION, javaRuntimeVersion()),
+                attr(SUPPORTS_EC_KEY, supportsECKey()),
+                attr(SUPPORTS_SNI, supportsSNI()),
+                attr(SUPPORTS_ALPN, supportsALPN())));
+    }
+
+    private static String attr(String name, Object value) {
+        return name + "=" + String.valueOf(value);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Parameter.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * A tagging interface that all TLS communication parameters must implement.
+ */
+public interface Parameter { }
+
+/* The followings are TLS communication parameters. */
+
+enum Protocol implements Parameter {
+
+    SSLV3_0(3, "SSLv3"),
+    TLSV1_0(4, "TLSv1"),
+    TLSV1_1(5, "TLSv1.1"),
+    TLSV1_2(6, "TLSv1.2");
+
+    public final int sequence;
+    public final String version;
+
+    private Protocol(int sequence, String version) {
+        this.sequence = sequence;
+        this.version = version;
+    }
+
+    static Protocol getProtocol(String version) {
+        for (Protocol protocol : values()) {
+            if (protocol.version.equals(version)) {
+                return protocol;
+            }
+        }
+
+        return null;
+    }
+
+    static Protocol[] getMandatoryValues() {
+        return new Protocol[] { TLSV1_0, TLSV1_1, TLSV1_2 };
+    }
+}
+
+enum CipherSuite implements Parameter {
+
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_RSA_WITH_AES_256_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA(),
+    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA(),
+    TLS_RSA_WITH_AES_256_CBC_SHA(),
+    TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA(),
+    TLS_ECDH_RSA_WITH_AES_256_CBC_SHA(),
+    TLS_DHE_RSA_WITH_AES_256_CBC_SHA(),
+    TLS_DHE_DSS_WITH_AES_256_CBC_SHA(),
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_RSA_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK7),
+    TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA(),
+    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA(),
+    TLS_RSA_WITH_AES_128_CBC_SHA(),
+    TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA(),
+    TLS_ECDH_RSA_WITH_AES_128_CBC_SHA(
+            Protocol.SSLV3_0, JdkRelease.JDK7),
+    TLS_DHE_RSA_WITH_AES_128_CBC_SHA(),
+    TLS_DHE_DSS_WITH_AES_128_CBC_SHA(),
+    TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_RSA_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_DHE_RSA_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_DHE_DSS_WITH_AES_256_GCM_SHA384(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_RSA_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_DHE_RSA_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_DHE_DSS_WITH_AES_128_GCM_SHA256(
+            Protocol.TLSV1_2, JdkRelease.JDK8),
+    TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA(),
+    TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA(),
+    TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA(),
+    TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA(),
+    TLS_ECDHE_ECDSA_WITH_RC4_128_SHA(),
+    TLS_ECDHE_RSA_WITH_RC4_128_SHA(),
+    TLS_ECDH_ECDSA_WITH_RC4_128_SHA(),
+    TLS_ECDH_RSA_WITH_RC4_128_SHA(),
+    SSL_RSA_WITH_RC4_128_SHA(),
+    SSL_RSA_WITH_3DES_EDE_CBC_SHA(),
+    SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA(
+            Protocol.SSLV3_0, JdkRelease.JDK6),
+    SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA(
+            Protocol.SSLV3_0, JdkRelease.JDK6),
+    SSL_RSA_WITH_RC4_128_MD5(
+            Protocol.SSLV3_0, JdkRelease.JDK6);
+
+    private static final boolean FULL_CIPHER_SUITES
+            = Utils.getBoolProperty("fullCipherSuites");
+
+    final Protocol startProtocol;
+    final Protocol endProtocol;
+
+    final JdkRelease startJdk;
+    final JdkRelease endJdk;
+
+    private CipherSuite(
+            Protocol startProtocol, Protocol endProtocol,
+            JdkRelease startJdk, JdkRelease endJdk) {
+        this.startProtocol = startProtocol;
+        this.endProtocol = endProtocol;
+
+        this.startJdk = startJdk;
+        this.endJdk = endJdk;
+    }
+
+    private CipherSuite(Protocol startProtocol, JdkRelease startJdk) {
+        this(startProtocol, null, startJdk, null);
+    }
+
+    private CipherSuite() {
+        this(Protocol.TLSV1_0, null, JdkRelease.JDK6, null);
+    }
+
+    boolean supportedByProtocol(Protocol protocol) {
+        return startProtocol.sequence <= protocol.sequence
+                && (endProtocol == null || endProtocol.sequence >= protocol.sequence);
+    }
+
+    static CipherSuite[] getMandatoryValues() {
+        return FULL_CIPHER_SUITES
+               ? values()
+               : new CipherSuite[] {
+                       TLS_RSA_WITH_AES_128_CBC_SHA,
+                       TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
+                       TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
+                       TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
+                       TLS_RSA_WITH_AES_256_CBC_SHA256,
+                       TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,
+                       TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,
+                       TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 };
+    }
+
+    static CipherSuite getCipherSuite(String name) {
+        for (CipherSuite cipherSuite : values()) {
+            if (cipherSuite.name().equals(name)) {
+                return cipherSuite;
+            }
+        }
+
+        return null;
+    }
+}
+
+enum ClientAuth implements Parameter {
+
+    FALSE,
+    TRUE;
+
+    static ClientAuth[] getMandatoryValues() {
+        return new ClientAuth[] { TRUE };
+    }
+}
+
+enum ServerName implements Parameter {
+
+    NONE(null),
+    EXAMPLE("www.example.com");
+
+    final String name;
+
+    private ServerName(String name) {
+        this.name = name;
+    }
+
+    static ServerName[] getMandatoryValues() {
+        return new ServerName[] { EXAMPLE };
+    }
+}
+
+enum AppProtocol implements Parameter {
+
+    NONE(null, null),
+    EXAMPLE(new String[] { Utils.HTTP_2, Utils.HTTP_1_1 }, Utils.HTTP_2);
+
+    final String[] appProtocols;
+
+    // Expected negotiated application protocol
+    final String negoAppProtocol;
+
+    private AppProtocol(String[] appProtocols, String negoAppProtocol) {
+        this.appProtocols = appProtocols;
+        this.negoAppProtocol = negoAppProtocol;
+    }
+
+    static AppProtocol[] getMandatoryValues() {
+        return new AppProtocol[] { EXAMPLE };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/ProcessUtils.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+/*
+ * Utilities for executing java process.
+ */
+public class ProcessUtils {
+
+    private static final String TEST_CLASSES = System.getProperty("test.classes");
+
+    public static OutputAnalyzer java(String jdkPath, Map<String, String> props,
+            Class<?> clazz) {
+        List<String> cmds = new ArrayList<>();
+        cmds.add(jdkPath + "/bin/java");
+
+        if (props != null) {
+            for (Map.Entry<String, String> prop : props.entrySet()) {
+                cmds.add("-D" + prop.getKey() + "=" + prop.getValue());
+            }
+        }
+
+        cmds.add("-cp");
+        cmds.add(TEST_CLASSES);
+        cmds.add(clazz.getName());
+        try {
+            return ProcessTools.executeCommand(
+                    cmds.toArray(new String[cmds.size()]));
+        } catch (Throwable e) {
+            throw new RuntimeException("Execute command failed: " + cmds, e);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/README	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,130 @@
+# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License version 2 only, as
+# published by the Free Software Foundation.
+#
+# This code is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+# version 2 for more details (a copy is included in the LICENSE file that
+# accompanied this code).
+#
+# You should have received a copy of the GNU General Public License version
+# 2 along with this work; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+# or visit www.oracle.com if you need additional information or have any
+# questions.
+
+##### Summary #####
+This test is used to check the interop compatibility on JSSE among different
+JDK releases. The oldest version supported by the test is JDK 6. Some of Java
+source files, JdkUtils.java, Parameter.java, Server.java, and Client.java, use
+only JDK 6-compliant language features and APIs, in order to allowing different
+JDK releases can load and run associated classes.
+
+##### Output #####
+The test can generate a report at $JTREG_WORKDIR/scratch/report.html to display
+the key information for each case. It also outputs all of details on both of
+server and client sides to a separated file at $JTREG_WORKDIR/scratch/test.html.
+
+##### Report Columns #####
+No.
+    A sequence number. It contains a hyper link to the corresponding details
+    in $JTREG_WORKDIR/scratch/test.html.
+
+ServerJDK
+    The version of the JDK that acts as server.
+
+ClientJDK
+    The version of the JDK that acts as client.
+
+Protocol
+    The TLS protocol version.
+
+CipherSuite
+    The only enabled cipher suite on both of server and client.
+
+ClientAuth
+    If the client authentication is checked, the value is "Y"; otherwise, "N".
+
+SNI
+    If the SNI is checked, the value is "Y"; otherwise, "N".
+
+ALPN
+    If the ALPN is checked, the value is "Y"; otherwise, "N".
+
+Status
+    It indicates the communication status for a test case.
+    There are three status:
+    SUCCESS: Communication succeed as expected.
+    UNEXPECTED_SUCCESS: Communication succeed as unexpected.
+    FAIL: Communication fails with unexpected failure.
+    EXPECTED_FAIL: Communication fails with expected failure.
+    Please note that, if a case finishes as status UNEXPECTED_SUCCESS or FAIL,
+    that means the case fails. Any failed case results in the test goes to fail.
+
+##### Usage #####
+jtreg [-options] \
+    [-Ddebug=<true|false>] \
+    [-DfullCases=<true|false>] \
+    [-DfullCipherSuites=<true|false>] \
+    [-DjdkListFile=</path/to/jdkListFile>] \
+    $JDK_WORKSPACE/test/jdk/javax/net/ssl/compatibility/Compatibility.java
+
+Besides the common jtreg options, like -jdk, this test introduces some more
+properties:
+debug
+    It indicates if the test enable -Djavax.net.ssl=debug. This is a boolean
+    property, and the default value is false.
+    It is not mandatory.
+
+fullCases
+    It indicates if testing the full or mandatory set of parameter values.
+    Every parameter provides a mandatory value set that must be covered.
+    For more details about the parameter value sets, please see Parameter.java.
+    This is a boolean property, and the default value is false.
+    It is not mandatory.
+
+fullCipherSuites
+    It indicates if testing the full or mandatory set of cipher suites.
+    For more details about the specific cipher suite sets, see CipherSuite in
+    Parameter.java.
+    This is a boolean property, and the default value is false.
+    It is not mandatory.
+
+jdkListFile
+    It indicate the path of a file, which lists the absolute paths of different
+    JDK builds. If no this property, the current testing JDK, specified by JTREG
+    option -jdk, is used as the testing JDK.
+    It is not mandatory.
+
+##### Usage Examples #####
+Example 1
+$ jtreg -jdk:/path/to/latest/jdk \
+    $JDK_WS/jdk/test/javax/net/ssl/compatibility/Compatibility.java
+This example doesn't specify any property introduced by the test. That means
+it uses the current testing JDK, namely /path/to/latest/jdk, as server and
+client. It doesn't output any debug log, and tests only mandatory parameter
+value sets.
+
+Example 2
+$ cat /path/to/jdkList
+/path/to/jdk6
+/path/to/jdk7
+/path/to/jdk8
+/path/to/jdk9
+/path/to/jdk10
+
+$ jtreg -jdk:/path/to/latest/jdk \
+    -Ddebug=true \
+    -DfullCipherSuites=true \
+    -DjdkListFile=/path/to/jdkList \
+    $JDK_WS/jdk/test/javax/net/ssl/compatibility/Compatibility.java
+The above example uses a file "/path/to/jdkList" to contain the paths of local
+different JDK builds through 6 to 10. The execution uses each of JDK builds as
+server and client respectively. And it enables SSL debug flag, and tests the
+full parameter value set.
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Server.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,171 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+
+/*
+ * A simple SSL socket server.
+ */
+public class Server {
+
+    private final SSLServerSocket serverSocket;
+
+    public Server(SSLContext context, int port) throws Exception {
+        SSLServerSocketFactory serverFactory = context.getServerSocketFactory();
+        serverSocket = (SSLServerSocket) serverFactory.createServerSocket(port);
+        serverSocket.setSoTimeout(Utils.TIMEOUT);
+    }
+
+    public Server(Cert[] certs, int port) throws Exception {
+        this(Utils.createSSLContext(certs), port);
+    }
+
+    public Server(Cert[] certs) throws Exception {
+        this(certs, 0);
+    }
+
+    private void setEnabledCipherSuites(String... cipherSuites) {
+        serverSocket.setEnabledCipherSuites(cipherSuites);
+    }
+
+    private void setEnabledProtocols(String... protocols) {
+        serverSocket.setEnabledProtocols(protocols);
+    }
+
+    private void setNeedClientAuth(boolean needClientAuth) {
+        serverSocket.setNeedClientAuth(needClientAuth);
+    }
+
+    private void setApplicationProtocols(String... protocols) {
+        SSLParameters params = serverSocket.getSSLParameters();
+        params.setApplicationProtocols(protocols);
+        serverSocket.setSSLParameters(params);
+    }
+
+    public int getPort() {
+        return serverSocket.getLocalPort();
+    }
+
+    private void accept() throws IOException {
+        SSLSocket socket = null;
+        try {
+            socket = (SSLSocket) serverSocket.accept();
+
+            InputStream in = socket.getInputStream();
+            in.read();
+
+            OutputStream out = socket.getOutputStream();
+            out.write('S');
+            out.flush();
+        } finally {
+            if (socket != null) {
+                socket.close();
+            }
+        }
+    }
+
+    public void close() throws IOException {
+        serverSocket.close();
+    }
+
+    public static void main(String[] args) throws IOException {
+        System.out.println("----- Server start -----");
+        String protocol = System.getProperty(Utils.PROP_PROTOCOL);
+        String cipherSuite = System.getProperty(Utils.PROP_CIPHER_SUITE);
+        boolean clientAuth
+                = Utils.getBoolProperty(Utils.PROP_CLIENT_AUTH);
+        String appProtocols = System.getProperty(Utils.PROP_APP_PROTOCOLS);
+        boolean supportsALPN
+                = Utils.getBoolProperty(Utils.PROP_SUPPORTS_ALPN_ON_SERVER);
+        boolean negativeCase
+                = Utils.getBoolProperty(Utils.PROP_NEGATIVE_CASE_ON_SERVER);
+
+        System.out.println(Utils.join(Utils.PARAM_DELIMITER,
+                "ServerJDK=" + System.getProperty(Utils.PROP_SERVER_JDK),
+                "Protocol=" + protocol,
+                "CipherSuite=" + cipherSuite,
+                "ClientAuth=" + clientAuth,
+                "AppProtocols=" + appProtocols));
+
+        Status status = Status.SUCCESS;
+        Server server = null;
+        try {
+            server = new Server(Cert.getCerts(cipherSuite));
+            System.out.println("port=" + server.getPort());
+            server.setNeedClientAuth(clientAuth);
+            server.setEnabledProtocols(protocol);
+            server.setEnabledCipherSuites(cipherSuite);
+            if (appProtocols != null) {
+                if (supportsALPN) {
+                    server.setApplicationProtocols(
+                            Utils.split(appProtocols, Utils.VALUE_DELIMITER));
+                } else {
+                    System.out.println(
+                            "Ignored due to server doesn't support ALPN.");
+                }
+            }
+
+            savePort(server.getPort());
+            server.accept();
+
+            status = negativeCase ? Status.UNEXPECTED_SUCCESS : Status.SUCCESS;
+        } catch (Exception exception) {
+            status = Utils.handleException(exception, negativeCase);
+        } finally {
+            if (server != null) {
+                server.close();
+            }
+
+            // Cleanups port.log.
+            File file = new File(Utils.PORT_LOG);
+            if (file.exists()) {
+                file.delete();
+            }
+        }
+
+        System.out.println("STATUS: " + status);
+        System.out.println("----- Server end -----");
+    }
+
+    private static void savePort(int port) throws IOException {
+        FileWriter writer = null;
+        try {
+            writer = new FileWriter(new File(Utils.PORT_LOG));
+            writer.write(port + "");
+        } finally {
+            if (writer != null) {
+                writer.close();
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Status.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * Test case result status.
+ */
+public enum Status {
+
+    SUCCESS, UNEXPECTED_SUCCESS, FAIL, EXPECTED_FAIL, TIMEOUT;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/TestCase.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * A test case for a specific TLS communication use case between two JDKs.
+ */
+public class TestCase {
+
+    public final JdkInfo serverJdk;
+    public final JdkInfo clientJdk;
+    public final UseCase useCase;
+
+    public final boolean negativeCaseOnServer;
+    public final boolean negativeCaseOnClient;
+
+    private Status status;
+
+    public TestCase(JdkInfo serverJdk, JdkInfo clientJdk, UseCase useCase) {
+        this.serverJdk = serverJdk;
+        this.clientJdk = clientJdk;
+        this.useCase = useCase;
+
+        negativeCaseOnServer = useCase.negativeCase
+                || !serverJdk.supportsCipherSuite(useCase.cipherSuite);
+        negativeCaseOnClient = useCase.negativeCase
+                || !clientJdk.supportsCipherSuite(useCase.cipherSuite);
+    }
+
+    public Status getStatus() {
+        return status;
+    }
+
+    public void setStatus(Status status) {
+        this.status = status;
+    }
+
+    @Override
+    public String toString() {
+        return Utils.join(Utils.PARAM_DELIMITER,
+                "ServerJDK=" + serverJdk.version,
+                "ClientJDK=" + clientJdk.version,
+                useCase.toString());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/UseCase.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+/*
+ * The TLS communication use case.
+ */
+public class UseCase {
+
+    private static final boolean FULL_CASES
+            = Utils.getBoolProperty("fullCases");
+
+    private static final Parameter[][] PARAMS = new Parameter[][] {
+            FULL_CASES ? Protocol.values() : Protocol.getMandatoryValues(),
+            FULL_CASES ? CipherSuite.values() : CipherSuite.getMandatoryValues(),
+            FULL_CASES ? ClientAuth.values() : ClientAuth.getMandatoryValues(),
+            FULL_CASES ? ServerName.values() : ServerName.getMandatoryValues(),
+            FULL_CASES ? AppProtocol.values() : AppProtocol.getMandatoryValues() };
+
+    public final Protocol protocol;
+    public final CipherSuite cipherSuite;
+    public final ClientAuth clientAuth;
+    public final ServerName serverName;
+    public final AppProtocol appProtocol;
+
+    public final boolean negativeCase;
+
+    public UseCase(
+            Protocol protocol,
+            CipherSuite cipherSuite,
+            ClientAuth clientAuth,
+            ServerName serverName,
+            AppProtocol appProtocol) {
+        this.protocol = protocol;
+        this.cipherSuite = cipherSuite;
+        this.clientAuth = clientAuth;
+        this.serverName = serverName;
+        this.appProtocol = appProtocol;
+
+        negativeCase = !cipherSuite.supportedByProtocol(protocol);
+    }
+
+    // JDK 6 doesn't support EC key algorithm.
+    public boolean ignoredByJdk(JdkInfo jdkInfo) {
+        return cipherSuite.name().contains("_EC") && !jdkInfo.supportsECKey;
+    }
+
+    @Override
+    public String toString() {
+        return Utils.join(Utils.PARAM_DELIMITER,
+                "Protocol=" + protocol.version,
+                "CipherSuite=" + cipherSuite,
+                "ClientAuth=" + clientAuth,
+                "ServerName=" + serverName,
+                "AppProtocols=" + appProtocol);
+    }
+
+    public static List<UseCase> getAllUseCases() {
+        List<UseCase> useCases = new ArrayList<>();
+        getUseCases(PARAMS, 0, new Parameter[PARAMS.length], useCases);
+        return useCases;
+    }
+
+    private static void getUseCases(Parameter[][] params, int index,
+            Parameter[] currentValues, List<UseCase> useCases) {
+        if (index == params.length) {
+            Protocol protocol = (Protocol) currentValues[0];
+            CipherSuite cipherSuite = (CipherSuite) currentValues[1];
+
+            UseCase useCase = new UseCase(
+                    protocol,
+                    cipherSuite,
+                    (ClientAuth) currentValues[2],
+                    (ServerName) currentValues[3],
+                    (AppProtocol) currentValues[4]);
+            useCases.add(useCase);
+        } else {
+            Parameter[] values = params[index];
+            for (int i = 0; i < values.length; i++) {
+                currentValues[index] = values[i];
+                getUseCases(params, index + 1, currentValues, useCases);
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/Utils.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.net.SocketTimeoutException;
+import java.security.KeyFactory;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.TrustManagerFactory;
+
+/*
+ * Utilities for testing.
+ */
+public class Utils {
+
+    /* ***** Properties ***** */
+    public static final String PROP_PORT = "test.port";
+    public static final String PROP_PROTOCOL = "test.protocol";
+    public static final String PROP_CIPHER_SUITE = "test.cipher.suite";
+    public static final String PROP_CLIENT_AUTH = "test.client.auth";
+    public static final String PROP_SERVER_JDK = "test.server.jdk";
+    public static final String PROP_CLIENT_JDK = "test.client.jdk";
+    public static final String PROP_SERVER_NAME = "test.server.name";
+    public static final String PROP_APP_PROTOCOLS
+            = "test.app.protocols";
+    public static final String PROP_NEGO_APP_PROTOCOL
+            = "test.negotiated.app.protocol";
+    public static final String PROP_SUPPORTS_SNI_ON_SERVER
+            = "test.supports.sni.on.server";
+    public static final String PROP_SUPPORTS_SNI_ON_CLIENT
+            = "test.supports.sni.on.client";
+    public static final String PROP_SUPPORTS_ALPN_ON_SERVER
+            = "test.supports.alpn.on.server";
+    public static final String PROP_SUPPORTS_ALPN_ON_CLIENT
+            = "test.supports.alpn.on.client";
+    public static final String PROP_NEGATIVE_CASE_ON_SERVER
+            = "test.negative.case.on.server";
+    public static final String PROP_NEGATIVE_CASE_ON_CLIENT
+            = "test.negative.case.on.client";
+
+    public static final int TIMEOUT = 10000;
+    public static final char[] PASSWORD = "testpass".toCharArray();
+
+    public static final String TEST_LOG = "test.html";
+    public static final String PORT_LOG = "port";
+
+    public static final String HTTP_2 = "h2";
+    public static final String HTTP_1_1 = "http/1.1";
+
+    public static final String PARAM_DELIMITER = ";";
+    public static final String VALUE_DELIMITER = ",";
+
+    /*
+     * Creates SSL context with the specified certificate.
+     */
+    public static SSLContext createSSLContext(Cert... certs) throws Exception {
+        KeyStore trustStore = KeyStore.getInstance("JKS");
+        trustStore.load(null, null);
+        for (int i = 0; i < certs.length; i++) {
+            trustStore.setCertificateEntry("trust-" + certs[i].name(),
+                    createCert(certs[i]));
+        }
+        TrustManagerFactory tmf = TrustManagerFactory.getInstance("PKIX");
+        tmf.init(trustStore);
+
+        KeyStore keyStore = KeyStore.getInstance("JKS");
+        keyStore.load(null, null);
+        for (int i = 0; i < certs.length; i++) {
+            PrivateKey privKey = createKey(certs[i]);
+            keyStore.setKeyEntry("cert-" + certs[i].name(), privKey, PASSWORD,
+                    new Certificate[] { createCert(certs[i]) });
+        }
+        KeyManagerFactory kmf = KeyManagerFactory.getInstance("NewSunX509");
+        kmf.init(keyStore, PASSWORD);
+
+        SSLContext context = SSLContext.getInstance("TLS");
+        context.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+        return context;
+    }
+
+    private static Certificate createCert(Cert cert) throws IOException {
+        try {
+            CertificateFactory certFactory
+                    = CertificateFactory.getInstance("X.509");
+            return certFactory.generateCertificate(
+                    new ByteArrayInputStream(cert.certMaterials.getBytes()));
+        } catch (Exception e) {
+            throw new RuntimeException("Create key failed: " + cert, e);
+        }
+    }
+
+    private static PrivateKey createKey(Cert cert)
+            throws NoSuchAlgorithmException, InvalidKeySpecException {
+        PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(
+                hexToBytes(cert.privKeyMaterials));
+        KeyFactory keyFactory = KeyFactory.getInstance(
+                getKeyAlgorithm(cert.signatureAlgorithm));
+        PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
+        return privKey;
+    }
+
+    private static String getKeyAlgorithm(
+            SignatureAlgorithm signatureAlgorithm) {
+        String signatureAlogrithmName = signatureAlgorithm.name();
+        return signatureAlogrithmName.equals(SignatureAlgorithm.ECDSA.name())
+               ? "EC"
+               : signatureAlogrithmName;
+    }
+
+    public static byte[] hexToBytes(String hex) {
+        if (hex == null) {
+            return null;
+        }
+
+        int length = hex.length();
+        if (length % 2 != 0) {
+            throw new IllegalArgumentException("Hex format is wrong.");
+        }
+
+        byte[] bytes = new byte[length / 2];
+        for (int i = 0; i < length; i += 2) {
+            bytes[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+                    + Character.digit(hex.charAt(i + 1), 16));
+        }
+        return bytes;
+    }
+
+    public static String join(String delimiter, String... values) {
+        StringBuilder result = new StringBuilder();
+        if (values != null && values.length > 0) {
+            for (int i = 0; i < values.length - 1; i++) {
+                result.append(values[i]).append(delimiter);
+            }
+            result.append(values[values.length - 1]);
+        }
+        return result.toString();
+    }
+
+    public static String[] split(String str, String delimiter) {
+        return str == null ? new String[0] : str.split(delimiter);
+    }
+
+    public static String boolToStr(boolean bool) {
+        return bool ? "Y" : "N";
+    }
+
+    public static boolean getBoolProperty(String prop) {
+        return Boolean.valueOf(System.getProperty(prop));
+    }
+
+    public static Status handleException(Exception exception,
+            boolean negativeCase) {
+        Status status;
+        if ((exception instanceof SSLHandshakeException
+                || exception instanceof IllegalArgumentException)
+                && negativeCase) {
+            System.out.println("Expected exception: " + exception);
+            status = Status.EXPECTED_FAIL;
+        } else if (exception instanceof SocketTimeoutException) {
+            status = Status.TIMEOUT;
+        } else {
+            exception.printStackTrace(System.out);
+            status = Status.FAIL;
+        }
+        return status;
+    }
+
+    /* The HTML-related constants and methods. */
+
+    private static final String STYLE
+            = "style=\"font-family: Courier New; "
+            + "font-size: 12px; "
+            + "white-space: pre-wrap\"";
+
+    private static final String TABLE_STYLE
+            = "#test { font-family: \"Courier New\"; font-size: 12px; border-collapse: collapse; }\n"
+            + "#test td { border: 1px solid #ddd; padding: 4px; }\n"
+            + "#test tr:nth-child(odd) { background-color: #f2f2f2; }";
+
+    public static String row(Object... values) {
+        StringBuilder row = new StringBuilder();
+        row.append(startTr());
+        for (Object value : values) {
+            row.append(startTd());
+            row.append(value);
+            row.append(endTd());
+        }
+        row.append(endTr());
+        return row.toString();
+    }
+
+    public static String startHtml() {
+        return startTag("html");
+    }
+
+    public static String endHtml() {
+        return endTag("html");
+    }
+
+    public static String startPre() {
+        return startTag("pre " + STYLE);
+    }
+
+    public static String endPre() {
+        return endTag("pre");
+    }
+
+    public static String anchorName(String name, String text) {
+        return "<a name=" + name + ">" + text + "</a>";
+    }
+
+    public static String anchorLink(String file, String anchorName,
+            String text) {
+        return "<a href=" + file + "#" + anchorName + ">" + text + "</a>";
+    }
+
+    public static String tableStyle() {
+        return startTag("style") + TABLE_STYLE  +endTag("style");
+    }
+
+    public static String startTable() {
+        return startTag("table id=\"test\"");
+    }
+
+    public static String endTable() {
+        return endTag("table");
+    }
+
+    private static String startTr() {
+        return startTag("tr");
+    }
+
+    private static String endTr() {
+        return endTag("tr");
+    }
+
+    private static String startTd() {
+        return startTag("td");
+    }
+
+    private static String endTd() {
+        return endTag("td");
+    }
+
+    private static String startTag(String tag) {
+        return "<" + tag + ">";
+    }
+
+    private static String endTag(String tag) {
+        return "</" + tag + ">";
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/javax/net/ssl/compatibility/java.security	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,2 @@
+jdk.certpath.disabledAlgorithms=
+jdk.tls.disabledAlgorithms=
\ No newline at end of file
--- a/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/test/langtools/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Wed Nov 29 09:07:01 2017 -0800
@@ -24,7 +24,7 @@
 /*
  * @test
  * @bug      4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261 8162363 8160196 8151743 8177417
- *           8175218 8176452 8181215 8182263 8183511 8169819 8183037
+ *           8175218 8176452 8181215 8182263 8183511 8169819 8183037 8185369
  * @summary  Run tests on doclet stylesheet.
  * @author   jamieh
  * @library  ../lib
@@ -50,16 +50,6 @@
         // TODO: most of this test seems a bit silly, since javadoc is simply
         // copying in the stylesheet from the source directory
         checkOutput("stylesheet.css", true,
-                "/* Javadoc style sheet */",
-                "/*\n"
-                + "Overall document style\n"
-                + "*/",
-                "/*\n"
-                + "Heading styles\n"
-                + "*/",
-                "/*\n"
-                + "Navigation bar styles\n"
-                + "*/",
                 "body {\n"
                 + "    background-color:#ffffff;\n"
                 + "    color:#353833;\n"
@@ -173,8 +163,8 @@
                 + "    position:relative;\n"
                 + "    padding-top:129px;\n"
                 + "    margin-top:-129px;\n"
-                + "}\n"
-                + ".searchTagResult:before, .searchTagResult:target {\n"
+                + "}",
+                ".searchTagResult:before, .searchTagResult:target {\n"
                 + "    color:red;\n"
                 + "}",
                 "a[href]:hover, a[href]:focus {\n"
--- a/test/langtools/jdk/jshell/ForwardReferenceImportTest.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/test/langtools/jdk/jshell/ForwardReferenceImportTest.java	Wed Nov 29 09:07:01 2017 -0800
@@ -188,7 +188,7 @@
                 DiagCheck.DIAG_ERROR,
                 added(VALID),
                 ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null)));
-        assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.static.single.import");
+        assertDeclareFail("A.list = Arrays.asList(1, 2, 3);", "compiler.err.already.defined.single.import");
         assertActiveKeys();
         assertDrop(list,
                 ste(list, VALID, DROPPED, true, null),
--- a/test/langtools/tools/javac/4980495/std/NonStatic2StaticImportClash.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/test/langtools/tools/javac/4980495/std/NonStatic2StaticImportClash.java	Wed Nov 29 09:07:01 2017 -0800
@@ -1,14 +1,14 @@
 /*
  * @test  /nodynamiccopyright/
- * @bug 7101822
+ * @bug 7101822 8133616
  * @summary Check the when clashing types are imported through an ordinary and static import,
  *          the compile-time error is properly reported.
  * @compile/fail/ref=NonStatic2StaticImportClash.out -XDrawDiagnostics NonStatic2StaticImportClash.java p1/A1.java p2/A2.java
  *
  */
 
-import p1.A1.f;
-import static p2.A2.f;
+import static p1.A1.f;
+import p2.A2.f;
 
 public class NonStatic2StaticImportClash {
 }
--- a/test/langtools/tools/javac/4980495/std/Static2NonStaticImportClash.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/test/langtools/tools/javac/4980495/std/Static2NonStaticImportClash.java	Wed Nov 29 09:07:01 2017 -0800
@@ -1,14 +1,14 @@
 /*
  * @test  /nodynamiccopyright/
- * @bug 7101822
+ * @bug 7101822 8133616
  * @summary Check the when clashing types are imported through an ordinary and static import,
  *          the compile-time error is properly reported.
  * @compile/fail/ref=Static2NonStaticImportClash.out -XDrawDiagnostics Static2NonStaticImportClash.java p1/A1.java p2/A2.java
  *
  */
 
-import static p2.A2.f;
-import p1.A1.f;
+import p2.A2.f;
+import static p1.A1.f;
 
 public class Static2NonStaticImportClash {
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/analyzer/LambdaWithMethod.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,17 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8191981
+ * @compile/fail/ref=LambdaWithMethod.out -Werror -XDrawDiagnostics -XDfind=lambda LambdaWithMethod.java
+ */
+
+public class LambdaWithMethod {
+    public static void run(Runnable r) {
+        run(new Runnable() {
+            public void run() {
+                put(get());
+            }
+        });
+    }
+    private static String get() { return null; }
+    private static void put(String i) {}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/analyzer/LambdaWithMethod.out	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,4 @@
+LambdaWithMethod.java:9:28: compiler.warn.potential.lambda.found
+- compiler.err.warnings.and.werror
+1 error
+1 warning
--- a/test/langtools/tools/javac/diags/examples/AlreadyDefinedStaticImport/AlreadDefinedStaticImport.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/test/langtools/tools/javac/diags/examples/AlreadyDefinedStaticImport/AlreadDefinedStaticImport.java	Wed Nov 29 09:07:01 2017 -0800
@@ -23,5 +23,5 @@
 
 // key: compiler.err.already.defined.static.single.import
 
-import p.E1.A;
-import static p.E2.A;
+import static p.E1.A;
+import p.E2.A;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/generics/inference/8178427/T8178427.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8178427
+ * @summary NPE in Infer$CheckUpperBounds
+ * @compile T8178427.java
+ */
+
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.function.*;
+import java.util.stream.*;
+
+abstract class X {
+    public interface N<K, V> {
+        Stream<V> getValues();
+    }
+
+    abstract <K, V> N<K, V> c();
+
+    abstract <T, K, V, M extends N<K, V>> Collector<T, ?, M> f(
+            Function<? super T, ? extends K> k,
+            Function<? super T, ? extends Stream<? extends V>> v,
+            Supplier<M> multimapSupplier);
+
+    void m(Map<String, N<?, ?>> c, ExecutorService s) {
+        s.submit(() -> {
+            return c.entrySet().parallelStream()
+                    .collect(f(Map.Entry::getKey, e -> e.getValue().getValues(), this::c));
+        });
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/langtools/tools/javac/processing/model/util/TestTypeKindVisitors.java	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug     8191234
+ * @summary Test TypeKind visitors on pseudo types.
+ * @library /tools/javac/lib
+ * @modules java.compiler
+ * @build   JavacTestingAbstractProcessor TestTypeKindVisitors
+ * @compile -processor TestTypeKindVisitors -proc:only TestTypeKindVisitors.java
+ */
+
+import java.lang.annotation.Annotation;
+import java.util.*;
+import javax.annotation.processing.*;
+import javax.lang.model.element.*;
+import javax.lang.model.type.*;
+import javax.lang.model.util.*;
+import static javax.lang.model.SourceVersion.*;
+
+public class TestTypeKindVisitors extends JavacTestingAbstractProcessor {
+    @Override
+    public boolean process(Set<? extends TypeElement> tes,
+                           RoundEnvironment round) {
+        if (round.processingOver())
+            return true;
+
+        List<NoType> tradNoTypes = List.of(types.getNoType(TypeKind.NONE),
+                                           types.getNoType(TypeKind.VOID),
+                                           getPackageNoType());
+        NoType moduleNoType = getModuleNoType();
+
+        // For KindVisitors based on 6, 7, and 8
+        for (TypeVisitor<TypeKind, String> visitor : getVisitors()) {
+            System.out.println(visitor.getClass().getSuperclass().getName());
+
+            for (NoType noType : tradNoTypes) {
+                System.out.println("\t" + noType.toString());
+                checkTypeKind(noType.getKind(), visitor.visit(noType));
+            }
+
+            if (RELEASE_9.compareTo(visitor.getClass().getSuperclass().
+                                    getAnnotation(SupportedSourceVersion.class).
+                                    value()) > 0) {
+                try {
+                    System.out.println("\t" + moduleNoType.toString());
+                    visitor.visit(moduleNoType);
+                } catch (UnknownTypeException ute) {
+                    ; // Expected
+                }
+            } else {
+                checkTypeKind(moduleNoType.getKind(), visitor.visit(moduleNoType));
+            }
+        }
+
+        return true;
+    }
+
+    private NoType getPackageNoType() {
+        TypeMirror type = elements.getPackageElement("java.lang").asType();
+        checkTypeKind(TypeKind.PACKAGE, type.getKind());
+        return (NoType) type;
+    }
+
+    private NoType getModuleNoType() {
+        TypeMirror type = elements.getModuleElement("java.base").asType();
+        checkTypeKind(TypeKind.MODULE, type.getKind());
+        return (NoType) type;
+    }
+
+    private void checkTypeKind(TypeKind expected, TypeKind retreived) {
+        if (retreived != expected)
+            throw new AssertionError("Unexpected type kind " + retreived);
+    }
+
+    List<TypeVisitor<TypeKind, String>> getVisitors() {
+        return List.of(new TypeKindVisitor6<>(null) {
+                           @Override
+                           protected TypeKind defaultAction(TypeMirror e, String p) {
+                               throw new AssertionError("Should not reach");
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsNone(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+                               return t.getKind();
+                           }
+                           // Leave default behavior for a NoType module
+                       },
+
+                       new TypeKindVisitor7<>(null){
+                           @Override
+                           protected TypeKind defaultAction(TypeMirror e, String p) {
+                               throw new AssertionError("Should not reach");
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsNone(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+                               return t.getKind();
+                           }
+                           // Leave default behavior for a NoType module
+
+                       },
+
+                       new TypeKindVisitor8<>(null){
+                           @Override
+                           protected TypeKind defaultAction(TypeMirror e, String p) {
+                               throw new AssertionError("Should not reach");
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsNone(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+                               return t.getKind();
+                           }
+                           // Leave default behavior for a NoType module
+
+                       },
+
+                       new TypeKindVisitor9<>(null){
+                           @Override
+                           protected TypeKind defaultAction(TypeMirror e, String p) {
+                               throw new AssertionError("Should not reach");
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsVoid(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsNone(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsPackage(NoType t, String p) {
+                               return t.getKind();
+                           }
+
+                           @Override
+                           public TypeKind visitNoTypeAsModule(NoType t, String p) {
+                               return t.getKind();
+                           }
+                       });
+    }
+}
--- a/test/langtools/tools/jdeps/MultiReleaseJar.java	Tue Nov 28 15:01:00 2017 -0800
+++ b/test/langtools/tools/jdeps/MultiReleaseJar.java	Wed Nov 29 09:07:01 2017 -0800
@@ -240,17 +240,26 @@
         cmds[0] = cmdPath.resolve(cmds[0]).toString();
         ProcessBuilder pb = new ProcessBuilder(cmds);
         pb.directory(mrjar.toFile());
-        Process p = pb.start();
-        p.waitFor(10, TimeUnit.SECONDS);
-        String out;
-        try (InputStream is = p.getInputStream()) {
-            out = new String(is.readAllBytes());
+        Process p = null;
+        try {
+            p = pb.start();
+            p.waitFor();
+
+            String out;
+            try (InputStream is = p.getInputStream()) {
+                out = new String(is.readAllBytes());
+            }
+            String err;
+            try (InputStream is = p.getErrorStream()) {
+                err = new String(is.readAllBytes());
+            }
+            return new Result(cmd, p.exitValue(), out, err);
+        } catch (Throwable t) {
+            if (p != null) {
+                p.destroyForcibly().waitFor();
+            }
+            throw t;
         }
-        String err;
-        try (InputStream is = p.getErrorStream()) {
-            err = new String(is.readAllBytes());
-        }
-        return new Result(cmd, p.exitValue(), out, err);
     }
 
     void checkResult(Result r) throws Exception {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/nashorn/script/basic/es6/JDK-8059835.js	Wed Nov 29 09:07:01 2017 -0800
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ * 
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ * 
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ * 
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ * 
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * JDK-8059835: Optimistic splitting doesn't work with let and const
+ *
+ * @test
+ * @run
+ * @option --language=es6
+ * @option -Dnashorn.compiler.splitter.threshold=100
+ * @fork
+ */
+
+function f() {
+    let sum = 0;
+    const c = 13;
+    if (true) {
+        let x = 0;
+        const y = 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        sum += x;
+        sum += y;
+    }
+    outer: while (true) {
+        let x = 0;
+        const y = 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        sum += x;
+        sum += y;
+        sum += c;
+        let i = 0;
+        const k = 1;
+        while (true) {
+            x += k;
+            if (++i === 10) {
+                break outer;
+            }
+        }
+        x += k;
+    }
+    return sum;
+}
+
+function g() {
+    let sum = 0;
+    const c = 13;
+    if (true) {
+        let x = 0;
+        const y = 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        sum += x;
+        sum += y;
+    }
+    outer: while (true) {
+        let x = 0;
+        const y = 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        x += 1;
+        sum += x;
+        sum += y;
+        sum += c;
+        let i = 0;
+        const k = 1;
+        while (true) {
+            x += k;
+            if (++i === 10) return 'abc';
+        }
+        x += k;
+    }
+    return sum;
+}
+
+Assert.assertTrue(f() === 80);
+Assert.assertTrue(g() === 'abc');