Merge
authoramurillo
Mon, 18 Jul 2016 09:38:08 -0700
changeset 39742 f5d65fcf55e4
parent 39741 8bc25e077e83 (current diff)
parent 39730 196f4e25d9f5 (diff)
child 39743 10d92aa550aa
Merge
langtools/test/tools/javac/cast/6219964/T6219964.out
langtools/test/tools/jdeps/jdkinternals/p/NoRepl.java
langtools/test/tools/jdeps/jdkinternals/p/WithRepl.java
--- a/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -369,3 +369,4 @@
 2a5697a98620c4f40e4a1a71478464399b8878de jdk-9+124
 3aa52182b3ad7c5b3a61cf05a59dd07e4c5884e5 jdk-9+125
 03e7b2c5ae345be3caf981d76ceb3efe5ff447f8 jdk-9+126
+8e45018bde9de4ad15b972ae62874bba52dba2d5 jdk-9+127
--- a/.hgtags-top-repo	Fri Jul 15 09:05:36 2016 -0700
+++ b/.hgtags-top-repo	Mon Jul 18 09:38:08 2016 -0700
@@ -369,3 +369,4 @@
 f80c841ae2545eaf9acd2724bccc305d98cefbe2 jdk-9+124
 9aa7d40f3a453f51e47f4c1b19eff5740a74a9f8 jdk-9+125
 3a58466296d36944454756ef01e7513ac5e14a16 jdk-9+126
+8fa686245bd2a072ece3392743460030f0854520 jdk-9+127
--- a/corba/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/corba/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -369,3 +369,4 @@
 45121d5afb9d5bfadab75378572ad96832e0809e jdk-9+124
 1d48e67d1b91eb9f72e49e69a4021edb85e357fc jdk-9+125
 c7f5ba08fcd4b8416e62c21229f9a07c95498919 jdk-9+126
+8fab452b6f4710762ba1d8e55fd62db00b1355fe jdk-9+127
--- a/hotspot/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -529,3 +529,4 @@
 479631362b4930be985245ea063d87d821a472eb jdk-9+124
 bb640b49741af3f57f9994129934c46fc173219f jdk-9+125
 adc8c84b7cf8c540d920182f78a2bc982366432a jdk-9+126
+352357128f602dcf0426b1cbe011a4685a4d9f97 jdk-9+127
--- a/hotspot/make/gensrc/GensrcDtrace.gmk	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/make/gensrc/GensrcDtrace.gmk	Mon Jul 18 09:38:08 2016 -0700
@@ -45,7 +45,8 @@
   $(DTRACE_GENSRC_DIR)/%.h: $(DTRACE_SOURCE_DIR)/%.d
 	$(call LogInfo, Generating dtrace header file $(@F))
 	$(call MakeDir, $(@D) $(DTRACE_SUPPORT_DIR))
-	$(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d)
+	$(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, \
+	    ( $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d ) )
 	$(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d)
 
   # Process all .d files in DTRACE_SOURCE_DIR. They are:
--- a/hotspot/make/lib/CompileDtracePostJvm.gmk	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/make/lib/CompileDtracePostJvm.gmk	Mon Jul 18 09:38:08 2016 -0700
@@ -68,7 +68,7 @@
       $1: $$(BUILD_DTRACE_GEN_OFFSETS)
 	$$(call LogInfo, Generating dtrace $2 file $$(@F))
 	$$(call MakeDir, $$(@D))
-	$$(call ExecuteWithLog, $$@, $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@)
+	$$(call ExecuteWithLog, $$@, ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@ ) )
 
       TARGETS += $1
     endef
--- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/UncommonTrap.java	Mon Jul 18 09:38:08 2016 -0700
@@ -16,9 +16,9 @@
  * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * CA 95054 USA or visit www.sun.com if you need additional information or
- * have any questions.
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  *
  */
 package com.sun.hotspot.tools.compiler;
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -501,13 +501,26 @@
   }
 }
 
-/**
- * Returns true if this class loader data is for the platform class loader.
- */
+// Returns true if this class loader data is for the system class loader.
+bool ClassLoaderData::is_system_class_loader_data() const {
+  return SystemDictionary::is_system_class_loader(class_loader());
+}
+
+// Returns true if this class loader data is for the platform class loader.
 bool ClassLoaderData::is_platform_class_loader_data() const {
   return SystemDictionary::is_platform_class_loader(class_loader());
 }
 
+// Returns true if this class loader data is one of the 3 builtin
+// (boot, application/system or platform) class loaders. Note, the
+// builtin loaders are not freed by a GC.
+bool ClassLoaderData::is_builtin_class_loader_data() const {
+  Handle classLoaderHandle = class_loader();
+  return (is_the_null_class_loader_data() ||
+          SystemDictionary::is_system_class_loader(classLoaderHandle) ||
+          SystemDictionary::is_platform_class_loader(classLoaderHandle));
+}
+
 Metaspace* ClassLoaderData::metaspace_non_null() {
   assert(!DumpSharedSpaces, "wrong metaspace!");
   // If the metaspace has not been allocated, create a new one.  Might want
@@ -957,12 +970,6 @@
   data = _head;
   while (data != NULL) {
     if (data->is_alive(is_alive_closure)) {
-      if (data->packages_defined()) {
-        data->packages()->purge_all_package_exports();
-      }
-      if (data->modules_defined()) {
-        data->modules()->purge_all_module_reads();
-      }
       // clean metaspace
       if (walk_all_metadata) {
         data->classes_do(InstanceKlass::purge_previous_versions);
@@ -990,6 +997,23 @@
   }
 
   if (seen_dead_loader) {
+    // Walk a ModuleEntry's reads and a PackageEntry's exports lists
+    // to determine if there are modules on those lists that are now
+    // dead and should be removed.  A module's life cycle is equivalent
+    // to its defining class loader's life cycle.  Since a module is
+    // considered dead if its class loader is dead, these walks must
+    // occur after each class loader's aliveness is determined.
+    data = _head;
+    while (data != NULL) {
+      if (data->packages_defined()) {
+        data->packages()->purge_all_package_exports();
+      }
+      if (data->modules_defined()) {
+        data->modules()->purge_all_module_reads();
+      }
+      data = data->next();
+    }
+
     post_class_unload_events();
   }
 
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp	Mon Jul 18 09:38:08 2016 -0700
@@ -270,7 +270,9 @@
   bool is_the_null_class_loader_data() const {
     return this == _the_null_class_loader_data;
   }
+  bool is_system_class_loader_data() const;
   bool is_platform_class_loader_data() const;
+  bool is_builtin_class_loader_data() const;
 
   // The Metaspace is created lazily so may be NULL.  This
   // method will allocate a Metaspace if needed.
--- a/hotspot/src/share/vm/classfile/compactHashtable.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/compactHashtable.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -248,7 +248,7 @@
     } else {
       u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]);
       while (entry < entry_max) {
-        iterator.do_value(_base_address, entry[0]);
+        iterator.do_value(_base_address, entry[1]);
         entry += 2;
       }
     }
--- a/hotspot/src/share/vm/classfile/moduleEntry.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/moduleEntry.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -40,7 +40,6 @@
 
 ModuleEntry* ModuleEntryTable::_javabase_module = NULL;
 
-
 void ModuleEntry::set_location(Symbol* location) {
   if (_location != NULL) {
     // _location symbol's refcounts are managed by ModuleEntry,
@@ -115,10 +114,35 @@
       // Lazily create a module's reads list
       _reads = new (ResourceObj::C_HEAP, mtModule)GrowableArray<ModuleEntry*>(MODULE_READS_SIZE, true);
     }
+
+    // Determine, based on this newly established read edge to module m,
+    // if this module's read list should be walked at a GC safepoint.
+    set_read_walk_required(m->loader_data());
+
+    // Establish readability to module m
     _reads->append_if_missing(m);
   }
 }
 
+// If the module's loader, that a read edge is being established to, is
+// not the same loader as this module's and is not one of the 3 builtin
+// class loaders, then this module's reads list must be walked at GC
+// safepoint. Modules have the same life cycle as their defining class
+// loaders and should be removed if dead.
+void ModuleEntry::set_read_walk_required(ClassLoaderData* m_loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+  if (!_must_walk_reads &&
+      loader_data() != m_loader_data &&
+      !m_loader_data->is_builtin_class_loader_data()) {
+    _must_walk_reads = true;
+    if (log_is_enabled(Trace, modules)) {
+      ResourceMark rm;
+      log_trace(modules)("ModuleEntry::set_read_walk_required(): module %s reads list must be walked",
+                         (name() != NULL) ? name()->as_C_string() : UNNAMED_MODULE);
+    }
+  }
+}
+
 bool ModuleEntry::has_reads() const {
   assert_locked_or_safepoint(Module_lock);
   return ((_reads != NULL) && !_reads->is_empty());
@@ -127,14 +151,28 @@
 // Purge dead module entries out of reads list.
 void ModuleEntry::purge_reads() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  if (has_reads()) {
+
+  if (_must_walk_reads && has_reads()) {
+    // This module's _must_walk_reads flag will be reset based
+    // on the remaining live modules on the reads list.
+    _must_walk_reads = false;
+
+    if (log_is_enabled(Trace, modules)) {
+      ResourceMark rm;
+      log_trace(modules)("ModuleEntry::purge_reads(): module %s reads list being walked",
+                         (name() != NULL) ? name()->as_C_string() : UNNAMED_MODULE);
+    }
+
     // Go backwards because this removes entries that are dead.
     int len = _reads->length();
     for (int idx = len - 1; idx >= 0; idx--) {
       ModuleEntry* module_idx = _reads->at(idx);
-      ClassLoaderData* cld = module_idx->loader();
-      if (cld->is_unloading()) {
+      ClassLoaderData* cld_idx = module_idx->loader_data();
+      if (cld_idx->is_unloading()) {
         _reads->delete_at(idx);
+      } else {
+        // Update the need to walk this module's reads based on live modules
+        set_read_walk_required(cld_idx);
       }
     }
   }
@@ -248,7 +286,7 @@
     entry->set_module(loader_data->add_handle(module_handle));
   }
 
-  entry->set_loader(loader_data);
+  entry->set_loader_data(loader_data);
   entry->set_version(version);
   entry->set_location(location);
 
@@ -375,11 +413,11 @@
 
 void ModuleEntry::print(outputStream* st) {
   ResourceMark rm;
-  st->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT,
+  st->print_cr("entry " PTR_FORMAT " name %s module " PTR_FORMAT " loader %s version %s location %s strict %s next " PTR_FORMAT,
                p2i(this),
                name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
                p2i(module()),
-               loader()->loader_name(),
+               loader_data()->loader_name(),
                version() != NULL ? version()->as_C_string() : "NULL",
                location() != NULL ? location()->as_C_string() : "NULL",
                BOOL_TO_STR(!can_read_all_unnamed()), p2i(next()));
@@ -401,5 +439,5 @@
 }
 
 void ModuleEntry::verify() {
-  guarantee(loader() != NULL, "A module entry must be associated with a loader.");
+  guarantee(loader_data() != NULL, "A module entry must be associated with a loader.");
 }
--- a/hotspot/src/share/vm/classfile/moduleEntry.hpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/moduleEntry.hpp	Mon Jul 18 09:38:08 2016 -0700
@@ -43,6 +43,7 @@
 // It contains:
 //   - Symbol* containing the module's name.
 //   - pointer to the java.lang.reflect.Module for this module.
+//   - pointer to the java.security.ProtectionDomain shared by classes defined to this module.
 //   - ClassLoaderData*, class loader of this module.
 //   - a growable array containg other module entries that this module can read.
 //   - a flag indicating if this module can read all unnamed modules.
@@ -54,56 +55,58 @@
   jobject _module;                     // java.lang.reflect.Module
   jobject _pd;                         // java.security.ProtectionDomain, cached
                                        // for shared classes from this module
-  ClassLoaderData* _loader;
+  ClassLoaderData* _loader_data;
   GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
   Symbol* _version;                    // module version number
   Symbol* _location;                   // module location
   bool _can_read_all_unnamed;
   bool _has_default_read_edges;        // JVMTI redefine/retransform support
+  bool _must_walk_reads;               // walk module's reads list at GC safepoints to purge out dead modules
   TRACE_DEFINE_TRACE_ID_FIELD;
   enum {MODULE_READS_SIZE = 101};      // Initial size of list of modules that the module can read.
 
 public:
   void init() {
     _module = NULL;
-    _loader = NULL;
+    _loader_data = NULL;
     _pd = NULL;
     _reads = NULL;
     _version = NULL;
     _location = NULL;
     _can_read_all_unnamed = false;
     _has_default_read_edges = false;
+    _must_walk_reads = false;
   }
 
-  Symbol*            name() const          { return literal(); }
-  void               set_name(Symbol* n)   { set_literal(n); }
+  Symbol*          name() const          { return literal(); }
+  void             set_name(Symbol* n)   { set_literal(n); }
 
-  jobject            module() const        { return _module; }
-  void               set_module(jobject j) { _module = j; }
+  jobject          module() const        { return _module; }
+  void             set_module(jobject j) { _module = j; }
 
   // The shared ProtectionDomain reference is set once the VM loads a shared class
   // originated from the current Module. The referenced ProtectionDomain object is
   // created by the ClassLoader when loading a class (shared or non-shared) from the
   // Module for the first time. This ProtectionDomain object is used for all
   // classes from the Module loaded by the same ClassLoader.
-  Handle             shared_protection_domain();
-  void               set_shared_protection_domain(ClassLoaderData *loader_data,
-                                                  Handle pd);
+  Handle           shared_protection_domain();
+  void             set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd);
 
-  ClassLoaderData*   loader() const                 { return _loader; }
-  void               set_loader(ClassLoaderData* l) { _loader = l; }
+  ClassLoaderData* loader_data() const                 { return _loader_data; }
+  void             set_loader_data(ClassLoaderData* l) { _loader_data = l; }
+
+  Symbol*          version() const                     { return _version; }
+  void             set_version(Symbol* version);
 
-  Symbol*            version() const                { return _version; }
-  void               set_version(Symbol* version);
-
-  Symbol*            location() const               { return _location; }
-  void               set_location(Symbol* location);
+  Symbol*          location() const                    { return _location; }
+  void             set_location(Symbol* location);
 
-  bool               can_read(ModuleEntry* m) const;
-  bool               has_reads() const;
-  void               add_read(ModuleEntry* m);
+  bool             can_read(ModuleEntry* m) const;
+  bool             has_reads() const;
+  void             add_read(ModuleEntry* m);
+  void             set_read_walk_required(ClassLoaderData* m_loader_data);
 
-  bool               is_named() const               { return (literal() != NULL); }
+  bool             is_named() const                    { return (name() != NULL); }
 
   bool can_read_all_unnamed() const {
     assert(is_named() || _can_read_all_unnamed == true,
@@ -178,7 +181,7 @@
   ModuleEntry* _unnamed_module;
 
   ModuleEntry* new_entry(unsigned int hash, Handle module_handle, Symbol* name, Symbol* version,
-                         Symbol* location, ClassLoaderData* class_loader);
+                         Symbol* location, ClassLoaderData* loader_data);
   void add_entry(int index, ModuleEntry* new_entry);
 
   int entry_size() const { return BasicHashtable<mtModule>::entry_size(); }
--- a/hotspot/src/share/vm/classfile/modules.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/modules.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -113,7 +113,7 @@
   const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
   if (package_name == NULL) return NULL;
   TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
-  PackageEntryTable* package_entry_table = module_entry->loader()->packages();
+  PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
   assert(package_entry_table != NULL, "Unexpected null package entry table");
   return package_entry_table->lookup_only(pkg_symbol);
 }
@@ -868,7 +868,7 @@
                      package_name, module_entry->name()->as_C_string());
 
   TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
-  PackageEntryTable* package_table = module_entry->loader()->packages();
+  PackageEntryTable* package_table = module_entry->loader_data()->packages();
   assert(package_table != NULL, "Missing package_table");
 
   bool pkg_exists = false;
--- a/hotspot/src/share/vm/classfile/packageEntry.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/packageEntry.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/moduleEntry.hpp"
 #include "classfile/packageEntry.hpp"
+#include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
@@ -53,12 +54,40 @@
   if (!has_qual_exports_list()) {
     // Lazily create a package's qualified exports list.
     // Initial size is small, do not anticipate export lists to be large.
-    _qualified_exports =
-      new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
+    _qualified_exports = new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
   }
+
+  // Determine, based on this newly established export to module m,
+  // if this package's export list should be walked at a GC safepoint.
+  set_export_walk_required(m->loader_data());
+
+  // Establish exportability to module m
   _qualified_exports->append_if_missing(m);
 }
 
+// If the module's loader, that an export is being established to, is
+// not the same loader as this module's and is not one of the 3 builtin
+// class loaders, then this package's export list must be walked at GC
+// safepoint. Modules have the same life cycle as their defining class
+// loaders and should be removed if dead.
+void PackageEntry::set_export_walk_required(ClassLoaderData* m_loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+  ModuleEntry* this_pkg_mod = module();
+  if (!_must_walk_exports &&
+      (this_pkg_mod == NULL || this_pkg_mod->loader_data() != m_loader_data) &&
+      !m_loader_data->is_builtin_class_loader_data()) {
+    _must_walk_exports = true;
+    if (log_is_enabled(Trace, modules)) {
+      ResourceMark rm;
+      assert(name() != NULL, "PackageEntry without a valid name");
+      log_trace(modules)("PackageEntry::set_export_walk_required(): package %s defined in module %s, exports list must be walked",
+                         name()->as_C_string(),
+                         (this_pkg_mod == NULL || this_pkg_mod->name() == NULL) ?
+                           UNNAMED_MODULE : this_pkg_mod->name()->as_C_string());
+    }
+  }
+}
+
 // Set the package's exported states based on the value of the ModuleEntry.
 void PackageEntry::set_exported(ModuleEntry* m) {
   MutexLocker m1(Module_lock);
@@ -96,14 +125,34 @@
 // Remove dead module entries within the package's exported list.
 void PackageEntry::purge_qualified_exports() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  if (_qualified_exports != NULL) {
+  if (_must_walk_exports &&
+      _qualified_exports != NULL &&
+      !_qualified_exports->is_empty()) {
+    ModuleEntry* pkg_module = module();
+
+    // This package's _must_walk_exports flag will be reset based
+    // on the remaining live modules on the exports list.
+    _must_walk_exports = false;
+
+    if (log_is_enabled(Trace, modules)) {
+      ResourceMark rm;
+      assert(name() != NULL, "PackageEntry without a valid name");
+      ModuleEntry* pkg_mod = module();
+      log_trace(modules)("PackageEntry::purge_qualified_exports(): package %s defined in module %s, exports list being walked",
+                         name()->as_C_string(),
+                         (pkg_mod == NULL || pkg_mod->name() == NULL) ? UNNAMED_MODULE : pkg_mod->name()->as_C_string());
+    }
+
     // Go backwards because this removes entries that are dead.
     int len = _qualified_exports->length();
     for (int idx = len - 1; idx >= 0; idx--) {
       ModuleEntry* module_idx = _qualified_exports->at(idx);
-      ClassLoaderData* cld = module_idx->loader();
-      if (cld->is_unloading()) {
+      ClassLoaderData* cld_idx = module_idx->loader_data();
+      if (cld_idx->is_unloading()) {
         _qualified_exports->delete_at(idx);
+      } else {
+        // Update the need to walk this package's exports based on live modules
+        set_export_walk_required(cld_idx);
       }
     }
   }
@@ -297,8 +346,8 @@
 
 void PackageEntry::print(outputStream* st) {
   ResourceMark rm;
-  st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index "
-               INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next "PTR_FORMAT,
+  st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
+               INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
                p2i(this), name()->as_C_string(),
                (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
                _classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next()));
--- a/hotspot/src/share/vm/classfile/packageEntry.hpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/packageEntry.hpp	Mon Jul 18 09:38:08 2016 -0700
@@ -69,6 +69,7 @@
   s2 _classpath_index;
   bool _is_exported_unqualified;
   bool _is_exported_allUnnamed;
+  bool _must_walk_exports;
   GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
   GrowableArray<ModuleEntry*>* _qualified_exports;
   TRACE_DEFINE_TRACE_ID_FIELD;
@@ -82,6 +83,7 @@
     _classpath_index = -1;
     _is_exported_unqualified = false;
     _is_exported_allUnnamed = false;
+    _must_walk_exports = false;
     _exported_pending_delete = NULL;
     _qualified_exports = NULL;
   }
@@ -147,6 +149,7 @@
 
   // add the module to the package's qualified exports
   void add_qexport(ModuleEntry* m);
+  void set_export_walk_required(ClassLoaderData* m_loader_data);
 
   PackageEntry* next() const {
     return (PackageEntry*)HashtableEntry<Symbol*, mtModule>::next();
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -175,9 +175,18 @@
    return false;
 }
 
-/**
- * Returns true if the passed class loader is the platform class loader.
- */
+// Returns true if the passed class loader is the builtin application class loader
+// or a custom system class loader. A customer system class loader can be
+// specified via -Djava.system.class.loader.
+bool SystemDictionary::is_system_class_loader(Handle class_loader) {
+  if (class_loader.is_null()) {
+    return false;
+  }
+  return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() ||
+          class_loader() == _java_system_loader);
+}
+
+// Returns true if the passed class loader is the platform class loader.
 bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
   if (class_loader.is_null()) {
     return false;
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Mon Jul 18 09:38:08 2016 -0700
@@ -660,6 +660,7 @@
   static instanceKlassHandle load_shared_class(Symbol* class_name,
                                                Handle class_loader,
                                                TRAPS);
+  static bool is_system_class_loader(Handle class_loader);
   static bool is_platform_class_loader(Handle class_loader);
 
 protected:
--- a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -48,10 +48,10 @@
 
 #ifndef PRODUCT
 void PreservedMarks::assert_empty() {
-  assert(_stack.is_empty(), "stack expected to be empty, size = "SIZE_FORMAT,
+  assert(_stack.is_empty(), "stack expected to be empty, size = " SIZE_FORMAT,
          _stack.size());
   assert(_stack.cache_size() == 0,
-         "stack expected to have no cached segments, cache size = "SIZE_FORMAT,
+         "stack expected to have no cached segments, cache size = " SIZE_FORMAT,
          _stack.cache_size());
 }
 #endif // ndef PRODUCT
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -419,21 +419,20 @@
             InstanceKlass* klass = method->method_holder();
             u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
             constantPoolHandle cp(method->constants());
-            Symbol* field_name = cp->name_ref_at(bc_index);
-            Symbol* field_sig = cp->signature_ref_at(bc_index);
             Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
 
             if (klass->name() == ref_class_name) {
+              Symbol* field_name = cp->name_ref_at(bc_index);
+              Symbol* field_sig = cp->signature_ref_at(bc_index);
+
               fieldDescriptor fd;
               klass->find_field(field_name, field_sig, &fd);
               if (fd.access_flags().is_final()) {
                 if (fd.access_flags().is_static()) {
-                  assert(c == Bytecodes::_putstatic, "must be putstatic");
                   if (!method->is_static_initializer()) {
                     fd.set_has_initialized_final_update(true);
                   }
                 } else {
-                  assert(c == Bytecodes::_putfield, "must be putfield");
                   if (!method->is_object_initializer()) {
                     fd.set_has_initialized_final_update(true);
                   }
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -584,27 +584,26 @@
 // Parses a size specification string.
 bool Arguments::atojulong(const char *s, julong* result) {
   julong n = 0;
-  int args_read = 0;
-  bool is_hex = false;
-  // Skip leading 0[xX] for hexadecimal
-  if (*s =='0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
-    s += 2;
-    is_hex = true;
-    args_read = sscanf(s, JULONG_FORMAT_X, &n);
-  } else {
-    args_read = sscanf(s, JULONG_FORMAT, &n);
-  }
-  if (args_read != 1) {
+
+  // First char must be a digit. Don't allow negative numbers or leading spaces.
+  if (!isdigit(*s)) {
     return false;
   }
-  while (*s != '\0' && (isdigit(*s) || (is_hex && isxdigit(*s)))) {
-    s++;
-  }
-  // 4705540: illegal if more characters are found after the first non-digit
-  if (strlen(s) > 1) {
+
+  bool is_hex = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
+  char* remainder;
+  errno = 0;
+  n = strtoull(s, &remainder, (is_hex ? 16 : 10));
+  if (errno != 0) {
     return false;
   }
-  switch (*s) {
+
+  // Fail if no number was read at all or if the remainder contains more than a single non-digit character.
+  if (remainder == s || strlen(remainder) > 1) {
+    return false;
+  }
+
+  switch (*remainder) {
     case 'T': case 't':
       *result = n * G * K;
       // Check for overflow.
--- a/hotspot/src/share/vm/utilities/vmError.cpp	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -205,16 +205,39 @@
 static void print_oom_reasons(outputStream* st) {
   st->print_cr("# Possible reasons:");
   st->print_cr("#   The system is out of physical RAM or swap space");
-  st->print_cr("#   In 32 bit mode, the process size limit was hit");
+  if (UseCompressedOops) {
+    st->print_cr("#   The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap");
+  }
+  if (LogBytesPerWord == 2) {
+    st->print_cr("#   In 32 bit mode, the process size limit was hit");
+  }
   st->print_cr("# Possible solutions:");
   st->print_cr("#   Reduce memory load on the system");
   st->print_cr("#   Increase physical memory or swap space");
   st->print_cr("#   Check if swap backing store is full");
-  st->print_cr("#   Use 64 bit Java on a 64 bit OS");
+  if (LogBytesPerWord == 2) {
+    st->print_cr("#   Use 64 bit Java on a 64 bit OS");
+  }
   st->print_cr("#   Decrease Java heap size (-Xmx/-Xms)");
   st->print_cr("#   Decrease number of Java threads");
   st->print_cr("#   Decrease Java thread stack sizes (-Xss)");
   st->print_cr("#   Set larger code cache with -XX:ReservedCodeCacheSize=");
+  if (UseCompressedOops) {
+    switch (Universe::narrow_oop_mode()) {
+      case Universe::UnscaledNarrowOop:
+        st->print_cr("#   JVM is running with Unscaled Compressed Oops mode in which the Java heap is");
+        st->print_cr("#     placed in the first 4GB address space. The Java Heap base address is the");
+        st->print_cr("#     maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress");
+        st->print_cr("#     to set the Java Heap base and to place the Java Heap above 4GB virtual address.");
+        break;
+      case Universe::ZeroBasedNarrowOop:
+        st->print_cr("#   JVM is running with Zero Based Compressed Oops mode in which the Java heap is");
+        st->print_cr("#     placed in the first 32GB address space. The Java Heap base address is the");
+        st->print_cr("#     maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress");
+        st->print_cr("#     to set the Java Heap base and to place the Java Heap above 32GB virtual address.");
+        break;
+    }
+  }
   st->print_cr("# This output file may be truncated or incomplete.");
 }
 
--- a/hotspot/test/TEST.groups	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/test/TEST.groups	Mon Jul 18 09:38:08 2016 -0700
@@ -395,6 +395,17 @@
   :hotspot_fast_gc_gcold \
   :hotspot_fast_runtime \
   :hotspot_fast_serviceability
+  
+hotspot_runtime_tier2 = \
+  runtime/ \
+  serviceability/ \
+ -:hotspot_fast_runtime \
+ -:hotspot_fast_serviceability \
+ -:hotspot_runtime_tier2_platform_agnostic
+ 
+hotspot_runtime_tier2_platform_agnostic = \
+  runtime/SelectionResolution \
+ -:hotspot_fast_runtime
 
 #All tests that depends on nashorn extension.
 #
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/gc/g1/humongousObjects/TestNoAllocationsInHRegions.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,234 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package gc.g1.humongousObjects;
+
+import jdk.test.lib.Utils;
+import sun.hotspot.WhiteBox;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Random;
+import java.util.stream.Collectors;
+
+/**
+ * @test TestNoAllocationsInHRegions
+ * @summary Checks that no additional allocations are made in humongous regions
+ * @requires vm.gc.G1
+ * @library /testlibrary /test/lib /
+ * @modules java.management java.base/jdk.internal.misc
+ * @build sun.hotspot.WhiteBox
+ *        gc.testlibrary.Helpers
+ *        gc.g1.humongousObjects.TestNoAllocationsInHRegions
+ *
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ *      sun.hotspot.WhiteBox$WhiteBoxPermission
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *                   -XX:G1HeapRegionSize=1M -Xms200m -Xmx200m -XX:MaxTenuringThreshold=0
+ *                   -Xlog:gc=trace:file=TestNoAllocationsInHRegions10.log
+ *                   gc.g1.humongousObjects.TestNoAllocationsInHRegions 30 10
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *                   -XX:G1HeapRegionSize=1M -Xms200m -Xmx200m -XX:MaxTenuringThreshold=0
+ *                   -Xlog:gc=trace:file=TestNoAllocationsInHRegions50.log
+ *                   gc.g1.humongousObjects.TestNoAllocationsInHRegions 30 50
+ *
+ * @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ *                   -XX:G1HeapRegionSize=1M -Xms200m -Xmx200m -XX:MaxTenuringThreshold=0
+ *                   -Xlog:gc=trace:file=TestNoAllocationsInHRegions70.log
+ *                   gc.g1.humongousObjects.TestNoAllocationsInHRegions 30 70
+ */
+public class TestNoAllocationsInHRegions {
+    private static final WhiteBox WB = WhiteBox.getWhiteBox();
+    private static final Random RND = Utils.getRandomInstance();
+    private static final int G1_REGION_SIZE = WB.g1RegionSize();
+    private static final int[] HUMONGOUS_SIZES = {G1_REGION_SIZE / 2, G1_REGION_SIZE + 1, G1_REGION_SIZE * 2 + 1};
+    private static final int ALLOC_THREAD_COUNT = 5;
+
+    // We fill specified part of heap with humongous objects - we need public static to prevent escape analysis to
+    // collect this field
+    public static LinkedList<byte[]> humongousAllocations = new LinkedList<>();
+
+    private static volatile boolean shouldStop = false;
+    private static volatile Error error = null;
+
+    static class Allocator implements Runnable {
+
+        private final List<byte[]> liveObjects = new LinkedList<>();
+        private int usedMemory = 0;
+        public final Runnable[] actions;
+
+        /**
+         * Maximum size of simple allocation
+         */
+        private static final int MAX_ALLOCATION_SIZE = (int) (G1_REGION_SIZE / 2 * 0.9);
+
+        /**
+         * Maximum size of dead (i.e. one which is made unreachable right after allocation) object
+         */
+        private static final int DEAD_OBJECT_MAX_SIZE = G1_REGION_SIZE / 10;
+
+        public Allocator(int maxAllocationMemory) {
+
+            actions = new Runnable[]{
+                    // Allocation
+                    () -> {
+                        if (maxAllocationMemory - usedMemory != 0) {
+                            int arraySize = RND.nextInt(Math.min(maxAllocationMemory - usedMemory,
+                                    MAX_ALLOCATION_SIZE));
+
+                            if (arraySize != 0) {
+                                byte[] allocation = new byte[arraySize];
+                                liveObjects.add(allocation);
+                                usedMemory += arraySize;
+
+                                // Sanity check
+                                if (WB.g1IsHumongous(allocation)) {
+                                    String errorMessage = String.format("Test Bug: Byte array of size"
+                                                    + " %d is expected to be non-humongous but it is humongous",
+                                            allocation.length);
+
+                                    System.out.println(errorMessage);
+                                    error = new Error(errorMessage);
+                                    shouldStop = true;
+                                }
+
+                                // Test check
+                                if (WB.g1BelongsToHumongousRegion(WB.getObjectAddress(allocation))) {
+                                    String errorMessage = String.format("Non-humongous allocation of byte array of "
+                                            + "length %d and size %d with address %d was made in Humongous Region",
+                                            allocation.length, WB.getObjectSize(allocation),
+                                            WB.getObjectAddress(allocation));
+
+                                    System.out.println(errorMessage);
+                                    error = new Error(errorMessage);
+                                    shouldStop = true;
+                                }
+                            }
+                        }
+                    },
+
+                    // Deallocation
+                    () -> {
+                        if (liveObjects.size() != 0) {
+                            int elementNum = RND.nextInt(liveObjects.size());
+                            int shouldFree = liveObjects.get(elementNum).length;
+                            liveObjects.remove(elementNum);
+                            usedMemory -= shouldFree;
+                        }
+                    },
+
+                    // Dead object allocation
+                    () -> {
+                        int size = RND.nextInt(DEAD_OBJECT_MAX_SIZE);
+                        byte[] deadObject = new byte[size];
+                    },
+
+                    // Check
+                    () -> {
+                        List<byte[]> wrongHumongousAllocations = liveObjects.stream()
+                                .filter(WB::g1IsHumongous)
+                                .collect(Collectors.toList());
+
+                        if (wrongHumongousAllocations.size() > 0) {
+                            wrongHumongousAllocations.stream().forEach(a ->
+                                    System.out.format("Non-humongous allocation of byte array of length %d and"
+                                                    + " size %d with address %d was made in Humongous Region",
+                                            a.length, WB.getObjectSize(a), WB.getObjectAddress(a)));
+                            error = new Error("Some non-humongous allocations were made to humongous region");
+                            shouldStop = true;
+                        }
+                    }
+            };
+        }
+
+        @Override
+        public void run() {
+            while (!shouldStop) {
+                actions[RND.nextInt(actions.length)].run();
+                Thread.yield();
+            }
+        }
+    }
+
+    public static void main(String[] args) {
+        if (args.length != 2) {
+            throw new Error("Test Bug: Expected duration (in seconds) and percent of allocated regions were not "
+                    + "provided as command line argument");
+        }
+
+        // test duration
+        long duration = Integer.parseInt(args[0]) * 1000L;
+        // part of heap preallocated with humongous objects (in percents)
+        int percentOfAllocatedHeap = Integer.parseInt(args[1]);
+
+        long startTime = System.currentTimeMillis();
+
+        long initialFreeRegionsCount = WB.g1NumFreeRegions();
+        int regionsToAllocate = (int) ((double) initialFreeRegionsCount / 100.0 * percentOfAllocatedHeap);
+        long freeRegionLeft = initialFreeRegionsCount - regionsToAllocate;
+
+        System.out.println("Regions to allocate: " + regionsToAllocate + "; regions to left free: " + freeRegionLeft);
+
+        int maxMemoryPerAllocThread = (int) ((Runtime.getRuntime().freeMemory() / 100.0
+                * (100 - percentOfAllocatedHeap)) / ALLOC_THREAD_COUNT * 0.5);
+
+        System.out.println("Using " + maxMemoryPerAllocThread / 1024 + "KB for each of " + ALLOC_THREAD_COUNT
+                + " allocation threads");
+
+        while (WB.g1NumFreeRegions() > freeRegionLeft) {
+            try {
+                humongousAllocations.add(new byte[HUMONGOUS_SIZES[RND.nextInt(HUMONGOUS_SIZES.length)]]);
+            } catch (OutOfMemoryError oom) {
+                //We got OOM trying to fill heap with humongous objects
+                //It probably means that heap is fragmented which is strange since the test logic should avoid it
+                System.out.println("Warning: OOM while allocating humongous objects - it likely means "
+                        + "that heap is fragmented");
+                break;
+            }
+        }
+
+        System.out.println("Initial free regions " + initialFreeRegionsCount + "; Free regions left "
+                + WB.g1NumFreeRegions());
+
+        LinkedList<Thread> threads = new LinkedList<>();
+
+        for (int i = 0; i < ALLOC_THREAD_COUNT; i++) {
+            threads.add(new Thread(new Allocator(maxMemoryPerAllocThread)));
+        }
+
+        threads.stream().forEach(Thread::start);
+
+        while ((System.currentTimeMillis() - startTime < duration) && error == null) {
+            Thread.yield();
+        }
+
+        shouldStop = true;
+        System.out.println("Finished test");
+        if (error != null) {
+            throw error;
+        }
+    }
+}
--- a/hotspot/test/gc/g1/humongousObjects/objectGraphTest/GC.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/test/gc/g1/humongousObjects/objectGraphTest/GC.java	Mon Jul 18 09:38:08 2016 -0700
@@ -138,6 +138,41 @@
         }
     },
 
+    MIXED_GC {
+        @Override
+        public Runnable get() {
+            return () -> {
+                WHITE_BOX.youngGC();
+                Helpers.waitTillCMCFinished(WHITE_BOX, 0);
+                WHITE_BOX.youngGC();
+                Helpers.waitTillCMCFinished(WHITE_BOX, 0);
+
+                WHITE_BOX.g1StartConcMarkCycle();
+                Helpers.waitTillCMCFinished(WHITE_BOX, 0);
+
+                WHITE_BOX.youngGC();
+                Helpers.waitTillCMCFinished(WHITE_BOX, 0);
+                // Provoking Mixed GC
+                WHITE_BOX.youngGC();// second evacuation pause will be mixed
+                Helpers.waitTillCMCFinished(WHITE_BOX, 0);
+            };
+        }
+
+        public Consumer<ReferenceInfo<Object[]>> getChecker() {
+            return getCheckerImpl(true, false, true, false);
+        }
+
+        @Override
+        public List<String> shouldContain() {
+            return Arrays.asList(GCTokens.WB_INITIATED_CMC);
+        }
+
+        @Override
+        public List<String> shouldNotContain() {
+            return Arrays.asList(GCTokens.YOUNG_GC);
+        }
+    },
+
     FULL_GC_MEMORY_PRESSURE {
         @Override
         public Runnable get() {
--- a/hotspot/test/gc/g1/humongousObjects/objectGraphTest/README	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/test/gc/g1/humongousObjects/objectGraphTest/README	Mon Jul 18 09:38:08 2016 -0700
@@ -38,6 +38,9 @@
                         non-humongous and humongous objects are not collected since we make 2 Young GC to promote all
                         weak references to Old Gen.
 
+6. Mixed GC - weakly referenced non-humongous and humongous objects are collected, softly referenced non-humongous and
+              humongous objects are not collected.
+
 The test gets gc type as a command line argument.
 Then the test allocates object graph in heap (currently testing scenarios are pre-generated and stored in
 TestcaseData.getPregeneratedTestcases()) with TestObjectGraphAfterGC::allocateObjectGraph.
--- a/hotspot/test/gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/hotspot/test/gc/g1/humongousObjects/objectGraphTest/TestObjectGraphAfterGC.java	Mon Jul 18 09:38:08 2016 -0700
@@ -66,6 +66,12 @@
  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  *
  * @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
+ * -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=30000 -XX:G1MixedGCLiveThresholdPercent=100 -XX:G1HeapWastePercent=0
+ * -XX:G1HeapRegionSize=1M -Xlog:gc=info:file=TestObjectGraphAfterGC_MIXED_GC.gc.log -XX:MaxTenuringThreshold=1
+ * -XX:G1MixedGCCountTarget=1  -XX:G1OldCSetRegionThresholdPercent=100 -XX:SurvivorRatio=1 -XX:InitiatingHeapOccupancyPercent=0
+ * gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC MIXED_GC
+ *
+ * @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
  * -XX:G1HeapRegionSize=1M -Xlog:gc*=debug:file=TestObjectGraphAfterGC_YOUNG_GC.gc.log
  * gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC YOUNG_GC
  *
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/runtime/test_arguments.cpp	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#include "precompiled.hpp"
+#include "runtime/arguments.hpp"
+#include "unittest.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+TEST(arguments, atojulong) {
+  char ullong_max[32];
+  int ret = jio_snprintf(ullong_max, sizeof(ullong_max), JULONG_FORMAT, ULLONG_MAX);
+  ASSERT_NE(-1, ret);
+
+  julong value;
+  const char* invalid_strings[] = {
+    "", "-1", "-100", " 1", "2 ", "3 2", "1.0",
+    "0x4.5", "0x", "0x0x1" "0.001", "4e10", "e"
+    "K", "M", "G", "1MB", "1KM", "AA", "0B",
+    "18446744073709551615K", "17179869184G",
+    "999999999999999999999999999999"
+  };
+  for (uint i = 0; i < ARRAY_SIZE(invalid_strings); i++) {
+    ASSERT_FALSE(Arguments::atojulong(invalid_strings[i], &value))
+        << "Invalid string '" << invalid_strings[i] << "' parsed without error.";
+  }
+
+  struct {
+    const char* str;
+    julong expected_value;
+  } valid_strings[] = {
+      { "0", 0 },
+      { "4711", 4711 },
+      { "1K", 1ULL * K },
+      { "1k", 1ULL * K },
+      { "2M", 2ULL * M },
+      { "2m", 2ULL * M },
+      { "4G", 4ULL * G },
+      { "4g", 4ULL * G },
+      { "0K", 0 },
+      { ullong_max, ULLONG_MAX },
+      { "0xcafebabe", 0xcafebabe },
+      { "0XCAFEBABE", 0xcafebabe },
+      { "0XCAFEbabe", 0xcafebabe },
+      { "0x10K", 0x10 * K }
+  };
+  for (uint i = 0; i < ARRAY_SIZE(valid_strings); i++) {
+    ASSERT_TRUE(Arguments::atojulong(valid_strings[i].str, &value))
+        << "Valid string '" << valid_strings[i].str << "' did not parse.";
+    ASSERT_EQ(valid_strings[i].expected_value, value);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Final/Bad.jasm	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/* Recoded in jasm to provoke an ICCE assigning a non-static final field with putstatic.
+class Bad {
+  public static final int i; //rewritten
+  //rewritten to: public final int i;
+  static { i = 5; } // putstatic instruction
+}
+*/
+
+super class Bad
+	version 53:0
+{
+
+// Remove 'static' keyword
+public final Field i:I;
+
+Method "<init>":"()V"
+	stack 1 locals 1
+{
+		aload_0;
+		invokespecial	Method java/lang/Object."<init>":"()V";
+		return;
+}
+
+static Method "<clinit>":"()V"
+	stack 1 locals 0
+{
+		iconst_5;
+		putstatic	Field i:"I";
+		return;
+}
+
+} // end Class Bad
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/Final/PutfieldError.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test PutfieldError
+ * @bug 8160551
+ * @summary Throw ICCE rather than crashing for nonstatic final field in static initializer
+ * @compile Bad.jasm
+ * @run main PutfieldError
+ */
+
+public class PutfieldError {
+  public static void main(java.lang.String[] unused) {
+    try {
+      Bad b = new Bad();
+      System.out.println("Bad.i = " + 5);
+      throw new RuntimeException("ICCE NOT thrown as expected");
+    } catch (IncompatibleClassChangeError icce) {
+      System.out.println("ICCE thrown as expected");
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/SharedArchiveFile/SharedStringsDedup.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test SharedStringsDedup
+ * @summary Test -Xshare:auto with shared strings and -XX:+UseStringDeduplication
+ * Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
+ * @requires (sun.arch.data.model != "32") & (os.family != "windows")
+ * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
+ * @requires vm.gc.G1
+ * @library /testlibrary
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ * @run main SharedStringsDedup
+ */
+
+import jdk.test.lib.*;
+import java.io.File;
+
+// The main purpose is to test the interaction between shared strings
+// and -XX:+UseStringDeduplication. We run in -Xshare:auto mode so
+// we don't need to worry about CDS archive mapping failure (which
+// doesn't happen often so it won't impact coverage).
+public class SharedStringsDedup {
+    public static void main(String[] args) throws Exception {
+        // Dump
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:SharedArchiveFile=./SharedStringsDedup.jsa",
+            "-XX:+UseCompressedOops", "-XX:+UseG1GC",
+            "-XX:+PrintSharedSpaces",
+            "-Xshare:dump");
+
+        new OutputAnalyzer(pb.start())
+            .shouldContain("Loading classes to share")
+            .shouldContain("Shared string table stats")
+            .shouldHaveExitValue(0);
+
+        // Run with -Xshare:auto
+        pb = ProcessTools.createJavaProcessBuilder(
+           "-XX:+UnlockDiagnosticVMOptions",
+           "-XX:SharedArchiveFile=./SharedStringsDedup.jsa",
+           "-XX:+UseCompressedOops", "-XX:+UseG1GC",
+           "-XX:+UseStringDeduplication",
+           "-Xshare:auto",
+           "-version");
+
+        new OutputAnalyzer(pb.start())
+            .shouldMatch("(java|openjdk) version")
+            .shouldHaveExitValue(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/CustomSystemClassLoader.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * A custom system ClassLoader to define the module "m2" to during iterations of
+ * differing test runs within the test ModuleStress.java
+ */
+public class CustomSystemClassLoader extends ClassLoader {
+    public CustomSystemClassLoader() {
+        super();
+    }
+    public CustomSystemClassLoader(ClassLoader parent) {
+        super(parent);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/ModuleNonBuiltinCLMain.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader2 --> defines m2 --> packages p2
+// Java System Class Loader --> defines m3 --> packages p3
+//
+// m1 can read m2
+// package p2 in m2 is exported to m1 and m3
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access allowed since m1 can read m2 and package p2 is exported to m1.
+//
+public class ModuleNonBuiltinCLMain {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported to unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base, m3
+        // Packages:          p2
+        // Packages exported: package p2 is exported to m1 and m3
+        Set<String> targets = new HashSet<>();
+        targets.add("m1");
+        targets.add("m3");
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .requires("m3")
+                        .exports("p2", targets)
+                        .build();
+
+        // Define module:     m3
+        // Can read:          java.base
+        // Packages:          p3
+        // Packages exported: none
+        ModuleDescriptor descriptor_m3 =
+                new ModuleDescriptor.Builder("m3")
+                        .requires("java.base")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+
+        // map each module to differing user defined class loaders for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        Loader1 cl1 = new Loader1();
+        Loader2 cl2 = new Loader2();
+        ClassLoader cl3 = ClassLoader.getSystemClassLoader();
+        map.put("m1", cl1);
+        map.put("m2", cl2);
+        map.put("m3", cl3);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+        assertTrue(layer.findLoader("m1") == cl1);
+        assertTrue(layer.findLoader("m2") == cl2);
+        assertTrue(layer.findLoader("m3") == cl3);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = cl1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ModuleNonBuiltinCLMain test = new ModuleNonBuiltinCLMain();
+      test.createLayerOnBoot();
+    }
+
+    static class Loader1 extends ClassLoader { }
+    static class Loader2 extends ClassLoader { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+import java.lang.reflect.Layer;
+import java.lang.module.Configuration;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+//
+// ClassLoader1 --> defines m1 --> packages p1
+// ClassLoader1 --> defines m2 --> packages p2
+//
+// m1 can read m2
+// package p2 in m2 is exported to m1
+//
+// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
+// Access allowed since m1 can read m2 and package p2 is exported to m1.
+//
+public class ModuleSameCLMain {
+
+    // Create a Layer over the boot layer.
+    // Define modules within this layer to test access between
+    // publically defined classes within packages of those modules.
+    public void createLayerOnBoot() throws Throwable {
+
+        // Define module:     m1
+        // Can read:          java.base, m2
+        // Packages:          p1
+        // Packages exported: p1 is exported to unqualifiedly
+        ModuleDescriptor descriptor_m1 =
+                new ModuleDescriptor.Builder("m1")
+                        .requires("java.base")
+                        .requires("m2")
+                        .exports("p1")
+                        .build();
+
+        // Define module:     m2
+        // Can read:          java.base
+        // Packages:          p2
+        // Packages exported: package p2 is exported to m1
+        ModuleDescriptor descriptor_m2 =
+                new ModuleDescriptor.Builder("m2")
+                        .requires("java.base")
+                        .exports("p2", "m1")
+                        .build();
+
+        // Set up a ModuleFinder containing all modules for this layer.
+        ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
+
+        // Resolves "m1"
+        Configuration cf = Layer.boot()
+                .configuration()
+                .resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
+
+        // map each module to the same class loader for this test
+        Map<String, ClassLoader> map = new HashMap<>();
+        Loader1 cl1 = new Loader1();
+        map.put("m1", cl1);
+        map.put("m2", cl1);
+
+        // Create Layer that contains m1 & m2
+        Layer layer = Layer.boot().defineModules(cf, map::get);
+        assertTrue(layer.findLoader("m1") == cl1);
+        assertTrue(layer.findLoader("m2") == cl1);
+        assertTrue(layer.findLoader("java.base") == null);
+
+        // now use the same loader to load class p1.c1
+        Class p1_c1_class = cl1.loadClass("p1.c1");
+        try {
+            p1_c1_class.newInstance();
+        } catch (IllegalAccessError e) {
+            throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
+        }
+    }
+
+    public static void main(String args[]) throws Throwable {
+      ModuleSameCLMain test = new ModuleSameCLMain();
+      test.createLayerOnBoot();
+    }
+
+    static class Loader1 extends ClassLoader { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/ModuleStress.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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 8159262
+ * @summary Test differing scenarios where a module's readability list and a package's exportability list should be walked
+ * @modules java.base/jdk.internal.misc
+ * @library /testlibrary /test/lib
+ * @compile ../AccessCheck/ModuleLibrary.java
+ * @compile ModuleSameCLMain.java
+ * @compile ModuleNonBuiltinCLMain.java
+ * @compile CustomSystemClassLoader.java
+ * @build ModuleStress
+ * @run main/othervm ModuleStress
+ */
+
+import jdk.test.lib.*;
+import java.io.File;
+
+public class ModuleStress {
+
+    public static void main(String[] args) throws Exception {
+
+        // Test #1: java -version
+        //   All modules' readability lists and packages' exportability
+        //   lists should contain only modules defined to the 3 builtin
+        //   loaders (boot, application, platform).  Thus there is
+        //   not a need to walk those lists at a GC safepoint since
+        //   those loaders never die.
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+             "-Xbootclasspath/a:.",
+             "-Xlog:modules=trace",
+             "-version");
+
+        OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+        oa.shouldNotContain("must be walked")
+          .shouldNotContain("being walked")
+          .shouldHaveExitValue(0);
+
+        // Next 2 tests involve the use of class p1.c1 and p2.c2
+        String source1 = "package p1;"   +
+                         "import p2.c2;" +
+                         "public class c1 {" +
+                         "    public c1() {" +
+                         "       p2.c2 c2_obj = new p2.c2();" +
+                         "       c2_obj.method2();" +
+                         "   }" +
+                         "}";
+
+        String source2 = "package p2;" +
+                         "public class c2 {" +
+                         "    public void method2() { }" +
+                         "}";
+
+        ClassFileInstaller.writeClassToDisk("p2/c2",
+             InMemoryJavaCompiler.compile("p2.c2", source2),  System.getProperty("test.classes"));
+
+        ClassFileInstaller.writeClassToDisk("p1/c1",
+             InMemoryJavaCompiler.compile("p1.c1", source1), System.getProperty("test.classes"));
+
+        // Test #2: Load two modules defined to the same customer class loader.
+        //   m1's module readability list and package p2's exportability should
+        //   not be walked at a GC safepoint since both modules are defined to
+        //   the same loader and thus have the exact same life cycle.
+        pb = ProcessTools.createJavaProcessBuilder(
+             "-Xbootclasspath/a:.",
+             "-Xlog:modules=trace",
+             "ModuleSameCLMain");
+
+        oa = new OutputAnalyzer(pb.start());
+        oa.shouldNotContain("must be walked")
+          .shouldNotContain("being walked")
+          .shouldHaveExitValue(0);
+
+        // Test #3: Load two modules in differing custom class loaders.
+        //   m1's module readability list and package p2's exportability list must
+        //   be walked at a GC safepoint since both modules are defined to non-builtin
+        //   class loaders which could die and thus be unloaded.
+        pb = ProcessTools.createJavaProcessBuilder(
+             "-Xbootclasspath/a:.",
+             "-Xlog:modules=trace",
+             "ModuleNonBuiltinCLMain");
+
+        oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("module m1 reads list must be walked")
+          .shouldContain("package p2 defined in module m2, exports list must be walked")
+          .shouldNotContain("module m2 reads list must be walked")
+          .shouldHaveExitValue(0);
+
+        // Test #4: Load two modules in differing custom class loaders,
+        //   of which one has been designated as the custom system class loader
+        //   via -Djava.system.class.loader=CustomSystemClassLoader. Since
+        //   m3 is defined to the system class loader, m2's module readability
+        //   list does not have to be walked at a GC safepoint, but package p2's
+        //   exportability list does.
+        pb = ProcessTools.createJavaProcessBuilder(
+             "-Djava.system.class.loader=CustomSystemClassLoader",
+             "-Xbootclasspath/a:.",
+             "-Xlog:modules=trace",
+             "ModuleNonBuiltinCLMain");
+
+        oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("package p2 defined in module m2, exports list must be walked")
+          .shouldNotContain("module m2 reads list must be walked")
+          .shouldHaveExitValue(0);
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/ModuleStressGC.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8159262
+ * @summary layers over the boot layer are repeatedly created, during this iteration, GCs are forced to verify correct walk of module and package lists.
+ * @modules java.base/jdk.internal.misc
+ * @library /testlibrary /test/lib
+ * @compile ../CompilerUtils.java
+ * @build ModuleStressGC
+ * @run main/othervm ModuleStressGC
+ */
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.*;
+
+public class ModuleStressGC {
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+    private static final String TEST_CLASSES = System.getProperty("test.classes");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get(TEST_CLASSES, "mods");
+
+    /**
+     * Compile two module definitions used by the test, jdk.test and jdk.translet.
+     */
+    public static void main(String[] args) throws Exception {
+
+        boolean compiled;
+        // Compile module jdk.test declaration
+        compiled = CompilerUtils.compile(
+            SRC_DIR.resolve("jdk.test"),
+            MODS_DIR.resolve("jdk.test"));
+        if (!compiled) {
+            throw new RuntimeException("Test failed to compile module jdk.test");
+        }
+
+        // Compile module jdk.translet declaration
+        compiled = CompilerUtils.compile(
+            SRC_DIR.resolve("jdk.translet"),
+            MODS_DIR.resolve("jdk.translet"),
+            "-XaddExports:jdk.test/test=jdk.translet",
+            "-mp", MODS_DIR.toString());
+        if (!compiled) {
+            throw new RuntimeException("Test failed to compile module jdk.translet");
+        }
+
+        // Sanity check that the test, jdk.test/test/MainGC.java,
+        // correctly walks module jdk.test's reads list and package
+        // test's, defined to module jdk.translet, export list at
+        // GC safepoints.
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-Xlog:modules=trace",
+            "-mp", MODS_DIR.toString(),
+            "-m", "jdk.test/test.MainGC");
+        OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("package test defined in module jdk.test, exports list being walked")
+          .shouldContain("module jdk.test reads list being walked")
+          .shouldHaveExitValue(0);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/src/jdk.test/test/MainGC.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package test;
+
+import java.lang.module.Configuration;
+import java.lang.module.ModuleFinder;
+import java.lang.reflect.Layer;
+import java.lang.reflect.Method;
+import java.lang.reflect.Module;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+public class MainGC {
+
+    private static final Path MODS_DIR = Paths.get(System.getProperty("jdk.module.path"));
+    static final String MODULE_NAME = "jdk.translet";
+
+    public static void main(String[] args) throws Exception {
+
+        ModuleFinder finder = ModuleFinder.of(MODS_DIR);
+        Layer layerBoot = Layer.boot();
+
+        Configuration cf = layerBoot
+                .configuration()
+                .resolveRequires(ModuleFinder.of(), finder, Set.of(MODULE_NAME));
+
+        Module testModule = MainGC.class.getModule();
+        ClassLoader scl = ClassLoader.getSystemClassLoader();
+
+        // Create an unique module/class loader in a layer above the boot layer.
+        // Export this module to the jdk.test/test package.
+        // Add a read edge from module jdk.test to this module.
+        Callable<Void> task = new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
+                Module transletModule = layer.findModule(MODULE_NAME).get();
+                testModule.addExports("test", transletModule);
+                testModule.addReads(transletModule);
+                Class<?> c = layer.findLoader(MODULE_NAME).loadClass("translet.MainGC");
+                Method method = c.getDeclaredMethod("go");
+                method.invoke(null);
+                return null;
+            }
+        };
+
+        List<Future<Void>> results = new ArrayList<>();
+
+        // Repeatedly create the layer above stressing the exportation of
+        // package jdk.test/test to several different modules.
+        ExecutorService pool = Executors.newFixedThreadPool(Math.min(100, Runtime.getRuntime().availableProcessors()*10));
+        try {
+            for (int i = 0; i < 10000; i++) {
+                results.add(pool.submit(task));
+                // At specified intervals, force a GC. This provides an
+                // opportunity to verify that both the module jdk.test's reads
+                // and the package test's, which is defined to jdk.test, exports
+                // lists are being walked.
+                if (i == 3000 || i == 6000 || i == 9000) {
+                    System.gc();
+                }
+            }
+        } finally {
+            pool.shutdown();
+        }
+
+        int passed = 0;
+        int failed = 0;
+
+        // The failed state should be 0, the created modules in layers above the
+        // boot layer should be allowed access to the contents of the jdk.test/test
+        // package since that package was exported to the transletModule above.
+        for (Future<Void> result : results) {
+            try {
+                result.get();
+                passed++;
+            } catch (Throwable x) {
+                x.printStackTrace();
+                failed++;
+            }
+        }
+
+        System.out.println("passed: " + passed);
+        System.out.println("failed: " + failed);
+    }
+
+    public static void callback() { }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/modules/ModuleStress/src/jdk.translet/translet/MainGC.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package translet;
+
+public class MainGC {
+    public static void go() {
+        test.MainGC.callback();
+    }
+}
--- a/jaxp/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/jaxp/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -369,3 +369,4 @@
 e04a15153cc293f05fcd60bc98236f50e16af46a jdk-9+124
 493eb91ec32a6dea7604cfbd86c10045ad9af15b jdk-9+125
 15722f71281f034bc696d8b96136da2ef34da44f jdk-9+126
+bdc3c0b737efbf899709eb3121ce760dcfb51151 jdk-9+127
--- a/jaxws/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/jaxws/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -372,3 +372,4 @@
 1600da1665cd2cc127014e8c002b328ec33a9147 jdk-9+124
 5b0570e3db29f6b8c80a4beac70d51284507b203 jdk-9+125
 264a44128cd6286e598d5a849ceeb613c06269d0 jdk-9+126
+06d706c70634775418dc79a2671780ba1c624fd2 jdk-9+127
--- a/jdk/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/com/sun/security/ntlm/NTLM.java	Mon Jul 18 09:38:08 2016 -0700
@@ -169,7 +169,7 @@
 
         byte[] readSecurityBuffer(int offset) throws NTLMException {
             int pos = readInt(offset+4);
-            if (pos == 0) return null;
+            if (pos == 0) return new byte[0];
             try {
                 return Arrays.copyOfRange(
                         internal, pos, pos + readShort(offset));
--- a/jdk/src/java.base/share/classes/java/lang/Math.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/Math.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1613,6 +1613,8 @@
      * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
      * computed, as if with unlimited range and precision, and rounded
      * once to the nearest {@code double} value
+     *
+     * @since 9
      */
     // @HotSpotIntrinsicCandidate
     public static double fma(double a, double b, double c) {
@@ -1728,6 +1730,8 @@
      * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
      * computed, as if with unlimited range and precision, and rounded
      * once to the nearest {@code float} value
+     *
+     * @since 9
      */
     // @HotSpotIntrinsicCandidate
     public static float fma(float a, float b, float c) {
--- a/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/StrictMath.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1276,6 +1276,8 @@
      * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
      * computed, as if with unlimited range and precision, and rounded
      * once to the nearest {@code double} value
+     *
+     * @since 9
      */
     public static double fma(double a, double b, double c) {
         return Math.fma(a, b, c);
@@ -1328,6 +1330,8 @@
      * @return (<i>a</i>&nbsp;&times;&nbsp;<i>b</i>&nbsp;+&nbsp;<i>c</i>)
      * computed, as if with unlimited range and precision, and rounded
      * once to the nearest {@code float} value
+     *
+     * @since 9
      */
     public static float fma(float a, float b, float c) {
         return Math.fma(a, b, c);
--- a/jdk/src/java.base/share/classes/java/lang/module/package-info.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/lang/module/package-info.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/jdk/src/java.base/share/classes/java/nio/file/Files.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/nio/file/Files.java	Mon Jul 18 09:38:08 2016 -0700
@@ -3290,8 +3290,8 @@
      * a size of {@code 0}. All bytes in the byte array are written to the file.
      * The method ensures that the file is closed when all bytes have been
      * written (or an I/O error or other runtime exception is thrown). If an I/O
-     * error occurs then it may do so after the file has created or truncated,
-     * or after some bytes have been written to the file.
+     * error occurs then it may do so after the file has been created or
+     * truncated, or after some bytes have been written to the file.
      *
      * <p> <b>Usage example</b>: By default the method creates a new file or
      * overwrites an existing file. Suppose you instead want to append bytes
@@ -3360,7 +3360,8 @@
      * a size of {@code 0}. The method ensures that the file is closed when all
      * lines have been written (or an I/O error or other runtime exception is
      * thrown). If an I/O error occurs then it may do so after the file has
-     * created or truncated, or after some bytes have been written to the file.
+     * been created or truncated, or after some bytes have been written to the
+     * file.
      *
      * @param   path
      *          the path to the file
--- a/jdk/src/java.base/share/classes/java/util/Queue.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/Queue.java	Mon Jul 18 09:38:08 2016 -0700
@@ -124,7 +124,6 @@
  * always well-defined for queues with the same elements but different
  * ordering properties.
  *
- *
  * <p>This interface is a member of the
  * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  * Java Collections Framework</a>.
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.locks.LockSupport;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
@@ -149,26 +151,29 @@
      * applies across normal vs exceptional outcomes, sync vs async
      * actions, binary triggers, and various forms of completions.
      *
-     * Non-nullness of field result (set via CAS) indicates done.  An
-     * AltResult is used to box null as a result, as well as to hold
-     * exceptions.  Using a single field makes completion simple to
-     * detect and trigger.  Encoding and decoding is straightforward
-     * but adds to the sprawl of trapping and associating exceptions
-     * with targets.  Minor simplifications rely on (static) NIL (to
-     * box null results) being the only AltResult with a null
-     * exception field, so we don't usually need explicit comparisons.
-     * Even though some of the generics casts are unchecked (see
-     * SuppressWarnings annotations), they are placed to be
-     * appropriate even if checked.
+     * Non-nullness of volatile field "result" indicates done.  It may
+     * be set directly if known to be thread-confined, else via CAS.
+     * An AltResult is used to box null as a result, as well as to
+     * hold exceptions.  Using a single field makes completion simple
+     * to detect and trigger.  Result encoding and decoding is
+     * straightforward but tedious and adds to the sprawl of trapping
+     * and associating exceptions with targets.  Minor simplifications
+     * rely on (static) NIL (to box null results) being the only
+     * AltResult with a null exception field, so we don't usually need
+     * explicit comparisons.  Even though some of the generics casts
+     * are unchecked (see SuppressWarnings annotations), they are
+     * placed to be appropriate even if checked.
      *
      * Dependent actions are represented by Completion objects linked
      * as Treiber stacks headed by field "stack". There are Completion
-     * classes for each kind of action, grouped into single-input
-     * (UniCompletion), two-input (BiCompletion), projected
-     * (BiCompletions using either (not both) of two inputs), shared
-     * (CoCompletion, used by the second of two sources), zero-input
-     * source actions, and Signallers that unblock waiters. Class
-     * Completion extends ForkJoinTask to enable async execution
+     * classes for each kind of action, grouped into:
+     * - single-input (UniCompletion),
+     * - two-input (BiCompletion),
+     * - projected (BiCompletions using exactly one of two inputs),
+     * - shared (CoCompletion, used by the second of two sources),
+     * - zero-input source actions,
+     * - Signallers that unblock waiters.
+     * Class Completion extends ForkJoinTask to enable async execution
      * (adding no space overhead because we exploit its "tag" methods
      * to maintain claims). It is also declared as Runnable to allow
      * usage with arbitrary executors.
@@ -184,7 +189,7 @@
      *   encounter layers of adapters in common usages.
      *
      * * Boolean CompletableFuture method x(...) (for example
-     *   uniApply) takes all of the arguments needed to check that an
+     *   biApply) takes all of the arguments needed to check that an
      *   action is triggerable, and then either runs the action or
      *   arranges its async execution by executing its Completion
      *   argument, if present. The method returns true if known to be
@@ -194,24 +199,29 @@
      *   method with its held arguments, and on success cleans up.
      *   The mode argument allows tryFire to be called twice (SYNC,
      *   then ASYNC); the first to screen and trap exceptions while
-     *   arranging to execute, and the second when called from a
-     *   task. (A few classes are not used async so take slightly
-     *   different forms.)  The claim() callback suppresses function
-     *   invocation if already claimed by another thread.
+     *   arranging to execute, and the second when called from a task.
+     *   (A few classes are not used async so take slightly different
+     *   forms.)  The claim() callback suppresses function invocation
+     *   if already claimed by another thread.
+     *
+     * * Some classes (for example UniApply) have separate handling
+     *   code for when known to be thread-confined ("now" methods) and
+     *   for when shared (in tryFire), for efficiency.
      *
      * * CompletableFuture method xStage(...) is called from a public
-     *   stage method of CompletableFuture x. It screens user
+     *   stage method of CompletableFuture f. It screens user
      *   arguments and invokes and/or creates the stage object.  If
-     *   not async and x is already complete, the action is run
-     *   immediately.  Otherwise a Completion c is created, pushed to
-     *   x's stack (unless done), and started or triggered via
-     *   c.tryFire.  This also covers races possible if x completes
-     *   while pushing.  Classes with two inputs (for example BiApply)
-     *   deal with races across both while pushing actions.  The
-     *   second completion is a CoCompletion pointing to the first,
-     *   shared so that at most one performs the action.  The
-     *   multiple-arity methods allOf and anyOf do this pairwise to
-     *   form trees of completions.
+     *   not async and already triggerable, the action is run
+     *   immediately.  Otherwise a Completion c is created, and
+     *   submitted to the executor if triggerable, or pushed onto f's
+     *   stack if not.  Completion actions are started via c.tryFire.
+     *   We recheck after pushing to a source future's stack to cover
+     *   possible races if the source completes while pushing.
+     *   Classes with two inputs (for example BiApply) deal with races
+     *   across both while pushing actions.  The second completion is
+     *   a CoCompletion pointing to the first, shared so that at most
+     *   one performs the action.  The multiple-arity methods allOf
+     *   and anyOf do this pairwise to form trees of completions.
      *
      * Note that the generic type parameters of methods vary according
      * to whether "this" is a source, dependent, or completion.
@@ -236,29 +246,30 @@
      * pointing back to its sources. So we null out fields as soon as
      * possible.  The screening checks needed anyway harmlessly ignore
      * null arguments that may have been obtained during races with
-     * threads nulling out fields.  We also try to unlink fired
-     * Completions from stacks that might never be popped (see method
-     * postFire).  Completion fields need not be declared as final or
-     * volatile because they are only visible to other threads upon
-     * safe publication.
+     * threads nulling out fields.  We also try to unlink non-isLive
+     * (fired or cancelled) Completions from stacks that might
+     * otherwise never be popped: Method cleanStack always unlinks non
+     * isLive completions from the head of stack; others may
+     * occasionally remain if racing with other cancellations or
+     * removals.
+     *
+     * Completion fields need not be declared as final or volatile
+     * because they are only visible to other threads upon safe
+     * publication.
      */
 
     volatile Object result;       // Either the result or boxed AltResult
     volatile Completion stack;    // Top of Treiber stack of dependent actions
 
     final boolean internalComplete(Object r) { // CAS from null to r
-        return U.compareAndSwapObject(this, RESULT, null, r);
-    }
-
-    final boolean casStack(Completion cmp, Completion val) {
-        return U.compareAndSwapObject(this, STACK, cmp, val);
+        return RESULT.compareAndSet(this, null, r);
     }
 
     /** Returns true if successfully pushed c onto stack. */
     final boolean tryPushStack(Completion c) {
         Completion h = stack;
-        lazySetNext(c, h);
-        return U.compareAndSwapObject(this, STACK, h, c);
+        NEXT.set(c, h);         // CAS piggyback
+        return STACK.compareAndSet(this, h, c);
     }
 
     /** Unconditionally pushes c onto stack, retrying if necessary. */
@@ -278,8 +289,7 @@
 
     /** Completes with the null value, unless already completed. */
     final boolean completeNull() {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      NIL);
+        return RESULT.compareAndSet(this, null, NIL);
     }
 
     /** Returns the encoding of the given non-exceptional value. */
@@ -289,8 +299,7 @@
 
     /** Completes with a non-exceptional result, unless already completed. */
     final boolean completeValue(T t) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      (t == null) ? NIL : t);
+        return RESULT.compareAndSet(this, null, (t == null) ? NIL : t);
     }
 
     /**
@@ -304,8 +313,7 @@
 
     /** Completes with an exceptional result, unless already completed. */
     final boolean completeThrowable(Throwable x) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeThrowable(x));
+        return RESULT.compareAndSet(this, null, encodeThrowable(x));
     }
 
     /**
@@ -332,8 +340,7 @@
      * existing CompletionException.
      */
     final boolean completeThrowable(Throwable x, Object r) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeThrowable(x, r));
+        return RESULT.compareAndSet(this, null, encodeThrowable(x, r));
     }
 
     /**
@@ -351,10 +358,11 @@
      */
     static Object encodeRelay(Object r) {
         Throwable x;
-        return (((r instanceof AltResult) &&
-                 (x = ((AltResult)r).ex) != null &&
-                 !(x instanceof CompletionException)) ?
-                new AltResult(new CompletionException(x)) : r);
+        if (r instanceof AltResult
+            && (x = ((AltResult)r).ex) != null
+            && !(x instanceof CompletionException))
+            r = new AltResult(new CompletionException(x));
+        return r;
     }
 
     /**
@@ -362,14 +370,13 @@
      * If exceptional, r is first coerced to a CompletionException.
      */
     final boolean completeRelay(Object r) {
-        return U.compareAndSwapObject(this, RESULT, null,
-                                      encodeRelay(r));
+        return RESULT.compareAndSet(this, null, encodeRelay(r));
     }
 
     /**
      * Reports result using Future.get conventions.
      */
-    private static <T> T reportGet(Object r)
+    private static Object reportGet(Object r)
         throws InterruptedException, ExecutionException {
         if (r == null) // by convention below, null means interrupted
             throw new InterruptedException();
@@ -384,14 +391,13 @@
                 x = cause;
             throw new ExecutionException(x);
         }
-        @SuppressWarnings("unchecked") T t = (T) r;
-        return t;
+        return r;
     }
 
     /**
      * Decodes outcome to return result or throw unchecked exception.
      */
-    private static <T> T reportJoin(Object r) {
+    private static Object reportJoin(Object r) {
         if (r instanceof AltResult) {
             Throwable x;
             if ((x = ((AltResult)r).ex) == null)
@@ -402,8 +408,7 @@
                 throw (CompletionException)x;
             throw new CompletionException(x);
         }
-        @SuppressWarnings("unchecked") T t = (T) r;
-        return t;
+        return r;
     }
 
     /* ------------- Async task preliminaries -------------- */
@@ -449,12 +454,6 @@
     static final int ASYNC  =  1;
     static final int NESTED = -1;
 
-    /**
-     * Spins before blocking in waitingGet
-     */
-    static final int SPINS = (Runtime.getRuntime().availableProcessors() > 1 ?
-                              1 << 8 : 0);
-
     /* ------------- Base Completion classes and operations -------------- */
 
     @SuppressWarnings("serial")
@@ -479,10 +478,6 @@
         public final void setRawResult(Void v) {}
     }
 
-    static void lazySetNext(Completion c, Completion next) {
-        U.putObjectRelease(c, NEXT, next);
-    }
-
     /**
      * Pops and tries to trigger all reachable dependents.  Call only
      * when known to be done.
@@ -497,40 +492,47 @@
         while ((h = f.stack) != null ||
                (f != this && (h = (f = this).stack) != null)) {
             CompletableFuture<?> d; Completion t;
-            if (f.casStack(h, t = h.next)) {
+            if (STACK.compareAndSet(f, h, t = h.next)) {
                 if (t != null) {
                     if (f != this) {
                         pushStack(h);
                         continue;
                     }
-                    h.next = null;    // detach
+                    NEXT.compareAndSet(h, t, null); // try to detach
                 }
                 f = (d = h.tryFire(NESTED)) == null ? this : d;
             }
         }
     }
 
-    /** Traverses stack and unlinks dead Completions. */
+    /** Traverses stack and unlinks one or more dead Completions, if found. */
     final void cleanStack() {
-        for (Completion p = null, q = stack; q != null;) {
+        Completion p = stack;
+        // ensure head of stack live
+        for (boolean unlinked = false;;) {
+            if (p == null)
+                return;
+            else if (p.isLive()) {
+                if (unlinked)
+                    return;
+                else
+                    break;
+            }
+            else if (STACK.weakCompareAndSetVolatile(this, p, (p = p.next)))
+                unlinked = true;
+            else
+                p = stack;
+        }
+        // try to unlink first non-live
+        for (Completion q = p.next; q != null;) {
             Completion s = q.next;
             if (q.isLive()) {
                 p = q;
                 q = s;
-            }
-            else if (p == null) {
-                casStack(q, s);
-                q = stack;
-            }
-            else {
-                p.next = s;
-                if (p.isLive())
-                    q = s;
-                else {
-                    p = null;  // restart
-                    q = stack;
-                }
-            }
+            } else if (NEXT.weakCompareAndSetVolatile(p, q, s))
+                break;
+            else
+                q = p.next;
         }
     }
 
@@ -568,11 +570,20 @@
         final boolean isLive() { return dep != null; }
     }
 
-    /** Pushes the given completion (if it exists) unless done. */
-    final void push(UniCompletion<?,?> c) {
+    /**
+     * Pushes the given completion unless it completes while trying.
+     * Caller should first check that result is null.
+     */
+    final void unipush(Completion c) {
         if (c != null) {
-            while (result == null && !tryPushStack(c))
-                lazySetNext(c, null); // clear on failure
+            while (!tryPushStack(c)) {
+                if (result != null) {
+                    NEXT.set(c, null);
+                    break;
+                }
+            }
+            if (result != null)
+                c.tryFire(SYNC);
         }
     }
 
@@ -583,9 +594,10 @@
      */
     final CompletableFuture<T> postFire(CompletableFuture<?> a, int mode) {
         if (a != null && a.stack != null) {
-            if (a.result == null)
+            Object r;
+            if ((r = a.result) == null)
                 a.cleanStack();
-            else if (mode >= 0)
+            if (mode >= 0 && (r != null || a.result != null))
                 a.postComplete();
         }
         if (result != null && stack != null) {
@@ -607,48 +619,65 @@
         }
         final CompletableFuture<V> tryFire(int mode) {
             CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniApply(a = src, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Function<? super T,? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            tryComplete: if (d.result == null) {
+                if (r instanceof AltResult) {
+                    if ((x = ((AltResult)r).ex) != null) {
+                        d.completeThrowable(x, r);
+                        break tryComplete;
+                    }
+                    r = null;
+                }
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    else {
+                        @SuppressWarnings("unchecked") T t = (T) r;
+                        d.completeValue(f.apply(t));
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniApply(CompletableFuture<S> a,
-                               Function<? super S,? extends T> f,
-                               UniApply<S,T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                completeValue(f.apply(s));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <V> CompletableFuture<V> uniApplyStage(
         Executor e, Function<? super T,? extends V> f) {
         if (f == null) throw new NullPointerException();
+        Object r;
+        if ((r = result) != null)
+            return uniApplyNow(r, e, f);
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.uniApply(this, f, null)) {
-            UniApply<T,V> c = new UniApply<T,V>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        unipush(new UniApply<T,V>(e, d, this, f));
+        return d;
+    }
+
+    private <V> CompletableFuture<V> uniApplyNow(
+        Object r, Executor e, Function<? super T,? extends V> f) {
+        Throwable x;
+        CompletableFuture<V> d = newIncompleteFuture();
+        if (r instanceof AltResult) {
+            if ((x = ((AltResult)r).ex) != null) {
+                d.result = encodeThrowable(x, r);
+                return d;
+            }
+            r = null;
+        }
+        try {
+            if (e != null) {
+                e.execute(new UniApply<T,V>(null, d, this, f));
+            } else {
+                @SuppressWarnings("unchecked") T t = (T) r;
+                d.result = d.encodeValue(f.apply(t));
+            }
+        } catch (Throwable ex) {
+            d.result = encodeThrowable(ex);
         }
         return d;
     }
@@ -662,48 +691,67 @@
         }
         final CompletableFuture<Void> tryFire(int mode) {
             CompletableFuture<Void> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniAccept(a = src, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Consumer<? super T> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            tryComplete: if (d.result == null) {
+                if (r instanceof AltResult) {
+                    if ((x = ((AltResult)r).ex) != null) {
+                        d.completeThrowable(x, r);
+                        break tryComplete;
+                    }
+                    r = null;
+                }
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    else {
+                        @SuppressWarnings("unchecked") T t = (T) r;
+                        f.accept(t);
+                        d.completeNull();
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniAccept(CompletableFuture<S> a,
-                                Consumer<? super S> f, UniAccept<S> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                f.accept(s);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private CompletableFuture<Void> uniAcceptStage(Executor e,
                                                    Consumer<? super T> f) {
         if (f == null) throw new NullPointerException();
+        Object r;
+        if ((r = result) != null)
+            return uniAcceptNow(r, e, f);
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.uniAccept(this, f, null)) {
-            UniAccept<T> c = new UniAccept<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        unipush(new UniAccept<T>(e, d, this, f));
+        return d;
+    }
+
+    private CompletableFuture<Void> uniAcceptNow(
+        Object r, Executor e, Consumer<? super T> f) {
+        Throwable x;
+        CompletableFuture<Void> d = newIncompleteFuture();
+        if (r instanceof AltResult) {
+            if ((x = ((AltResult)r).ex) != null) {
+                d.result = encodeThrowable(x, r);
+                return d;
+            }
+            r = null;
+        }
+        try {
+            if (e != null) {
+                e.execute(new UniAccept<T>(null, d, this, f));
+            } else {
+                @SuppressWarnings("unchecked") T t = (T) r;
+                f.accept(t);
+                d.result = NIL;
+            }
+        } catch (Throwable ex) {
+            d.result = encodeThrowable(ex);
         }
         return d;
     }
@@ -717,42 +765,56 @@
         }
         final CompletableFuture<Void> tryFire(int mode) {
             CompletableFuture<Void> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniRun(a = src, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Runnable f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            if (d.result == null) {
+                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
+                    d.completeThrowable(x, r);
+                else
+                    try {
+                        if (mode <= 0 && !claim())
+                            return null;
+                        else {
+                            f.run();
+                            d.completeNull();
+                        }
+                    } catch (Throwable ex) {
+                        d.completeThrowable(ex);
+                    }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniRun(CompletableFuture<?> a, Runnable f, UniRun<?> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else
-                try {
-                    if (c != null && !c.claim())
-                        return false;
-                    f.run();
-                    completeNull();
-                } catch (Throwable ex) {
-                    completeThrowable(ex);
-                }
-        }
-        return true;
+    private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
+        if (f == null) throw new NullPointerException();
+        Object r;
+        if ((r = result) != null)
+            return uniRunNow(r, e, f);
+        CompletableFuture<Void> d = newIncompleteFuture();
+        unipush(new UniRun<T>(e, d, this, f));
+        return d;
     }
 
-    private CompletableFuture<Void> uniRunStage(Executor e, Runnable f) {
-        if (f == null) throw new NullPointerException();
+    private CompletableFuture<Void> uniRunNow(Object r, Executor e, Runnable f) {
+        Throwable x;
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.uniRun(this, f, null)) {
-            UniRun<T> c = new UniRun<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
+        if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
+            d.result = encodeThrowable(x, r);
+        else
+            try {
+                if (e != null) {
+                    e.execute(new UniRun<T>(null, d, this, f));
+                } else {
+                    f.run();
+                    d.result = NIL;
+                }
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -766,20 +828,20 @@
         }
         final CompletableFuture<T> tryFire(int mode) {
             CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniWhenComplete(a = src, fn, mode > 0 ? null : this))
+            Object r; BiConsumer<? super T, ? super Throwable> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || !d.uniWhenComplete(r, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniWhenComplete(CompletableFuture<T> a,
+    final boolean uniWhenComplete(Object r,
                                   BiConsumer<? super T,? super Throwable> f,
                                   UniWhenComplete<T> c) {
-        Object r; T t; Throwable x = null;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
+        T t; Throwable x = null;
         if (result == null) {
             try {
                 if (c != null && !c.claim())
@@ -811,10 +873,17 @@
         Executor e, BiConsumer<? super T, ? super Throwable> f) {
         if (f == null) throw new NullPointerException();
         CompletableFuture<T> d = newIncompleteFuture();
-        if (e != null || !d.uniWhenComplete(this, f, null)) {
-            UniWhenComplete<T> c = new UniWhenComplete<T>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        Object r;
+        if ((r = result) == null)
+            unipush(new UniWhenComplete<T>(e, d, this, f));
+        else if (e == null)
+            d.uniWhenComplete(r, f, null);
+        else {
+            try {
+                e.execute(new UniWhenComplete<T>(null, d, this, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         }
         return d;
     }
@@ -829,20 +898,20 @@
         }
         final CompletableFuture<V> tryFire(int mode) {
             CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniHandle(a = src, fn, mode > 0 ? null : this))
+            Object r; BiFunction<? super T, Throwable, ? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || !d.uniHandle(r, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniHandle(CompletableFuture<S> a,
+    final <S> boolean uniHandle(Object r,
                                 BiFunction<? super S, Throwable, ? extends T> f,
                                 UniHandle<S,T> c) {
-        Object r; S s; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
+        S s; Throwable x;
         if (result == null) {
             try {
                 if (c != null && !c.claim())
@@ -867,10 +936,17 @@
         Executor e, BiFunction<? super T, Throwable, ? extends V> f) {
         if (f == null) throw new NullPointerException();
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.uniHandle(this, f, null)) {
-            UniHandle<T,V> c = new UniHandle<T,V>(e, d, this, f);
-            push(c);
-            c.tryFire(SYNC);
+        Object r;
+        if ((r = result) == null)
+            unipush(new UniHandle<T,V>(e, d, this, f));
+        else if (e == null)
+            d.uniHandle(r, f, null);
+        else {
+            try {
+                e.execute(new UniHandle<T,V>(null, d, this, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         }
         return d;
     }
@@ -885,19 +961,20 @@
         final CompletableFuture<T> tryFire(int mode) { // never ASYNC
             // assert mode != ASYNC;
             CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null || !d.uniExceptionally(a = src, fn, this))
+            Object r; Function<? super Throwable, ? extends T> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || !d.uniExceptionally(r, f, this))
                 return null;
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniExceptionally(CompletableFuture<T> a,
+    final boolean uniExceptionally(Object r,
                                    Function<? super Throwable, ? extends T> f,
                                    UniExceptionally<T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
+        Throwable x;
         if (result == null) {
             try {
                 if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) {
@@ -917,47 +994,38 @@
         Function<Throwable, ? extends T> f) {
         if (f == null) throw new NullPointerException();
         CompletableFuture<T> d = newIncompleteFuture();
-        if (!d.uniExceptionally(this, f, null)) {
-            UniExceptionally<T> c = new UniExceptionally<T>(d, this, f);
-            push(c);
-            c.tryFire(SYNC);
-        }
+        Object r;
+        if ((r = result) == null)
+            unipush(new UniExceptionally<T>(d, this, f));
+        else
+            d.uniExceptionally(r, f, null);
         return d;
     }
 
     @SuppressWarnings("serial")
-    static final class UniRelay<T> extends UniCompletion<T,T> { // for Compose
+    static final class UniRelay<T> extends UniCompletion<T,T> {
         UniRelay(CompletableFuture<T> dep, CompletableFuture<T> src) {
             super(null, dep, src);
         }
         final CompletableFuture<T> tryFire(int mode) {
-            CompletableFuture<T> d; CompletableFuture<T> a;
-            if ((d = dep) == null || !d.uniRelay(a = src))
+            CompletableFuture<T> d; CompletableFuture<T> a; Object r;
+            if ((d = dep) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            if (d.result == null)
+                d.completeRelay(r);
             src = null; dep = null;
             return d.postFire(a, mode);
         }
     }
 
-    final boolean uniRelay(CompletableFuture<T> a) {
-        Object r;
-        if (a == null || (r = a.result) == null)
-            return false;
-        if (result == null) // no need to claim
-            completeRelay(r);
-        return true;
-    }
-
     private CompletableFuture<T> uniCopyStage() {
         Object r;
         CompletableFuture<T> d = newIncompleteFuture();
         if ((r = result) != null)
-            d.completeRelay(r);
-        else {
-            UniRelay<T> c = new UniRelay<T>(d, this);
-            push(c);
-            c.tryFire(SYNC);
-        }
+            d.result = encodeRelay(r);
+        else
+            unipush(new UniRelay<T>(d, this));
         return d;
     }
 
@@ -966,9 +1034,7 @@
         if ((r = result) != null)
             return new MinimalStage<T>(encodeRelay(r));
         MinimalStage<T> d = new MinimalStage<T>();
-        UniRelay<T> c = new UniRelay<T>(d, this);
-        push(c);
-        c.tryFire(SYNC);
+        unipush(new UniRelay<T>(d, this));
         return d;
     }
 
@@ -982,54 +1048,48 @@
         }
         final CompletableFuture<V> tryFire(int mode) {
             CompletableFuture<V> d; CompletableFuture<T> a;
-            if ((d = dep) == null ||
-                !d.uniCompose(a = src, fn, mode > 0 ? null : this))
+            Function<? super T, ? extends CompletionStage<V>> f;
+            Object r; Throwable x;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null)
                 return null;
+            tryComplete: if (d.result == null) {
+                if (r instanceof AltResult) {
+                    if ((x = ((AltResult)r).ex) != null) {
+                        d.completeThrowable(x, r);
+                        break tryComplete;
+                    }
+                    r = null;
+                }
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    @SuppressWarnings("unchecked") T t = (T) r;
+                    CompletableFuture<V> g = f.apply(t).toCompletableFuture();
+                    if ((r = g.result) != null)
+                        d.completeRelay(r);
+                    else {
+                        g.unipush(new UniRelay<V>(d, g));
+                        if (d.result == null)
+                            return null;
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; fn = null;
             return d.postFire(a, mode);
         }
     }
 
-    final <S> boolean uniCompose(
-        CompletableFuture<S> a,
-        Function<? super S, ? extends CompletionStage<T>> f,
-        UniCompose<S,T> c) {
-        Object r; Throwable x;
-        if (a == null || (r = a.result) == null || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            if (r instanceof AltResult) {
-                if ((x = ((AltResult)r).ex) != null) {
-                    completeThrowable(x, r);
-                    break tryComplete;
-                }
-                r = null;
-            }
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                @SuppressWarnings("unchecked") S s = (S) r;
-                CompletableFuture<T> g = f.apply(s).toCompletableFuture();
-                if (g.result == null || !uniRelay(g)) {
-                    UniRelay<T> copy = new UniRelay<T>(this, g);
-                    g.push(copy);
-                    copy.tryFire(SYNC);
-                    if (result == null)
-                        return false;
-                }
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <V> CompletableFuture<V> uniComposeStage(
         Executor e, Function<? super T, ? extends CompletionStage<V>> f) {
         if (f == null) throw new NullPointerException();
+        CompletableFuture<V> d = newIncompleteFuture();
         Object r, s; Throwable x;
-        CompletableFuture<V> d = newIncompleteFuture();
-        if (e == null && (r = result) != null) {
+        if ((r = result) == null)
+            unipush(new UniCompose<T,V>(e, d, this, f));
+        else if (e == null) {
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
                     d.result = encodeThrowable(x, r);
@@ -1041,21 +1101,20 @@
                 @SuppressWarnings("unchecked") T t = (T) r;
                 CompletableFuture<V> g = f.apply(t).toCompletableFuture();
                 if ((s = g.result) != null)
-                    d.completeRelay(s);
+                    d.result = encodeRelay(s);
                 else {
-                    UniRelay<V> c = new UniRelay<V>(d, g);
-                    g.push(c);
-                    c.tryFire(SYNC);
+                    g.unipush(new UniRelay<V>(d, g));
                 }
-                return d;
             } catch (Throwable ex) {
                 d.result = encodeThrowable(ex);
-                return d;
             }
         }
-        UniCompose<T,V> c = new UniCompose<T,V>(e, d, this, f);
-        push(c);
-        c.tryFire(SYNC);
+        else
+            try {
+                e.execute(new UniCompose<T,V>(null, d, this, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -1085,21 +1144,28 @@
         }
         final boolean isLive() {
             BiCompletion<?,?,?> c;
-            return (c = base) != null && c.dep != null;
+            return (c = base) != null
+                // && c.isLive()
+                && c.dep != null;
         }
     }
 
-    /** Pushes completion to this and b unless both done. */
+    /**
+     * Pushes completion to this and b unless both done.
+     * Caller should first check that either result or b.result is null.
+     */
     final void bipush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
         if (c != null) {
-            Object r;
-            while ((r = result) == null && !tryPushStack(c))
-                lazySetNext(c, null); // clear on failure
-            if (b != null && b != this && b.result == null) {
-                Completion q = (r != null) ? c : new CoCompletion(c);
-                while (b.result == null && !b.tryPushStack(q))
-                    lazySetNext(q, null); // clear on failure
+            while (result == null) {
+                if (tryPushStack(c)) {
+                    if (b.result == null)
+                        b.unipush(new CoCompletion(c));
+                    else if (result != null)
+                        c.tryFire(SYNC);
+                    return;
+                }
             }
+            b.unipush(c);
         }
     }
 
@@ -1107,9 +1173,10 @@
     final CompletableFuture<T> postFire(CompletableFuture<?> a,
                                         CompletableFuture<?> b, int mode) {
         if (b != null && b.stack != null) { // clean second source
-            if (b.result == null)
+            Object r;
+            if ((r = b.result) == null)
                 b.cleanStack();
-            else if (mode >= 0)
+            if (mode >= 0 && (r != null || b.result != null))
                 b.postComplete();
         }
         return postFire(a, mode);
@@ -1127,22 +1194,21 @@
             CompletableFuture<V> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biApply(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r, s; BiFunction<? super T,? super U,? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null
+                || !d.biApply(r, s, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S> boolean biApply(CompletableFuture<R> a,
-                                CompletableFuture<S> b,
+    final <R,S> boolean biApply(Object r, Object s,
                                 BiFunction<? super R,? super S,? extends T> f,
                                 BiApply<R,S,T> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
+        Throwable x;
         tryComplete: if (result == null) {
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
@@ -1174,15 +1240,20 @@
     private <U,V> CompletableFuture<V> biApplyStage(
         Executor e, CompletionStage<U> o,
         BiFunction<? super T,? super U,? extends V> f) {
-        CompletableFuture<U> b;
+        CompletableFuture<U> b; Object r, s;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.biApply(this, b, f, null)) {
-            BiApply<T,U,V> c = new BiApply<T,U,V>(e, d, this, b, f);
-            bipush(b, c);
-            c.tryFire(SYNC);
-        }
+        if ((r = result) == null || (s = b.result) == null)
+            bipush(b, new BiApply<T,U,V>(e, d, this, b, f));
+        else if (e == null)
+            d.biApply(r, s, f, null);
+        else
+            try {
+                e.execute(new BiApply<T,U,V>(null, d, this, b, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -1198,22 +1269,21 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biAccept(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r, s; BiConsumer<? super T,? super U> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null
+                || !d.biAccept(r, s, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S> boolean biAccept(CompletableFuture<R> a,
-                                 CompletableFuture<S> b,
+    final <R,S> boolean biAccept(Object r, Object s,
                                  BiConsumer<? super R,? super S> f,
                                  BiAccept<R,S> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
+        Throwable x;
         tryComplete: if (result == null) {
             if (r instanceof AltResult) {
                 if ((x = ((AltResult)r).ex) != null) {
@@ -1246,15 +1316,20 @@
     private <U> CompletableFuture<Void> biAcceptStage(
         Executor e, CompletionStage<U> o,
         BiConsumer<? super T,? super U> f) {
-        CompletableFuture<U> b;
+        CompletableFuture<U> b; Object r, s;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.biAccept(this, b, f, null)) {
-            BiAccept<T,U> c = new BiAccept<T,U>(e, d, this, b, f);
-            bipush(b, c);
-            c.tryFire(SYNC);
-        }
+        if ((r = result) == null || (s = b.result) == null)
+            bipush(b, new BiAccept<T,U>(e, d, this, b, f));
+        else if (e == null)
+            d.biAccept(r, s, f, null);
+        else
+            try {
+                e.execute(new BiAccept<T,U>(null, d, this, b, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
@@ -1262,8 +1337,7 @@
     static final class BiRun<T,U> extends BiCompletion<T,U,Void> {
         Runnable fn;
         BiRun(Executor executor, CompletableFuture<Void> dep,
-              CompletableFuture<T> src,
-              CompletableFuture<U> snd,
+              CompletableFuture<T> src, CompletableFuture<U> snd,
               Runnable fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1271,25 +1345,25 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.biRun(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r, s; Runnable f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null
+                || !d.biRun(r, s, f, mode > 0 ? null : this))
                 return null;
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final boolean biRun(CompletableFuture<?> a, CompletableFuture<?> b,
-                        Runnable f, BiRun<?,?> c) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null || f == null)
-            return false;
+    final boolean biRun(Object r, Object s, Runnable f, BiRun<?,?> c) {
+        Throwable x; Object z;
         if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
-                completeThrowable(x, s);
+            if ((r instanceof AltResult
+                 && (x = ((AltResult)(z = r)).ex) != null) ||
+                (s instanceof AltResult
+                 && (x = ((AltResult)(z = s)).ex) != null))
+                completeThrowable(x, z);
             else
                 try {
                     if (c != null && !c.claim())
@@ -1305,52 +1379,52 @@
 
     private CompletableFuture<Void> biRunStage(Executor e, CompletionStage<?> o,
                                                Runnable f) {
-        CompletableFuture<?> b;
+        CompletableFuture<?> b; Object r, s;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.biRun(this, b, f, null)) {
-            BiRun<T,?> c = new BiRun<>(e, d, this, b, f);
-            bipush(b, c);
-            c.tryFire(SYNC);
-        }
+        if ((r = result) == null || (s = b.result) == null)
+            bipush(b, new BiRun<>(e, d, this, b, f));
+        else if (e == null)
+            d.biRun(r, s, f, null);
+        else
+            try {
+                e.execute(new BiRun<>(null, d, this, b, f));
+            } catch (Throwable ex) {
+                d.result = encodeThrowable(ex);
+            }
         return d;
     }
 
     @SuppressWarnings("serial")
     static final class BiRelay<T,U> extends BiCompletion<T,U,Void> { // for And
         BiRelay(CompletableFuture<Void> dep,
-                CompletableFuture<T> src,
-                CompletableFuture<U> snd) {
+                CompletableFuture<T> src, CompletableFuture<U> snd) {
             super(null, dep, src, snd);
         }
         final CompletableFuture<Void> tryFire(int mode) {
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null || !d.biRelay(a = src, b = snd))
+            Object r, s, z; Throwable x;
+            if ((d = dep) == null
+                || (a = src) == null || (r = a.result) == null
+                || (b = snd) == null || (s = b.result) == null)
                 return null;
+            if (d.result == null) {
+                if ((r instanceof AltResult
+                     && (x = ((AltResult)(z = r)).ex) != null) ||
+                    (s instanceof AltResult
+                     && (x = ((AltResult)(z = s)).ex) != null))
+                    d.completeThrowable(x, z);
+                else
+                    d.completeNull();
+            }
             src = null; snd = null; dep = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    boolean biRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
-        Object r, s; Throwable x;
-        if (a == null || (r = a.result) == null ||
-            b == null || (s = b.result) == null)
-            return false;
-        if (result == null) {
-            if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                completeThrowable(x, r);
-            else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null)
-                completeThrowable(x, s);
-            else
-                completeNull();
-        }
-        return true;
-    }
-
     /** Recursively constructs a tree of completions. */
     static CompletableFuture<Void> andTree(CompletableFuture<?>[] cfs,
                                            int lo, int hi) {
@@ -1358,39 +1432,44 @@
         if (lo > hi) // empty
             d.result = NIL;
         else {
-            CompletableFuture<?> a, b;
+            CompletableFuture<?> a, b; Object r, s, z; Throwable x;
             int mid = (lo + hi) >>> 1;
             if ((a = (lo == mid ? cfs[lo] :
                       andTree(cfs, lo, mid))) == null ||
                 (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
                       andTree(cfs, mid+1, hi))) == null)
                 throw new NullPointerException();
-            if (!d.biRelay(a, b)) {
-                BiRelay<?,?> c = new BiRelay<>(d, a, b);
-                a.bipush(b, c);
-                c.tryFire(SYNC);
-            }
+            if ((r = a.result) == null || (s = b.result) == null)
+                a.bipush(b, new BiRelay<>(d, a, b));
+            else if ((r instanceof AltResult
+                      && (x = ((AltResult)(z = r)).ex) != null) ||
+                     (s instanceof AltResult
+                      && (x = ((AltResult)(z = s)).ex) != null))
+                d.result = encodeThrowable(x, z);
+            else
+                d.result = NIL;
         }
         return d;
     }
 
     /* ------------- Projected (Ored) BiCompletions -------------- */
 
-    /** Pushes completion to this and b unless either done. */
+    /**
+     * Pushes completion to this and b unless either done.
+     * Caller should first check that result and b.result are both null.
+     */
     final void orpush(CompletableFuture<?> b, BiCompletion<?,?,?> c) {
         if (c != null) {
-            while ((b == null || b.result == null) && result == null) {
-                if (tryPushStack(c)) {
-                    if (b != null && b != this && b.result == null) {
-                        Completion q = new CoCompletion(c);
-                        while (result == null && b.result == null &&
-                               !b.tryPushStack(q))
-                            lazySetNext(q, null); // clear on failure
-                    }
+            while (!tryPushStack(c)) {
+                if (result != null) {
+                    NEXT.set(c, null);
                     break;
                 }
-                lazySetNext(c, null); // clear on failure
             }
+            if (result != null)
+                c.tryFire(SYNC);
+            else
+                b.unipush(new CoCompletion(c));
         }
     }
 
@@ -1398,8 +1477,7 @@
     static final class OrApply<T,U extends T,V> extends BiCompletion<T,U,V> {
         Function<? super T,? extends V> fn;
         OrApply(Executor executor, CompletableFuture<V> dep,
-                CompletableFuture<T> src,
-                CompletableFuture<U> snd,
+                CompletableFuture<T> src, CompletableFuture<U> snd,
                 Function<? super T,? extends V> fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1407,54 +1485,46 @@
             CompletableFuture<V> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orApply(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Function<? super T,? extends V> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            tryComplete: if (d.result == null) {
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    if (r instanceof AltResult) {
+                        if ((x = ((AltResult)r).ex) != null) {
+                            d.completeThrowable(x, r);
+                            break tryComplete;
+                        }
+                        r = null;
+                    }
+                    @SuppressWarnings("unchecked") T t = (T) r;
+                    d.completeValue(f.apply(t));
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S extends R> boolean orApply(CompletableFuture<R> a,
-                                          CompletableFuture<S> b,
-                                          Function<? super R, ? extends T> f,
-                                          OrApply<R,S,T> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    if ((x = ((AltResult)r).ex) != null) {
-                        completeThrowable(x, r);
-                        break tryComplete;
-                    }
-                    r = null;
-                }
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                completeValue(f.apply(rr));
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <U extends T,V> CompletableFuture<V> orApplyStage(
-        Executor e, CompletionStage<U> o,
-        Function<? super T, ? extends V> f) {
+        Executor e, CompletionStage<U> o, Function<? super T, ? extends V> f) {
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
+
+        Object r; CompletableFuture<? extends T> z;
+        if ((r = (z = this).result) != null ||
+            (r = (z = b).result) != null)
+            return z.uniApplyNow(r, e, f);
+
         CompletableFuture<V> d = newIncompleteFuture();
-        if (e != null || !d.orApply(this, b, f, null)) {
-            OrApply<T,U,V> c = new OrApply<T,U,V>(e, d, this, b, f);
-            orpush(b, c);
-            c.tryFire(SYNC);
-        }
+        orpush(b, new OrApply<T,U,V>(e, d, this, b, f));
         return d;
     }
 
@@ -1462,8 +1532,7 @@
     static final class OrAccept<T,U extends T> extends BiCompletion<T,U,Void> {
         Consumer<? super T> fn;
         OrAccept(Executor executor, CompletableFuture<Void> dep,
-                 CompletableFuture<T> src,
-                 CompletableFuture<U> snd,
+                 CompletableFuture<T> src, CompletableFuture<U> snd,
                  Consumer<? super T> fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1471,54 +1540,47 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orAccept(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Consumer<? super T> f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            tryComplete: if (d.result == null) {
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    if (r instanceof AltResult) {
+                        if ((x = ((AltResult)r).ex) != null) {
+                            d.completeThrowable(x, r);
+                            break tryComplete;
+                        }
+                        r = null;
+                    }
+                    @SuppressWarnings("unchecked") T t = (T) r;
+                    f.accept(t);
+                    d.completeNull();
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final <R,S extends R> boolean orAccept(CompletableFuture<R> a,
-                                           CompletableFuture<S> b,
-                                           Consumer<? super R> f,
-                                           OrAccept<R,S> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        tryComplete: if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult) {
-                    if ((x = ((AltResult)r).ex) != null) {
-                        completeThrowable(x, r);
-                        break tryComplete;
-                    }
-                    r = null;
-                }
-                @SuppressWarnings("unchecked") R rr = (R) r;
-                f.accept(rr);
-                completeNull();
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private <U extends T> CompletableFuture<Void> orAcceptStage(
         Executor e, CompletionStage<U> o, Consumer<? super T> f) {
         CompletableFuture<U> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
+
+        Object r; CompletableFuture<? extends T> z;
+        if ((r = (z = this).result) != null ||
+            (r = (z = b).result) != null)
+            return z.uniAcceptNow(r, e, f);
+
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.orAccept(this, b, f, null)) {
-            OrAccept<T,U> c = new OrAccept<T,U>(e, d, this, b, f);
-            orpush(b, c);
-            c.tryFire(SYNC);
-        }
+        orpush(b, new OrAccept<T,U>(e, d, this, b, f));
         return d;
     }
 
@@ -1526,8 +1588,7 @@
     static final class OrRun<T,U> extends BiCompletion<T,U,Void> {
         Runnable fn;
         OrRun(Executor executor, CompletableFuture<Void> dep,
-              CompletableFuture<T> src,
-              CompletableFuture<U> snd,
+              CompletableFuture<T> src, CompletableFuture<U> snd,
               Runnable fn) {
             super(executor, dep, src, snd); this.fn = fn;
         }
@@ -1535,95 +1596,84 @@
             CompletableFuture<Void> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null ||
-                !d.orRun(a = src, b = snd, fn, mode > 0 ? null : this))
+            Object r; Throwable x; Runnable f;
+            if ((d = dep) == null || (f = fn) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            if (d.result == null) {
+                try {
+                    if (mode <= 0 && !claim())
+                        return null;
+                    else if (r instanceof AltResult
+                        && (x = ((AltResult)r).ex) != null)
+                        d.completeThrowable(x, r);
+                    else {
+                        f.run();
+                        d.completeNull();
+                    }
+                } catch (Throwable ex) {
+                    d.completeThrowable(ex);
+                }
+            }
             dep = null; src = null; snd = null; fn = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final boolean orRun(CompletableFuture<?> a, CompletableFuture<?> b,
-                        Runnable f, OrRun<?,?> c) {
-        Object r; Throwable x;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null) || f == null)
-            return false;
-        if (result == null) {
-            try {
-                if (c != null && !c.claim())
-                    return false;
-                if (r instanceof AltResult && (x = ((AltResult)r).ex) != null)
-                    completeThrowable(x, r);
-                else {
-                    f.run();
-                    completeNull();
-                }
-            } catch (Throwable ex) {
-                completeThrowable(ex);
-            }
-        }
-        return true;
-    }
-
     private CompletableFuture<Void> orRunStage(Executor e, CompletionStage<?> o,
                                                Runnable f) {
         CompletableFuture<?> b;
         if (f == null || (b = o.toCompletableFuture()) == null)
             throw new NullPointerException();
+
+        Object r; CompletableFuture<?> z;
+        if ((r = (z = this).result) != null ||
+            (r = (z = b).result) != null)
+            return z.uniRunNow(r, e, f);
+
         CompletableFuture<Void> d = newIncompleteFuture();
-        if (e != null || !d.orRun(this, b, f, null)) {
-            OrRun<T,?> c = new OrRun<>(e, d, this, b, f);
-            orpush(b, c);
-            c.tryFire(SYNC);
-        }
+        orpush(b, new OrRun<>(e, d, this, b, f));
         return d;
     }
 
     @SuppressWarnings("serial")
     static final class OrRelay<T,U> extends BiCompletion<T,U,Object> { // for Or
-        OrRelay(CompletableFuture<Object> dep, CompletableFuture<T> src,
-                CompletableFuture<U> snd) {
+        OrRelay(CompletableFuture<Object> dep,
+                CompletableFuture<T> src, CompletableFuture<U> snd) {
             super(null, dep, src, snd);
         }
         final CompletableFuture<Object> tryFire(int mode) {
             CompletableFuture<Object> d;
             CompletableFuture<T> a;
             CompletableFuture<U> b;
-            if ((d = dep) == null || !d.orRelay(a = src, b = snd))
+            Object r;
+            if ((d = dep) == null
+                || (a = src) == null || (b = snd) == null
+                || ((r = a.result) == null && (r = b.result) == null))
                 return null;
+            d.completeRelay(r);
             src = null; snd = null; dep = null;
             return d.postFire(a, b, mode);
         }
     }
 
-    final boolean orRelay(CompletableFuture<?> a, CompletableFuture<?> b) {
-        Object r;
-        if (a == null || b == null ||
-            ((r = a.result) == null && (r = b.result) == null))
-            return false;
-        if (result == null)
-            completeRelay(r);
-        return true;
-    }
-
     /** Recursively constructs a tree of completions. */
     static CompletableFuture<Object> orTree(CompletableFuture<?>[] cfs,
                                             int lo, int hi) {
         CompletableFuture<Object> d = new CompletableFuture<Object>();
         if (lo <= hi) {
-            CompletableFuture<?> a, b;
+            CompletableFuture<?> a, b; Object r;
             int mid = (lo + hi) >>> 1;
             if ((a = (lo == mid ? cfs[lo] :
                       orTree(cfs, lo, mid))) == null ||
                 (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] :
                       orTree(cfs, mid+1, hi))) == null)
                 throw new NullPointerException();
-            if (!d.orRelay(a, b)) {
-                OrRelay<?,?> c = new OrRelay<>(d, a, b);
-                a.orpush(b, c);
-                c.tryFire(SYNC);
-            }
+            if ((r = a.result) != null && (r = b.result) != null)
+                d.result = encodeRelay(r);
+            else
+                a.orpush(b, new OrRelay<>(d, a, b));
         }
         return d;
     }
@@ -1640,7 +1690,7 @@
 
         public final Void getRawResult() { return null; }
         public final void setRawResult(Void v) {}
-        public final boolean exec() { run(); return true; }
+        public final boolean exec() { run(); return false; }
 
         public void run() {
             CompletableFuture<T> d; Supplier<? extends T> f;
@@ -1676,7 +1726,7 @@
 
         public final Void getRawResult() { return null; }
         public final void setRawResult(Void v) {}
-        public final boolean exec() { run(); return true; }
+        public final boolean exec() { run(); return false; }
 
         public void run() {
             CompletableFuture<Void> d; Runnable f;
@@ -1760,15 +1810,13 @@
     private Object waitingGet(boolean interruptible) {
         Signaller q = null;
         boolean queued = false;
-        int spins = SPINS;
         Object r;
         while ((r = result) == null) {
-            if (spins > 0) {
-                if (ThreadLocalRandom.nextSecondarySeed() >= 0)
-                    --spins;
+            if (q == null) {
+                q = new Signaller(interruptible, 0L, 0L);
+                if (Thread.currentThread() instanceof ForkJoinWorkerThread)
+                    ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);
             }
-            else if (q == null)
-                q = new Signaller(interruptible, 0L, 0L);
             else if (!queued)
                 queued = tryPushStack(q);
             else {
@@ -1781,16 +1829,14 @@
                     break;
             }
         }
-        if (q != null) {
+        if (q != null && queued) {
             q.thread = null;
-            if (q.interrupted) {
-                if (interruptible)
-                    cleanStack();
-                else
-                    Thread.currentThread().interrupt();
-            }
+            if (!interruptible && q.interrupted)
+                Thread.currentThread().interrupt();
+            if (r == null)
+                cleanStack();
         }
-        if (r != null)
+        if (r != null || (r = result) != null)
             postComplete();
         return r;
     }
@@ -1808,9 +1854,12 @@
             Signaller q = null;
             boolean queued = false;
             Object r;
-            while ((r = result) == null) { // similar to untimed, without spins
-                if (q == null)
+            while ((r = result) == null) { // similar to untimed
+                if (q == null) {
                     q = new Signaller(true, nanos, deadline);
+                    if (Thread.currentThread() instanceof ForkJoinWorkerThread)
+                        ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q);
+                }
                 else if (!queued)
                     queued = tryPushStack(q);
                 else if (q.nanos <= 0L)
@@ -1825,12 +1874,13 @@
                         break;
                 }
             }
-            if (q != null)
+            if (q != null && queued) {
                 q.thread = null;
-            if (r != null)
+                if (r == null)
+                    cleanStack();
+            }
+            if (r != null || (r = result) != null)
                 postComplete();
-            else
-                cleanStack();
             if (r != null || (q != null && q.interrupted))
                 return r;
         }
@@ -1942,9 +1992,12 @@
      * @throws InterruptedException if the current thread was interrupted
      * while waiting
      */
+    @SuppressWarnings("unchecked")
     public T get() throws InterruptedException, ExecutionException {
         Object r;
-        return reportGet((r = result) == null ? waitingGet(true) : r);
+        if ((r = result) == null)
+            r = waitingGet(true);
+        return (T) reportGet(r);
     }
 
     /**
@@ -1960,11 +2013,14 @@
      * while waiting
      * @throws TimeoutException if the wait timed out
      */
+    @SuppressWarnings("unchecked")
     public T get(long timeout, TimeUnit unit)
         throws InterruptedException, ExecutionException, TimeoutException {
+        long nanos = unit.toNanos(timeout);
         Object r;
-        long nanos = unit.toNanos(timeout);
-        return reportGet((r = result) == null ? timedGet(nanos) : r);
+        if ((r = result) == null)
+            r = timedGet(nanos);
+        return (T) reportGet(r);
     }
 
     /**
@@ -1981,9 +2037,12 @@
      * @throws CompletionException if this future completed
      * exceptionally or a completion computation threw an exception
      */
+    @SuppressWarnings("unchecked")
     public T join() {
         Object r;
-        return reportJoin((r = result) == null ? waitingGet(false) : r);
+        if ((r = result) == null)
+            r = waitingGet(false);
+        return (T) reportJoin(r);
     }
 
     /**
@@ -1996,9 +2055,10 @@
      * @throws CompletionException if this future completed
      * exceptionally or a completion computation threw an exception
      */
+    @SuppressWarnings("unchecked")
     public T getNow(T valueIfAbsent) {
         Object r;
-        return ((r = result) == null) ? valueIfAbsent : reportJoin(r);
+        return ((r = result) == null) ? valueIfAbsent : (T) reportJoin(r);
     }
 
     /**
@@ -2775,19 +2835,16 @@
             throw new UnsupportedOperationException(); }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long RESULT;
-    private static final long STACK;
-    private static final long NEXT;
+    // VarHandle mechanics
+    private static final VarHandle RESULT;
+    private static final VarHandle STACK;
+    private static final VarHandle NEXT;
     static {
         try {
-            RESULT = U.objectFieldOffset
-                (CompletableFuture.class.getDeclaredField("result"));
-            STACK = U.objectFieldOffset
-                (CompletableFuture.class.getDeclaredField("stack"));
-            NEXT = U.objectFieldOffset
-                (Completion.class.getDeclaredField("next"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            RESULT = l.findVarHandle(CompletableFuture.class, "result", Object.class);
+            STACK = l.findVarHandle(CompletableFuture.class, "stack", Completion.class);
+            NEXT = l.findVarHandle(Completion.class, "next", Completion.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java	Mon Jul 18 09:38:08 2016 -0700
@@ -68,6 +68,7 @@
 import java.util.function.ToLongBiFunction;
 import java.util.function.ToLongFunction;
 import java.util.stream.Stream;
+import jdk.internal.misc.Unsafe;
 
 /**
  * A hash table supporting full concurrency of retrievals and
@@ -747,7 +748,7 @@
     /* ---------------- Table element access -------------- */
 
     /*
-     * Volatile access methods are used for table elements as well as
+     * Atomic access methods are used for table elements as well as
      * elements of in-progress next table while resizing.  All uses of
      * the tab arguments must be null checked by callers.  All callers
      * also paranoically precheck that tab's length is not zero (or an
@@ -757,14 +758,12 @@
      * errors by users, these checks must operate on local variables,
      * which accounts for some odd-looking inline assignments below.
      * Note that calls to setTabAt always occur within locked regions,
-     * and so in principle require only release ordering, not
-     * full volatile semantics, but are currently coded as volatile
-     * writes to be conservative.
+     * and so require only release ordering.
      */
 
     @SuppressWarnings("unchecked")
     static final <K,V> Node<K,V> tabAt(Node<K,V>[] tab, int i) {
-        return (Node<K,V>)U.getObjectVolatile(tab, ((long)i << ASHIFT) + ABASE);
+        return (Node<K,V>)U.getObjectAcquire(tab, ((long)i << ASHIFT) + ABASE);
     }
 
     static final <K,V> boolean casTabAt(Node<K,V>[] tab, int i,
@@ -773,7 +772,7 @@
     }
 
     static final <K,V> void setTabAt(Node<K,V>[] tab, int i, Node<K,V> v) {
-        U.putObjectVolatile(tab, ((long)i << ASHIFT) + ABASE, v);
+        U.putObjectRelease(tab, ((long)i << ASHIFT) + ABASE, v);
     }
 
     /* ---------------- Fields -------------- */
@@ -3298,7 +3297,7 @@
             return true;
         }
 
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private static final long LOCKSTATE;
         static {
             try {
@@ -6341,7 +6340,7 @@
     }
 
     // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long SIZECTL;
     private static final long TRANSFERINDEX;
     private static final long BASECOUNT;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedDeque.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractCollection;
 import java.util.Arrays;
 import java.util.Collection;
@@ -292,64 +294,23 @@
         volatile Node<E> prev;
         volatile E item;
         volatile Node<E> next;
-
-        Node() {  // default constructor for NEXT_TERMINATOR, PREV_TERMINATOR
-        }
-
-        /**
-         * Constructs a new node.  Uses relaxed write because item can
-         * only be seen after publication via casNext or casPrev.
-         */
-        Node(E item) {
-            U.putObject(this, ITEM, item);
-        }
-
-        boolean casItem(E cmp, E val) {
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
-        }
-
-        void lazySetNext(Node<E> val) {
-            U.putObjectRelease(this, NEXT, val);
-        }
-
-        boolean casNext(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
-        }
+    }
 
-        void lazySetPrev(Node<E> val) {
-            U.putObjectRelease(this, PREV, val);
-        }
-
-        boolean casPrev(Node<E> cmp, Node<E> val) {
-            return U.compareAndSwapObject(this, PREV, cmp, val);
-        }
-
-        // Unsafe mechanics
-
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long PREV;
-        private static final long ITEM;
-        private static final long NEXT;
-
-        static {
-            try {
-                PREV = U.objectFieldOffset
-                    (Node.class.getDeclaredField("prev"));
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-        }
+    /**
+     * Returns a new node holding item.  Uses relaxed write because item
+     * can only be seen after piggy-backing publication via CAS.
+     */
+    static <E> Node<E> newNode(E item) {
+        Node<E> node = new Node<E>();
+        ITEM.set(node, item);
+        return node;
     }
 
     /**
      * Links e as first element.
      */
     private void linkFirst(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         restartFromHead:
         for (;;)
@@ -363,13 +324,13 @@
                     continue restartFromHead;
                 else {
                     // p is first node
-                    newNode.lazySetNext(p); // CAS piggyback
-                    if (p.casPrev(null, newNode)) {
+                    NEXT.set(newNode, p); // CAS piggyback
+                    if (PREV.compareAndSet(p, null, newNode)) {
                         // Successful CAS is the linearization point
                         // for e to become an element of this deque,
                         // and for newNode to become "live".
-                        if (p != h) // hop two nodes at a time
-                            casHead(h, newNode);  // Failure is OK.
+                        if (p != h) // hop two nodes at a time; failure is OK
+                            HEAD.weakCompareAndSetVolatile(this, h, newNode);
                         return;
                     }
                     // Lost CAS race to another thread; re-read prev
@@ -381,7 +342,7 @@
      * Links e as last element.
      */
     private void linkLast(E e) {
-        final Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+        final Node<E> newNode = newNode(Objects.requireNonNull(e));
 
         restartFromTail:
         for (;;)
@@ -395,13 +356,13 @@
                     continue restartFromTail;
                 else {
                     // p is last node
-                    newNode.lazySetPrev(p); // CAS piggyback
-                    if (p.casNext(null, newNode)) {
+                    PREV.set(newNode, p); // CAS piggyback
+                    if (NEXT.compareAndSet(p, null, newNode)) {
                         // Successful CAS is the linearization point
                         // for e to become an element of this deque,
                         // and for newNode to become "live".
-                        if (p != t) // hop two nodes at a time
-                            casTail(t, newNode);  // Failure is OK.
+                        if (p != t) // hop two nodes at a time; failure is OK
+                            TAIL.weakCompareAndSetVolatile(this, t, newNode);
                         return;
                     }
                     // Lost CAS race to another thread; re-read next
@@ -516,8 +477,8 @@
                 updateTail(); // Ensure x is not reachable from tail
 
                 // Finally, actually gc-unlink
-                x.lazySetPrev(isFirst ? prevTerminator() : x);
-                x.lazySetNext(isLast  ? nextTerminator() : x);
+                PREV.setRelease(x, isFirst ? prevTerminator() : x);
+                NEXT.setRelease(x, isLast  ? nextTerminator() : x);
             }
         }
     }
@@ -531,7 +492,8 @@
         // assert first.item == null;
         for (Node<E> o = null, p = next, q;;) {
             if (p.item != null || (q = p.next) == null) {
-                if (o != null && p.prev != p && first.casNext(next, p)) {
+                if (o != null && p.prev != p &&
+                    NEXT.compareAndSet(first, next, p)) {
                     skipDeletedPredecessors(p);
                     if (first.prev == null &&
                         (p.next == null || p.item != null) &&
@@ -541,8 +503,8 @@
                         updateTail(); // Ensure o is not reachable from tail
 
                         // Finally, actually gc-unlink
-                        o.lazySetNext(o);
-                        o.lazySetPrev(prevTerminator());
+                        NEXT.setRelease(o, o);
+                        PREV.setRelease(o, prevTerminator());
                     }
                 }
                 return;
@@ -565,7 +527,8 @@
         // assert last.item == null;
         for (Node<E> o = null, p = prev, q;;) {
             if (p.item != null || (q = p.prev) == null) {
-                if (o != null && p.next != p && last.casPrev(prev, p)) {
+                if (o != null && p.next != p &&
+                    PREV.compareAndSet(last, prev, p)) {
                     skipDeletedSuccessors(p);
                     if (last.next == null &&
                         (p.prev == null || p.item != null) &&
@@ -575,8 +538,8 @@
                         updateTail(); // Ensure o is not reachable from tail
 
                         // Finally, actually gc-unlink
-                        o.lazySetPrev(o);
-                        o.lazySetNext(nextTerminator());
+                        PREV.setRelease(o, o);
+                        NEXT.setRelease(o, nextTerminator());
                     }
                 }
                 return;
@@ -607,7 +570,7 @@
                     (q = (p = q).prev) == null) {
                     // It is possible that p is PREV_TERMINATOR,
                     // but if so, the CAS is guaranteed to fail.
-                    if (casHead(h, p))
+                    if (HEAD.compareAndSet(this, h, p))
                         return;
                     else
                         continue restartFromHead;
@@ -637,7 +600,7 @@
                     (q = (p = q).next) == null) {
                     // It is possible that p is NEXT_TERMINATOR,
                     // but if so, the CAS is guaranteed to fail.
-                    if (casTail(t, p))
+                    if (TAIL.compareAndSet(this, t, p))
                         return;
                     else
                         continue restartFromTail;
@@ -675,7 +638,7 @@
             }
 
             // found active CAS target
-            if (prev == p || x.casPrev(prev, p))
+            if (prev == p || PREV.compareAndSet(x, prev, p))
                 return;
 
         } while (x.item != null || x.next == null);
@@ -706,7 +669,7 @@
             }
 
             // found active CAS target
-            if (next == p || x.casNext(next, p))
+            if (next == p || NEXT.compareAndSet(x, next, p))
                 return;
 
         } while (x.item != null || x.prev == null);
@@ -751,7 +714,7 @@
                 else if (p == h
                          // It is possible that p is PREV_TERMINATOR,
                          // but if so, the CAS is guaranteed to fail.
-                         || casHead(h, p))
+                         || HEAD.compareAndSet(this, h, p))
                     return p;
                 else
                     continue restartFromHead;
@@ -776,7 +739,7 @@
                 else if (p == t
                          // It is possible that p is NEXT_TERMINATOR,
                          // but if so, the CAS is guaranteed to fail.
-                         || casTail(t, p))
+                         || TAIL.compareAndSet(this, t, p))
                     return p;
                 else
                     continue restartFromTail;
@@ -802,7 +765,7 @@
      * Constructs an empty deque.
      */
     public ConcurrentLinkedDeque() {
-        head = tail = new Node<E>(null);
+        head = tail = new Node<E>();
     }
 
     /**
@@ -818,12 +781,12 @@
         // Copy c into a private chain of Nodes
         Node<E> h = null, t = null;
         for (E e : c) {
-            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
@@ -836,12 +799,12 @@
     private void initHeadTail(Node<E> h, Node<E> t) {
         if (h == t) {
             if (h == null)
-                h = t = new Node<E>(null);
+                h = t = new Node<E>();
             else {
                 // Avoid edge case of a single Node with non-null item.
-                Node<E> newNode = new Node<E>(null);
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                Node<E> newNode = new Node<E>();
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
@@ -934,7 +897,7 @@
     public E pollFirst() {
         for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.item;
-            if (item != null && p.casItem(item, null)) {
+            if (item != null && ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return item;
             }
@@ -945,7 +908,7 @@
     public E pollLast() {
         for (Node<E> p = last(); p != null; p = pred(p)) {
             E item = p.item;
-            if (item != null && p.casItem(item, null)) {
+            if (item != null && ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return item;
             }
@@ -1031,7 +994,8 @@
         Objects.requireNonNull(o);
         for (Node<E> p = first(); p != null; p = succ(p)) {
             E item = p.item;
-            if (item != null && o.equals(item) && p.casItem(item, null)) {
+            if (item != null && o.equals(item) &&
+                ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return true;
             }
@@ -1055,7 +1019,8 @@
         Objects.requireNonNull(o);
         for (Node<E> p = last(); p != null; p = pred(p)) {
             E item = p.item;
-            if (item != null && o.equals(item) && p.casItem(item, null)) {
+            if (item != null && o.equals(item) &&
+                ITEM.compareAndSet(p, item, null)) {
                 unlink(p);
                 return true;
             }
@@ -1159,12 +1124,12 @@
         // Copy c into a private chain of Nodes
         Node<E> beginningOfTheEnd = null, last = null;
         for (E e : c) {
-            Node<E> newNode = new Node<E>(Objects.requireNonNull(e));
+            Node<E> newNode = newNode(Objects.requireNonNull(e));
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                last.lazySetNext(newNode);
-                newNode.lazySetPrev(last);
+                NEXT.set(last, newNode);
+                PREV.set(newNode, last);
                 last = newNode;
             }
         }
@@ -1184,16 +1149,16 @@
                     continue restartFromTail;
                 else {
                     // p is last node
-                    beginningOfTheEnd.lazySetPrev(p); // CAS piggyback
-                    if (p.casNext(null, beginningOfTheEnd)) {
+                    PREV.set(beginningOfTheEnd, p); // CAS piggyback
+                    if (NEXT.compareAndSet(p, null, beginningOfTheEnd)) {
                         // Successful CAS is the linearization point
                         // for all elements to be added to this deque.
-                        if (!casTail(t, last)) {
+                        if (!TAIL.weakCompareAndSetVolatile(this, t, last)) {
                             // Try a little harder to update tail,
                             // since we may be adding many elements.
                             t = tail;
                             if (last.next == null)
-                                casTail(t, last);
+                                TAIL.weakCompareAndSetVolatile(this, t, last);
                         }
                         return true;
                     }
@@ -1586,41 +1551,38 @@
         Node<E> h = null, t = null;
         for (Object item; (item = s.readObject()) != null; ) {
             @SuppressWarnings("unchecked")
-            Node<E> newNode = new Node<E>((E) item);
+            Node<E> newNode = newNode((E) item);
             if (h == null)
                 h = t = newNode;
             else {
-                t.lazySetNext(newNode);
-                newNode.lazySetPrev(t);
+                NEXT.set(t, newNode);
+                PREV.set(newNode, t);
                 t = newNode;
             }
         }
         initHeadTail(h, t);
     }
 
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
-    }
-
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
-    }
-
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle PREV;
+    private static final VarHandle NEXT;
+    private static final VarHandle ITEM;
     static {
         PREV_TERMINATOR = new Node<Object>();
         PREV_TERMINATOR.next = PREV_TERMINATOR;
         NEXT_TERMINATOR = new Node<Object>();
         NEXT_TERMINATOR.prev = NEXT_TERMINATOR;
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentLinkedDeque.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (ConcurrentLinkedDeque.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentLinkedDeque.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(ConcurrentLinkedDeque.class, "tail",
+                                   Node.class);
+            PREV = l.findVarHandle(Node.class, "prev", Node.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentLinkedQueue.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -166,9 +168,8 @@
      * this is merely an optimization.
      *
      * When constructing a Node (before enqueuing it) we avoid paying
-     * for a volatile write to item by using Unsafe.putObject instead
-     * of a normal write.  This allows the cost of enqueue to be
-     * "one-and-a-half" CASes.
+     * for a volatile write to item.  This allows the cost of enqueue
+     * to be "one-and-a-half" CASes.
      *
      * Both head and tail may or may not point to a Node with a
      * non-null item.  If the queue is empty, all items must of course
@@ -178,33 +179,21 @@
      * optimization.
      */
 
-    private static class Node<E> {
+    static final class Node<E> {
         volatile E item;
         volatile Node<E> next;
     }
 
     /**
      * Returns a new node holding item.  Uses relaxed write because item
-     * can only be seen after piggy-backing publication via casNext.
+     * can only be seen after piggy-backing publication via CAS.
      */
     static <E> Node<E> newNode(E item) {
         Node<E> node = new Node<E>();
-        U.putObject(node, ITEM, item);
+        ITEM.set(node, item);
         return node;
     }
 
-    static <E> boolean casItem(Node<E> node, E cmp, E val) {
-        return U.compareAndSwapObject(node, ITEM, cmp, val);
-    }
-
-    static <E> void lazySetNext(Node<E> node, Node<E> val) {
-        U.putObjectRelease(node, NEXT, val);
-    }
-
-    static <E> boolean casNext(Node<E> node, Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(node, NEXT, cmp, val);
-    }
-
     /**
      * A node from which the first live (non-deleted) node (if any)
      * can be reached in O(1) time.
@@ -256,7 +245,7 @@
             if (h == null)
                 h = t = newNode;
             else {
-                lazySetNext(t, newNode);
+                NEXT.set(t, newNode);
                 t = newNode;
             }
         }
@@ -286,8 +275,8 @@
      */
     final void updateHead(Node<E> h, Node<E> p) {
         // assert h != null && p != null && (h == p || h.item == null);
-        if (h != p && casHead(h, p))
-            lazySetNext(h, h);
+        if (h != p && HEAD.compareAndSet(this, h, p))
+            NEXT.setRelease(h, h);
     }
 
     /**
@@ -314,12 +303,12 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, newNode)) {
+                if (NEXT.compareAndSet(p, null, newNode)) {
                     // Successful CAS is the linearization point
                     // for e to become an element of this queue,
                     // and for newNode to become "live".
-                    if (p != t) // hop two nodes at a time
-                        casTail(t, newNode);  // Failure is OK.
+                    if (p != t) // hop two nodes at a time; failure is OK
+                        TAIL.weakCompareAndSetVolatile(this, t, newNode);
                     return true;
                 }
                 // Lost CAS race to another thread; re-read next
@@ -342,7 +331,7 @@
             for (Node<E> h = head, p = h, q;;) {
                 E item = p.item;
 
-                if (item != null && casItem(p, item, null)) {
+                if (item != null && ITEM.compareAndSet(p, item, null)) {
                     // Successful CAS is the linearization point
                     // for item to be removed from this queue.
                     if (p != h) // hop two nodes at a time
@@ -483,12 +472,12 @@
                         next = succ(p);
                         continue;
                     }
-                    removed = casItem(p, item, null);
+                    removed = ITEM.compareAndSet(p, item, null);
                 }
 
                 next = succ(p);
                 if (pred != null && next != null) // unlink
-                    casNext(pred, p, next);
+                    NEXT.weakCompareAndSetVolatile(pred, p, next);
                 if (removed)
                     return true;
             }
@@ -520,7 +509,7 @@
             if (beginningOfTheEnd == null)
                 beginningOfTheEnd = last = newNode;
             else {
-                lazySetNext(last, newNode);
+                NEXT.set(last, newNode);
                 last = newNode;
             }
         }
@@ -532,15 +521,15 @@
             Node<E> q = p.next;
             if (q == null) {
                 // p is last node
-                if (casNext(p, null, beginningOfTheEnd)) {
+                if (NEXT.compareAndSet(p, null, beginningOfTheEnd)) {
                     // Successful CAS is the linearization point
                     // for all elements to be added to this queue.
-                    if (!casTail(t, last)) {
+                    if (!TAIL.weakCompareAndSetVolatile(this, t, last)) {
                         // Try a little harder to update tail,
                         // since we may be adding many elements.
                         t = tail;
                         if (last.next == null)
-                            casTail(t, last);
+                            TAIL.weakCompareAndSetVolatile(this, t, last);
                     }
                     return true;
                 }
@@ -744,7 +733,7 @@
                 }
                 // unlink deleted nodes
                 if ((q = succ(p)) != null)
-                    casNext(pred, p, q);
+                    NEXT.compareAndSet(pred, p, q);
             }
         }
 
@@ -801,7 +790,7 @@
             if (h == null)
                 h = t = newNode;
             else {
-                lazySetNext(t, newNode);
+                NEXT.set(t, newNode);
                 t = newNode;
             }
         }
@@ -919,31 +908,20 @@
         return new CLQSpliterator<E>(this);
     }
 
-    private boolean casTail(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
-    }
-
-    private boolean casHead(Node<E> cmp, Node<E> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
-    }
-
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
-    private static final long ITEM;
-    private static final long NEXT;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle ITEM;
+    private static final VarHandle NEXT;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentLinkedQueue.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (ConcurrentLinkedQueue.class.getDeclaredField("tail"));
-            ITEM = U.objectFieldOffset
-                (Node.class.getDeclaredField("item"));
-            NEXT = U.objectFieldOffset
-                (Node.class.getDeclaredField("next"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentLinkedQueue.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(ConcurrentLinkedQueue.class, "tail",
+                                   Node.class);
+            ITEM = l.findVarHandle(Node.class, "item", Object.class);
+            NEXT = l.findVarHandle(Node.class, "next", Node.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListMap.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.io.Serializable;
 import java.util.AbstractCollection;
 import java.util.AbstractMap;
@@ -401,7 +403,7 @@
      * compareAndSet head node.
      */
     private boolean casHead(HeadIndex<K,V> cmp, HeadIndex<K,V> val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return HEAD.compareAndSet(this, cmp, val);
     }
 
     /* ---------------- Nodes -------------- */
@@ -444,14 +446,14 @@
          * compareAndSet value field.
          */
         boolean casValue(Object cmp, Object val) {
-            return U.compareAndSwapObject(this, VALUE, cmp, val);
+            return VALUE.compareAndSet(this, cmp, val);
         }
 
         /**
          * compareAndSet next field.
          */
         boolean casNext(Node<K,V> cmp, Node<K,V> val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return NEXT.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -532,20 +534,16 @@
             return new AbstractMap.SimpleImmutableEntry<K,V>(key, vv);
         }
 
-        // Unsafe mechanics
-
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
-        private static final long NEXT;
-
+        // VarHandle mechanics
+        private static final VarHandle VALUE;
+        private static final VarHandle NEXT;
         static {
             try {
-                VALUE = U.objectFieldOffset
-                    (Node.class.getDeclaredField("value"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                VALUE = l.findVarHandle(Node.class, "value", Object.class);
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
             } catch (ReflectiveOperationException e) {
-                throw new Error(e);
+                    throw new Error(e);
             }
         }
     }
@@ -577,7 +575,7 @@
          * compareAndSet right field.
          */
         final boolean casRight(Index<K,V> cmp, Index<K,V> val) {
-            return U.compareAndSwapObject(this, RIGHT, cmp, val);
+            return RIGHT.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -613,13 +611,12 @@
             return node.value != null && casRight(succ, succ.right);
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long RIGHT;
+        // VarHandle mechanics
+        private static final VarHandle RIGHT;
         static {
             try {
-                RIGHT = U.objectFieldOffset
-                    (Index.class.getDeclaredField("right"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                RIGHT = l.findVarHandle(Index.class, "right", Index.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -3607,13 +3604,13 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (ConcurrentSkipListMap.class.getDeclaredField("head"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(ConcurrentSkipListMap.class, "head",
+                                   HeadIndex.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ConcurrentSkipListSet.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractSet;
 import java.util.Collection;
 import java.util.Collections;
@@ -507,15 +509,16 @@
 
     // Support for resetting map in clone
     private void setMap(ConcurrentNavigableMap<E,Object> map) {
-        U.putObjectVolatile(this, MAP, map);
+        MAP.setVolatile(this, map);
     }
 
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long MAP;
+    // VarHandle mechanics
+    private static final VarHandle MAP;
     static {
         try {
-            MAP = U.objectFieldOffset
-                (ConcurrentSkipListSet.class.getDeclaredField("m"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            MAP = l.findVarHandle(ConcurrentSkipListSet.class, "m",
+                                  ConcurrentNavigableMap.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CopyOnWriteArrayList.java	Mon Jul 18 09:38:08 2016 -0700
@@ -34,6 +34,7 @@
 
 package java.util.concurrent;
 
+import java.lang.reflect.Field;
 import java.util.AbstractList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -1541,17 +1542,21 @@
         }
     }
 
-    // Support for resetting lock while deserializing
+    /** Initializes the lock; for use when deserializing or cloning. */
     private void resetLock() {
-        U.putObjectVolatile(this, LOCK, new Object());
-    }
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long LOCK;
-    static {
+        Field lockField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = CopyOnWriteArrayList.class
+                        .getDeclaredField("lock");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
         try {
-            LOCK = U.objectFieldOffset
-                (CopyOnWriteArrayList.class.getDeclaredField("lock"));
-        } catch (ReflectiveOperationException e) {
+            lockField.set(this, new Object());
+        } catch (IllegalAccessException e) {
             throw new Error(e);
         }
     }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/CountedCompleter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * A {@link ForkJoinTask} with a completion action performed when
  * triggered and there are no remaining pending actions.
@@ -524,7 +527,7 @@
      * @param delta the value to add
      */
     public final void addToPendingCount(int delta) {
-        U.getAndAddInt(this, PENDING, delta);
+        PENDING.getAndAdd(this, delta);
     }
 
     /**
@@ -536,7 +539,7 @@
      * @return {@code true} if successful
      */
     public final boolean compareAndSetPendingCount(int expected, int count) {
-        return U.compareAndSwapInt(this, PENDING, expected, count);
+        return PENDING.compareAndSet(this, expected, count);
     }
 
     /**
@@ -548,7 +551,7 @@
     public final int decrementPendingCountUnlessZero() {
         int c;
         do {} while ((c = pending) != 0 &&
-                     !U.compareAndSwapInt(this, PENDING, c, c - 1));
+                     !PENDING.weakCompareAndSetVolatile(this, c, c - 1));
         return c;
     }
 
@@ -581,7 +584,7 @@
                     return;
                 }
             }
-            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSetVolatile(a, c, c - 1))
                 return;
         }
     }
@@ -604,7 +607,7 @@
                     return;
                 }
             }
-            else if (U.compareAndSwapInt(a, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSetVolatile(a, c, c - 1))
                 return;
         }
     }
@@ -649,7 +652,7 @@
         for (int c;;) {
             if ((c = pending) == 0)
                 return this;
-            else if (U.compareAndSwapInt(this, PENDING, c, c - 1))
+            else if (PENDING.weakCompareAndSetVolatile(this, c, c - 1))
                 return null;
         }
     }
@@ -753,13 +756,13 @@
      */
     protected void setRawResult(T t) { }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long PENDING;
+    // VarHandle mechanics
+    private static final VarHandle PENDING;
     static {
         try {
-            PENDING = U.objectFieldOffset
-                (CountedCompleter.class.getDeclaredField("pending"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PENDING = l.findVarHandle(CountedCompleter.class, "pending", int.class);
+
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Exchanger.java	Mon Jul 18 09:38:08 2016 -0700
@@ -36,6 +36,10 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+import java.util.concurrent.locks.LockSupport;
+
 /**
  * A synchronization point at which threads can pair and swap elements
  * within pairs.  Each thread presents some object on entry to the
@@ -155,9 +159,7 @@
      * a value that is enough for common platforms.  Additionally,
      * extra care elsewhere is taken to avoid other false/unintended
      * sharing and to enhance locality, including adding padding (via
-     * @Contended) to Nodes, embedding "bound" as an Exchanger field,
-     * and reworking some park/unpark mechanics compared to
-     * LockSupport versions.
+     * @Contended) to Nodes, embedding "bound" as an Exchanger field.
      *
      * The arena starts out with only one used slot. We expand the
      * effective arena size by tracking collisions; i.e., failed CASes
@@ -234,12 +236,12 @@
      * because most of the logic relies on reads of fields that are
      * maintained as local variables so can't be nicely factored --
      * mainly, here, bulky spin->yield->block/cancel code), and
-     * heavily dependent on intrinsics (Unsafe) to use inlined
+     * heavily dependent on intrinsics (VarHandles) to use inlined
      * embedded CAS and related memory access operations (that tend
      * not to be as readily inlined by dynamic compilers when they are
      * hidden behind other methods that would more nicely name and
      * encapsulate the intended effects). This includes the use of
-     * putXRelease to clear fields of the per-thread Nodes between
+     * setRelease to clear fields of the per-thread Nodes between
      * uses. Note that field Node.item is not declared as volatile
      * even though it is read by releasing threads, because they only
      * do so after CAS operations that must precede access, and all
@@ -252,10 +254,10 @@
      */
 
     /**
-     * The byte distance (as a shift value) between any two used slots
-     * in the arena.  1 << ASHIFT should be at least cacheline size.
+     * The index distance (as a shift value) between any two used slots
+     * in the arena, spacing them out to avoid false sharing.
      */
-    private static final int ASHIFT = 7;
+    private static final int ASHIFT = 5;
 
     /**
      * The maximum supported arena index. The maximum allocatable
@@ -356,27 +358,31 @@
      */
     private final Object arenaExchange(Object item, boolean timed, long ns) {
         Node[] a = arena;
+        int alen = a.length;
         Node p = participant.get();
         for (int i = p.index;;) {                      // access slot at i
-            int b, m, c; long j;                       // j is raw array offset
-            Node q = (Node)U.getObjectVolatile(a, j = (i << ASHIFT) + ABASE);
-            if (q != null && U.compareAndSwapObject(a, j, q, null)) {
+            int b, m, c;
+            int j = (i << ASHIFT) + ((1 << ASHIFT) - 1);
+            if (j < 0 || j >= alen)
+                j = alen - 1;
+            Node q = (Node)AA.getAcquire(a, j);
+            if (q != null && AA.compareAndSet(a, j, q, null)) {
                 Object v = q.item;                     // release
                 q.match = item;
                 Thread w = q.parked;
                 if (w != null)
-                    U.unpark(w);
+                    LockSupport.unpark(w);
                 return v;
             }
             else if (i <= (m = (b = bound) & MMASK) && q == null) {
                 p.item = item;                         // offer
-                if (U.compareAndSwapObject(a, j, null, p)) {
+                if (AA.compareAndSet(a, j, null, p)) {
                     long end = (timed && m == 0) ? System.nanoTime() + ns : 0L;
                     Thread t = Thread.currentThread(); // wait
                     for (int h = p.hash, spins = SPINS;;) {
                         Object v = p.match;
                         if (v != null) {
-                            U.putObjectRelease(p, MATCH, null);
+                            MATCH.setRelease(p, null);
                             p.item = null;             // clear for next use
                             p.hash = h;
                             return v;
@@ -389,22 +395,24 @@
                                      (--spins & ((SPINS >>> 1) - 1)) == 0)
                                 Thread.yield();        // two yields per wait
                         }
-                        else if (U.getObjectVolatile(a, j) != p)
+                        else if (AA.getAcquire(a, j) != p)
                             spins = SPINS;       // releaser hasn't set match yet
                         else if (!t.isInterrupted() && m == 0 &&
                                  (!timed ||
                                   (ns = end - System.nanoTime()) > 0L)) {
-                            U.putObject(t, BLOCKER, this); // emulate LockSupport
                             p.parked = t;              // minimize window
-                            if (U.getObjectVolatile(a, j) == p)
-                                U.park(false, ns);
+                            if (AA.getAcquire(a, j) == p) {
+                                if (ns == 0L)
+                                    LockSupport.park(this);
+                                else
+                                    LockSupport.parkNanos(this, ns);
+                            }
                             p.parked = null;
-                            U.putObject(t, BLOCKER, null);
                         }
-                        else if (U.getObjectVolatile(a, j) == p &&
-                                 U.compareAndSwapObject(a, j, p, null)) {
+                        else if (AA.getAcquire(a, j) == p &&
+                                 AA.compareAndSet(a, j, p, null)) {
                             if (m != 0)                // try to shrink
-                                U.compareAndSwapInt(this, BOUND, b, b + SEQ - 1);
+                                BOUND.compareAndSet(this, b, b + SEQ - 1);
                             p.item = null;
                             p.hash = h;
                             i = p.index >>>= 1;        // descend
@@ -426,7 +434,7 @@
                     i = (i != m || m == 0) ? m : m - 1;
                 }
                 else if ((c = p.collides) < m || m == FULL ||
-                         !U.compareAndSwapInt(this, BOUND, b, b + SEQ + 1)) {
+                         !BOUND.compareAndSet(this, b, b + SEQ + 1)) {
                     p.collides = c + 1;
                     i = (i == 0) ? m : i - 1;          // cyclically traverse
                 }
@@ -455,24 +463,24 @@
 
         for (Node q;;) {
             if ((q = slot) != null) {
-                if (U.compareAndSwapObject(this, SLOT, q, null)) {
+                if (SLOT.compareAndSet(this, q, null)) {
                     Object v = q.item;
                     q.match = item;
                     Thread w = q.parked;
                     if (w != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                     return v;
                 }
                 // create arena on contention, but continue until slot null
                 if (NCPU > 1 && bound == 0 &&
-                    U.compareAndSwapInt(this, BOUND, 0, SEQ))
+                    BOUND.compareAndSet(this, 0, SEQ))
                     arena = new Node[(FULL + 2) << ASHIFT];
             }
             else if (arena != null)
                 return null; // caller must reroute to arenaExchange
             else {
                 p.item = item;
-                if (U.compareAndSwapObject(this, SLOT, null, p))
+                if (SLOT.compareAndSet(this, null, p))
                     break;
                 p.item = null;
             }
@@ -495,19 +503,21 @@
                 spins = SPINS;
             else if (!t.isInterrupted() && arena == null &&
                      (!timed || (ns = end - System.nanoTime()) > 0L)) {
-                U.putObject(t, BLOCKER, this);
                 p.parked = t;
-                if (slot == p)
-                    U.park(false, ns);
+                if (slot == p) {
+                    if (ns == 0L)
+                        LockSupport.park(this);
+                    else
+                        LockSupport.parkNanos(this, ns);
+                }
                 p.parked = null;
-                U.putObject(t, BLOCKER, null);
             }
-            else if (U.compareAndSwapObject(this, SLOT, p, null)) {
+            else if (SLOT.compareAndSet(this, p, null)) {
                 v = timed && ns <= 0L && !t.isInterrupted() ? TIMED_OUT : null;
                 break;
             }
         }
-        U.putObjectRelease(p, MATCH, null);
+        MATCH.setRelease(p, null);
         p.item = null;
         p.hash = h;
         return v;
@@ -556,8 +566,9 @@
     @SuppressWarnings("unchecked")
     public V exchange(V x) throws InterruptedException {
         Object v;
+        Node[] a;
         Object item = (x == null) ? NULL_ITEM : x; // translate null args
-        if ((arena != null ||
+        if (((a = arena) != null ||
              (v = slotExchange(item, false, 0L)) == null) &&
             ((Thread.interrupted() || // disambiguates null return
               (v = arenaExchange(item, false, 0L)) == null)))
@@ -623,31 +634,18 @@
         return (v == NULL_ITEM) ? null : (V)v;
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long BOUND;
-    private static final long SLOT;
-    private static final long MATCH;
-    private static final long BLOCKER;
-    private static final int ABASE;
+    // VarHandle mechanics
+    private static final VarHandle BOUND;
+    private static final VarHandle SLOT;
+    private static final VarHandle MATCH;
+    private static final VarHandle AA;
     static {
         try {
-            BOUND = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("bound"));
-            SLOT = U.objectFieldOffset
-                (Exchanger.class.getDeclaredField("slot"));
-
-            MATCH = U.objectFieldOffset
-                (Node.class.getDeclaredField("match"));
-
-            BLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
-
-            int scale = U.arrayIndexScale(Node[].class);
-            if ((scale & (scale - 1)) != 0 || scale > (1 << ASHIFT))
-                throw new Error("Unsupported array scale");
-            // ABASE absorbs padding in front of element 0
-            ABASE = U.arrayBaseOffset(Node[].class) + (1 << ASHIFT);
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            BOUND = l.findVarHandle(Exchanger.class, "bound", int.class);
+            SLOT = l.findVarHandle(Exchanger.class, "slot", Node.class);
+            MATCH = l.findVarHandle(Node.class, "match", Object.class);
+            AA = MethodHandles.arrayElementVarHandle(Node[].class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java	Mon Jul 18 09:38:08 2016 -0700
@@ -36,6 +36,8 @@
 package java.util.concurrent;
 
 import java.lang.Thread.UncaughtExceptionHandler;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.security.AccessControlContext;
 import java.security.Permissions;
 import java.security.ProtectionDomain;
@@ -44,7 +46,11 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
-import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Predicate;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.CountedCompleter;
+import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.ForkJoinWorkerThread;
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -81,7 +87,9 @@
  * However, no such adjustments are guaranteed in the face of blocked
  * I/O or other unmanaged synchronization. The nested {@link
  * ManagedBlocker} interface enables extension of the kinds of
- * synchronization accommodated.
+ * synchronization accommodated. The default policies may be
+ * overridden using a constructor with parameters corresponding to
+ * those documented in class {@link ThreadPoolExecutor}.
  *
  * <p>In addition to execution and lifecycle control methods, this
  * class provides status check methods (for example
@@ -162,7 +170,6 @@
  * @since 1.7
  * @author Doug Lea
  */
-@jdk.internal.vm.annotation.Contended
 public class ForkJoinPool extends AbstractExecutorService {
 
     /*
@@ -229,10 +236,9 @@
      *        (CAS slot to null))
      *           increment base and return task;
      *
-     * There are several variants of each of these; for example most
-     * versions of poll pre-screen the CAS by rechecking that the base
-     * has not changed since reading the slot, and most methods only
-     * attempt the CAS if base appears not to be equal to top.
+     * There are several variants of each of these. In particular,
+     * almost all uses of poll occur within scan operations that also
+     * interleave contention tracking (with associated code sprawl.)
      *
      * Memory ordering.  See "Correct and Efficient Work-Stealing for
      * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013
@@ -264,10 +270,7 @@
      * thief chooses a different random victim target to try next. So,
      * in order for one thief to progress, it suffices for any
      * in-progress poll or new push on any empty queue to
-     * complete. (This is why we normally use method pollAt and its
-     * variants that try once at the apparent base index, else
-     * consider alternative actions, rather than method poll, which
-     * retries.)
+     * complete.
      *
      * This approach also enables support of a user mode in which
      * local task processing is in FIFO, not LIFO order, simply by
@@ -282,16 +285,13 @@
      * choosing existing queues, and may be randomly repositioned upon
      * contention with other submitters.  In essence, submitters act
      * like workers except that they are restricted to executing local
-     * tasks that they submitted (or in the case of CountedCompleters,
-     * others with the same root task).  Insertion of tasks in shared
-     * mode requires a lock but we use only a simple spinlock (using
-     * field qlock), because submitters encountering a busy queue move
-     * on to try or create other queues -- they block only when
-     * creating and registering new queues. Because it is used only as
-     * a spinlock, unlocking requires only a "releasing" store (using
-     * putIntRelease).  The qlock is also used during termination
-     * detection, in which case it is forced to a negative
-     * non-lockable value.
+     * tasks that they submitted.  Insertion of tasks in shared mode
+     * requires a lock but we use only a simple spinlock (using field
+     * phase), because submitters encountering a busy queue move to a
+     * different position to use or create other queues -- they block
+     * only when creating and registering new queues. Because it is
+     * used only as a spinlock, unlocking requires only a "releasing"
+     * store (using setRelease).
      *
      * Management
      * ==========
@@ -305,42 +305,34 @@
      * There are only a few properties that we can globally track or
      * maintain, so we pack them into a small number of variables,
      * often maintaining atomicity without blocking or locking.
-     * Nearly all essentially atomic control state is held in two
+     * Nearly all essentially atomic control state is held in a few
      * volatile variables that are by far most often read (not
-     * written) as status and consistency checks. (Also, field
-     * "config" holds unchanging configuration state.)
+     * written) as status and consistency checks. We pack as much
+     * information into them as we can.
      *
      * Field "ctl" contains 64 bits holding information needed to
-     * atomically decide to add, inactivate, enqueue (on an event
-     * queue), dequeue, and/or re-activate workers.  To enable this
+     * atomically decide to add, enqueue (on an event queue), and
+     * dequeue (and release)-activate workers.  To enable this
      * packing, we restrict maximum parallelism to (1<<15)-1 (which is
      * far in excess of normal operating range) to allow ids, counts,
      * and their negations (used for thresholding) to fit into 16bit
      * subfields.
      *
-     * Field "runState" holds lifetime status, atomically and
-     * monotonically setting STARTED, SHUTDOWN, STOP, and finally
-     * TERMINATED bits.
-     *
-     * Field "auxState" is a ReentrantLock subclass that also
-     * opportunistically holds some other bookkeeping fields accessed
-     * only when locked.  It is mainly used to lock (infrequent)
-     * updates to workQueues.  The auxState instance is itself lazily
-     * constructed (see tryInitialize), requiring a double-check-style
-     * bootstrapping use of field runState, and locking a private
-     * static.
+     * Field "mode" holds configuration parameters as well as lifetime
+     * status, atomically and monotonically setting SHUTDOWN, STOP,
+     * and finally TERMINATED bits.
      *
      * Field "workQueues" holds references to WorkQueues.  It is
-     * updated (only during worker creation and termination) under the
-     * lock, but is otherwise concurrently readable, and accessed
-     * directly. We also ensure that reads of the array reference
-     * itself never become too stale (for example, re-reading before
-     * each scan). To simplify index-based operations, the array size
-     * is always a power of two, and all readers must tolerate null
-     * slots. Worker queues are at odd indices. Shared (submission)
-     * queues are at even indices, up to a maximum of 64 slots, to
-     * limit growth even if array needs to expand to add more
-     * workers. Grouping them together in this way simplifies and
+     * updated (only during worker creation and termination) under
+     * lock (using field workerNamePrefix as lock), but is otherwise
+     * concurrently readable, and accessed directly. We also ensure
+     * that uses of the array reference itself never become too stale
+     * in case of resizing.  To simplify index-based operations, the
+     * array size is always a power of two, and all readers must
+     * tolerate null slots. Worker queues are at odd indices. Shared
+     * (submission) queues are at even indices, up to a maximum of 64
+     * slots, to limit growth even if array needs to expand to add
+     * more workers. Grouping them together in this way simplifies and
      * speeds up task scanning.
      *
      * All worker thread creation is on-demand, triggered by task
@@ -360,30 +352,37 @@
      * workers unless there appear to be tasks available.  On the
      * other hand, we must quickly prod them into action when new
      * tasks are submitted or generated. In many usages, ramp-up time
-     * to activate workers is the main limiting factor in overall
-     * performance, which is compounded at program start-up by JIT
-     * compilation and allocation. So we streamline this as much as
-     * possible.
+     * is the main limiting factor in overall performance, which is
+     * compounded at program start-up by JIT compilation and
+     * allocation. So we streamline this as much as possible.
      *
-     * The "ctl" field atomically maintains active and total worker
-     * counts as well as a queue to place waiting threads so they can
-     * be located for signalling. Active counts also play the role of
-     * quiescence indicators, so are decremented when workers believe
-     * that there are no more tasks to execute. The "queue" is
-     * actually a form of Treiber stack.  A stack is ideal for
-     * activating threads in most-recently used order. This improves
+     * The "ctl" field atomically maintains total worker and
+     * "released" worker counts, plus the head of the available worker
+     * queue (actually stack, represented by the lower 32bit subfield
+     * of ctl).  Released workers are those known to be scanning for
+     * and/or running tasks. Unreleased ("available") workers are
+     * recorded in the ctl stack. These workers are made available for
+     * signalling by enqueuing in ctl (see method runWorker).  The
+     * "queue" is a form of Treiber stack. This is ideal for
+     * activating threads in most-recently used order, and improves
      * performance and locality, outweighing the disadvantages of
      * being prone to contention and inability to release a worker
-     * unless it is topmost on stack.  We block/unblock workers after
-     * pushing on the idle worker stack (represented by the lower
-     * 32bit subfield of ctl) when they cannot find work.  The top
-     * stack state holds the value of the "scanState" field of the
-     * worker: its index and status, plus a version counter that, in
-     * addition to the count subfields (also serving as version
-     * stamps) provide protection against Treiber stack ABA effects.
+     * unless it is topmost on stack.  To avoid missed signal problems
+     * inherent in any wait/signal design, available workers rescan
+     * for (and if found run) tasks after enqueuing.  Normally their
+     * release status will be updated while doing so, but the released
+     * worker ctl count may underestimate the number of active
+     * threads. (However, it is still possible to determine quiescence
+     * via a validation traversal -- see isQuiescent).  After an
+     * unsuccessful rescan, available workers are blocked until
+     * signalled (see signalWork).  The top stack state holds the
+     * value of the "phase" field of the worker: its index and status,
+     * plus a version counter that, in addition to the count subfields
+     * (also serving as version stamps) provide protection against
+     * Treiber stack ABA effects.
      *
-     * Creating workers. To create a worker, we pre-increment total
-     * count (serving as a reservation), and attempt to construct a
+     * Creating workers. To create a worker, we pre-increment counts
+     * (serving as a reservation), and attempt to construct a
      * ForkJoinWorkerThread via its factory. Upon construction, the
      * new thread invokes registerWorker, where it constructs a
      * WorkQueue and is assigned an index in the workQueues array
@@ -405,16 +404,15 @@
      * submission queues for existing external threads (see
      * externalPush).
      *
-     * WorkQueue field scanState is used by both workers and the pool
-     * to manage and track whether a worker is UNSIGNALLED (possibly
-     * blocked waiting for a signal).  When a worker is inactivated,
-     * its scanState field is set, and is prevented from executing
-     * tasks, even though it must scan once for them to avoid queuing
-     * races. Note that scanState updates lag queue CAS releases so
-     * usage requires care. When queued, the lower 16 bits of
-     * scanState must hold its pool index. So we place the index there
-     * upon initialization (see registerWorker) and otherwise keep it
-     * there or restore it when necessary.
+     * WorkQueue field "phase" is used by both workers and the pool to
+     * manage and track whether a worker is UNSIGNALLED (possibly
+     * blocked waiting for a signal).  When a worker is enqueued its
+     * phase field is set. Note that phase field updates lag queue CAS
+     * releases so usage requires care -- seeing a negative phase does
+     * not guarantee that the worker is available. When queued, the
+     * lower 16 bits of scanState must hold its pool index. So we
+     * place the index there upon initialization (see registerWorker)
+     * and otherwise keep it there or restore it when necessary.
      *
      * The ctl field also serves as the basis for memory
      * synchronization surrounding activation. This uses a more
@@ -423,15 +421,14 @@
      * if to its current value).  This would be extremely costly. So
      * we relax it in several ways: (1) Producers only signal when
      * their queue is empty. Other workers propagate this signal (in
-     * method scan) when they find tasks. (2) Workers only enqueue
-     * after scanning (see below) and not finding any tasks.  (3)
-     * Rather than CASing ctl to its current value in the common case
-     * where no action is required, we reduce write contention by
-     * equivalently prefacing signalWork when called by an external
-     * task producer using a memory access with full-volatile
-     * semantics or a "fullFence". (4) For internal task producers we
-     * rely on the fact that even if no other workers awaken, the
-     * producer itself will eventually see the task and execute it.
+     * method scan) when they find tasks; to further reduce flailing,
+     * each worker signals only one other per activation. (2) Workers
+     * only enqueue after scanning (see below) and not finding any
+     * tasks.  (3) Rather than CASing ctl to its current value in the
+     * common case where no action is required, we reduce write
+     * contention by equivalently prefacing signalWork when called by
+     * an external task producer using a memory access with
+     * full-volatile semantics or a "fullFence".
      *
      * Almost always, too many signals are issued. A task producer
      * cannot in general tell if some existing worker is in the midst
@@ -443,64 +440,40 @@
      * and bookkeeping bottlenecks during ramp-up, ramp-down, and small
      * computations involving only a few workers.
      *
-     * Scanning. Method scan() performs top-level scanning for tasks.
-     * Each scan traverses (and tries to poll from) each queue in
-     * pseudorandom permutation order by randomly selecting an origin
-     * index and a step value.  (The pseudorandom generator need not
-     * have high-quality statistical properties in the long term, but
-     * just within computations; We use 64bit and 32bit Marsaglia
-     * XorShifts, which are cheap and suffice here.)  Scanning also
-     * employs contention reduction: When scanning workers fail a CAS
-     * polling for work, they soon restart with a different
-     * pseudorandom scan order (thus likely retrying at different
-     * intervals). This improves throughput when many threads are
-     * trying to take tasks from few queues.  Scans do not otherwise
-     * explicitly take into account core affinities, loads, cache
-     * localities, etc, However, they do exploit temporal locality
-     * (which usually approximates these) by preferring to re-poll (up
-     * to POLL_LIMIT times) from the same queue after a successful
-     * poll before trying others.  Restricted forms of scanning occur
-     * in methods helpComplete and findNonEmptyStealQueue, and take
-     * similar but simpler forms.
-     *
-     * Deactivation and waiting. Queuing encounters several intrinsic
-     * races; most notably that an inactivating scanning worker can
-     * miss seeing a task produced during a scan.  So when a worker
-     * cannot find a task to steal, it inactivates and enqueues, and
-     * then rescans to ensure that it didn't miss one, reactivating
-     * upon seeing one with probability approximately proportional to
-     * probability of a miss.  (In most cases, the worker will be
-     * signalled before self-signalling, avoiding cascades of multiple
-     * signals for the same task).
-     *
-     * Workers block (in method awaitWork) using park/unpark;
-     * advertising the need for signallers to unpark by setting their
-     * "parker" fields.
+     * Scanning. Method runWorker performs top-level scanning for
+     * tasks.  Each scan traverses and tries to poll from each queue
+     * starting at a random index and circularly stepping. Scans are
+     * not performed in ideal random permutation order, to reduce
+     * cacheline contention.  The pseudorandom generator need not have
+     * high-quality statistical properties in the long term, but just
+     * within computations; We use Marsaglia XorShifts (often via
+     * ThreadLocalRandom.nextSecondarySeed), which are cheap and
+     * suffice. Scanning also employs contention reduction: When
+     * scanning workers fail to extract an apparently existing task,
+     * they soon restart at a different pseudorandom index.  This
+     * improves throughput when many threads are trying to take tasks
+     * from few queues, which can be common in some usages.  Scans do
+     * not otherwise explicitly take into account core affinities,
+     * loads, cache localities, etc, However, they do exploit temporal
+     * locality (which usually approximates these) by preferring to
+     * re-poll (at most #workers times) from the same queue after a
+     * successful poll before trying others.
      *
      * Trimming workers. To release resources after periods of lack of
      * use, a worker starting to wait when the pool is quiescent will
-     * time out and terminate (see awaitWork) if the pool has remained
-     * quiescent for period given by IDLE_TIMEOUT_MS, increasing the
-     * period as the number of threads decreases, eventually removing
-     * all workers.
+     * time out and terminate (see method scan) if the pool has
+     * remained quiescent for period given by field keepAlive.
      *
      * Shutdown and Termination. A call to shutdownNow invokes
      * tryTerminate to atomically set a runState bit. The calling
      * thread, as well as every other worker thereafter terminating,
-     * helps terminate others by setting their (qlock) status,
-     * cancelling their unprocessed tasks, and waking them up, doing
-     * so repeatedly until stable. Calls to non-abrupt shutdown()
-     * preface this by checking whether termination should commence.
-     * This relies primarily on the active count bits of "ctl"
-     * maintaining consensus -- tryTerminate is called from awaitWork
-     * whenever quiescent. However, external submitters do not take
-     * part in this consensus.  So, tryTerminate sweeps through queues
-     * (until stable) to ensure lack of in-flight submissions and
-     * workers about to process them before triggering the "STOP"
-     * phase of termination. (Note: there is an intrinsic conflict if
-     * helpQuiescePool is called when shutdown is enabled. Both wait
-     * for quiescence, but tryTerminate is biased to not trigger until
-     * helpQuiescePool completes.)
+     * helps terminate others by cancelling their unprocessed tasks,
+     * and waking them up, doing so repeatedly until stable. Calls to
+     * non-abrupt shutdown() preface this by checking whether
+     * termination should commence by sweeping through queues (until
+     * stable) to ensure lack of in-flight submissions and workers
+     * about to process them before triggering the "STOP" phase of
+     * termination.
      *
      * Joining Tasks
      * =============
@@ -508,12 +481,12 @@
      * Any of several actions may be taken when one worker is waiting
      * to join a task stolen (or always held) by another.  Because we
      * are multiplexing many tasks on to a pool of workers, we can't
-     * just let them block (as in Thread.join).  We also cannot just
-     * reassign the joiner's run-time stack with another and replace
-     * it later, which would be a form of "continuation", that even if
-     * possible is not necessarily a good idea since we may need both
-     * an unblocked task and its continuation to progress.  Instead we
-     * combine two tactics:
+     * always just let them block (as in Thread.join).  We also cannot
+     * just reassign the joiner's run-time stack with another and
+     * replace it later, which would be a form of "continuation", that
+     * even if possible is not necessarily a good idea since we may
+     * need both an unblocked task and its continuation to progress.
+     * Instead we combine two tactics:
      *
      *   Helping: Arranging for the joiner to execute some task that it
      *      would be running if the steal had not occurred.
@@ -526,79 +499,43 @@
      * helping a hypothetical compensator: If we can readily tell that
      * a possible action of a compensator is to steal and execute the
      * task being joined, the joining thread can do so directly,
-     * without the need for a compensation thread (although at the
-     * expense of larger run-time stacks, but the tradeoff is
-     * typically worthwhile).
+     * without the need for a compensation thread.
      *
      * The ManagedBlocker extension API can't use helping so relies
      * only on compensation in method awaitBlocker.
      *
-     * The algorithm in helpStealer entails a form of "linear
-     * helping".  Each worker records (in field currentSteal) the most
-     * recent task it stole from some other worker (or a submission).
-     * It also records (in field currentJoin) the task it is currently
-     * actively joining. Method helpStealer uses these markers to try
-     * to find a worker to help (i.e., steal back a task from and
-     * execute it) that could hasten completion of the actively joined
-     * task.  Thus, the joiner executes a task that would be on its
-     * own local deque had the to-be-joined task not been stolen. This
-     * is a conservative variant of the approach described in Wagner &
-     * Calder "Leapfrogging: a portable technique for implementing
-     * efficient futures" SIGPLAN Notices, 1993
-     * (http://portal.acm.org/citation.cfm?id=155354). It differs in
-     * that: (1) We only maintain dependency links across workers upon
-     * steals, rather than use per-task bookkeeping.  This sometimes
-     * requires a linear scan of workQueues array to locate stealers,
-     * but often doesn't because stealers leave hints (that may become
-     * stale/wrong) of where to locate them.  It is only a hint
-     * because a worker might have had multiple steals and the hint
-     * records only one of them (usually the most current).  Hinting
-     * isolates cost to when it is needed, rather than adding to
-     * per-task overhead.  (2) It is "shallow", ignoring nesting and
-     * potentially cyclic mutual steals.  (3) It is intentionally
-     * racy: field currentJoin is updated only while actively joining,
-     * which means that we miss links in the chain during long-lived
-     * tasks, GC stalls etc (which is OK since blocking in such cases
-     * is usually a good idea).  (4) We bound the number of attempts
-     * to find work using checksums and fall back to suspending the
-     * worker and if necessary replacing it with another.
+     * The algorithm in awaitJoin entails a form of "linear helping".
+     * Each worker records (in field source) the id of the queue from
+     * which it last stole a task.  The scan in method awaitJoin uses
+     * these markers to try to find a worker to help (i.e., steal back
+     * a task from and execute it) that could hasten completion of the
+     * actively joined task.  Thus, the joiner executes a task that
+     * would be on its own local deque if the to-be-joined task had
+     * not been stolen. This is a conservative variant of the approach
+     * described in Wagner & Calder "Leapfrogging: a portable
+     * technique for implementing efficient futures" SIGPLAN Notices,
+     * 1993 (http://portal.acm.org/citation.cfm?id=155354). It differs
+     * mainly in that we only record queue ids, not full dependency
+     * links.  This requires a linear scan of the workQueues array to
+     * locate stealers, but isolates cost to when it is needed, rather
+     * than adding to per-task overhead. Searches can fail to locate
+     * stealers GC stalls and the like delay recording sources.
+     * Further, even when accurately identified, stealers might not
+     * ever produce a task that the joiner can in turn help with. So,
+     * compensation is tried upon failure to find tasks to run.
      *
-     * Helping actions for CountedCompleters do not require tracking
-     * currentJoins: Method helpComplete takes and executes any task
-     * with the same root as the task being waited on (preferring
-     * local pops to non-local polls). However, this still entails
-     * some traversal of completer chains, so is less efficient than
-     * using CountedCompleters without explicit joins.
-     *
-     * Compensation does not aim to keep exactly the target
+     * Compensation does not by default aim to keep exactly the target
      * parallelism number of unblocked threads running at any given
      * time. Some previous versions of this class employed immediate
      * compensations for any blocked join. However, in practice, the
      * vast majority of blockages are transient byproducts of GC and
      * other JVM or OS activities that are made worse by replacement.
-     * Currently, compensation is attempted only after validating that
-     * all purportedly active threads are processing tasks by checking
-     * field WorkQueue.scanState, which eliminates most false
-     * positives.  Also, compensation is bypassed (tolerating fewer
-     * threads) in the most common case in which it is rarely
-     * beneficial: when a worker with an empty queue (thus no
-     * continuation tasks) blocks on a join and there still remain
-     * enough threads to ensure liveness.
-     *
-     * Spare threads are removed as soon as they notice that the
-     * target parallelism level has been exceeded, in method
-     * tryDropSpare. (Method scan arranges returns for rechecks upon
-     * each probe via the "bound" parameter.)
-     *
-     * The compensation mechanism may be bounded.  Bounds for the
-     * commonPool (see COMMON_MAX_SPARES) better enable JVMs to cope
-     * with programming errors and abuse before running out of
-     * resources to do so. In other cases, users may supply factories
-     * that limit thread construction. The effects of bounding in this
-     * pool (like all others) is imprecise.  Total worker counts are
-     * decremented when threads deregister, not when they exit and
-     * resources are reclaimed by the JVM and OS. So the number of
-     * simultaneously live threads may transiently exceed bounds.
+     * Rather than impose arbitrary policies, we allow users to
+     * override the default of only adding threads upon apparent
+     * starvation.  The compensation mechanism may also be bounded.
+     * Bounds for the commonPool (see COMMON_MAX_SPARES) better enable
+     * JVMs to cope with programming errors and abuse before running
+     * out of resources to do so.
      *
      * Common Pool
      * ===========
@@ -606,9 +543,7 @@
      * The static common pool always exists after static
      * initialization.  Since it (or any other created pool) need
      * never be used, we minimize initial construction overhead and
-     * footprint to the setup of about a dozen fields, with no nested
-     * allocation. Most bootstrapping occurs within method
-     * externalSubmit during the first submission to the pool.
+     * footprint to the setup of about a dozen fields.
      *
      * When external threads submit to the common pool, they can
      * perform subtask processing (see externalHelpComplete and
@@ -628,28 +563,22 @@
      * InnocuousForkJoinWorkerThread when there is a SecurityManager
      * present. These workers have no permissions set, do not belong
      * to any user-defined ThreadGroup, and erase all ThreadLocals
-     * after executing any top-level task (see WorkQueue.runTask).
-     * The associated mechanics (mainly in ForkJoinWorkerThread) may
-     * be JVM-dependent and must access particular Thread class fields
-     * to achieve this effect.
+     * after executing any top-level task (see
+     * WorkQueue.afterTopLevelExec).  The associated mechanics (mainly
+     * in ForkJoinWorkerThread) may be JVM-dependent and must access
+     * particular Thread class fields to achieve this effect.
      *
      * Style notes
      * ===========
      *
-     * Memory ordering relies mainly on Unsafe intrinsics that carry
-     * the further responsibility of explicitly performing null- and
-     * bounds- checks otherwise carried out implicitly by JVMs.  This
-     * can be awkward and ugly, but also reflects the need to control
+     * Memory ordering relies mainly on VarHandles.  This can be
+     * awkward and ugly, but also reflects the need to control
      * outcomes across the unusual cases that arise in very racy code
-     * with very few invariants. So these explicit checks would exist
-     * in some form anyway.  All fields are read into locals before
-     * use, and null-checked if they are references.  This is usually
-     * done in a "C"-like style of listing declarations at the heads
-     * of methods or blocks, and using inline assignments on first
-     * encounter.  Array bounds-checks are usually performed by
-     * masking with array.length-1, which relies on the invariant that
-     * these arrays are created with positive lengths, which is itself
-     * paranoically checked. Nearly all explicit checks lead to
+     * with very few invariants. All fields are read into locals
+     * before use, and null-checked if they are references.  This is
+     * usually done in a "C"-like style of listing declarations at the
+     * heads of methods or blocks, and using inline assignments on
+     * first encounter.  Nearly all explicit checks lead to
      * bypass/return, not exception throws, because they may
      * legitimately arise due to cancellation/revocation during
      * shutdown.
@@ -701,10 +630,17 @@
     public static interface ForkJoinWorkerThreadFactory {
         /**
          * Returns a new worker thread operating in the given pool.
+         * Returning null or throwing an exception may result in tasks
+         * never being executed.  If this method throws an exception,
+         * it is relayed to the caller of the method (for example
+         * {@code execute}) causing attempted thread creation. If this
+         * method returns null or throws an exception, it is not
+         * retried until the next attempted creation (for example
+         * another call to {@code execute}).
          *
          * @param pool the pool this thread works in
          * @return the new worker thread, or {@code null} if the request
-         *         to create a thread is rejected
+         *         to create a thread is rejected.
          * @throws NullPointerException if the pool is null
          */
         public ForkJoinWorkerThread newThread(ForkJoinPool pool);
@@ -721,56 +657,35 @@
         }
     }
 
-    /**
-     * Class for artificial tasks that are used to replace the target
-     * of local joins if they are removed from an interior queue slot
-     * in WorkQueue.tryRemoveAndExec. We don't need the proxy to
-     * actually do anything beyond having a unique identity.
-     */
-    private static final class EmptyTask extends ForkJoinTask<Void> {
-        private static final long serialVersionUID = -7721805057305804111L;
-        EmptyTask() { status = ForkJoinTask.NORMAL; } // force done
-        public final Void getRawResult() { return null; }
-        public final void setRawResult(Void x) {}
-        public final boolean exec() { return true; }
-    }
-
-    /**
-     * Additional fields and lock created upon initialization.
-     */
-    private static final class AuxState extends ReentrantLock {
-        private static final long serialVersionUID = -6001602636862214147L;
-        volatile long stealCount;     // cumulative steal count
-        long indexSeed;               // index bits for registerWorker
-        AuxState() {}
-    }
-
     // Constants shared across ForkJoinPool and WorkQueue
 
     // Bounds
+    static final int SWIDTH       = 16;            // width of short
     static final int SMASK        = 0xffff;        // short bits == max index
     static final int MAX_CAP      = 0x7fff;        // max #workers - 1
-    static final int EVENMASK     = 0xfffe;        // even short bits
     static final int SQMASK       = 0x007e;        // max 64 (even) slots
 
-    // Masks and units for WorkQueue.scanState and ctl sp subfield
+    // Masks and units for WorkQueue.phase and ctl sp subfield
     static final int UNSIGNALLED  = 1 << 31;       // must be negative
     static final int SS_SEQ       = 1 << 16;       // version count
+    static final int QLOCK        = 1;             // must be 1
 
-    // Mode bits for ForkJoinPool.config and WorkQueue.config
-    static final int MODE_MASK    = 0xffff << 16;  // top half of int
-    static final int SPARE_WORKER = 1 << 17;       // set if tc > 0 on creation
-    static final int UNREGISTERED = 1 << 18;       // to skip some of deregister
-    static final int FIFO_QUEUE   = 1 << 31;       // must be negative
-    static final int LIFO_QUEUE   = 0;             // for clarity
-    static final int IS_OWNED     = 1;             // low bit 0 if shared
+    // Mode bits and sentinels, some also used in WorkQueue id and.source fields
+    static final int OWNED        = 1;             // queue has owner thread
+    static final int FIFO         = 1 << 16;       // fifo queue or access mode
+    static final int SHUTDOWN     = 1 << 18;
+    static final int TERMINATED   = 1 << 19;
+    static final int STOP         = 1 << 31;       // must be negative
+    static final int QUIET        = 1 << 30;       // not scanning or working
+    static final int DORMANT      = QUIET | UNSIGNALLED;
 
     /**
-     * The maximum number of task executions from the same queue
-     * before checking other queues, bounding unfairness and impact of
-     * infinite user task recursion.  Must be a power of two minus 1.
+     * The maximum number of local polls from the same queue before
+     * checking others. This is a safeguard against infinitely unfair
+     * looping under unbounded user task recursion, and must be larger
+     * than plausible cases of intentional bounded task recursion.
      */
-    static final int POLL_LIMIT = (1 << 10) - 1;
+    static final int POLL_LIMIT = 1 << 10;
 
     /**
      * Queues supporting work-stealing as well as external task
@@ -805,23 +720,16 @@
         static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M
 
         // Instance fields
-
-        volatile int scanState;    // versioned, negative if inactive
-        int stackPred;             // pool stack (ctl) predecessor
+        volatile int phase;        // versioned, negative: queued, 1: locked
+        int stackPred;             // pool stack (ctl) predecessor link
         int nsteals;               // number of steals
-        int hint;                  // randomization and stealer index hint
-        int config;                // pool index and mode
-        volatile int qlock;        // 1: locked, < 0: terminate; else 0
+        int id;                    // index, mode, tag
+        volatile int source;       // source queue id, or sentinel
         volatile int base;         // index of next slot for poll
         int top;                   // index of next slot for push
         ForkJoinTask<?>[] array;   // the elements (initially unallocated)
         final ForkJoinPool pool;   // the containing pool (may be null)
         final ForkJoinWorkerThread owner; // owning thread or null if shared
-        volatile Thread parker;    // == owner during call to park; else null
-        volatile ForkJoinTask<?> currentJoin; // task being joined in awaitJoin
-
-        @jdk.internal.vm.annotation.Contended("group2") // segregate
-        volatile ForkJoinTask<?> currentSteal; // nonnull when running some task
 
         WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) {
             this.pool = pool;
@@ -834,7 +742,7 @@
          * Returns an exportable index (used by ForkJoinWorkerThread).
          */
         final int getPoolIndex() {
-            return (config & 0xffff) >>> 1; // ignore odd/even tag bit
+            return (id & 0xffff) >>> 1; // ignore odd/even tag bit
         }
 
         /**
@@ -851,13 +759,14 @@
          * near-empty queue has at least one unclaimed task.
          */
         final boolean isEmpty() {
-            ForkJoinTask<?>[] a; int n, al, s;
-            return ((n = base - (s = top)) >= 0 || // possibly one task
+            ForkJoinTask<?>[] a; int n, al, b;
+            return ((n = (b = base) - top) >= 0 || // possibly one task
                     (n == -1 && ((a = array) == null ||
                                  (al = a.length) == 0 ||
-                                 a[(al - 1) & (s - 1)] == null)));
+                                 a[(al - 1) & b] == null)));
         }
 
+
         /**
          * Pushes a task. Call only by owner in unshared queues.
          *
@@ -865,17 +774,17 @@
          * @throws RejectedExecutionException if array cannot be resized
          */
         final void push(ForkJoinTask<?> task) {
-            U.storeFence();              // ensure safe publication
-            int s = top, al, d; ForkJoinTask<?>[] a;
+            int s = top; ForkJoinTask<?>[] a; int al, d;
             if ((a = array) != null && (al = a.length) > 0) {
-                a[(al - 1) & s] = task;  // relaxed writes OK
-                top = s + 1;
+                int index = (al - 1) & s;
                 ForkJoinPool p = pool;
+                top = s + 1;
+                QA.setRelease(a, index, task);
                 if ((d = base - s) == 0 && p != null) {
-                    U.fullFence();
+                    VarHandle.fullFence();
                     p.signalWork();
                 }
-                else if (al + d == 1)
+                else if (d + al == 1)
                     growArray();
             }
         }
@@ -887,24 +796,24 @@
          */
         final ForkJoinTask<?>[] growArray() {
             ForkJoinTask<?>[] oldA = array;
-            int size = oldA != null ? oldA.length << 1 : INITIAL_QUEUE_CAPACITY;
+            int oldSize = oldA != null ? oldA.length : 0;
+            int size = oldSize > 0 ? oldSize << 1 : INITIAL_QUEUE_CAPACITY;
             if (size < INITIAL_QUEUE_CAPACITY || size > MAXIMUM_QUEUE_CAPACITY)
                 throw new RejectedExecutionException("Queue capacity exceeded");
             int oldMask, t, b;
             ForkJoinTask<?>[] a = array = new ForkJoinTask<?>[size];
-            if (oldA != null && (oldMask = oldA.length - 1) > 0 &&
+            if (oldA != null && (oldMask = oldSize - 1) > 0 &&
                 (t = top) - (b = base) > 0) {
                 int mask = size - 1;
                 do { // emulate poll from old array, push to new array
                     int index = b & oldMask;
-                    long offset = ((long)index << ASHIFT) + ABASE;
                     ForkJoinTask<?> x = (ForkJoinTask<?>)
-                        U.getObjectVolatile(oldA, offset);
+                        QA.getAcquire(oldA, index);
                     if (x != null &&
-                        U.compareAndSwapObject(oldA, offset, x, null))
+                        QA.compareAndSet(oldA, index, x, null))
                         a[b & mask] = x;
                 } while (++b != t);
-                U.storeFence();
+                VarHandle.releaseFence();
             }
             return a;
         }
@@ -917,33 +826,12 @@
             int b = base, s = top, al, i; ForkJoinTask<?>[] a;
             if ((a = array) != null && b != s && (al = a.length) > 0) {
                 int index = (al - 1) & --s;
-                long offset = ((long)index << ASHIFT) + ABASE;
                 ForkJoinTask<?> t = (ForkJoinTask<?>)
-                    U.getObject(a, offset);
+                    QA.get(a, index);
                 if (t != null &&
-                    U.compareAndSwapObject(a, offset, t, null)) {
+                    QA.compareAndSet(a, index, t, null)) {
                     top = s;
-                    return t;
-                }
-            }
-            return null;
-        }
-
-        /**
-         * Takes a task in FIFO order if b is base of queue and a task
-         * can be claimed without contention. Specialized versions
-         * appear in ForkJoinPool methods scan and helpStealer.
-         */
-        final ForkJoinTask<?> pollAt(int b) {
-            ForkJoinTask<?>[] a; int al;
-            if ((a = array) != null && (al = a.length) > 0) {
-                int index = (al - 1) & b;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> t = (ForkJoinTask<?>)
-                    U.getObjectVolatile(a, offset);
-                if (t != null && b++ == base &&
-                    U.compareAndSwapObject(a, offset, t, null)) {
-                    base = b;
+                    VarHandle.releaseFence();
                     return t;
                 }
             }
@@ -959,12 +847,11 @@
                 if ((a = array) != null && (d = b - s) < 0 &&
                     (al = a.length) > 0) {
                     int index = (al - 1) & b;
-                    long offset = ((long)index << ASHIFT) + ABASE;
                     ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getObjectVolatile(a, offset);
+                        QA.getAcquire(a, index);
                     if (b++ == base) {
                         if (t != null) {
-                            if (U.compareAndSwapObject(a, offset, t, null)) {
+                            if (QA.compareAndSet(a, index, t, null)) {
                                 base = b;
                                 return t;
                             }
@@ -983,7 +870,7 @@
          * Takes next task, if one exists, in order specified by mode.
          */
         final ForkJoinTask<?> nextLocalTask() {
-            return (config < 0) ? poll() : pop();
+            return ((id & FIFO) != 0) ? poll() : pop();
         }
 
         /**
@@ -992,7 +879,8 @@
         final ForkJoinTask<?> peek() {
             int al; ForkJoinTask<?>[] a;
             return ((a = array) != null && (al = a.length) > 0) ?
-                a[(al - 1) & (config < 0 ? base : top - 1)] : null;
+                a[(al - 1) &
+                  ((id & FIFO) != 0 ? base : top - 1)] : null;
         }
 
         /**
@@ -1002,9 +890,9 @@
             int b = base, s = top, al; ForkJoinTask<?>[] a;
             if ((a = array) != null && b != s && (al = a.length) > 0) {
                 int index = (al - 1) & --s;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                if (U.compareAndSwapObject(a, offset, task, null)) {
+                if (QA.compareAndSet(a, index, task, null)) {
                     top = s;
+                    VarHandle.releaseFence();
                     return true;
                 }
             }
@@ -1012,105 +900,32 @@
         }
 
         /**
-         * Shared version of push. Fails if already locked.
-         *
-         * @return status: > 0 locked, 0 possibly was empty, < 0 was nonempty
-         */
-        final int sharedPush(ForkJoinTask<?> task) {
-            int stat;
-            if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                int b = base, s = top, al, d; ForkJoinTask<?>[] a;
-                if ((a = array) != null && (al = a.length) > 0 &&
-                    al - 1 + (d = b - s) > 0) {
-                    a[(al - 1) & s] = task;
-                    top = s + 1;                 // relaxed writes OK here
-                    qlock = 0;
-                    stat = (d < 0 && b == base) ? d : 0;
-                }
-                else {
-                    growAndSharedPush(task);
-                    stat = 0;
-                }
-            }
-            else
-                stat = 1;
-            return stat;
-        }
-
-        /**
-         * Helper for sharedPush; called only when locked and resize
-         * needed.
-         */
-        private void growAndSharedPush(ForkJoinTask<?> task) {
-            try {
-                growArray();
-                int s = top, al; ForkJoinTask<?>[] a;
-                if ((a = array) != null && (al = a.length) > 0) {
-                    a[(al - 1) & s] = task;
-                    top = s + 1;
-                }
-            } finally {
-                qlock = 0;
-            }
-        }
-
-        /**
-         * Shared version of tryUnpush.
-         */
-        final boolean trySharedUnpush(ForkJoinTask<?> task) {
-            boolean popped = false;
-            int s = top - 1, al; ForkJoinTask<?>[] a;
-            if ((a = array) != null && (al = a.length) > 0) {
-                int index = (al - 1) & s;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> t = (ForkJoinTask<?>) U.getObject(a, offset);
-                if (t == task &&
-                    U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                    if (top == s + 1 && array == a &&
-                        U.compareAndSwapObject(a, offset, task, null)) {
-                        popped = true;
-                        top = s;
-                    }
-                    U.putIntRelease(this, QLOCK, 0);
-                }
-            }
-            return popped;
-        }
-
-        /**
          * Removes and cancels all known tasks, ignoring any exceptions.
          */
         final void cancelAll() {
-            ForkJoinTask<?> t;
-            if ((t = currentJoin) != null) {
-                currentJoin = null;
-                ForkJoinTask.cancelIgnoringExceptions(t);
-            }
-            if ((t = currentSteal) != null) {
-                currentSteal = null;
-                ForkJoinTask.cancelIgnoringExceptions(t);
-            }
-            while ((t = poll()) != null)
+            for (ForkJoinTask<?> t; (t = poll()) != null; )
                 ForkJoinTask.cancelIgnoringExceptions(t);
         }
 
         // Specialized execution methods
 
         /**
-         * Pops and executes up to POLL_LIMIT tasks or until empty.
+         * Pops and executes up to limit consecutive tasks or until empty.
+         *
+         * @param limit max runs, or zero for no limit
          */
-        final void localPopAndExec() {
-            for (int nexec = 0;;) {
+        final void localPopAndExec(int limit) {
+            for (;;) {
                 int b = base, s = top, al; ForkJoinTask<?>[] a;
                 if ((a = array) != null && b != s && (al = a.length) > 0) {
                     int index = (al - 1) & --s;
-                    long offset = ((long)index << ASHIFT) + ABASE;
                     ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getAndSetObject(a, offset, null);
+                        QA.getAndSet(a, index, null);
                     if (t != null) {
                         top = s;
-                        (currentSteal = t).doExec();
-                        if (++nexec > POLL_LIMIT)
+                        VarHandle.releaseFence();
+                        t.doExec();
+                        if (limit != 0 && --limit == 0)
                             break;
                     }
                     else
@@ -1122,22 +937,28 @@
         }
 
         /**
-         * Polls and executes up to POLL_LIMIT tasks or until empty.
+         * Polls and executes up to limit consecutive tasks or until empty.
+         *
+         * @param limit, or zero for no limit
          */
-        final void localPollAndExec() {
-            for (int nexec = 0;;) {
-                int b = base, s = top, al; ForkJoinTask<?>[] a;
-                if ((a = array) != null && b != s && (al = a.length) > 0) {
+        final void localPollAndExec(int limit) {
+            for (int polls = 0;;) {
+                int b = base, s = top, d, al; ForkJoinTask<?>[] a;
+                if ((a = array) != null && (d = b - s) < 0 &&
+                    (al = a.length) > 0) {
                     int index = (al - 1) & b++;
-                    long offset = ((long)index << ASHIFT) + ABASE;
                     ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getAndSetObject(a, offset, null);
+                        QA.getAndSet(a, index, null);
                     if (t != null) {
                         base = b;
                         t.doExec();
-                        if (++nexec > POLL_LIMIT)
+                        if (limit != 0 && ++polls == limit)
                             break;
                     }
+                    else if (d == -1)
+                        break;     // now empty
+                    else
+                        polls = 0; // stolen; reset
                 }
                 else
                     break;
@@ -1145,188 +966,156 @@
         }
 
         /**
-         * Executes the given task and (some) remaining local tasks.
+         * If present, removes task from queue and executes it.
          */
-        final void runTask(ForkJoinTask<?> task) {
-            if (task != null) {
-                task.doExec();
-                if (config < 0)
-                    localPollAndExec();
-                else
-                    localPopAndExec();
-                int ns = ++nsteals;
-                ForkJoinWorkerThread thread = owner;
-                currentSteal = null;
-                if (ns < 0)           // collect on overflow
-                    transferStealCount(pool);
-                if (thread != null)
-                    thread.afterTopLevelExec();
-            }
-        }
-
-        /**
-         * Adds steal count to pool steal count if it exists, and resets.
-         */
-        final void transferStealCount(ForkJoinPool p) {
-            AuxState aux;
-            if (p != null && (aux = p.auxState) != null) {
-                long s = nsteals;
-                nsteals = 0;            // if negative, correct for overflow
-                if (s < 0) s = Integer.MAX_VALUE;
-                aux.lock();
-                try {
-                    aux.stealCount += s;
-                } finally {
-                    aux.unlock();
+        final void tryRemoveAndExec(ForkJoinTask<?> task) {
+            ForkJoinTask<?>[] wa; int s, wal;
+            if (base - (s = top) < 0 && // traverse from top
+                (wa = array) != null && (wal = wa.length) > 0) {
+                for (int m = wal - 1, ns = s - 1, i = ns; ; --i) {
+                    int index = i & m;
+                    ForkJoinTask<?> t = (ForkJoinTask<?>)
+                        QA.get(wa, index);
+                    if (t == null)
+                        break;
+                    else if (t == task) {
+                        if (QA.compareAndSet(wa, index, t, null)) {
+                            top = ns;   // safely shift down
+                            for (int j = i; j != ns; ++j) {
+                                ForkJoinTask<?> f;
+                                int pindex = (j + 1) & m;
+                                f = (ForkJoinTask<?>)QA.get(wa, pindex);
+                                QA.setVolatile(wa, pindex, null);
+                                int jindex = j & m;
+                                QA.setRelease(wa, jindex, f);
+                            }
+                            VarHandle.releaseFence();
+                            t.doExec();
+                        }
+                        break;
+                    }
                 }
             }
         }
 
         /**
-         * If present, removes from queue and executes the given task,
-         * or any other cancelled task. Used only by awaitJoin.
+         * Tries to steal and run tasks within the target's
+         * computation until done, not found, or limit exceeded.
          *
-         * @return true if queue empty and task not known to be done
+         * @param task root of CountedCompleter computation
+         * @param limit max runs, or zero for no limit
+         * @return task status on exit
          */
-        final boolean tryRemoveAndExec(ForkJoinTask<?> task) {
-            if (task != null && task.status >= 0) {
-                int b, s, d, al; ForkJoinTask<?>[] a;
-                while ((d = (b = base) - (s = top)) < 0 &&
-                       (a = array) != null && (al = a.length) > 0) {
-                    for (;;) {      // traverse from s to b
-                        int index = --s & (al - 1);
-                        long offset = (index << ASHIFT) + ABASE;
-                        ForkJoinTask<?> t = (ForkJoinTask<?>)
-                            U.getObjectVolatile(a, offset);
-                        if (t == null)
-                            break;                   // restart
-                        else if (t == task) {
-                            boolean removed = false;
-                            if (s + 1 == top) {      // pop
-                                if (U.compareAndSwapObject(a, offset, t, null)) {
-                                    top = s;
-                                    removed = true;
+        final int localHelpCC(CountedCompleter<?> task, int limit) {
+            int status = 0;
+            if (task != null && (status = task.status) >= 0) {
+                for (;;) {
+                    boolean help = false;
+                    int b = base, s = top, al; ForkJoinTask<?>[] a;
+                    if ((a = array) != null && b != s && (al = a.length) > 0) {
+                        int index = (al - 1) & (s - 1);
+                        ForkJoinTask<?> o = (ForkJoinTask<?>)
+                            QA.get(a, index);
+                        if (o instanceof CountedCompleter) {
+                            CountedCompleter<?> t = (CountedCompleter<?>)o;
+                            for (CountedCompleter<?> f = t;;) {
+                                if (f != task) {
+                                    if ((f = f.completer) == null) // try parent
+                                        break;
+                                }
+                                else {
+                                    if (QA.compareAndSet(a, index, t, null)) {
+                                        top = s - 1;
+                                        VarHandle.releaseFence();
+                                        t.doExec();
+                                        help = true;
+                                    }
+                                    break;
                                 }
                             }
-                            else if (base == b)      // replace with proxy
-                                removed = U.compareAndSwapObject(a, offset, t,
-                                                                 new EmptyTask());
-                            if (removed) {
-                                ForkJoinTask<?> ps = currentSteal;
-                                (currentSteal = task).doExec();
-                                currentSteal = ps;
-                            }
-                            break;
-                        }
-                        else if (t.status < 0 && s + 1 == top) {
-                            if (U.compareAndSwapObject(a, offset, t, null)) {
-                                top = s;
-                            }
-                            break;                  // was cancelled
-                        }
-                        else if (++d == 0) {
-                            if (base != b)          // rescan
-                                break;
-                            return false;
                         }
                     }
-                    if (task.status < 0)
-                        return false;
+                    if ((status = task.status) < 0 || !help ||
+                        (limit != 0 && --limit == 0))
+                        break;
                 }
             }
-            return true;
+            return status;
+        }
+
+        // Operations on shared queues
+
+        /**
+         * Tries to lock shared queue by CASing phase field.
+         */
+        final boolean tryLockSharedQueue() {
+            return PHASE.compareAndSet(this, 0, QLOCK);
         }
 
         /**
-         * Pops task if in the same CC computation as the given task,
-         * in either shared or owned mode. Used only by helpComplete.
+         * Shared version of tryUnpush.
          */
-        final CountedCompleter<?> popCC(CountedCompleter<?> task, int mode) {
-            int b = base, s = top, al; ForkJoinTask<?>[] a;
-            if ((a = array) != null && b != s && (al = a.length) > 0) {
-                int index = (al - 1) & (s - 1);
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> o = (ForkJoinTask<?>)
-                    U.getObjectVolatile(a, offset);
-                if (o instanceof CountedCompleter) {
-                    CountedCompleter<?> t = (CountedCompleter<?>)o;
-                    for (CountedCompleter<?> r = t;;) {
-                        if (r == task) {
-                            if ((mode & IS_OWNED) == 0) {
-                                boolean popped = false;
-                                if (U.compareAndSwapInt(this, QLOCK, 0, 1)) {
-                                    if (top == s && array == a &&
-                                        U.compareAndSwapObject(a, offset,
-                                                               t, null)) {
-                                        popped = true;
-                                        top = s - 1;
-                                    }
-                                    U.putIntRelease(this, QLOCK, 0);
-                                    if (popped)
-                                        return t;
-                                }
-                            }
-                            else if (U.compareAndSwapObject(a, offset,
-                                                            t, null)) {
-                                top = s - 1;
-                                return t;
-                            }
-                            break;
-                        }
-                        else if ((r = r.completer) == null) // try parent
-                            break;
+        final boolean trySharedUnpush(ForkJoinTask<?> task) {
+            boolean popped = false;
+            int s = top - 1, al; ForkJoinTask<?>[] a;
+            if ((a = array) != null && (al = a.length) > 0) {
+                int index = (al - 1) & s;
+                ForkJoinTask<?> t = (ForkJoinTask<?>) QA.get(a, index);
+                if (t == task &&
+                    PHASE.compareAndSet(this, 0, QLOCK)) {
+                    if (top == s + 1 && array == a &&
+                        QA.compareAndSet(a, index, task, null)) {
+                        popped = true;
+                        top = s;
                     }
+                    PHASE.setRelease(this, 0);
                 }
             }
-            return null;
+            return popped;
         }
 
         /**
-         * Steals and runs a task in the same CC computation as the
-         * given task if one exists and can be taken without
-         * contention. Otherwise returns a checksum/control value for
-         * use by method helpComplete.
-         *
-         * @return 1 if successful, 2 if retryable (lost to another
-         * stealer), -1 if non-empty but no matching task found, else
-         * the base index, forced negative.
+         * Shared version of localHelpCC.
          */
-        final int pollAndExecCC(CountedCompleter<?> task) {
-            ForkJoinTask<?>[] a;
-            int b = base, s = top, al, h;
-            if ((a = array) != null && b != s && (al = a.length) > 0) {
-                int index = (al - 1) & b;
-                long offset = ((long)index << ASHIFT) + ABASE;
-                ForkJoinTask<?> o = (ForkJoinTask<?>)
-                    U.getObjectVolatile(a, offset);
-                if (o == null)
-                    h = 2;                      // retryable
-                else if (!(o instanceof CountedCompleter))
-                    h = -1;                     // unmatchable
-                else {
-                    CountedCompleter<?> t = (CountedCompleter<?>)o;
-                    for (CountedCompleter<?> r = t;;) {
-                        if (r == task) {
-                            if (b++ == base &&
-                                U.compareAndSwapObject(a, offset, t, null)) {
-                                base = b;
-                                t.doExec();
-                                h = 1;          // success
+        final int sharedHelpCC(CountedCompleter<?> task, int limit) {
+            int status = 0;
+            if (task != null && (status = task.status) >= 0) {
+                for (;;) {
+                    boolean help = false;
+                    int b = base, s = top, al; ForkJoinTask<?>[] a;
+                    if ((a = array) != null && b != s && (al = a.length) > 0) {
+                        int index = (al - 1) & (s - 1);
+                        ForkJoinTask<?> o = (ForkJoinTask<?>)
+                            QA.get(a, index);
+                        if (o instanceof CountedCompleter) {
+                            CountedCompleter<?> t = (CountedCompleter<?>)o;
+                            for (CountedCompleter<?> f = t;;) {
+                                if (f != task) {
+                                    if ((f = f.completer) == null)
+                                        break;
+                                }
+                                else {
+                                    if (PHASE.compareAndSet(this, 0, QLOCK)) {
+                                        if (top == s && array == a &&
+                                            QA.compareAndSet(a, index, t, null)) {
+                                            help = true;
+                                            top = s - 1;
+                                        }
+                                        PHASE.setRelease(this, 0);
+                                        if (help)
+                                            t.doExec();
+                                    }
+                                    break;
+                                }
                             }
-                            else
-                                h = 2;          // lost CAS
-                            break;
-                        }
-                        else if ((r = r.completer) == null) {
-                            h = -1;             // unmatched
-                            break;
                         }
                     }
+                    if ((status = task.status) < 0 || !help ||
+                        (limit != 0 && --limit == 0))
+                        break;
                 }
             }
-            else
-                h = b | Integer.MIN_VALUE;      // to sense movement on re-poll
-            return h;
+            return status;
         }
 
         /**
@@ -1334,27 +1123,18 @@
          */
         final boolean isApparentlyUnblocked() {
             Thread wt; Thread.State s;
-            return (scanState >= 0 &&
-                    (wt = owner) != null &&
+            return ((wt = owner) != null &&
                     (s = wt.getState()) != Thread.State.BLOCKED &&
                     s != Thread.State.WAITING &&
                     s != Thread.State.TIMED_WAITING);
         }
 
-        // Unsafe mechanics. Note that some are (and must be) the same as in FJP
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long QLOCK;
-        private static final int ABASE;
-        private static final int ASHIFT;
+        // VarHandle mechanics.
+        private static final VarHandle PHASE;
         static {
             try {
-                QLOCK = U.objectFieldOffset
-                    (WorkQueue.class.getDeclaredField("qlock"));
-                ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
-                int scale = U.arrayIndexScale(ForkJoinTask[].class);
-                if ((scale & (scale - 1)) != 0)
-                    throw new Error("array index scale not a power of two");
-                ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                PHASE = l.findVarHandle(WorkQueue.class, "phase", int.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -1372,7 +1152,7 @@
 
     /**
      * Permission required for callers of methods that may start or
-     * kill threads.  Also used as a static lock in tryInitialize.
+     * kill threads.
      */
     static final RuntimePermission modifyThreadPermission;
 
@@ -1413,18 +1193,15 @@
     // static configuration constants
 
     /**
-     * Initial timeout value (in milliseconds) for the thread
-     * triggering quiescence to park waiting for new work. On timeout,
-     * the thread will instead try to shrink the number of workers.
-     * The value should be large enough to avoid overly aggressive
-     * shrinkage during most transient stalls (long GCs etc).
+     * Default idle timeout value (in milliseconds) for the thread
+     * triggering quiescence to park waiting for new work
      */
-    private static final long IDLE_TIMEOUT_MS = 2000L; // 2sec
+    private static final long DEFAULT_KEEPALIVE = 60000L;
 
     /**
-     * Tolerance for idle timeouts, to cope with timer undershoots.
+     * Undershoot tolerance for idle timeouts
      */
-    private static final long TIMEOUT_SLOP_MS =   20L; // 20ms
+    private static final long TIMEOUT_SLOP = 20L;
 
     /**
      * The default value for COMMON_MAX_SPARES.  Overridable using the
@@ -1444,7 +1221,7 @@
 
     /*
      * Bits and masks for field ctl, packed with 4 16 bit subfields:
-     * AC: Number of active running workers minus target parallelism
+     * RC: Number of released (unqueued) workers minus target parallelism
      * TC: Number of total workers minus target parallelism
      * SS: version count and status of top waiting thread
      * ID: poolIndex of top of Treiber stack of waiters
@@ -1453,26 +1230,30 @@
      * (including version bits) as sp=(int)ctl.  The offsets of counts
      * by the target parallelism and the positionings of fields makes
      * it possible to perform the most common checks via sign tests of
-     * fields: When ac is negative, there are not enough active
+     * fields: When ac is negative, there are not enough unqueued
      * workers, when tc is negative, there are not enough total
      * workers.  When sp is non-zero, there are waiting workers.  To
      * deal with possibly negative fields, we use casts in and out of
      * "short" and/or signed shifts to maintain signedness.
      *
-     * Because it occupies uppermost bits, we can add one active count
-     * using getAndAddLong of AC_UNIT, rather than CAS, when returning
+     * Because it occupies uppermost bits, we can add one release count
+     * using getAndAddLong of RC_UNIT, rather than CAS, when returning
      * from a blocked join.  Other updates entail multiple subfields
      * and masking, requiring CAS.
+     *
+     * The limits packed in field "bounds" are also offset by the
+     * parallelism level to make them comparable to the ctl rc and tc
+     * fields.
      */
 
     // Lower and upper word masks
     private static final long SP_MASK    = 0xffffffffL;
     private static final long UC_MASK    = ~SP_MASK;
 
-    // Active counts
-    private static final int  AC_SHIFT   = 48;
-    private static final long AC_UNIT    = 0x0001L << AC_SHIFT;
-    private static final long AC_MASK    = 0xffffL << AC_SHIFT;
+    // Release counts
+    private static final int  RC_SHIFT   = 48;
+    private static final long RC_UNIT    = 0x0001L << RC_SHIFT;
+    private static final long RC_MASK    = 0xffffL << RC_SHIFT;
 
     // Total counts
     private static final int  TC_SHIFT   = 32;
@@ -1480,52 +1261,21 @@
     private static final long TC_MASK    = 0xffffL << TC_SHIFT;
     private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign
 
-    // runState bits: SHUTDOWN must be negative, others arbitrary powers of two
-    private static final int  STARTED    = 1;
-    private static final int  STOP       = 1 << 1;
-    private static final int  TERMINATED = 1 << 2;
-    private static final int  SHUTDOWN   = 1 << 31;
+    // Instance fields
 
-    // Instance fields
-    volatile long ctl;                   // main pool control
-    volatile int runState;
-    final int config;                    // parallelism, mode
-    AuxState auxState;                   // lock, steal counts
-    volatile WorkQueue[] workQueues;     // main registry
-    final String workerNamePrefix;       // to create worker name string
+    volatile long stealCount;            // collects worker nsteals
+    final long keepAlive;                // milliseconds before dropping if idle
+    int indexSeed;                       // next worker index
+    final int bounds;                    // min, max threads packed as shorts
+    volatile int mode;                   // parallelism, runstate, queue mode
+    WorkQueue[] workQueues;              // main registry
+    final String workerNamePrefix;       // for worker thread string; sync lock
     final ForkJoinWorkerThreadFactory factory;
     final UncaughtExceptionHandler ueh;  // per-worker UEH
+    final Predicate<? super ForkJoinPool> saturate;
 
-    /**
-     * Instantiates fields upon first submission, or upon shutdown if
-     * no submissions. If checkTermination true, also responds to
-     * termination by external calls submitting tasks.
-     */
-    private void tryInitialize(boolean checkTermination) {
-        if (runState == 0) { // bootstrap by locking static field
-            int p = config & SMASK;
-            int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots
-            n |= n >>> 1;    // create workQueues array with size a power of two
-            n |= n >>> 2;
-            n |= n >>> 4;
-            n |= n >>> 8;
-            n |= n >>> 16;
-            n = ((n + 1) << 1) & SMASK;
-            AuxState aux = new AuxState();
-            WorkQueue[] ws = new WorkQueue[n];
-            synchronized (modifyThreadPermission) { // double-check
-                if (runState == 0) {
-                    workQueues = ws;
-                    auxState = aux;
-                    runState = STARTED;
-                }
-            }
-        }
-        if (checkTermination && runState < 0) {
-            tryTerminate(false, false); // help terminate
-            throw new RejectedExecutionException();
-        }
-    }
+    @jdk.internal.vm.annotation.Contended("fjpctl") // segregate
+    volatile long ctl;                   // main pool control
 
     // Creating, registering and deregistering workers
 
@@ -1534,18 +1284,14 @@
      * count has already been incremented as a reservation.  Invokes
      * deregisterWorker on any failure.
      *
-     * @param isSpare true if this is a spare thread
      * @return true if successful
      */
-    private boolean createWorker(boolean isSpare) {
+    private boolean createWorker() {
         ForkJoinWorkerThreadFactory fac = factory;
         Throwable ex = null;
         ForkJoinWorkerThread wt = null;
-        WorkQueue q;
         try {
             if (fac != null && (wt = fac.newThread(this)) != null) {
-                if (isSpare && (q = wt.workQueue) != null)
-                    q.config |= SPARE_WORKER;
                 wt.start();
                 return true;
             }
@@ -1566,10 +1312,10 @@
      */
     private void tryAddWorker(long c) {
         do {
-            long nc = ((AC_MASK & (c + AC_UNIT)) |
+            long nc = ((RC_MASK & (c + RC_UNIT)) |
                        (TC_MASK & (c + TC_UNIT)));
-            if (ctl == c && U.compareAndSwapLong(this, CTL, c, nc)) {
-                createWorker(false);
+            if (ctl == c && CTL.compareAndSet(this, c, nc)) {
+                createWorker();
                 break;
             }
         } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0);
@@ -1584,41 +1330,57 @@
      */
     final WorkQueue registerWorker(ForkJoinWorkerThread wt) {
         UncaughtExceptionHandler handler;
-        AuxState aux;
-        wt.setDaemon(true);                           // configure thread
+        wt.setDaemon(true);                             // configure thread
         if ((handler = ueh) != null)
             wt.setUncaughtExceptionHandler(handler);
         WorkQueue w = new WorkQueue(this, wt);
-        int i = 0;                                    // assign a pool index
-        int mode = config & MODE_MASK;
-        if ((aux = auxState) != null) {
-            aux.lock();
-            try {
-                int s = (int)(aux.indexSeed += SEED_INCREMENT), n, m;
-                WorkQueue[] ws = workQueues;
-                if (ws != null && (n = ws.length) > 0) {
-                    i = (m = n - 1) & ((s << 1) | 1); // odd-numbered indices
-                    if (ws[i] != null) {              // collision
-                        int probes = 0;               // step by approx half n
-                        int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2;
-                        while (ws[i = (i + step) & m] != null) {
-                            if (++probes >= n) {
-                                workQueues = ws = Arrays.copyOf(ws, n <<= 1);
-                                m = n - 1;
-                                probes = 0;
-                            }
+        int tid = 0;                                    // for thread name
+        int fifo = mode & FIFO;
+        String prefix = workerNamePrefix;
+        if (prefix != null) {
+            synchronized (prefix) {
+                WorkQueue[] ws = workQueues; int n;
+                int s = indexSeed += SEED_INCREMENT;
+                if (ws != null && (n = ws.length) > 1) {
+                    int m = n - 1;
+                    tid = s & m;
+                    int i = m & ((s << 1) | 1);         // odd-numbered indices
+                    for (int probes = n >>> 1;;) {      // find empty slot
+                        WorkQueue q;
+                        if ((q = ws[i]) == null || q.phase == QUIET)
+                            break;
+                        else if (--probes == 0) {
+                            i = n | 1;                  // resize below
+                            break;
                         }
+                        else
+                            i = (i + 2) & m;
                     }
-                    w.hint = s;                       // use as random seed
-                    w.config = i | mode;
-                    w.scanState = i | (s & 0x7fff0000); // random seq bits
-                    ws[i] = w;
+
+                    int id = i | fifo | (s & ~(SMASK | FIFO | DORMANT));
+                    w.phase = w.id = id;                // now publishable
+
+                    if (i < n)
+                        ws[i] = w;
+                    else {                              // expand array
+                        int an = n << 1;
+                        WorkQueue[] as = new WorkQueue[an];
+                        as[i] = w;
+                        int am = an - 1;
+                        for (int j = 0; j < n; ++j) {
+                            WorkQueue v;                // copy external queue
+                            if ((v = ws[j]) != null)    // position may change
+                                as[v.id & am & SQMASK] = v;
+                            if (++j >= n)
+                                break;
+                            as[j] = ws[j];              // copy worker
+                        }
+                        workQueues = as;
+                    }
                 }
-            } finally {
-                aux.unlock();
             }
+            wt.setName(prefix.concat(Integer.toString(tid)));
         }
-        wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1)));
         return w;
     }
 
@@ -1633,64 +1395,48 @@
      */
     final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) {
         WorkQueue w = null;
+        int phase = 0;
         if (wt != null && (w = wt.workQueue) != null) {
-            AuxState aux; WorkQueue[] ws;          // remove index from array
-            int idx = w.config & SMASK;
-            int ns = w.nsteals;
-            if ((aux = auxState) != null) {
-                aux.lock();
-                try {
+            Object lock = workerNamePrefix;
+            long ns = (long)w.nsteals & 0xffffffffL;
+            int idx = w.id & SMASK;
+            if (lock != null) {
+                WorkQueue[] ws;                       // remove index from array
+                synchronized (lock) {
                     if ((ws = workQueues) != null && ws.length > idx &&
                         ws[idx] == w)
                         ws[idx] = null;
-                    aux.stealCount += ns;
-                } finally {
-                    aux.unlock();
+                    stealCount += ns;
                 }
             }
-        }
-        if (w == null || (w.config & UNREGISTERED) == 0) { // else pre-adjusted
-            long c;                                   // decrement counts
-            do {} while (!U.compareAndSwapLong
-                         (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) |
-                                               (TC_MASK & (c - TC_UNIT)) |
-                                               (SP_MASK & c))));
-        }
-        if (w != null) {
-            w.currentSteal = null;
-            w.qlock = -1;                             // ensure set
-            w.cancelAll();                            // cancel remaining tasks
+            phase = w.phase;
         }
-        while (tryTerminate(false, false) >= 0) {     // possibly replace
-            WorkQueue[] ws; int wl, sp; long c;
-            if (w == null || w.array == null ||
-                (ws = workQueues) == null || (wl = ws.length) <= 0)
-                break;
-            else if ((sp = (int)(c = ctl)) != 0) {    // wake up replacement
-                if (tryRelease(c, ws[(wl - 1) & sp], AC_UNIT))
-                    break;
-            }
-            else if (ex != null && (c & ADD_WORKER) != 0L) {
-                tryAddWorker(c);                      // create replacement
-                break;
-            }
-            else                                      // don't need replacement
-                break;
+        if (phase != QUIET) {                         // else pre-adjusted
+            long c;                                   // decrement counts
+            do {} while (!CTL.weakCompareAndSetVolatile
+                         (this, c = ctl, ((RC_MASK & (c - RC_UNIT)) |
+                                          (TC_MASK & (c - TC_UNIT)) |
+                                          (SP_MASK & c))));
         }
+        if (w != null)
+            w.cancelAll();                            // cancel remaining tasks
+
+        if (!tryTerminate(false, false) &&            // possibly replace worker
+            w != null && w.array != null)             // avoid repeated failures
+            signalWork();
+
         if (ex == null)                               // help clean on way out
             ForkJoinTask.helpExpungeStaleExceptions();
         else                                          // rethrow
             ForkJoinTask.rethrow(ex);
     }
 
-    // Signalling
-
     /**
-     * Tries to create or activate a worker if too few are active.
+     * Tries to create or release a worker if too few are running.
      */
     final void signalWork() {
         for (;;) {
-            long c; int sp, i; WorkQueue v; WorkQueue[] ws;
+            long c; int sp; WorkQueue[] ws; int i; WorkQueue v;
             if ((c = ctl) >= 0L)                      // enough workers
                 break;
             else if ((sp = (int)c) == 0) {            // no idle workers
@@ -1705,12 +1451,14 @@
             else if ((v = ws[i]) == null)
                 break;                                // terminating
             else {
-                int ns = sp & ~UNSIGNALLED;
-                int vs = v.scanState;
-                long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
-                if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
-                    v.scanState = ns;
-                    LockSupport.unpark(v.parker);
+                int np = sp & ~UNSIGNALLED;
+                int vp = v.phase;
+                long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + RC_UNIT));
+                Thread vt = v.owner;
+                if (sp == vp && CTL.compareAndSet(this, c, nc)) {
+                    v.phase = np;
+                    if (v.source < 0)
+                        LockSupport.unpark(vt);
                     break;
                 }
             }
@@ -1718,442 +1466,183 @@
     }
 
     /**
-     * Signals and releases worker v if it is top of idle worker
-     * stack.  This performs a one-shot version of signalWork only if
-     * there is (apparently) at least one idle worker.
+     * Tries to decrement counts (sometimes implicitly) and possibly
+     * arrange for a compensating worker in preparation for blocking:
+     * If not all core workers yet exist, creates one, else if any are
+     * unreleased (possibly including caller) releases one, else if
+     * fewer than the minimum allowed number of workers running,
+     * checks to see that they are all active, and if so creates an
+     * extra worker unless over maximum limit and policy is to
+     * saturate.  Most of these steps can fail due to interference, in
+     * which case 0 is returned so caller will retry. A negative
+     * return value indicates that the caller doesn't need to
+     * re-adjust counts when later unblocked.
      *
-     * @param c incoming ctl value
-     * @param v if non-null, a worker
-     * @param inc the increment to active count (zero when compensating)
-     * @return true if successful
-     */
-    private boolean tryRelease(long c, WorkQueue v, long inc) {
-        int sp = (int)c, ns = sp & ~UNSIGNALLED;
-        if (v != null) {
-            int vs = v.scanState;
-            long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + inc));
-            if (sp == vs && U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = ns;
-                LockSupport.unpark(v.parker);
-                return true;
-            }
-        }
-        return false;
-    }
-
-    /**
-     * With approx probability of a missed signal, tries (once) to
-     * reactivate worker w (or some other worker), failing if stale or
-     * known to be already active.
-     *
-     * @param w the worker
-     * @param ws the workQueue array to use
-     * @param r random seed
-     */
-    private void tryReactivate(WorkQueue w, WorkQueue[] ws, int r) {
-        long c; int sp, wl; WorkQueue v;
-        if ((sp = (int)(c = ctl)) != 0 && w != null &&
-            ws != null && (wl = ws.length) > 0 &&
-            ((sp ^ r) & SS_SEQ) == 0 &&
-            (v = ws[(wl - 1) & sp]) != null) {
-            long nc = (v.stackPred & SP_MASK) | (UC_MASK & (c + AC_UNIT));
-            int ns = sp & ~UNSIGNALLED;
-            if (w.scanState < 0 &&
-                v.scanState == sp &&
-                U.compareAndSwapLong(this, CTL, c, nc)) {
-                v.scanState = ns;
-                LockSupport.unpark(v.parker);
-            }
-        }
-    }
-
-    /**
-     * If worker w exists and is active, enqueues and sets status to inactive.
-     *
-     * @param w the worker
-     * @param ss current (non-negative) scanState
+     * @return 1: block then adjust, -1: block without adjust, 0 : retry
      */
-    private void inactivate(WorkQueue w, int ss) {
-        int ns = (ss + SS_SEQ) | UNSIGNALLED;
-        long lc = ns & SP_MASK, nc, c;
-        if (w != null) {
-            w.scanState = ns;
-            do {
-                nc = lc | (UC_MASK & ((c = ctl) - AC_UNIT));
-                w.stackPred = (int)c;
-            } while (!U.compareAndSwapLong(this, CTL, c, nc));
-        }
-    }
-
-    /**
-     * Possibly blocks worker w waiting for signal, or returns
-     * negative status if the worker should terminate. May return
-     * without status change if multiple stale unparks and/or
-     * interrupts occur.
-     *
-     * @param w the calling worker
-     * @return negative if w should terminate
-     */
-    private int awaitWork(WorkQueue w) {
-        int stat = 0;
-        if (w != null && w.scanState < 0) {
-            long c = ctl;
-            if ((int)(c >> AC_SHIFT) + (config & SMASK) <= 0)
-                stat = timedAwaitWork(w, c);     // possibly quiescent
-            else if ((runState & STOP) != 0)
-                stat = w.qlock = -1;             // pool terminating
-            else if (w.scanState < 0) {
-                w.parker = Thread.currentThread();
-                if (w.scanState < 0)             // recheck after write
-                    LockSupport.park(this);
-                w.parker = null;
-                if ((runState & STOP) != 0)
-                    stat = w.qlock = -1;         // recheck
-                else if (w.scanState < 0)
-                    Thread.interrupted();        // clear status
+    private int tryCompensate(WorkQueue w) {
+        int t, n, sp;
+        long c = ctl;
+        WorkQueue[] ws = workQueues;
+        if ((t = (short)(c >>> TC_SHIFT)) >= 0) {
+            if (ws == null || (n = ws.length) <= 0 || w == null)
+                return 0;                        // disabled
+            else if ((sp = (int)c) != 0) {       // replace or release
+                WorkQueue v = ws[sp & (n - 1)];
+                int wp = w.phase;
+                long uc = UC_MASK & ((wp < 0) ? c + RC_UNIT : c);
+                int np = sp & ~UNSIGNALLED;
+                if (v != null) {
+                    int vp = v.phase;
+                    Thread vt = v.owner;
+                    long nc = ((long)v.stackPred & SP_MASK) | uc;
+                    if (vp == sp && CTL.compareAndSet(this, c, nc)) {
+                        v.phase = np;
+                        if (v.source < 0)
+                            LockSupport.unpark(vt);
+                        return (wp < 0) ? -1 : 1;
+                    }
+                }
+                return 0;
+            }
+            else if ((int)(c >> RC_SHIFT) -      // reduce parallelism
+                     (short)(bounds & SMASK) > 0) {
+                long nc = ((RC_MASK & (c - RC_UNIT)) | (~RC_MASK & c));
+                return CTL.compareAndSet(this, c, nc) ? 1 : 0;
             }
-        }
-        return stat;
-    }
-
-    /**
-     * Possibly triggers shutdown and tries (once) to block worker
-     * when pool is (or may be) quiescent. Waits up to a duration
-     * determined by number of workers.  On timeout, if ctl has not
-     * changed, terminates the worker, which will in turn wake up
-     * another worker to possibly repeat this process.
-     *
-     * @param w the calling worker
-     * @return negative if w should terminate
-     */
-    private int timedAwaitWork(WorkQueue w, long c) {
-        int stat = 0;
-        int scale = 1 - (short)(c >>> TC_SHIFT);
-        long deadline = (((scale <= 0) ? 1 : scale) * IDLE_TIMEOUT_MS +
-                         System.currentTimeMillis());
-        if ((runState >= 0 || (stat = tryTerminate(false, false)) > 0) &&
-            w != null && w.scanState < 0) {
-            int ss; AuxState aux;
-            w.parker = Thread.currentThread();
-            if (w.scanState < 0)
-                LockSupport.parkUntil(this, deadline);
-            w.parker = null;
-            if ((runState & STOP) != 0)
-                stat = w.qlock = -1;         // pool terminating
-            else if ((ss = w.scanState) < 0 && !Thread.interrupted() &&
-                     (int)c == ss && (aux = auxState) != null && ctl == c &&
-                     deadline - System.currentTimeMillis() <= TIMEOUT_SLOP_MS) {
-                aux.lock();
-                try {                        // pre-deregister
-                    WorkQueue[] ws;
-                    int cfg = w.config, idx = cfg & SMASK;
-                    long nc = ((UC_MASK & (c - TC_UNIT)) |
-                               (SP_MASK & w.stackPred));
-                    if ((runState & STOP) == 0 &&
-                        (ws = workQueues) != null &&
-                        idx < ws.length && idx >= 0 && ws[idx] == w &&
-                        U.compareAndSwapLong(this, CTL, c, nc)) {
-                        ws[idx] = null;
-                        w.config = cfg | UNREGISTERED;
-                        stat = w.qlock = -1;
+            else {                               // validate
+                int md = mode, pc = md & SMASK, tc = pc + t, bc = 0;
+                boolean unstable = false;
+                for (int i = 1; i < n; i += 2) {
+                    WorkQueue q; Thread wt; Thread.State ts;
+                    if ((q = ws[i]) != null) {
+                        if (q.source == 0) {
+                            unstable = true;
+                            break;
+                        }
+                        else {
+                            --tc;
+                            if ((wt = q.owner) != null &&
+                                ((ts = wt.getState()) == Thread.State.BLOCKED ||
+                                 ts == Thread.State.WAITING))
+                                ++bc;            // worker is blocking
+                        }
                     }
-                } finally {
-                    aux.unlock();
+                }
+                if (unstable || tc != 0 || ctl != c)
+                    return 0;                    // inconsistent
+                else if (t + pc >= MAX_CAP || t >= (bounds >>> SWIDTH)) {
+                    Predicate<? super ForkJoinPool> sat;
+                    if ((sat = saturate) != null && sat.test(this))
+                        return -1;
+                    else if (bc < pc) {          // lagging
+                        Thread.yield();          // for retry spins
+                        return 0;
+                    }
+                    else
+                        throw new RejectedExecutionException(
+                            "Thread limit exceeded replacing blocked worker");
                 }
             }
         }
-        return stat;
-    }
 
-    /**
-     * If the given worker is a spare with no queued tasks, and there
-     * are enough existing workers, drops it from ctl counts and sets
-     * its state to terminated.
-     *
-     * @param w the calling worker -- must be a spare
-     * @return true if dropped (in which case it must not process more tasks)
-     */
-    private boolean tryDropSpare(WorkQueue w) {
-        if (w != null && w.isEmpty()) {           // no local tasks
-            long c; int sp, wl; WorkQueue[] ws; WorkQueue v;
-            while ((short)((c = ctl) >> TC_SHIFT) > 0 &&
-                   ((sp = (int)c) != 0 || (int)(c >> AC_SHIFT) > 0) &&
-                   (ws = workQueues) != null && (wl = ws.length) > 0) {
-                boolean dropped, canDrop;
-                if (sp == 0) {                    // no queued workers
-                    long nc = ((AC_MASK & (c - AC_UNIT)) |
-                               (TC_MASK & (c - TC_UNIT)) | (SP_MASK & c));
-                    dropped = U.compareAndSwapLong(this, CTL, c, nc);
-                }
-                else if (
-                    (v = ws[(wl - 1) & sp]) == null || v.scanState != sp)
-                    dropped = false;              // stale; retry
-                else {
-                    long nc = v.stackPred & SP_MASK;
-                    if (w == v || w.scanState >= 0) {
-                        canDrop = true;           // w unqueued or topmost
-                        nc |= ((AC_MASK & c) |    // ensure replacement
-                               (TC_MASK & (c - TC_UNIT)));
-                    }
-                    else {                        // w may be queued
-                        canDrop = false;          // help uncover
-                        nc |= ((AC_MASK & (c + AC_UNIT)) |
-                               (TC_MASK & c));
-                    }
-                    if (U.compareAndSwapLong(this, CTL, c, nc)) {
-                        v.scanState = sp & ~UNSIGNALLED;
-                        LockSupport.unpark(v.parker);
-                        dropped = canDrop;
-                    }
-                    else
-                        dropped = false;
-                }
-                if (dropped) {                    // pre-deregister
-                    int cfg = w.config, idx = cfg & SMASK;
-                    if (idx >= 0 && idx < ws.length && ws[idx] == w)
-                        ws[idx] = null;
-                    w.config = cfg | UNREGISTERED;
-                    w.qlock = -1;
-                    return true;
-                }
-            }
-        }
-        return false;
+        long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK); // expand pool
+        return CTL.compareAndSet(this, c, nc) && createWorker() ? 1 : 0;
     }
 
     /**
      * Top-level runloop for workers, called by ForkJoinWorkerThread.run.
+     * See above for explanation.
      */
     final void runWorker(WorkQueue w) {
+        WorkQueue[] ws;
         w.growArray();                                  // allocate queue
-        int bound = (w.config & SPARE_WORKER) != 0 ? 0 : POLL_LIMIT;
-        long seed = w.hint * 0xdaba0b6eb09322e3L;       // initial random seed
-        if ((runState & STOP) == 0) {
-            for (long r = (seed == 0L) ? 1L : seed;;) { // ensure nonzero
-                if (bound == 0 && tryDropSpare(w))
-                    break;
-                // high bits of prev seed for step; current low bits for idx
-                int step = (int)(r >>> 48) | 1;
-                r ^= r >>> 12; r ^= r << 25; r ^= r >>> 27; // xorshift
-                if (scan(w, bound, step, (int)r) < 0 && awaitWork(w) < 0)
-                    break;
-            }
-        }
-    }
-
-    // Scanning for tasks
-
-    /**
-     * Repeatedly scans for and tries to steal and execute (via
-     * workQueue.runTask) a queued task. Each scan traverses queues in
-     * pseudorandom permutation. Upon finding a non-empty queue, makes
-     * at most the given bound attempts to re-poll (fewer if
-     * contended) on the same queue before returning (impossible
-     * scanState value) 0 to restart scan. Else returns after at least
-     * 1 and at most 32 full scans.
-     *
-     * @param w the worker (via its WorkQueue)
-     * @param bound repoll bound as bitmask (0 if spare)
-     * @param step (circular) index increment per iteration (must be odd)
-     * @param r a random seed for origin index
-     * @return negative if should await signal
-     */
-    private int scan(WorkQueue w, int bound, int step, int r) {
-        int stat = 0, wl; WorkQueue[] ws;
-        if ((ws = workQueues) != null && w != null && (wl = ws.length) > 0) {
-            for (int m = wl - 1,
-                     origin = m & r, idx = origin,
-                     npolls = 0,
-                     ss = w.scanState;;) {         // negative if inactive
-                WorkQueue q; ForkJoinTask<?>[] a; int b, al;
-                if ((q = ws[idx]) != null && (b = q.base) - q.top < 0 &&
+        int r = w.id ^ ThreadLocalRandom.nextSecondarySeed();
+        if (r == 0)                                     // initial nonzero seed
+            r = 1;
+        int lastSignalId = 0;                           // avoid unneeded signals
+        while ((ws = workQueues) != null) {
+            boolean nonempty = false;                   // scan
+            for (int n = ws.length, j = n, m = n - 1; j > 0; --j) {
+                WorkQueue q; int i, b, al; ForkJoinTask<?>[] a;
+                if ((i = r & m) >= 0 && i < n &&        // always true
+                    (q = ws[i]) != null && (b = q.base) - q.top < 0 &&
                     (a = q.array) != null && (al = a.length) > 0) {
+                    int qid = q.id;                     // (never zero)
                     int index = (al - 1) & b;
-                    long offset = ((long)index << ASHIFT) + ABASE;
                     ForkJoinTask<?> t = (ForkJoinTask<?>)
-                        U.getObjectVolatile(a, offset);
-                    if (t == null)
-                        break;                     // empty or busy
-                    else if (b++ != q.base)
-                        break;                     // busy
-                    else if (ss < 0) {
-                        tryReactivate(w, ws, r);
-                        break;                     // retry upon rescan
-                    }
-                    else if (!U.compareAndSwapObject(a, offset, t, null))
-                        break;                     // contended
-                    else {
-                        q.base = b;
-                        w.currentSteal = t;
-                        if (b != q.top)            // propagate signal
-                            signalWork();
-                        w.runTask(t);
-                        if (++npolls > bound)
-                            break;
+                        QA.getAcquire(a, index);
+                    if (t != null && b++ == q.base &&
+                        QA.compareAndSet(a, index, t, null)) {
+                        if ((q.base = b) - q.top < 0 && qid != lastSignalId)
+                            signalWork();               // propagate signal
+                        w.source = lastSignalId = qid;
+                        t.doExec();
+                        if ((w.id & FIFO) != 0)         // run remaining locals
+                            w.localPollAndExec(POLL_LIMIT);
+                        else
+                            w.localPopAndExec(POLL_LIMIT);
+                        ForkJoinWorkerThread thread = w.owner;
+                        ++w.nsteals;
+                        w.source = 0;                   // now idle
+                        if (thread != null)
+                            thread.afterTopLevelExec();
                     }
+                    nonempty = true;
                 }
-                else if (npolls != 0)              // rescan
+                else if (nonempty)
                     break;
-                else if ((idx = (idx + step) & m) == origin) {
-                    if (ss < 0) {                  // await signal
-                        stat = ss;
-                        break;
-                    }
-                    else if (r >= 0) {
-                        inactivate(w, ss);
-                        break;
-                    }
-                    else
-                        r <<= 1;                   // at most 31 rescans
-                }
+                else
+                    ++r;
             }
-        }
-        return stat;
-    }
-
-    // Joining tasks
 
-    /**
-     * Tries to steal and run tasks within the target's computation.
-     * Uses a variant of the top-level algorithm, restricted to tasks
-     * with the given task as ancestor: It prefers taking and running
-     * eligible tasks popped from the worker's own queue (via
-     * popCC). Otherwise it scans others, randomly moving on
-     * contention or execution, deciding to give up based on a
-     * checksum (via return codes from pollAndExecCC). The maxTasks
-     * argument supports external usages; internal calls use zero,
-     * allowing unbounded steps (external calls trap non-positive
-     * values).
-     *
-     * @param w caller
-     * @param maxTasks if non-zero, the maximum number of other tasks to run
-     * @return task status on exit
-     */
-    final int helpComplete(WorkQueue w, CountedCompleter<?> task,
-                           int maxTasks) {
-        WorkQueue[] ws; int s = 0, wl;
-        if ((ws = workQueues) != null && (wl = ws.length) > 1 &&
-            task != null && w != null) {
-            for (int m = wl - 1,
-                     mode = w.config,
-                     r = ~mode,                  // scanning seed
-                     origin = r & m, k = origin, // first queue to scan
-                     step = 3,                   // first scan step
-                     h = 1,                      // 1:ran, >1:contended, <0:hash
-                     oldSum = 0, checkSum = 0;;) {
-                CountedCompleter<?> p; WorkQueue q; int i;
-                if ((s = task.status) < 0)
-                    break;
-                if (h == 1 && (p = w.popCC(task, mode)) != null) {
-                    p.doExec();                  // run local task
-                    if (maxTasks != 0 && --maxTasks == 0)
-                        break;
-                    origin = k;                  // reset
-                    oldSum = checkSum = 0;
-                }
-                else {                           // poll other worker queues
-                    if ((i = k | 1) < 0 || i > m || (q = ws[i]) == null)
-                        h = 0;
-                    else if ((h = q.pollAndExecCC(task)) < 0)
-                        checkSum += h;
-                    if (h > 0) {
-                        if (h == 1 && maxTasks != 0 && --maxTasks == 0)
-                            break;
-                        step = (r >>> 16) | 3;
-                        r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift
-                        k = origin = r & m;      // move and restart
-                        oldSum = checkSum = 0;
-                    }
-                    else if ((k = (k + step) & m) == origin) {
-                        if (oldSum == (oldSum = checkSum))
-                            break;
-                        checkSum = 0;
-                    }
-                }
+            if (nonempty) {                             // move (xorshift)
+                r ^= r << 13; r ^= r >>> 17; r ^= r << 5;
             }
-        }
-        return s;
-    }
-
-    /**
-     * Tries to locate and execute tasks for a stealer of the given
-     * task, or in turn one of its stealers. Traces currentSteal ->
-     * currentJoin links looking for a thread working on a descendant
-     * of the given task and with a non-empty queue to steal back and
-     * execute tasks from. The first call to this method upon a
-     * waiting join will often entail scanning/search, (which is OK
-     * because the joiner has nothing better to do), but this method
-     * leaves hints in workers to speed up subsequent calls.
-     *
-     * @param w caller
-     * @param task the task to join
-     */
-    private void helpStealer(WorkQueue w, ForkJoinTask<?> task) {
-        if (task != null && w != null) {
-            ForkJoinTask<?> ps = w.currentSteal;
-            WorkQueue[] ws; int wl, oldSum = 0;
-            outer: while (w.tryRemoveAndExec(task) && task.status >= 0 &&
-                          (ws = workQueues) != null && (wl = ws.length) > 0) {
-                ForkJoinTask<?> subtask;
-                int m = wl - 1, checkSum = 0;          // for stability check
-                WorkQueue j = w, v;                    // v is subtask stealer
-                descent: for (subtask = task; subtask.status >= 0; ) {
-                    for (int h = j.hint | 1, k = 0, i;;) {
-                        if ((v = ws[i = (h + (k << 1)) & m]) != null) {
-                            if (v.currentSteal == subtask) {
-                                j.hint = i;
-                                break;
-                            }
-                            checkSum += v.base;
+            else {
+                int phase;
+                lastSignalId = 0;                       // clear for next scan
+                if ((phase = w.phase) >= 0) {           // enqueue
+                    int np = w.phase = (phase + SS_SEQ) | UNSIGNALLED;
+                    long c, nc;
+                    do {
+                        w.stackPred = (int)(c = ctl);
+                        nc = ((c - RC_UNIT) & UC_MASK) | (SP_MASK & np);
+                    } while (!CTL.weakCompareAndSetVolatile(this, c, nc));
+                }
+                else {                                  // already queued
+                    int pred = w.stackPred;
+                    w.source = DORMANT;                 // enable signal
+                    for (int steps = 0;;) {
+                        int md, rc; long c;
+                        if (w.phase >= 0) {
+                            w.source = 0;
+                            break;
                         }
-                        if (++k > m)                   // can't find stealer
-                            break outer;
-                    }
-
-                    for (;;) {                         // help v or descend
-                        ForkJoinTask<?>[] a; int b, al;
-                        if (subtask.status < 0)        // too late to help
-                            break descent;
-                        checkSum += (b = v.base);
-                        ForkJoinTask<?> next = v.currentJoin;
-                        ForkJoinTask<?> t = null;
-                        if ((a = v.array) != null && (al = a.length) > 0) {
-                            int index = (al - 1) & b;
-                            long offset = ((long)index << ASHIFT) + ABASE;
-                            t = (ForkJoinTask<?>)
-                                U.getObjectVolatile(a, offset);
-                            if (t != null && b++ == v.base) {
-                                if (j.currentJoin != subtask ||
-                                    v.currentSteal != subtask ||
-                                    subtask.status < 0)
-                                    break descent;     // stale
-                                if (U.compareAndSwapObject(a, offset, t, null)) {
-                                    v.base = b;
-                                    w.currentSteal = t;
-                                    for (int top = w.top;;) {
-                                        t.doExec();    // help
-                                        w.currentSteal = ps;
-                                        if (task.status < 0)
-                                            break outer;
-                                        if (w.top == top)
-                                            break;     // run local tasks
-                                        if ((t = w.pop()) == null)
-                                            break descent;
-                                        w.currentSteal = t;
-                                    }
+                        else if ((md = mode) < 0)       // shutting down
+                            return;
+                        else if ((rc = ((md & SMASK) +  // possibly quiescent
+                                        (int)((c = ctl) >> RC_SHIFT))) <= 0 &&
+                                 (md & SHUTDOWN) != 0 &&
+                                 tryTerminate(false, false))
+                            return;                     // help terminate
+                        else if ((++steps & 1) == 0)
+                            Thread.interrupted();       // clear between parks
+                        else if (rc <= 0 && pred != 0 && phase == (int)c) {
+                            long d = keepAlive + System.currentTimeMillis();
+                            LockSupport.parkUntil(this, d);
+                            if (ctl == c &&
+                                d - System.currentTimeMillis() <= TIMEOUT_SLOP) {
+                                long nc = ((UC_MASK & (c - TC_UNIT)) |
+                                           (SP_MASK & pred));
+                                if (CTL.compareAndSet(this, c, nc)) {
+                                    w.phase = QUIET;
+                                    return;             // drop on timeout
                                 }
                             }
                         }
-                        if (t == null && b == v.base && b - v.top >= 0) {
-                            if ((subtask = next) == null) {  // try to descend
-                                if (next == v.currentJoin &&
-                                    oldSum == (oldSum = checkSum))
-                                    break outer;
-                                break descent;
-                            }
-                            j = v;
-                            break;
-                        }
+                        else
+                            LockSupport.park(this);
                     }
                 }
             }
@@ -2161,59 +1650,10 @@
     }
 
     /**
-     * Tries to decrement active count (sometimes implicitly) and
-     * possibly release or create a compensating worker in preparation
-     * for blocking. Returns false (retryable by caller), on
-     * contention, detected staleness, instability, or termination.
-     *
-     * @param w caller
-     */
-    private boolean tryCompensate(WorkQueue w) {
-        boolean canBlock; int wl;
-        long c = ctl;
-        WorkQueue[] ws = workQueues;
-        int pc = config & SMASK;
-        int ac = pc + (int)(c >> AC_SHIFT);
-        int tc = pc + (short)(c >> TC_SHIFT);
-        if (w == null || w.qlock < 0 || pc == 0 ||  // terminating or disabled
-            ws == null || (wl = ws.length) <= 0)
-            canBlock = false;
-        else {
-            int m = wl - 1, sp;
-            boolean busy = true;                    // validate ac
-            for (int i = 0; i <= m; ++i) {
-                int k; WorkQueue v;
-                if ((k = (i << 1) | 1) <= m && k >= 0 && (v = ws[k]) != null &&
-                    v.scanState >= 0 && v.currentSteal == null) {
-                    busy = false;
-                    break;
-                }
-            }
-            if (!busy || ctl != c)
-                canBlock = false;                   // unstable or stale
-            else if ((sp = (int)c) != 0)            // release idle worker
-                canBlock = tryRelease(c, ws[m & sp], 0L);
-            else if (tc >= pc && ac > 1 && w.isEmpty()) {
-                long nc = ((AC_MASK & (c - AC_UNIT)) |
-                           (~AC_MASK & c));         // uncompensated
-                canBlock = U.compareAndSwapLong(this, CTL, c, nc);
-            }
-            else if (tc >= MAX_CAP ||
-                     (this == common && tc >= pc + COMMON_MAX_SPARES))
-                throw new RejectedExecutionException(
-                    "Thread limit exceeded replacing blocked worker");
-            else {                                  // similar to tryAddWorker
-                boolean isSpare = (tc >= pc);
-                long nc = (AC_MASK & c) | (TC_MASK & (c + TC_UNIT));
-                canBlock = (U.compareAndSwapLong(this, CTL, c, nc) &&
-                            createWorker(isSpare)); // throws on exception
-            }
-        }
-        return canBlock;
-    }
-
-    /**
      * Helps and/or blocks until the given task is done or timeout.
+     * First tries locally helping, then scans other queues for a task
+     * produced by one of w's stealers; compensating and blocking if
+     * none are found (rescanning if tryCompensate fails).
      *
      * @param w caller
      * @param task the task
@@ -2222,61 +1662,166 @@
      */
     final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
         int s = 0;
-        if (w != null) {
-            ForkJoinTask<?> prevJoin = w.currentJoin;
-            if (task != null && (s = task.status) >= 0) {
-                w.currentJoin = task;
-                CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
-                    (CountedCompleter<?>)task : null;
-                for (;;) {
-                    if (cc != null)
-                        helpComplete(w, cc, 0);
-                    else
-                        helpStealer(w, task);
-                    if ((s = task.status) < 0)
-                        break;
-                    long ms, ns;
+        if (w != null && task != null &&
+            (!(task instanceof CountedCompleter) ||
+             (s = w.localHelpCC((CountedCompleter<?>)task, 0)) >= 0)) {
+            w.tryRemoveAndExec(task);
+            int src = w.source, id = w.id;
+            s = task.status;
+            while (s >= 0) {
+                WorkQueue[] ws;
+                boolean nonempty = false;
+                int r = ThreadLocalRandom.nextSecondarySeed() | 1; // odd indices
+                if ((ws = workQueues) != null) {       // scan for matching id
+                    for (int n = ws.length, m = n - 1, j = -n; j < n; j += 2) {
+                        WorkQueue q; int i, b, al; ForkJoinTask<?>[] a;
+                        if ((i = (r + j) & m) >= 0 && i < n &&
+                            (q = ws[i]) != null && q.source == id &&
+                            (b = q.base) - q.top < 0 &&
+                            (a = q.array) != null && (al = a.length) > 0) {
+                            int qid = q.id;
+                            int index = (al - 1) & b;
+                            ForkJoinTask<?> t = (ForkJoinTask<?>)
+                                QA.getAcquire(a, index);
+                            if (t != null && b++ == q.base && id == q.source &&
+                                QA.compareAndSet(a, index, t, null)) {
+                                q.base = b;
+                                w.source = qid;
+                                t.doExec();
+                                w.source = src;
+                            }
+                            nonempty = true;
+                            break;
+                        }
+                    }
+                }
+                if ((s = task.status) < 0)
+                    break;
+                else if (!nonempty) {
+                    long ms, ns; int block;
                     if (deadline == 0L)
-                        ms = 0L;
+                        ms = 0L;                       // untimed
                     else if ((ns = deadline - System.nanoTime()) <= 0L)
-                        break;
+                        break;                         // timeout
                     else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
-                        ms = 1L;
-                    if (tryCompensate(w)) {
+                        ms = 1L;                       // avoid 0 for timed wait
+                    if ((block = tryCompensate(w)) != 0) {
                         task.internalWait(ms);
-                        U.getAndAddLong(this, CTL, AC_UNIT);
+                        CTL.getAndAdd(this, (block > 0) ? RC_UNIT : 0L);
                     }
-                    if ((s = task.status) < 0)
-                        break;
+                    s = task.status;
                 }
-                w.currentJoin = prevJoin;
             }
         }
         return s;
     }
 
-    // Specialized scanning
+    /**
+     * Runs tasks until {@code isQuiescent()}. Rather than blocking
+     * when tasks cannot be found, rescans until all others cannot
+     * find tasks either.
+     */
+    final void helpQuiescePool(WorkQueue w) {
+        int prevSrc = w.source, fifo = w.id & FIFO;
+        for (int source = prevSrc, released = -1;;) { // -1 until known
+            WorkQueue[] ws;
+            if (fifo != 0)
+                w.localPollAndExec(0);
+            else
+                w.localPopAndExec(0);
+            if (released == -1 && w.phase >= 0)
+                released = 1;
+            boolean quiet = true, empty = true;
+            int r = ThreadLocalRandom.nextSecondarySeed();
+            if ((ws = workQueues) != null) {
+                for (int n = ws.length, j = n, m = n - 1; j > 0; --j) {
+                    WorkQueue q; int i, b, al; ForkJoinTask<?>[] a;
+                    if ((i = (r - j) & m) >= 0 && i < n && (q = ws[i]) != null) {
+                        if ((b = q.base) - q.top < 0 &&
+                            (a = q.array) != null && (al = a.length) > 0) {
+                            int qid = q.id;
+                            if (released == 0) {    // increment
+                                released = 1;
+                                CTL.getAndAdd(this, RC_UNIT);
+                            }
+                            int index = (al - 1) & b;
+                            ForkJoinTask<?> t = (ForkJoinTask<?>)
+                                QA.getAcquire(a, index);
+                            if (t != null && b++ == q.base &&
+                                QA.compareAndSet(a, index, t, null)) {
+                                q.base = b;
+                                w.source = source = q.id;
+                                t.doExec();
+                                w.source = source = prevSrc;
+                            }
+                            quiet = empty = false;
+                            break;
+                        }
+                        else if ((q.source & QUIET) == 0)
+                            quiet = false;
+                    }
+                }
+            }
+            if (quiet) {
+                if (released == 0)
+                    CTL.getAndAdd(this, RC_UNIT);
+                w.source = prevSrc;
+                break;
+            }
+            else if (empty) {
+                if (source != QUIET)
+                    w.source = source = QUIET;
+                if (released == 1) {                 // decrement
+                    released = 0;
+                    CTL.getAndAdd(this, RC_MASK & -RC_UNIT);
+                }
+            }
+        }
+    }
 
     /**
-     * Returns a (probably) non-empty steal queue, if one is found
-     * during a scan, else null.  This method must be retried by
-     * caller if, by the time it tries to use the queue, it is empty.
+     * Scans for and returns a polled task, if available.
+     * Used only for untracked polls.
+     *
+     * @param submissionsOnly if true, only scan submission queues
      */
-    private WorkQueue findNonEmptyStealQueue() {
-        WorkQueue[] ws; int wl;  // one-shot version of scan loop
-        int r = ThreadLocalRandom.nextSecondarySeed();
-        if ((ws = workQueues) != null && (wl = ws.length) > 0) {
-            int m = wl - 1, origin = r & m;
+    private ForkJoinTask<?> pollScan(boolean submissionsOnly) {
+        WorkQueue[] ws; int n;
+        rescan: while ((mode & STOP) == 0 && (ws = workQueues) != null &&
+                      (n = ws.length) > 0) {
+            int m = n - 1;
+            int r = ThreadLocalRandom.nextSecondarySeed();
+            int h = r >>> 16;
+            int origin, step;
+            if (submissionsOnly) {
+                origin = (r & ~1) & m;         // even indices and steps
+                step = (h & ~1) | 2;
+            }
+            else {
+                origin = r & m;
+                step = h | 1;
+            }
             for (int k = origin, oldSum = 0, checkSum = 0;;) {
-                WorkQueue q; int b;
+                WorkQueue q; int b, al; ForkJoinTask<?>[] a;
                 if ((q = ws[k]) != null) {
-                    if ((b = q.base) - q.top < 0)
-                        return q;
-                    checkSum += b;
+                    checkSum += b = q.base;
+                    if (b - q.top < 0 &&
+                        (a = q.array) != null && (al = a.length) > 0) {
+                        int index = (al - 1) & b;
+                        ForkJoinTask<?> t = (ForkJoinTask<?>)
+                            QA.getAcquire(a, index);
+                        if (t != null && b++ == q.base &&
+                            QA.compareAndSet(a, index, t, null)) {
+                            q.base = b;
+                            return t;
+                        }
+                        else
+                            break; // restart
+                    }
                 }
-                if ((k = (k + 1) & m) == origin) {
+                if ((k = (k + step) & m) == origin) {
                     if (oldSum == (oldSum = checkSum))
-                        break;
+                        break rescan;
                     checkSum = 0;
                 }
             }
@@ -2285,58 +1830,160 @@
     }
 
     /**
-     * Runs tasks until {@code isQuiescent()}. We piggyback on
-     * active count ctl maintenance, but rather than blocking
-     * when tasks cannot be found, we rescan until all others cannot
-     * find tasks either.
-     */
-    final void helpQuiescePool(WorkQueue w) {
-        ForkJoinTask<?> ps = w.currentSteal; // save context
-        int wc = w.config;
-        for (boolean active = true;;) {
-            long c; WorkQueue q; ForkJoinTask<?> t;
-            if (wc >= 0 && (t = w.pop()) != null) { // run locals if LIFO
-                (w.currentSteal = t).doExec();
-                w.currentSteal = ps;
-            }
-            else if ((q = findNonEmptyStealQueue()) != null) {
-                if (!active) {      // re-establish active count
-                    active = true;
-                    U.getAndAddLong(this, CTL, AC_UNIT);
-                }
-                if ((t = q.pollAt(q.base)) != null) {
-                    (w.currentSteal = t).doExec();
-                    w.currentSteal = ps;
-                    if (++w.nsteals < 0)
-                        w.transferStealCount(this);
-                }
-            }
-            else if (active) {      // decrement active count without queuing
-                long nc = (AC_MASK & ((c = ctl) - AC_UNIT)) | (~AC_MASK & c);
-                if (U.compareAndSwapLong(this, CTL, c, nc))
-                    active = false;
-            }
-            else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) <= 0 &&
-                     U.compareAndSwapLong(this, CTL, c, c + AC_UNIT))
-                break;
-        }
-    }
-
-    /**
      * Gets and removes a local or stolen task for the given worker.
      *
      * @return a task, if available
      */
     final ForkJoinTask<?> nextTaskFor(WorkQueue w) {
-        for (ForkJoinTask<?> t;;) {
-            WorkQueue q;
-            if ((t = w.nextLocalTask()) != null)
-                return t;
-            if ((q = findNonEmptyStealQueue()) == null)
-                return null;
-            if ((t = q.pollAt(q.base)) != null)
-                return t;
+        ForkJoinTask<?> t;
+        if (w != null &&
+            (t = (w.id & FIFO) != 0 ? w.poll() : w.pop()) != null)
+            return t;
+        else
+            return pollScan(false);
+    }
+
+    // External operations
+
+    /**
+     * Adds the given task to a submission queue at submitter's
+     * current queue, creating one if null or contended.
+     *
+     * @param task the task. Caller must ensure non-null.
+     */
+    final void externalPush(ForkJoinTask<?> task) {
+        int r;                                // initialize caller's probe
+        if ((r = ThreadLocalRandom.getProbe()) == 0) {
+            ThreadLocalRandom.localInit();
+            r = ThreadLocalRandom.getProbe();
         }
+        for (;;) {
+            int md = mode, n;
+            WorkQueue[] ws = workQueues;
+            if ((md & SHUTDOWN) != 0 || ws == null || (n = ws.length) <= 0)
+                throw new RejectedExecutionException();
+            else {
+                WorkQueue q;
+                boolean push = false, grow = false;
+                if ((q = ws[(n - 1) & r & SQMASK]) == null) {
+                    Object lock = workerNamePrefix;
+                    int qid = (r | QUIET) & ~(FIFO | OWNED);
+                    q = new WorkQueue(this, null);
+                    q.id = qid;
+                    q.source = QUIET;
+                    q.phase = QLOCK;          // lock queue
+                    if (lock != null) {
+                        synchronized (lock) { // lock pool to install
+                            int i;
+                            if ((ws = workQueues) != null &&
+                                (n = ws.length) > 0 &&
+                                ws[i = qid & (n - 1) & SQMASK] == null) {
+                                ws[i] = q;
+                                push = grow = true;
+                            }
+                        }
+                    }
+                }
+                else if (q.tryLockSharedQueue()) {
+                    int b = q.base, s = q.top, al, d; ForkJoinTask<?>[] a;
+                    if ((a = q.array) != null && (al = a.length) > 0 &&
+                        al - 1 + (d = b - s) > 0) {
+                        a[(al - 1) & s] = task;
+                        q.top = s + 1;        // relaxed writes OK here
+                        q.phase = 0;
+                        if (d < 0 && q.base - s < -1)
+                            break;            // no signal needed
+                    }
+                    else
+                        grow = true;
+                    push = true;
+                }
+                if (push) {
+                    if (grow) {
+                        try {
+                            q.growArray();
+                            int s = q.top, al; ForkJoinTask<?>[] a;
+                            if ((a = q.array) != null && (al = a.length) > 0) {
+                                a[(al - 1) & s] = task;
+                                q.top = s + 1;
+                            }
+                        } finally {
+                            q.phase = 0;
+                        }
+                    }
+                    signalWork();
+                    break;
+                }
+                else                          // move if busy
+                    r = ThreadLocalRandom.advanceProbe(r);
+            }
+        }
+    }
+
+    /**
+     * Pushes a possibly-external submission.
+     */
+    private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
+        Thread t; ForkJoinWorkerThread w; WorkQueue q;
+        if (task == null)
+            throw new NullPointerException();
+        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
+            (w = (ForkJoinWorkerThread)t).pool == this &&
+            (q = w.workQueue) != null)
+            q.push(task);
+        else
+            externalPush(task);
+        return task;
+    }
+
+    /**
+     * Returns common pool queue for an external thread.
+     */
+    static WorkQueue commonSubmitterQueue() {
+        ForkJoinPool p = common;
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; int n;
+        return (p != null && (ws = p.workQueues) != null &&
+                (n = ws.length) > 0) ?
+            ws[(n - 1) & r & SQMASK] : null;
+    }
+
+    /**
+     * Performs tryUnpush for an external submitter.
+     */
+    final boolean tryExternalUnpush(ForkJoinTask<?> task) {
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; WorkQueue w; int n;
+        return ((ws = workQueues) != null &&
+                (n = ws.length) > 0 &&
+                (w = ws[(n - 1) & r & SQMASK]) != null &&
+                w.trySharedUnpush(task));
+    }
+
+    /**
+     * Performs helpComplete for an external submitter.
+     */
+    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
+        int r = ThreadLocalRandom.getProbe();
+        WorkQueue[] ws; WorkQueue w; int n;
+        return ((ws = workQueues) != null && (n = ws.length) > 0 &&
+                (w = ws[(n - 1) & r & SQMASK]) != null) ?
+            w.sharedHelpCC(task, maxTasks) : 0;
+    }
+
+    /**
+     * Tries to steal and run tasks within the target's computation.
+     * The maxTasks argument supports external usages; internal calls
+     * use zero, allowing unbounded steps (external calls trap
+     * non-positive values).
+     *
+     * @param w caller
+     * @param maxTasks if non-zero, the maximum number of other tasks to run
+     * @return task status on exit
+     */
+    final int helpComplete(WorkQueue w, CountedCompleter<?> task,
+                           int maxTasks) {
+        return (w == null) ? 0 : w.localHelpCC(task, maxTasks);
     }
 
     /**
@@ -2383,10 +2030,12 @@
      */
     static int getSurplusQueuedTaskCount() {
         Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q;
-        if ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) {
-            int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).config & SMASK;
-            int n = (q = wt.workQueue).top - q.base;
-            int a = (int)(pool.ctl >> AC_SHIFT) + p;
+        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
+            (pool = (wt = (ForkJoinWorkerThread)t).pool) != null &&
+            (q = wt.workQueue) != null) {
+            int p = pool.mode & SMASK;
+            int a = p + (int)(pool.ctl >> RC_SHIFT);
+            int n = q.top - q.base;
             return n - (a > (p >>>= 1) ? 0 :
                         a > (p >>>= 1) ? 1 :
                         a > (p >>>= 1) ? 2 :
@@ -2396,7 +2045,7 @@
         return 0;
     }
 
-    //  Termination
+    // Termination
 
     /**
      * Possibly initiates and/or completes termination.
@@ -2404,198 +2053,86 @@
      * @param now if true, unconditionally terminate, else only
      * if no work and no active workers
      * @param enable if true, terminate when next possible
-     * @return -1: terminating/terminated, 0: retry if internal caller, else 1
+     * @return true if terminating or terminated
      */
-    private int tryTerminate(boolean now, boolean enable) {
-        int rs; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
+    private boolean tryTerminate(boolean now, boolean enable) {
+        int md; // 3 phases: try to set SHUTDOWN, then STOP, then TERMINATED
 
-        while ((rs = runState) >= 0) {
+        while (((md = mode) & SHUTDOWN) == 0) {
             if (!enable || this == common)        // cannot shutdown
-                return 1;
-            else if (rs == 0)
-                tryInitialize(false);             // ensure initialized
+                return false;
             else
-                U.compareAndSwapInt(this, RUNSTATE, rs, rs | SHUTDOWN);
+                MODE.compareAndSet(this, md, md | SHUTDOWN);
         }
 
-        if ((rs & STOP) == 0) {                   // try to initiate termination
-            if (!now) {                           // check quiescence
+        while (((md = mode) & STOP) == 0) {       // try to initiate termination
+            if (!now) {                           // check if quiescent & empty
                 for (long oldSum = 0L;;) {        // repeat until stable
-                    WorkQueue[] ws; WorkQueue w; int b;
+                    boolean running = false;
                     long checkSum = ctl;
-                    if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0)
-                        return 0;                 // still active workers
-                    if ((ws = workQueues) != null) {
+                    WorkQueue[] ws = workQueues;
+                    if ((md & SMASK) + (int)(checkSum >> RC_SHIFT) > 0)
+                        running = true;
+                    else if (ws != null) {
+                        WorkQueue w; int b;
                         for (int i = 0; i < ws.length; ++i) {
                             if ((w = ws[i]) != null) {
-                                checkSum += (b = w.base);
-                                if (w.currentSteal != null || b != w.top)
-                                    return 0;     // retry if internal caller
+                                checkSum += (b = w.base) + w.id;
+                                if (b != w.top ||
+                                    ((i & 1) == 1 && w.source >= 0)) {
+                                    running = true;
+                                    break;
+                                }
                             }
                         }
                     }
-                    if (oldSum == (oldSum = checkSum))
+                    if (((md = mode) & STOP) != 0)
+                        break;                 // already triggered
+                    else if (running)
+                        return false;
+                    else if (workQueues == ws && oldSum == (oldSum = checkSum))
                         break;
                 }
             }
-            do {} while (!U.compareAndSwapInt(this, RUNSTATE,
-                                              rs = runState, rs | STOP));
+            if ((md & STOP) == 0)
+                MODE.compareAndSet(this, md, md | STOP);
         }
 
-        for (long oldSum = 0L;;) {                // repeat until stable
-            WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt;
-            long checkSum = ctl;
-            if ((ws = workQueues) != null) {      // help terminate others
-                for (int i = 0; i < ws.length; ++i) {
-                    if ((w = ws[i]) != null) {
-                        w.cancelAll();            // clear queues
-                        checkSum += w.base;
-                        if (w.qlock >= 0) {
-                            w.qlock = -1;         // racy set OK
-                            if ((wt = w.owner) != null) {
+        while (((md = mode) & TERMINATED) == 0) { // help terminate others
+            for (long oldSum = 0L;;) {            // repeat until stable
+                WorkQueue[] ws; WorkQueue w;
+                long checkSum = ctl;
+                if ((ws = workQueues) != null) {
+                    for (int i = 0; i < ws.length; ++i) {
+                        if ((w = ws[i]) != null) {
+                            ForkJoinWorkerThread wt = w.owner;
+                            w.cancelAll();        // clear queues
+                            if (wt != null) {
                                 try {             // unblock join or park
                                     wt.interrupt();
                                 } catch (Throwable ignore) {
                                 }
                             }
+                            checkSum += w.base + w.id;
                         }
                     }
                 }
-            }
-            if (oldSum == (oldSum = checkSum))
-                break;
-        }
-
-        if ((short)(ctl >>> TC_SHIFT) + (config & SMASK) <= 0) {
-            runState = (STARTED | SHUTDOWN | STOP | TERMINATED); // final write
-            synchronized (this) {
-                notifyAll();                      // for awaitTermination
+                if (((md = mode) & TERMINATED) != 0 ||
+                    (workQueues == ws && oldSum == (oldSum = checkSum)))
+                    break;
             }
-        }
-
-        return -1;
-    }
-
-    // External operations
-
-    /**
-     * Constructs and tries to install a new external queue,
-     * failing if the workQueues array already has a queue at
-     * the given index.
-     *
-     * @param index the index of the new queue
-     */
-    private void tryCreateExternalQueue(int index) {
-        AuxState aux;
-        if ((aux = auxState) != null && index >= 0) {
-            WorkQueue q = new WorkQueue(this, null);
-            q.config = index;
-            q.scanState = ~UNSIGNALLED;
-            q.qlock = 1;                   // lock queue
-            boolean installed = false;
-            aux.lock();
-            try {                          // lock pool to install
-                WorkQueue[] ws;
-                if ((ws = workQueues) != null && index < ws.length &&
-                    ws[index] == null) {
-                    ws[index] = q;         // else throw away
-                    installed = true;
+            if ((md & TERMINATED) != 0)
+                break;
+            else if ((md & SMASK) + (short)(ctl >>> TC_SHIFT) > 0)
+                break;
+            else if (MODE.compareAndSet(this, md, md | TERMINATED)) {
+                synchronized (this) {
+                    notifyAll();                  // for awaitTermination
                 }
-            } finally {
-                aux.unlock();
-            }
-            if (installed) {
-                try {
-                    q.growArray();
-                } finally {
-                    q.qlock = 0;
-                }
+                break;
             }
         }
-    }
-
-    /**
-     * Adds the given task to a submission queue at submitter's
-     * current queue. Also performs secondary initialization upon the
-     * first submission of the first task to the pool, and detects
-     * first submission by an external thread and creates a new shared
-     * queue if the one at index if empty or contended.
-     *
-     * @param task the task. Caller must ensure non-null.
-     */
-    final void externalPush(ForkJoinTask<?> task) {
-        int r;                            // initialize caller's probe
-        if ((r = ThreadLocalRandom.getProbe()) == 0) {
-            ThreadLocalRandom.localInit();
-            r = ThreadLocalRandom.getProbe();
-        }
-        for (;;) {
-            WorkQueue q; int wl, k, stat;
-            int rs = runState;
-            WorkQueue[] ws = workQueues;
-            if (rs <= 0 || ws == null || (wl = ws.length) <= 0)
-                tryInitialize(true);
-            else if ((q = ws[k = (wl - 1) & r & SQMASK]) == null)
-                tryCreateExternalQueue(k);
-            else if ((stat = q.sharedPush(task)) < 0)
-                break;
-            else if (stat == 0) {
-                signalWork();
-                break;
-            }
-            else                          // move if busy
-                r = ThreadLocalRandom.advanceProbe(r);
-        }
-    }
-
-    /**
-     * Pushes a possibly-external submission.
-     */
-    private <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) {
-        Thread t; ForkJoinWorkerThread w; WorkQueue q;
-        if (task == null)
-            throw new NullPointerException();
-        if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) &&
-            (w = (ForkJoinWorkerThread)t).pool == this &&
-            (q = w.workQueue) != null)
-            q.push(task);
-        else
-            externalPush(task);
-        return task;
-    }
-
-    /**
-     * Returns common pool queue for an external thread.
-     */
-    static WorkQueue commonSubmitterQueue() {
-        ForkJoinPool p = common;
-        int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; int wl;
-        return (p != null && (ws = p.workQueues) != null &&
-                (wl = ws.length) > 0) ?
-            ws[(wl - 1) & r & SQMASK] : null;
-    }
-
-    /**
-     * Performs tryUnpush for an external submitter.
-     */
-    final boolean tryExternalUnpush(ForkJoinTask<?> task) {
-        int r = ThreadLocalRandom.getProbe();
-        WorkQueue[] ws; WorkQueue w; int wl;
-        return ((ws = workQueues) != null &&
-                (wl = ws.length) > 0 &&
-                (w = ws[(wl - 1) & r & SQMASK]) != null &&
-                w.trySharedUnpush(task));
-    }
-
-    /**
-     * Performs helpComplete for an external submitter.
-     */
-    final int externalHelpComplete(CountedCompleter<?> task, int maxTasks) {
-        WorkQueue[] ws; int wl;
-        int r = ThreadLocalRandom.getProbe();
-        return ((ws = workQueues) != null && (wl = ws.length) > 0) ?
-            helpComplete(ws[(wl - 1) & r & SQMASK], task, maxTasks) : 0;
+        return true;
     }
 
     // Exported methods
@@ -2604,9 +2141,10 @@
 
     /**
      * Creates a {@code ForkJoinPool} with parallelism equal to {@link
-     * java.lang.Runtime#availableProcessors}, using the {@linkplain
-     * #defaultForkJoinWorkerThreadFactory default thread factory},
-     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
+     * java.lang.Runtime#availableProcessors}, using defaults for all
+     * other parameters (see {@link #ForkJoinPool(int,
+     * ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean,
+     * int, int, int, Predicate, long, TimeUnit)}).
      *
      * @throws SecurityException if a security manager exists and
      *         the caller is not permitted to modify threads
@@ -2615,14 +2153,16 @@
      */
     public ForkJoinPool() {
         this(Math.min(MAX_CAP, Runtime.getRuntime().availableProcessors()),
-             defaultForkJoinWorkerThreadFactory, null, false);
+             defaultForkJoinWorkerThreadFactory, null, false,
+             0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
     }
 
     /**
      * Creates a {@code ForkJoinPool} with the indicated parallelism
-     * level, the {@linkplain
-     * #defaultForkJoinWorkerThreadFactory default thread factory},
-     * no UncaughtExceptionHandler, and non-async LIFO processing mode.
+     * level, using defaults for all other parameters (see {@link
+     * #ForkJoinPool(int, ForkJoinWorkerThreadFactory,
+     * UncaughtExceptionHandler, boolean, int, int, int, Predicate,
+     * long, TimeUnit)}).
      *
      * @param parallelism the parallelism level
      * @throws IllegalArgumentException if parallelism less than or
@@ -2633,11 +2173,15 @@
      *         java.lang.RuntimePermission}{@code ("modifyThread")}
      */
     public ForkJoinPool(int parallelism) {
-        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false);
+        this(parallelism, defaultForkJoinWorkerThreadFactory, null, false,
+             0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
     }
 
     /**
-     * Creates a {@code ForkJoinPool} with the given parameters.
+     * Creates a {@code ForkJoinPool} with the given parameters (using
+     * defaults for others -- see {@link #ForkJoinPool(int,
+     * ForkJoinWorkerThreadFactory, UncaughtExceptionHandler, boolean,
+     * int, int, int, Predicate, long, TimeUnit)}).
      *
      * @param parallelism the parallelism level. For default value,
      * use {@link java.lang.Runtime#availableProcessors}.
@@ -2664,43 +2208,185 @@
                         ForkJoinWorkerThreadFactory factory,
                         UncaughtExceptionHandler handler,
                         boolean asyncMode) {
-        this(checkParallelism(parallelism),
-             checkFactory(factory),
-             handler,
-             asyncMode ? FIFO_QUEUE : LIFO_QUEUE,
-             "ForkJoinPool-" + nextPoolId() + "-worker-");
+        this(parallelism, factory, handler, asyncMode,
+             0, MAX_CAP, 1, null, DEFAULT_KEEPALIVE, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Creates a {@code ForkJoinPool} with the given parameters.
+     *
+     * @param parallelism the parallelism level. For default value,
+     * use {@link java.lang.Runtime#availableProcessors}.
+     *
+     * @param factory the factory for creating new threads. For
+     * default value, use {@link #defaultForkJoinWorkerThreadFactory}.
+     *
+     * @param handler the handler for internal worker threads that
+     * terminate due to unrecoverable errors encountered while
+     * executing tasks. For default value, use {@code null}.
+     *
+     * @param asyncMode if true, establishes local first-in-first-out
+     * scheduling mode for forked tasks that are never joined. This
+     * mode may be more appropriate than default locally stack-based
+     * mode in applications in which worker threads only process
+     * event-style asynchronous tasks.  For default value, use {@code
+     * false}.
+     *
+     * @param corePoolSize the number of threads to keep in the pool
+     * (unless timed out after an elapsed keep-alive). Normally (and
+     * by default) this is the same value as the parallelism level,
+     * but may be set to a larger value to reduce dynamic overhead if
+     * tasks regularly block. Using a smaller value (for example
+     * {@code 0}) has the same effect as the default.
+     *
+     * @param maximumPoolSize the maximum number of threads allowed.
+     * When the maximum is reached, attempts to replace blocked
+     * threads fail.  (However, because creation and termination of
+     * different threads may overlap, and may be managed by the given
+     * thread factory, this value may be transiently exceeded.)  To
+     * arrange the same value as is used by default for the common
+     * pool, use {@code 256} plus the {@code parallelism} level. (By
+     * default, the common pool allows a maximum of 256 spare
+     * threads.)  Using a value (for example {@code
+     * Integer.MAX_VALUE}) larger than the implementation's total
+     * thread limit has the same effect as using this limit (which is
+     * the default).
+     *
+     * @param minimumRunnable the minimum allowed number of core
+     * threads not blocked by a join or {@link ManagedBlocker}.  To
+     * ensure progress, when too few unblocked threads exist and
+     * unexecuted tasks may exist, new threads are constructed, up to
+     * the given maximumPoolSize.  For the default value, use {@code
+     * 1}, that ensures liveness.  A larger value might improve
+     * throughput in the presence of blocked activities, but might
+     * not, due to increased overhead.  A value of zero may be
+     * acceptable when submitted tasks cannot have dependencies
+     * requiring additional threads.
+     *
+     * @param saturate if non-null, a predicate invoked upon attempts
+     * to create more than the maximum total allowed threads.  By
+     * default, when a thread is about to block on a join or {@link
+     * ManagedBlocker}, but cannot be replaced because the
+     * maximumPoolSize would be exceeded, a {@link
+     * RejectedExecutionException} is thrown.  But if this predicate
+     * returns {@code true}, then no exception is thrown, so the pool
+     * continues to operate with fewer than the target number of
+     * runnable threads, which might not ensure progress.
+     *
+     * @param keepAliveTime the elapsed time since last use before
+     * a thread is terminated (and then later replaced if needed).
+     * For the default value, use {@code 60, TimeUnit.SECONDS}.
+     *
+     * @param unit the time unit for the {@code keepAliveTime} argument
+     *
+     * @throws IllegalArgumentException if parallelism is less than or
+     *         equal to zero, or is greater than implementation limit,
+     *         or if maximumPoolSize is less than parallelism,
+     *         of if the keepAliveTime is less than or equal to zero.
+     * @throws NullPointerException if the factory is null
+     * @throws SecurityException if a security manager exists and
+     *         the caller is not permitted to modify threads
+     *         because it does not hold {@link
+     *         java.lang.RuntimePermission}{@code ("modifyThread")}
+     * @since 9
+     */
+    public ForkJoinPool(int parallelism,
+                        ForkJoinWorkerThreadFactory factory,
+                        UncaughtExceptionHandler handler,
+                        boolean asyncMode,
+                        int corePoolSize,
+                        int maximumPoolSize,
+                        int minimumRunnable,
+                        Predicate<? super ForkJoinPool> saturate,
+                        long keepAliveTime,
+                        TimeUnit unit) {
+        // check, encode, pack parameters
+        if (parallelism <= 0 || parallelism > MAX_CAP ||
+            maximumPoolSize < parallelism || keepAliveTime <= 0L)
+            throw new IllegalArgumentException();
+        if (factory == null)
+            throw new NullPointerException();
+        long ms = Math.max(unit.toMillis(keepAliveTime), TIMEOUT_SLOP);
+
+        String prefix = "ForkJoinPool-" + nextPoolId() + "-worker-";
+        int corep = Math.min(Math.max(corePoolSize, parallelism), MAX_CAP);
+        long c = ((((long)(-corep)       << TC_SHIFT) & TC_MASK) |
+                  (((long)(-parallelism) << RC_SHIFT) & RC_MASK));
+        int m = parallelism | (asyncMode ? FIFO : 0);
+        int maxSpares = Math.min(maximumPoolSize, MAX_CAP) - parallelism;
+        int minAvail = Math.min(Math.max(minimumRunnable, 0), MAX_CAP);
+        int b = ((minAvail - parallelism) & SMASK) | (maxSpares << SWIDTH);
+        int n = (parallelism > 1) ? parallelism - 1 : 1; // at least 2 slots
+        n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
+        n = (n + 1) << 1; // power of two, including space for submission queues
+
+        this.workQueues = new WorkQueue[n];
+        this.workerNamePrefix = prefix;
+        this.factory = factory;
+        this.ueh = handler;
+        this.saturate = saturate;
+        this.keepAlive = ms;
+        this.bounds = b;
+        this.mode = m;
+        this.ctl = c;
         checkPermission();
     }
 
-    private static int checkParallelism(int parallelism) {
-        if (parallelism <= 0 || parallelism > MAX_CAP)
-            throw new IllegalArgumentException();
-        return parallelism;
-    }
-
-    private static ForkJoinWorkerThreadFactory checkFactory
-        (ForkJoinWorkerThreadFactory factory) {
-        if (factory == null)
-            throw new NullPointerException();
-        return factory;
-    }
+    /**
+     * Constructor for common pool using parameters possibly
+     * overridden by system properties
+     */
+    @SuppressWarnings("deprecation") // Class.newInstance
+    private ForkJoinPool(byte forCommonPoolOnly) {
+        int parallelism = -1;
+        ForkJoinWorkerThreadFactory fac = null;
+        UncaughtExceptionHandler handler = null;
+        try {  // ignore exceptions in accessing/parsing properties
+            String pp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.parallelism");
+            String fp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.threadFactory");
+            String hp = System.getProperty
+                ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
+            if (pp != null)
+                parallelism = Integer.parseInt(pp);
+            if (fp != null)
+                fac = ((ForkJoinWorkerThreadFactory)ClassLoader.
+                           getSystemClassLoader().loadClass(fp).newInstance());
+            if (hp != null)
+                handler = ((UncaughtExceptionHandler)ClassLoader.
+                           getSystemClassLoader().loadClass(hp).newInstance());
+        } catch (Exception ignore) {
+        }
 
-    /**
-     * Creates a {@code ForkJoinPool} with the given parameters, without
-     * any security checks or parameter validation.  Invoked directly by
-     * makeCommonPool.
-     */
-    private ForkJoinPool(int parallelism,
-                         ForkJoinWorkerThreadFactory factory,
-                         UncaughtExceptionHandler handler,
-                         int mode,
-                         String workerNamePrefix) {
-        this.workerNamePrefix = workerNamePrefix;
-        this.factory = factory;
+        if (fac == null) {
+            if (System.getSecurityManager() == null)
+                fac = defaultForkJoinWorkerThreadFactory;
+            else // use security-managed default
+                fac = new InnocuousForkJoinWorkerThreadFactory();
+        }
+        if (parallelism < 0 && // default 1 less than #cores
+            (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
+            parallelism = 1;
+        if (parallelism > MAX_CAP)
+            parallelism = MAX_CAP;
+
+        long c = ((((long)(-parallelism) << TC_SHIFT) & TC_MASK) |
+                  (((long)(-parallelism) << RC_SHIFT) & RC_MASK));
+        int b = ((1 - parallelism) & SMASK) | (COMMON_MAX_SPARES << SWIDTH);
+        int n = (parallelism > 1) ? parallelism - 1 : 1;
+        n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; n |= n >>> 8; n |= n >>> 16;
+        n = (n + 1) << 1;
+
+        this.workQueues = new WorkQueue[n];
+        this.workerNamePrefix = "ForkJoinPool.commonPool-worker-";
+        this.factory = fac;
         this.ueh = handler;
-        this.config = (parallelism & SMASK) | mode;
-        long np = (long)(-parallelism); // offset ctl counts
-        this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK);
+        this.saturate = null;
+        this.keepAlive = DEFAULT_KEEPALIVE;
+        this.bounds = b;
+        this.mode = parallelism;
+        this.ctl = c;
     }
 
     /**
@@ -2876,8 +2562,8 @@
      * @return the targeted parallelism level of this pool
      */
     public int getParallelism() {
-        int par;
-        return ((par = config & SMASK) > 0) ? par : 1;
+        int par = mode & SMASK;
+        return (par > 0) ? par : 1;
     }
 
     /**
@@ -2899,7 +2585,7 @@
      * @return the number of worker threads
      */
     public int getPoolSize() {
-        return (config & SMASK) + (short)(ctl >>> TC_SHIFT);
+        return ((mode & SMASK) + (short)(ctl >>> TC_SHIFT));
     }
 
     /**
@@ -2909,7 +2595,7 @@
      * @return {@code true} if this pool uses async mode
      */
     public boolean getAsyncMode() {
-        return (config & FIFO_QUEUE) != 0;
+        return (mode & FIFO) != 0;
     }
 
     /**
@@ -2940,7 +2626,7 @@
      * @return the number of active threads
      */
     public int getActiveThreadCount() {
-        int r = (config & SMASK) + (int)(ctl >> AC_SHIFT);
+        int r = (mode & SMASK) + (int)(ctl >> RC_SHIFT);
         return (r <= 0) ? 0 : r; // suppress momentarily negative values
     }
 
@@ -2956,7 +2642,30 @@
      * @return {@code true} if all threads are currently idle
      */
     public boolean isQuiescent() {
-        return (config & SMASK) + (int)(ctl >> AC_SHIFT) <= 0;
+        for (;;) {
+            long c = ctl;
+            int md = mode, pc = md & SMASK;
+            int tc = pc + (short)(c >>> TC_SHIFT);
+            int rc = pc + (int)(c >> RC_SHIFT);
+            if ((md & (STOP | TERMINATED)) != 0)
+                return true;
+            else if (rc > 0)
+                return false;
+            else {
+                WorkQueue[] ws; WorkQueue v;
+                if ((ws = workQueues) != null) {
+                    for (int i = 1; i < ws.length; i += 2) {
+                        if ((v = ws[i]) != null) {
+                            if ((v.source & QUIET) == 0)
+                                return false;
+                            --tc;
+                        }
+                    }
+                }
+                if (tc == 0 && ctl == c)
+                    return true;
+            }
+        }
     }
 
     /**
@@ -2971,13 +2680,12 @@
      * @return the number of steals
      */
     public long getStealCount() {
-        AuxState sc = auxState;
-        long count = (sc == null) ? 0L : sc.stealCount;
+        long count = stealCount;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
             for (int i = 1; i < ws.length; i += 2) {
                 if ((w = ws[i]) != null)
-                    count += w.nsteals;
+                    count += (long)w.nsteals & 0xffffffffL;
             }
         }
         return count;
@@ -3049,15 +2757,7 @@
      * @return the next submission, or {@code null} if none
      */
     protected ForkJoinTask<?> pollSubmission() {
-        WorkQueue[] ws; int wl; WorkQueue w; ForkJoinTask<?> t;
-        int r = ThreadLocalRandom.nextSecondarySeed();
-        if ((ws = workQueues) != null && (wl = ws.length) > 0) {
-            for (int m = wl - 1, i = 0; i < wl; ++i) {
-                if ((w = ws[(i << 1) & m]) != null && (t = w.poll()) != null)
-                    return t;
-            }
-        }
-        return null;
+        return pollScan(true);
     }
 
     /**
@@ -3103,9 +2803,7 @@
     public String toString() {
         // Use a single pass through workQueues to collect counts
         long qt = 0L, qs = 0L; int rc = 0;
-        AuxState sc = auxState;
-        long st = (sc == null) ? 0L : sc.stealCount;
-        long c = ctl;
+        long st = stealCount;
         WorkQueue[] ws; WorkQueue w;
         if ((ws = workQueues) != null) {
             for (int i = 0; i < ws.length; ++i) {
@@ -3115,22 +2813,24 @@
                         qs += size;
                     else {
                         qt += size;
-                        st += w.nsteals;
+                        st += (long)w.nsteals & 0xffffffffL;
                         if (w.isApparentlyUnblocked())
                             ++rc;
                     }
                 }
             }
         }
-        int pc = (config & SMASK);
+
+        int md = mode;
+        int pc = (md & SMASK);
+        long c = ctl;
         int tc = pc + (short)(c >>> TC_SHIFT);
-        int ac = pc + (int)(c >> AC_SHIFT);
+        int ac = pc + (int)(c >> RC_SHIFT);
         if (ac < 0) // ignore transient negative
             ac = 0;
-        int rs = runState;
-        String level = ((rs & TERMINATED) != 0 ? "Terminated" :
-                        (rs & STOP)       != 0 ? "Terminating" :
-                        (rs & SHUTDOWN)   != 0 ? "Shutting down" :
+        String level = ((md & TERMINATED) != 0 ? "Terminated" :
+                        (md & STOP)       != 0 ? "Terminating" :
+                        (md & SHUTDOWN)   != 0 ? "Shutting down" :
                         "Running");
         return super.toString() +
             "[" + level +
@@ -3193,7 +2893,7 @@
      * @return {@code true} if all tasks have completed following shut down
      */
     public boolean isTerminated() {
-        return (runState & TERMINATED) != 0;
+        return (mode & TERMINATED) != 0;
     }
 
     /**
@@ -3210,8 +2910,8 @@
      * @return {@code true} if terminating but not yet terminated
      */
     public boolean isTerminating() {
-        int rs = runState;
-        return (rs & STOP) != 0 && (rs & TERMINATED) == 0;
+        int md = mode;
+        return (md & STOP) != 0 && (md & TERMINATED) == 0;
     }
 
     /**
@@ -3220,7 +2920,7 @@
      * @return {@code true} if this pool has been shut down
      */
     public boolean isShutdown() {
-        return (runState & SHUTDOWN) != 0;
+        return (mode & SHUTDOWN) != 0;
     }
 
     /**
@@ -3284,30 +2984,19 @@
             helpQuiescePool(wt.workQueue);
             return true;
         }
-        long startTime = System.nanoTime();
-        WorkQueue[] ws;
-        int r = 0, wl;
-        boolean found = true;
-        while (!isQuiescent() && (ws = workQueues) != null &&
-               (wl = ws.length) > 0) {
-            if (!found) {
-                if ((System.nanoTime() - startTime) > nanos)
+        else {
+            for (long startTime = System.nanoTime();;) {
+                ForkJoinTask<?> t;
+                if ((t = pollScan(false)) != null)
+                    t.doExec();
+                else if (isQuiescent())
+                    return true;
+                else if ((System.nanoTime() - startTime) > nanos)
                     return false;
-                Thread.yield(); // cannot block
-            }
-            found = false;
-            for (int m = wl - 1, j = (m + 1) << 2; j >= 0; --j) {
-                ForkJoinTask<?> t; WorkQueue q; int b, k;
-                if ((k = r++ & m) <= m && k >= 0 && (q = ws[k]) != null &&
-                    (b = q.base) - q.top < 0) {
-                    found = true;
-                    if ((t = q.pollAt(b)) != null)
-                        t.doExec();
-                    break;
-                }
+                else
+                    Thread.yield(); // cannot block
             }
         }
-        return true;
     }
 
     /**
@@ -3422,17 +3111,19 @@
         throws InterruptedException {
         ForkJoinPool p;
         ForkJoinWorkerThread wt;
+        WorkQueue w;
         Thread t = Thread.currentThread();
         if ((t instanceof ForkJoinWorkerThread) &&
-            (p = (wt = (ForkJoinWorkerThread)t).pool) != null) {
-            WorkQueue w = wt.workQueue;
+            (p = (wt = (ForkJoinWorkerThread)t).pool) != null &&
+            (w = wt.workQueue) != null) {
+            int block;
             while (!blocker.isReleasable()) {
-                if (p.tryCompensate(w)) {
+                if ((block = p.tryCompensate(w)) != 0) {
                     try {
                         do {} while (!blocker.isReleasable() &&
                                      !blocker.block());
                     } finally {
-                        U.getAndAddLong(p, CTL, AC_UNIT);
+                        CTL.getAndAdd(p, (block > 0) ? RC_UNIT : 0L);
                     }
                     break;
                 }
@@ -3444,6 +3135,55 @@
         }
     }
 
+    /**
+     * If the given executor is a ForkJoinPool, poll and execute
+     * AsynchronousCompletionTasks from worker's queue until none are
+     * available or blocker is released.
+     */
+    static void helpAsyncBlocker(Executor e, ManagedBlocker blocker) {
+        if (blocker != null && (e instanceof ForkJoinPool)) {
+            WorkQueue w; ForkJoinWorkerThread wt; WorkQueue[] ws; int r, n;
+            ForkJoinPool p = (ForkJoinPool)e;
+            Thread thread = Thread.currentThread();
+            if (thread instanceof ForkJoinWorkerThread &&
+                (wt = (ForkJoinWorkerThread)thread).pool == p)
+                w = wt.workQueue;
+            else if ((r = ThreadLocalRandom.getProbe()) != 0 &&
+                     (ws = p.workQueues) != null && (n = ws.length) > 0)
+                w = ws[(n - 1) & r & SQMASK];
+            else
+                w = null;
+            if (w != null) {
+                for (;;) {
+                    int b = w.base, s = w.top, d, al; ForkJoinTask<?>[] a;
+                    if ((a = w.array) != null && (d = b - s) < 0 &&
+                        (al = a.length) > 0) {
+                        int index = (al - 1) & b;
+                        ForkJoinTask<?> t = (ForkJoinTask<?>)
+                            QA.getAcquire(a, index);
+                        if (blocker.isReleasable())
+                            break;
+                        else if (b++ == w.base) {
+                            if (t == null) {
+                                if (d == -1)
+                                    break;
+                            }
+                            else if (!(t instanceof CompletableFuture.
+                                  AsynchronousCompletionTask))
+                                break;
+                            else if (QA.compareAndSet(a, index, t, null)) {
+                                w.base = b;
+                                t.doExec();
+                            }
+                        }
+                    }
+                    else
+                        break;
+                }
+            }
+        }
+    }
+
     // AbstractExecutorService overrides.  These rely on undocumented
     // fact that ForkJoinTask.adapt returns ForkJoinTasks that also
     // implement RunnableFuture.
@@ -3456,24 +3196,17 @@
         return new ForkJoinTask.AdaptedCallable<T>(callable);
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long CTL;
-    private static final long RUNSTATE;
-    private static final int ABASE;
-    private static final int ASHIFT;
+    // VarHandle mechanics
+    private static final VarHandle CTL;
+    private static final VarHandle MODE;
+    private static final VarHandle QA;
 
     static {
         try {
-            CTL = U.objectFieldOffset
-                (ForkJoinPool.class.getDeclaredField("ctl"));
-            RUNSTATE = U.objectFieldOffset
-                (ForkJoinPool.class.getDeclaredField("runState"));
-            ABASE = U.arrayBaseOffset(ForkJoinTask[].class);
-            int scale = U.arrayIndexScale(ForkJoinTask[].class);
-            if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
-            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            CTL = l.findVarHandle(ForkJoinPool.class, "ctl", long.class);
+            MODE = l.findVarHandle(ForkJoinPool.class, "mode", int.class);
+            QA = MethodHandles.arrayElementVarHandle(ForkJoinTask[].class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -3497,51 +3230,10 @@
 
         common = java.security.AccessController.doPrivileged
             (new java.security.PrivilegedAction<ForkJoinPool>() {
-                public ForkJoinPool run() { return makeCommonPool(); }});
-
-        // report 1 even if threads disabled
-        COMMON_PARALLELISM = Math.max(common.config & SMASK, 1);
-    }
+                    public ForkJoinPool run() {
+                        return new ForkJoinPool((byte)0); }});
 
-    /**
-     * Creates and returns the common pool, respecting user settings
-     * specified via system properties.
-     */
-    @SuppressWarnings("deprecation") // Class.newInstance
-    static ForkJoinPool makeCommonPool() {
-        int parallelism = -1;
-        ForkJoinWorkerThreadFactory factory = null;
-        UncaughtExceptionHandler handler = null;
-        try {  // ignore exceptions in accessing/parsing properties
-            String pp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.parallelism");
-            String fp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.threadFactory");
-            String hp = System.getProperty
-                ("java.util.concurrent.ForkJoinPool.common.exceptionHandler");
-            if (pp != null)
-                parallelism = Integer.parseInt(pp);
-            if (fp != null)
-                factory = ((ForkJoinWorkerThreadFactory)ClassLoader.
-                           getSystemClassLoader().loadClass(fp).newInstance());
-            if (hp != null)
-                handler = ((UncaughtExceptionHandler)ClassLoader.
-                           getSystemClassLoader().loadClass(hp).newInstance());
-        } catch (Exception ignore) {
-        }
-        if (factory == null) {
-            if (System.getSecurityManager() == null)
-                factory = defaultForkJoinWorkerThreadFactory;
-            else // use security-managed default
-                factory = new InnocuousForkJoinWorkerThreadFactory();
-        }
-        if (parallelism < 0 && // default 1 less than #cores
-            (parallelism = Runtime.getRuntime().availableProcessors() - 1) <= 0)
-            parallelism = 1;
-        if (parallelism > MAX_CAP)
-            parallelism = MAX_CAP;
-        return new ForkJoinPool(parallelism, factory, handler, LIFO_QUEUE,
-                                "ForkJoinPool.commonPool-worker-");
+        COMMON_PARALLELISM = Math.max(common.mode & SMASK, 1);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java	Mon Jul 18 09:38:08 2016 -0700
@@ -36,6 +36,8 @@
 package java.util.concurrent;
 
 import java.io.Serializable;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Constructor;
@@ -92,7 +94,7 @@
  * encountering the exception; minimally only the latter.
  *
  * <p>It is possible to define and use ForkJoinTasks that may block,
- * but doing do requires three further considerations: (1) Completion
+ * but doing so requires three further considerations: (1) Completion
  * of few if any <em>other</em> tasks should be dependent on a task
  * that blocks on external synchronization or I/O. Event-style async
  * tasks that are never joined (for example, those subclassing {@link
@@ -259,7 +261,7 @@
         for (int s;;) {
             if ((s = status) < 0)
                 return s;
-            if (U.compareAndSwapInt(this, STATUS, s, s | completion)) {
+            if (STATUS.compareAndSet(this, s, s | completion)) {
                 if ((s >>> 16) != 0)
                     synchronized (this) { notifyAll(); }
                 return completion;
@@ -297,7 +299,7 @@
     final void internalWait(long timeout) {
         int s;
         if ((s = status) >= 0 && // force completer to issue notify
-            U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+            STATUS.compareAndSet(this, s, s | SIGNAL)) {
             synchronized (this) {
                 if (status >= 0)
                     try { wait(timeout); } catch (InterruptedException ie) { }
@@ -319,7 +321,7 @@
         if (s >= 0 && (s = status) >= 0) {
             boolean interrupted = false;
             do {
-                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                if (STATUS.compareAndSet(this, s, s | SIGNAL)) {
                     synchronized (this) {
                         if (status >= 0) {
                             try {
@@ -353,7 +355,7 @@
                   ForkJoinPool.common.tryExternalUnpush(this) ? doExec() :
                   0)) >= 0) {
             while ((s = status) >= 0) {
-                if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                if (STATUS.compareAndSet(this, s, s | SIGNAL)) {
                     synchronized (this) {
                         if (status >= 0)
                             wait(0L);
@@ -400,22 +402,24 @@
     // Exception table support
 
     /**
-     * Table of exceptions thrown by tasks, to enable reporting by
-     * callers. Because exceptions are rare, we don't directly keep
+     * Hash table of exceptions thrown by tasks, to enable reporting
+     * by callers. Because exceptions are rare, we don't directly keep
      * them with task objects, but instead use a weak ref table.  Note
      * that cancellation exceptions don't appear in the table, but are
      * instead recorded as status values.
      *
-     * Note: These statics are initialized below in static block.
+     * The exception table has a fixed capacity.
      */
-    private static final ExceptionNode[] exceptionTable;
-    private static final ReentrantLock exceptionTableLock;
-    private static final ReferenceQueue<Object> exceptionTableRefQueue;
+    private static final ExceptionNode[] exceptionTable
+        = new ExceptionNode[32];
 
-    /**
-     * Fixed capacity for exceptionTable.
-     */
-    private static final int EXCEPTION_MAP_CAPACITY = 32;
+    /** Lock protecting access to exceptionTable. */
+    private static final ReentrantLock exceptionTableLock
+        = new ReentrantLock();
+
+    /** Reference queue of stale exceptionally completed tasks. */
+    private static final ReferenceQueue<ForkJoinTask<?>> exceptionTableRefQueue
+        = new ReferenceQueue<ForkJoinTask<?>>();
 
     /**
      * Key-value nodes for exception table.  The chained hash table
@@ -435,7 +439,7 @@
         final long thrower;  // use id not ref to avoid weak cycles
         final int hashCode;  // store task hashCode before weak ref disappears
         ExceptionNode(ForkJoinTask<?> task, Throwable ex, ExceptionNode next,
-                      ReferenceQueue<Object> exceptionTableRefQueue) {
+                      ReferenceQueue<ForkJoinTask<?>> exceptionTableRefQueue) {
             super(task, exceptionTableRefQueue);
             this.ex = ex;
             this.next = next;
@@ -599,9 +603,8 @@
     private static void expungeStaleExceptions() {
         for (Object x; (x = exceptionTableRefQueue.poll()) != null;) {
             if (x instanceof ExceptionNode) {
-                int hashCode = ((ExceptionNode)x).hashCode;
                 ExceptionNode[] t = exceptionTable;
-                int i = hashCode & (t.length - 1);
+                int i = ((ExceptionNode)x).hashCode & (t.length - 1);
                 ExceptionNode e = t[i];
                 ExceptionNode pred = null;
                 while (e != null) {
@@ -1031,7 +1034,7 @@
                 while ((s = status) >= 0 &&
                        (ns = deadline - System.nanoTime()) > 0L) {
                     if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L &&
-                        U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
+                        STATUS.compareAndSet(this, s, s | SIGNAL)) {
                         synchronized (this) {
                             if (status >= 0)
                                 wait(ms); // OK to throw InterruptedException
@@ -1324,8 +1327,8 @@
      */
     public final short setForkJoinTaskTag(short newValue) {
         for (int s;;) {
-            if (U.compareAndSwapInt(this, STATUS, s = status,
-                                    (s & ~SMASK) | (newValue & SMASK)))
+            if (STATUS.compareAndSet(this, s = status,
+                                     (s & ~SMASK) | (newValue & SMASK)))
                 return (short)s;
         }
     }
@@ -1348,8 +1351,8 @@
         for (int s;;) {
             if ((short)(s = status) != expect)
                 return false;
-            if (U.compareAndSwapInt(this, STATUS, s,
-                                    (s & ~SMASK) | (update & SMASK)))
+            if (STATUS.compareAndSet(this, s,
+                                     (s & ~SMASK) | (update & SMASK)))
                 return true;
         }
     }
@@ -1510,17 +1513,12 @@
             setExceptionalCompletion((Throwable)ex);
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATUS;
-
+    // VarHandle mechanics
+    private static final VarHandle STATUS;
     static {
-        exceptionTableLock = new ReentrantLock();
-        exceptionTableRefQueue = new ReferenceQueue<Object>();
-        exceptionTable = new ExceptionNode[EXCEPTION_MAP_CAPACITY];
         try {
-            STATUS = U.objectFieldOffset
-                (ForkJoinTask.class.getDeclaredField("status"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATUS = l.findVarHandle(ForkJoinTask.class, "status", int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java	Mon Jul 18 09:38:08 2016 -0700
@@ -66,8 +66,9 @@
      * owning thread.
      *
      * Support for (non-public) subclass InnocuousForkJoinWorkerThread
-     * requires that we break quite a lot of encapsulation (via Unsafe)
-     * both here and in the subclass to access and set Thread fields.
+     * requires that we break quite a lot of encapsulation (via helper
+     * methods in ThreadLocalRandom) both here and in the subclass to
+     * access and set Thread fields.
      */
 
     final ForkJoinPool pool;                // the pool this thread works in
@@ -92,8 +93,8 @@
     ForkJoinWorkerThread(ForkJoinPool pool, ThreadGroup threadGroup,
                          AccessControlContext acc) {
         super(threadGroup, null, "aForkJoinWorkerThread");
-        U.putObjectRelease(this, INHERITEDACCESSCONTROLCONTEXT, acc);
-        eraseThreadLocals(); // clear before registering
+        ThreadLocalRandom.setInheritedAccessControlContext(this, acc);
+        ThreadLocalRandom.eraseThreadLocals(this); // clear before registering
         this.pool = pool;
         this.workQueue = pool.registerWorker(this);
     }
@@ -171,37 +172,11 @@
     }
 
     /**
-     * Erases ThreadLocals by nulling out Thread maps.
-     */
-    final void eraseThreadLocals() {
-        U.putObject(this, THREADLOCALS, null);
-        U.putObject(this, INHERITABLETHREADLOCALS, null);
-    }
-
-    /**
      * Non-public hook method for InnocuousForkJoinWorkerThread.
      */
     void afterTopLevelExec() {
     }
 
-    // Set up to allow setting thread fields in constructor
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long THREADLOCALS;
-    private static final long INHERITABLETHREADLOCALS;
-    private static final long INHERITEDACCESSCONTROLCONTEXT;
-    static {
-        try {
-            THREADLOCALS = U.objectFieldOffset
-                (Thread.class.getDeclaredField("threadLocals"));
-            INHERITABLETHREADLOCALS = U.objectFieldOffset
-                (Thread.class.getDeclaredField("inheritableThreadLocals"));
-            INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
-                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
     /**
      * A worker thread that has no permissions, is not a member of any
      * user-defined ThreadGroup, and erases all ThreadLocals after
@@ -210,7 +185,7 @@
     static final class InnocuousForkJoinWorkerThread extends ForkJoinWorkerThread {
         /** The ThreadGroup for all InnocuousForkJoinWorkerThreads */
         private static final ThreadGroup innocuousThreadGroup =
-            createThreadGroup();
+            ThreadLocalRandom.createThreadGroup("InnocuousForkJoinWorkerThreadGroup");
 
         /** An AccessControlContext supporting no privileges */
         private static final AccessControlContext INNOCUOUS_ACC =
@@ -225,7 +200,7 @@
 
         @Override // to erase ThreadLocals
         void afterTopLevelExec() {
-            eraseThreadLocals();
+            ThreadLocalRandom.eraseThreadLocals(this);
         }
 
         @Override // to always report system loader
@@ -241,33 +216,5 @@
             throw new SecurityException("setContextClassLoader");
         }
 
-        /**
-         * Returns a new group with the system ThreadGroup (the
-         * topmost, parent-less group) as parent.  Uses Unsafe to
-         * traverse Thread.group and ThreadGroup.parent fields.
-         */
-        private static ThreadGroup createThreadGroup() {
-            try {
-                jdk.internal.misc.Unsafe u = jdk.internal.misc.Unsafe.getUnsafe();
-                long tg = u.objectFieldOffset
-                    (Thread.class.getDeclaredField("group"));
-                long gp = u.objectFieldOffset
-                    (ThreadGroup.class.getDeclaredField("parent"));
-                ThreadGroup group = (ThreadGroup)
-                    u.getObject(Thread.currentThread(), tg);
-                while (group != null) {
-                    ThreadGroup parent = (ThreadGroup)u.getObject(group, gp);
-                    if (parent == null)
-                        return new ThreadGroup(group,
-                                               "InnocuousForkJoinWorkerThreadGroup");
-                    group = parent;
-                }
-            } catch (ReflectiveOperationException e) {
-                throw new Error(e);
-            }
-            // fall through if null as cannot-happen safeguard
-            throw new Error("Cannot create ThreadGroup");
-        }
     }
-
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/FutureTask.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.locks.LockSupport;
 
 /**
@@ -69,9 +71,6 @@
      * cancellation races. Sync control in the current design relies
      * on a "state" field updated via CAS to track completion, along
      * with a simple Treiber stack to hold waiting threads.
-     *
-     * Style note: As usual, we bypass overhead of using
-     * AtomicXFieldUpdaters and instead directly use Unsafe intrinsics.
      */
 
     /**
@@ -163,9 +162,8 @@
     }
 
     public boolean cancel(boolean mayInterruptIfRunning) {
-        if (!(state == NEW &&
-              U.compareAndSwapInt(this, STATE, NEW,
-                  mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
+        if (!(state == NEW && STATE.compareAndSet
+              (this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
             return false;
         try {    // in case call to interrupt throws exception
             if (mayInterruptIfRunning) {
@@ -174,7 +172,7 @@
                     if (t != null)
                         t.interrupt();
                 } finally { // final state
-                    U.putIntRelease(this, STATE, INTERRUPTED);
+                    STATE.setRelease(this, INTERRUPTED);
                 }
             }
         } finally {
@@ -228,9 +226,9 @@
      * @param v the value
      */
     protected void set(V v) {
-        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
+        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
             outcome = v;
-            U.putIntRelease(this, STATE, NORMAL); // final state
+            STATE.setRelease(this, NORMAL); // final state
             finishCompletion();
         }
     }
@@ -246,16 +244,16 @@
      * @param t the cause of failure
      */
     protected void setException(Throwable t) {
-        if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {
+        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
             outcome = t;
-            U.putIntRelease(this, STATE, EXCEPTIONAL); // final state
+            STATE.setRelease(this, EXCEPTIONAL); // final state
             finishCompletion();
         }
     }
 
     public void run() {
         if (state != NEW ||
-            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
+            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
             return;
         try {
             Callable<V> c = callable;
@@ -296,7 +294,7 @@
      */
     protected boolean runAndReset() {
         if (state != NEW ||
-            !U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
+            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
             return false;
         boolean ran = false;
         int s = state;
@@ -363,7 +361,7 @@
     private void finishCompletion() {
         // assert state > COMPLETING;
         for (WaitNode q; (q = waiters) != null;) {
-            if (U.compareAndSwapObject(this, WAITERS, q, null)) {
+            if (WAITERS.weakCompareAndSetVolatile(this, q, null)) {
                 for (;;) {
                     Thread t = q.thread;
                     if (t != null) {
@@ -425,8 +423,7 @@
                 q = new WaitNode();
             }
             else if (!queued)
-                queued = U.compareAndSwapObject(this, WAITERS,
-                                                q.next = waiters, q);
+                queued = WAITERS.weakCompareAndSetVolatile(this, q.next = waiters, q);
             else if (timed) {
                 final long parkNanos;
                 if (startTime == 0L) { // first time
@@ -475,7 +472,7 @@
                         if (pred.thread == null) // check for race
                             continue retry;
                     }
-                    else if (!U.compareAndSwapObject(this, WAITERS, q, s))
+                    else if (!WAITERS.compareAndSet(this, q, s))
                         continue retry;
                 }
                 break;
@@ -483,19 +480,16 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long RUNNER;
-    private static final long WAITERS;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle RUNNER;
+    private static final VarHandle WAITERS;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("state"));
-            RUNNER = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("runner"));
-            WAITERS = U.objectFieldOffset
-                (FutureTask.class.getDeclaredField("waiters"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(FutureTask.class, "state", int.class);
+            RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
+            WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/LinkedTransferQueue.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -444,7 +446,7 @@
 
     /**
      * Queue nodes. Uses Object, not E, for items to allow forgetting
-     * them after use.  Relies heavily on Unsafe mechanics to minimize
+     * them after use.  Relies heavily on VarHandles to minimize
      * unnecessary ordering constraints: Writes that are intrinsically
      * ordered wrt other accesses or CASes use simple relaxed forms.
      */
@@ -456,12 +458,12 @@
 
         // CAS methods for fields
         final boolean casNext(Node cmp, Node val) {
-            return U.compareAndSwapObject(this, NEXT, cmp, val);
+            return NEXT.compareAndSet(this, cmp, val);
         }
 
         final boolean casItem(Object cmp, Object val) {
             // assert cmp == null || cmp.getClass() != Node.class;
-            return U.compareAndSwapObject(this, ITEM, cmp, val);
+            return ITEM.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -469,7 +471,7 @@
          * only be seen after publication via casNext.
          */
         Node(Object item, boolean isData) {
-            U.putObject(this, ITEM, item); // relaxed write
+            ITEM.set(this, item); // relaxed write
             this.isData = isData;
         }
 
@@ -478,7 +480,7 @@
          * only after CASing head field, so uses relaxed write.
          */
         final void forgetNext() {
-            U.putObject(this, NEXT, this);
+            NEXT.set(this, this);
         }
 
         /**
@@ -491,8 +493,8 @@
          * else we don't care).
          */
         final void forgetContents() {
-            U.putObject(this, ITEM, this);
-            U.putObject(this, WAITER, null);
+            ITEM.set(this, this);
+            WAITER.set(this, null);
         }
 
         /**
@@ -537,19 +539,16 @@
 
         private static final long serialVersionUID = -3375979862319811754L;
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long ITEM;
-        private static final long NEXT;
-        private static final long WAITER;
+        // VarHandle mechanics
+        private static final VarHandle ITEM;
+        private static final VarHandle NEXT;
+        private static final VarHandle WAITER;
         static {
             try {
-                ITEM = U.objectFieldOffset
-                    (Node.class.getDeclaredField("item"));
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-                WAITER = U.objectFieldOffset
-                    (Node.class.getDeclaredField("waiter"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                ITEM = l.findVarHandle(Node.class, "item", Object.class);
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
+                WAITER = l.findVarHandle(Node.class, "waiter", Thread.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -567,15 +566,15 @@
 
     // CAS methods for fields
     private boolean casTail(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, TAIL, cmp, val);
+        return TAIL.compareAndSet(this, cmp, val);
     }
 
     private boolean casHead(Node cmp, Node val) {
-        return U.compareAndSwapObject(this, HEAD, cmp, val);
+        return HEAD.compareAndSet(this, cmp, val);
     }
 
     private boolean casSweepVotes(int cmp, int val) {
-        return U.compareAndSwapInt(this, SWEEPVOTES, cmp, val);
+        return SWEEPVOTES.compareAndSet(this, cmp, val);
     }
 
     /*
@@ -1562,20 +1561,19 @@
         }
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long HEAD;
-    private static final long TAIL;
-    private static final long SWEEPVOTES;
+    // VarHandle mechanics
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
+    private static final VarHandle SWEEPVOTES;
     static {
         try {
-            HEAD = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("tail"));
-            SWEEPVOTES = U.objectFieldOffset
-                (LinkedTransferQueue.class.getDeclaredField("sweepVotes"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            HEAD = l.findVarHandle(LinkedTransferQueue.class, "head",
+                                   Node.class);
+            TAIL = l.findVarHandle(LinkedTransferQueue.class, "tail",
+                                   Node.class);
+            SWEEPVOTES = l.findVarHandle(LinkedTransferQueue.class, "sweepVotes",
+                                         int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/Phaser.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.LockSupport;
 
@@ -221,7 +223,6 @@
  *   phaser.arriveAndDeregister();
  * }}</pre>
  *
- *
  * <p>To create a set of {@code n} tasks using a tree of phasers, you
  * could use code of the following form, assuming a Task class with a
  * constructor accepting a {@code Phaser} that it registers with upon
@@ -384,7 +385,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (U.compareAndSwapLong(this, STATE, s, s-=adjust)) {
+            if (STATE.compareAndSet(this, s, s-=adjust)) {
                 if (unarrived == 1) {
                     long n = s & PARTIES_MASK;  // base of next state
                     int nextUnarrived = (int)n >>> PARTIES_SHIFT;
@@ -397,12 +398,12 @@
                             n |= nextUnarrived;
                         int nextPhase = (phase + 1) & MAX_PHASE;
                         n |= (long)nextPhase << PHASE_SHIFT;
-                        U.compareAndSwapLong(this, STATE, s, n);
+                        STATE.compareAndSet(this, s, n);
                         releaseWaiters(phase);
                     }
                     else if (nextUnarrived == 0) { // propagate deregistration
                         phase = parent.doArrive(ONE_DEREGISTER);
-                        U.compareAndSwapLong(this, STATE, s, s | EMPTY);
+                        STATE.compareAndSet(this, s, s | EMPTY);
                     }
                     else
                         phase = parent.doArrive(ONE_ARRIVAL);
@@ -437,13 +438,13 @@
                 if (parent == null || reconcileState() == s) {
                     if (unarrived == 0)             // wait out advance
                         root.internalAwaitAdvance(phase, null);
-                    else if (U.compareAndSwapLong(this, STATE, s, s + adjust))
+                    else if (STATE.compareAndSet(this, s, s + adjust))
                         break;
                 }
             }
             else if (parent == null) {              // 1st root registration
                 long next = ((long)phase << PHASE_SHIFT) | adjust;
-                if (U.compareAndSwapLong(this, STATE, s, next))
+                if (STATE.compareAndSet(this, s, next))
                     break;
             }
             else {
@@ -455,8 +456,8 @@
                         // finish registration whenever parent registration
                         // succeeded, even when racing with termination,
                         // since these are part of the same "transaction".
-                        while (!U.compareAndSwapLong
-                               (this, STATE, s,
+                        while (!STATE.weakCompareAndSetVolatile
+                               (this, s,
                                 ((long)phase << PHASE_SHIFT) | adjust)) {
                             s = state;
                             phase = (int)(root.state >>> PHASE_SHIFT);
@@ -487,8 +488,8 @@
             // CAS to root phase with current parties, tripping unarrived
             while ((phase = (int)(root.state >>> PHASE_SHIFT)) !=
                    (int)(s >>> PHASE_SHIFT) &&
-                   !U.compareAndSwapLong
-                   (this, STATE, s,
+                   !STATE.weakCompareAndSetVolatile
+                   (this, s,
                     s = (((long)phase << PHASE_SHIFT) |
                          ((phase < 0) ? (s & COUNTS_MASK) :
                           (((p = (int)s >>> PARTIES_SHIFT) == 0) ? EMPTY :
@@ -677,7 +678,7 @@
             int unarrived = (counts == EMPTY) ? 0 : (counts & UNARRIVED_MASK);
             if (unarrived <= 0)
                 throw new IllegalStateException(badArrive(s));
-            if (U.compareAndSwapLong(this, STATE, s, s -= ONE_ARRIVAL)) {
+            if (STATE.compareAndSet(this, s, s -= ONE_ARRIVAL)) {
                 if (unarrived > 1)
                     return root.internalAwaitAdvance(phase, null);
                 if (root != this)
@@ -692,7 +693,7 @@
                     n |= nextUnarrived;
                 int nextPhase = (phase + 1) & MAX_PHASE;
                 n |= (long)nextPhase << PHASE_SHIFT;
-                if (!U.compareAndSwapLong(this, STATE, s, n))
+                if (!STATE.compareAndSet(this, s, n))
                     return (int)(state >>> PHASE_SHIFT); // terminated
                 releaseWaiters(phase);
                 return nextPhase;
@@ -808,7 +809,7 @@
         final Phaser root = this.root;
         long s;
         while ((s = root.state) >= 0) {
-            if (U.compareAndSwapLong(root, STATE, s, s | TERMINATION_BIT)) {
+            if (STATE.compareAndSet(root, s, s | TERMINATION_BIT)) {
                 // signal all threads
                 releaseWaiters(0); // Waiters on evenQ
                 releaseWaiters(1); // Waiters on oddQ
@@ -1043,6 +1044,8 @@
                     node = new QNode(this, phase, false, false, 0L);
                     node.wasInterrupted = interrupted;
                 }
+                else
+                    Thread.onSpinWait();
             }
             else if (node.isReleasable()) // done or aborted
                 break;
@@ -1131,14 +1134,12 @@
         }
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (Phaser.class.getDeclaredField("state"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(Phaser.class, "state", long.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/PriorityBlockingQueue.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Arrays;
 import java.util.Collection;
@@ -289,7 +291,7 @@
         lock.unlock(); // must release and then re-acquire main lock
         Object[] newArray = null;
         if (allocationSpinLock == 0 &&
-            U.compareAndSwapInt(this, ALLOCATIONSPINLOCK, 0, 1)) {
+            ALLOCATIONSPINLOCK.compareAndSet(this, 0, 1)) {
             try {
                 int newCap = oldCap + ((oldCap < 64) ?
                                        (oldCap + 2) : // grow faster if small
@@ -1009,13 +1011,14 @@
         return new PBQSpliterator<E>(this, null, 0, -1);
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long ALLOCATIONSPINLOCK;
+    // VarHandle mechanics
+    private static final VarHandle ALLOCATIONSPINLOCK;
     static {
         try {
-            ALLOCATIONSPINLOCK = U.objectFieldOffset
-                (PriorityBlockingQueue.class.getDeclaredField("allocationSpinLock"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            ALLOCATIONSPINLOCK = l.findVarHandle(PriorityBlockingQueue.class,
+                                                 "allocationSpinLock",
+                                                 int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.locks.LockSupport;
@@ -866,7 +868,7 @@
 
     /** Subscriber for method consume */
     private static final class ConsumerSubscriber<T>
-            implements Flow.Subscriber<T> {
+        implements Flow.Subscriber<T> {
         final CompletableFuture<Void> status;
         final Consumer<? super T> consumer;
         Flow.Subscription subscription;
@@ -906,7 +908,7 @@
      */
     @SuppressWarnings("serial")
     static final class ConsumerTask<T> extends ForkJoinTask<Void>
-        implements Runnable {
+        implements Runnable, CompletableFuture.AsynchronousCompletionTask {
         final BufferedSubscription<T> consumer;
         ConsumerTask(BufferedSubscription<T> consumer) {
             this.consumer = consumer;
@@ -959,11 +961,9 @@
      * Blocking control relies on the "waiter" field. Producers set
      * the field before trying to block, but must then recheck (via
      * offer) before parking. Signalling then just unparks and clears
-     * waiter field. If the producer and consumer are both in the same
-     * ForkJoinPool, or consumers are running in commonPool, the
-     * producer attempts to help run consumer tasks that it forked
-     * before blocking.  To avoid potential cycles, only one level of
-     * helping is currently supported.
+     * waiter field. If the producer and/or consumer are using a
+     * ForkJoinPool, the producer attempts to help run consumer tasks
+     * via ForkJoinPool.helpAsyncBlocker before blocking.
      *
      * This class uses @Contended and heuristic field declaration
      * ordering to reduce false-sharing-based memory contention among
@@ -983,7 +983,6 @@
         volatile long demand;              // # unfilled requests
         int maxCapacity;                   // reduced on OOME
         int putStat;                       // offer result for ManagedBlocker
-        int helpDepth;                     // nested helping depth (at most 1)
         volatile int ctl;                  // atomic run state flags
         volatile int head;                 // next position to take
         int tail;                          // next position to put
@@ -1077,7 +1076,7 @@
                 alloc = true;
             }
             else {
-                U.fullFence();                   // recheck
+                VarHandle.fullFence();           // recheck
                 int h = head, t = tail, size = t + 1 - h;
                 if (cap >= size) {
                     a[(cap - 1) & t] = item;
@@ -1116,10 +1115,10 @@
                         if (a != null && cap > 0) {
                             int mask = cap - 1;
                             for (int j = head; j != t; ++j) {
-                                long k = ((long)(j & mask) << ASHIFT) + ABASE;
-                                Object x = U.getObjectVolatile(a, k);
+                                int k = j & mask;
+                                Object x = QA.getAcquire(a, k);
                                 if (x != null && // races with consumer
-                                    U.compareAndSwapObject(a, k, x, null))
+                                    QA.compareAndSet(a, k, x, null))
                                     newArray[j & newMask] = x;
                             }
                         }
@@ -1136,28 +1135,20 @@
          * initial offer return 0.
          */
         final int submit(T item) {
-            int stat; Executor e; ForkJoinWorkerThread w;
-            if ((stat = offer(item)) == 0 && helpDepth == 0 &&
-                ((e = executor) instanceof ForkJoinPool)) {
-                helpDepth = 1;
-                Thread thread = Thread.currentThread();
-                if ((thread instanceof ForkJoinWorkerThread) &&
-                    ((w = (ForkJoinWorkerThread)thread)).getPool() == e)
-                    stat = internalHelpConsume(w.workQueue, item);
-                else if (e == ForkJoinPool.commonPool())
-                    stat = externalHelpConsume
-                        (ForkJoinPool.commonSubmitterQueue(), item);
-                helpDepth = 0;
-            }
-            if (stat == 0 && (stat = offer(item)) == 0) {
+            int stat;
+            if ((stat = offer(item)) == 0) {
                 putItem = item;
                 timeout = 0L;
-                try {
-                    ForkJoinPool.managedBlock(this);
-                } catch (InterruptedException ie) {
-                    timeout = INTERRUPTED;
+                putStat = 0;
+                ForkJoinPool.helpAsyncBlocker(executor, this);
+                if ((stat = putStat) == 0) {
+                    try {
+                        ForkJoinPool.managedBlock(this);
+                    } catch (InterruptedException ie) {
+                        timeout = INTERRUPTED;
+                    }
+                    stat = putStat;
                 }
-                stat = putStat;
                 if (timeout < 0L)
                     Thread.currentThread().interrupt();
             }
@@ -1165,71 +1156,22 @@
         }
 
         /**
-         * Tries helping for FJ submitter.
-         */
-        private int internalHelpConsume(ForkJoinPool.WorkQueue w, T item) {
-            int stat = 0;
-            if (w != null) {
-                ForkJoinTask<?> t;
-                while ((t = w.peek()) != null && (t instanceof ConsumerTask)) {
-                    if ((stat = offer(item)) != 0 || !w.tryUnpush(t))
-                        break;
-                    ((ConsumerTask<?>)t).consumer.consume();
-                }
-            }
-            return stat;
-        }
-
-        /**
-         * Tries helping for non-FJ submitter.
-         */
-        private int externalHelpConsume(ForkJoinPool.WorkQueue w, T item) {
-            int stat = 0;
-            if (w != null) {
-                ForkJoinTask<?> t;
-                while ((t = w.peek()) != null && (t instanceof ConsumerTask)) {
-                    if ((stat = offer(item)) != 0 || !w.trySharedUnpush(t))
-                        break;
-                    ((ConsumerTask<?>)t).consumer.consume();
-                }
-            }
-            return stat;
-        }
-
-        /**
          * Timeout version; similar to submit.
          */
         final int timedOffer(T item, long nanos) {
-            int stat; Executor e;
-            if ((stat = offer(item)) == 0 && helpDepth == 0 &&
-                ((e = executor) instanceof ForkJoinPool)) {
-                Thread thread = Thread.currentThread();
-                if (((thread instanceof ForkJoinWorkerThread) &&
-                     ((ForkJoinWorkerThread)thread).getPool() == e) ||
-                    e == ForkJoinPool.commonPool()) {
-                    helpDepth = 1;
-                    ForkJoinTask<?> t;
-                    long deadline = System.nanoTime() + nanos;
-                    while ((t = ForkJoinTask.peekNextLocalTask()) != null &&
-                           (t instanceof ConsumerTask)) {
-                        if ((stat = offer(item)) != 0 ||
-                            (nanos = deadline - System.nanoTime()) <= 0L ||
-                            !t.tryUnfork())
-                            break;
-                        ((ConsumerTask<?>)t).consumer.consume();
+            int stat;
+            if ((stat = offer(item)) == 0 && (timeout = nanos) > 0L) {
+                putItem = item;
+                putStat = 0;
+                ForkJoinPool.helpAsyncBlocker(executor, this);
+                if ((stat = putStat) == 0) {
+                    try {
+                        ForkJoinPool.managedBlock(this);
+                    } catch (InterruptedException ie) {
+                        timeout = INTERRUPTED;
                     }
-                    helpDepth = 0;
+                    stat = putStat;
                 }
-            }
-            if (stat == 0 && (stat = offer(item)) == 0 &&
-                (timeout = nanos) > 0L) {
-                putItem = item;
-                try {
-                    ForkJoinPool.managedBlock(this);
-                } catch (InterruptedException ie) {
-                    timeout = INTERRUPTED;
-                }
-                stat = putStat;
                 if (timeout < 0L)
                     Thread.currentThread().interrupt();
             }
@@ -1249,22 +1191,20 @@
                 }
                 else if ((c & ACTIVE) != 0) { // ensure keep-alive
                     if ((c & CONSUME) != 0 ||
-                        U.compareAndSwapInt(this, CTL, c,
-                                            c | CONSUME))
+                        CTL.compareAndSet(this, c, c | CONSUME))
                         break;
                 }
                 else if (demand == 0L || tail == head)
                     break;
-                else if (U.compareAndSwapInt(this, CTL, c,
-                                             c | (ACTIVE | CONSUME))) {
+                else if (CTL.compareAndSet(this, c, c | (ACTIVE | CONSUME))) {
                     try {
                         e.execute(new ConsumerTask<T>(this));
                         break;
                     } catch (RuntimeException | Error ex) { // back out
                         do {} while (((c = ctl) & DISABLED) == 0 &&
                                      (c & ACTIVE) != 0 &&
-                                     !U.compareAndSwapInt(this, CTL, c,
-                                                          c & ~ACTIVE));
+                                     !CTL.weakCompareAndSetVolatile
+                                     (this, c, c & ~ACTIVE));
                         throw ex;
                     }
                 }
@@ -1300,10 +1240,10 @@
                     break;
                 else if ((c & ACTIVE) != 0) {
                     pendingError = ex;
-                    if (U.compareAndSwapInt(this, CTL, c, c | ERROR))
+                    if (CTL.compareAndSet(this, c, c | ERROR))
                         break; // cause consumer task to exit
                 }
-                else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+                else if (CTL.compareAndSet(this, c, DISABLED)) {
                     Flow.Subscriber<? super T> s = subscriber;
                     if (s != null && ex != null) {
                         try {
@@ -1330,7 +1270,7 @@
                     for (int c;;) {
                         if ((c = ctl) == DISABLED || (c & ACTIVE) == 0)
                             break;
-                        if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE)) {
+                        if (CTL.compareAndSet(this, c, c & ~ACTIVE)) {
                             onError(ex);
                             break;
                         }
@@ -1343,8 +1283,8 @@
             for (int c;;) {
                 if ((c = ctl) == DISABLED)
                     break;
-                if (U.compareAndSwapInt(this, CTL, c,
-                                        c | (ACTIVE | CONSUME | COMPLETE))) {
+                if (CTL.compareAndSet(this, c,
+                                      c | (ACTIVE | CONSUME | COMPLETE))) {
                     if ((c & ACTIVE) == 0)
                         startOrDisable();
                     break;
@@ -1356,8 +1296,8 @@
             for (int c;;) {
                 if ((c = ctl) == DISABLED)
                     break;
-                if (U.compareAndSwapInt(this, CTL, c,
-                                        c | (ACTIVE | CONSUME | SUBSCRIBE))) {
+                if (CTL.compareAndSet(this, c,
+                                      c | (ACTIVE | CONSUME | SUBSCRIBE))) {
                     if ((c & ACTIVE) == 0)
                         startOrDisable();
                     break;
@@ -1375,11 +1315,11 @@
                 if ((c = ctl) == DISABLED)
                     break;
                 else if ((c & ACTIVE) != 0) {
-                    if (U.compareAndSwapInt(this, CTL, c,
-                                            c | (CONSUME | ERROR)))
+                    if (CTL.compareAndSet(this, c,
+                                          c | (CONSUME | ERROR)))
                         break;
                 }
-                else if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+                else if (CTL.compareAndSet(this, c, DISABLED)) {
                     detach();
                     break;
                 }
@@ -1395,19 +1335,18 @@
                     long prev = demand, d;
                     if ((d = prev + n) < prev) // saturate
                         d = Long.MAX_VALUE;
-                    if (U.compareAndSwapLong(this, DEMAND, prev, d)) {
+                    if (DEMAND.compareAndSet(this, prev, d)) {
                         for (int c, h;;) {
                             if ((c = ctl) == DISABLED)
                                 break;
                             else if ((c & ACTIVE) != 0) {
                                 if ((c & CONSUME) != 0 ||
-                                    U.compareAndSwapInt(this, CTL, c,
-                                                        c | CONSUME))
+                                    CTL.compareAndSet(this, c, c | CONSUME))
                                     break;
                             }
                             else if ((h = head) != tail) {
-                                if (U.compareAndSwapInt(this, CTL, c,
-                                                        c | (ACTIVE|CONSUME))) {
+                                if (CTL.compareAndSet(this, c,
+                                                      c | (ACTIVE|CONSUME))) {
                                     startOrDisable();
                                     break;
                                 }
@@ -1476,16 +1415,14 @@
             if ((s = subscriber) != null) {           // else disabled
                 for (;;) {
                     long d = demand;
-                    int c; Object[] a; int n; long i; Object x; Thread w;
+                    int c; Object[] a; int n, i; Object x; Thread w;
                     if (((c = ctl) & (ERROR | SUBSCRIBE | DISABLED)) != 0) {
                         if (!checkControl(s, c))
                             break;
                     }
                     else if ((a = array) == null || h == tail ||
                              (n = a.length) == 0 ||
-                             (x = U.getObjectVolatile
-                              (a, (i = ((long)((n - 1) & h) << ASHIFT) + ABASE)))
-                             == null) {
+                             (x = QA.getAcquire(a, i = (n - 1) & h)) == null) {
                         if (!checkEmpty(s, c))
                             break;
                     }
@@ -1494,10 +1431,10 @@
                             break;
                     }
                     else if (((c & CONSUME) != 0 ||
-                              U.compareAndSwapInt(this, CTL, c, c | CONSUME)) &&
-                             U.compareAndSwapObject(a, i, x, null)) {
-                        U.putIntRelease(this, HEAD, ++h);
-                        U.getAndAddLong(this, DEMAND, -1L);
+                              CTL.compareAndSet(this, c, c | CONSUME)) &&
+                             QA.compareAndSet(a, i, x, null)) {
+                        HEAD.setRelease(this, ++h);
+                        DEMAND.getAndAdd(this, -1L);
                         if ((w = waiter) != null)
                             signalWaiter(w);
                         try {
@@ -1528,7 +1465,7 @@
                 }
             }
             else if ((c & SUBSCRIBE) != 0) {
-                if (U.compareAndSwapInt(this, CTL, c, c & ~SUBSCRIBE)) {
+                if (CTL.compareAndSet(this, c, c & ~SUBSCRIBE)) {
                     try {
                         if (s != null)
                             s.onSubscribe(this);
@@ -1551,9 +1488,9 @@
             boolean stat = true;
             if (head == tail) {
                 if ((c & CONSUME) != 0)
-                    U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
+                    CTL.compareAndSet(this, c, c & ~CONSUME);
                 else if ((c & COMPLETE) != 0) {
-                    if (U.compareAndSwapInt(this, CTL, c, DISABLED)) {
+                    if (CTL.compareAndSet(this, c, DISABLED)) {
                         try {
                             if (s != null)
                                 s.onComplete();
@@ -1561,7 +1498,7 @@
                         }
                     }
                 }
-                else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE))
+                else if (CTL.compareAndSet(this, c, c & ~ACTIVE))
                     stat = false;
             }
             return stat;
@@ -1574,8 +1511,8 @@
             boolean stat = true;
             if (demand == 0L) {
                 if ((c & CONSUME) != 0)
-                    U.compareAndSwapInt(this, CTL, c, c & ~CONSUME);
-                else if (U.compareAndSwapInt(this, CTL, c, c & ~ACTIVE))
+                    CTL.compareAndSet(this, c, c & ~CONSUME);
+                else if (CTL.compareAndSet(this, c, c & ~ACTIVE))
                     stat = false;
             }
             return stat;
@@ -1595,31 +1532,25 @@
             onError(ex);
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long CTL;
-        private static final long TAIL;
-        private static final long HEAD;
-        private static final long DEMAND;
-        private static final int ABASE;
-        private static final int ASHIFT;
+        // VarHandle mechanics
+        private static final VarHandle CTL;
+        private static final VarHandle TAIL;
+        private static final VarHandle HEAD;
+        private static final VarHandle DEMAND;
+        private static final VarHandle QA;
 
         static {
             try {
-                CTL = U.objectFieldOffset
-                    (BufferedSubscription.class.getDeclaredField("ctl"));
-                TAIL = U.objectFieldOffset
-                    (BufferedSubscription.class.getDeclaredField("tail"));
-                HEAD = U.objectFieldOffset
-                    (BufferedSubscription.class.getDeclaredField("head"));
-                DEMAND = U.objectFieldOffset
-                    (BufferedSubscription.class.getDeclaredField("demand"));
-
-                ABASE = U.arrayBaseOffset(Object[].class);
-                int scale = U.arrayIndexScale(Object[].class);
-                if ((scale & (scale - 1)) != 0)
-                    throw new Error("data type scale not a power of two");
-                ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                CTL = l.findVarHandle(BufferedSubscription.class, "ctl",
+                                      int.class);
+                TAIL = l.findVarHandle(BufferedSubscription.class, "tail",
+                                       int.class);
+                HEAD = l.findVarHandle(BufferedSubscription.class, "head",
+                                       int.class);
+                DEMAND = l.findVarHandle(BufferedSubscription.class, "demand",
+                                         long.class);
+                QA = MethodHandles.arrayElementVarHandle(Object[].class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/SynchronousQueue.java	Mon Jul 18 09:38:08 2016 -0700
@@ -36,6 +36,8 @@
 
 package java.util.concurrent;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.AbstractQueue;
 import java.util.Collection;
 import java.util.Collections;
@@ -247,7 +249,7 @@
 
             boolean casNext(SNode cmp, SNode val) {
                 return cmp == next &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    SNEXT.compareAndSet(this, cmp, val);
             }
 
             /**
@@ -260,7 +262,7 @@
              */
             boolean tryMatch(SNode s) {
                 if (match == null &&
-                    U.compareAndSwapObject(this, MATCH, null, s)) {
+                    SMATCH.compareAndSet(this, null, s)) {
                     Thread w = waiter;
                     if (w != null) {    // waiters need at most one unpark
                         waiter = null;
@@ -275,24 +277,21 @@
              * Tries to cancel a wait by matching node to itself.
              */
             void tryCancel() {
-                U.compareAndSwapObject(this, MATCH, null, this);
+                SMATCH.compareAndSet(this, null, this);
             }
 
             boolean isCancelled() {
                 return match == this;
             }
 
-            // Unsafe mechanics
-            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-            private static final long MATCH;
-            private static final long NEXT;
-
+            // VarHandle mechanics
+            private static final VarHandle SMATCH;
+            private static final VarHandle SNEXT;
             static {
                 try {
-                    MATCH = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("match"));
-                    NEXT = U.objectFieldOffset
-                        (SNode.class.getDeclaredField("next"));
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+                    SMATCH = l.findVarHandle(SNode.class, "match", SNode.class);
+                    SNEXT = l.findVarHandle(SNode.class, "next", SNode.class);
                 } catch (ReflectiveOperationException e) {
                     throw new Error(e);
                 }
@@ -304,7 +303,7 @@
 
         boolean casHead(SNode h, SNode nh) {
             return h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh);
+                SHEAD.compareAndSet(this, h, nh);
         }
 
         /**
@@ -451,8 +450,10 @@
                         continue;
                     }
                 }
-                if (spins > 0)
+                if (spins > 0) {
+                    Thread.onSpinWait();
                     spins = shouldSpin(s) ? (spins - 1) : 0;
+                }
                 else if (s.waiter == null)
                     s.waiter = w; // establish waiter so can park next iter
                 else if (!timed)
@@ -508,13 +509,12 @@
             }
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
+        // VarHandle mechanics
+        private static final VarHandle SHEAD;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferStack.class.getDeclaredField("head"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                SHEAD = l.findVarHandle(TransferStack.class, "head", SNode.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -546,19 +546,19 @@
 
             boolean casNext(QNode cmp, QNode val) {
                 return next == cmp &&
-                    U.compareAndSwapObject(this, NEXT, cmp, val);
+                    QNEXT.compareAndSet(this, cmp, val);
             }
 
             boolean casItem(Object cmp, Object val) {
                 return item == cmp &&
-                    U.compareAndSwapObject(this, ITEM, cmp, val);
+                    QITEM.compareAndSet(this, cmp, val);
             }
 
             /**
              * Tries to cancel by CAS'ing ref to this as item.
              */
             void tryCancel(Object cmp) {
-                U.compareAndSwapObject(this, ITEM, cmp, this);
+                QITEM.compareAndSet(this, cmp, this);
             }
 
             boolean isCancelled() {
@@ -574,17 +574,14 @@
                 return next == this;
             }
 
-            // Unsafe mechanics
-            private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-            private static final long ITEM;
-            private static final long NEXT;
-
+            // VarHandle mechanics
+            private static final VarHandle QITEM;
+            private static final VarHandle QNEXT;
             static {
                 try {
-                    ITEM = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("item"));
-                    NEXT = U.objectFieldOffset
-                        (QNode.class.getDeclaredField("next"));
+                    MethodHandles.Lookup l = MethodHandles.lookup();
+                    QITEM = l.findVarHandle(QNode.class, "item", Object.class);
+                    QNEXT = l.findVarHandle(QNode.class, "next", QNode.class);
                 } catch (ReflectiveOperationException e) {
                     throw new Error(e);
                 }
@@ -614,7 +611,7 @@
          */
         void advanceHead(QNode h, QNode nh) {
             if (h == head &&
-                U.compareAndSwapObject(this, HEAD, h, nh))
+                QHEAD.compareAndSet(this, h, nh))
                 h.next = h; // forget old next
         }
 
@@ -623,7 +620,7 @@
          */
         void advanceTail(QNode t, QNode nt) {
             if (tail == t)
-                U.compareAndSwapObject(this, TAIL, t, nt);
+                QTAIL.compareAndSet(this, t, nt);
         }
 
         /**
@@ -631,7 +628,7 @@
          */
         boolean casCleanMe(QNode cmp, QNode val) {
             return cleanMe == cmp &&
-                U.compareAndSwapObject(this, CLEANME, cmp, val);
+                QCLEANME.compareAndSet(this, cmp, val);
         }
 
         /**
@@ -752,8 +749,10 @@
                         continue;
                     }
                 }
-                if (spins > 0)
+                if (spins > 0) {
                     --spins;
+                    Thread.onSpinWait();
+                }
                 else if (s.waiter == null)
                     s.waiter = w;
                 else if (!timed)
@@ -817,18 +816,19 @@
             }
         }
 
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long HEAD;
-        private static final long TAIL;
-        private static final long CLEANME;
+        // VarHandle mechanics
+        private static final VarHandle QHEAD;
+        private static final VarHandle QTAIL;
+        private static final VarHandle QCLEANME;
         static {
             try {
-                HEAD = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("head"));
-                TAIL = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("tail"));
-                CLEANME = U.objectFieldOffset
-                    (TransferQueue.class.getDeclaredField("cleanMe"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                QHEAD = l.findVarHandle(TransferQueue.class, "head",
+                                        QNode.class);
+                QTAIL = l.findVarHandle(TransferQueue.class, "tail",
+                                        QNode.class);
+                QCLEANME = l.findVarHandle(TransferQueue.class, "cleanMe",
+                                           QNode.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java	Mon Jul 18 09:38:08 2016 -0700
@@ -36,6 +36,7 @@
 package java.util.concurrent;
 
 import java.io.ObjectStreamField;
+import java.security.AccessControlContext;
 import java.util.Random;
 import java.util.Spliterator;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -47,6 +48,7 @@
 import java.util.stream.IntStream;
 import java.util.stream.LongStream;
 import java.util.stream.StreamSupport;
+import jdk.internal.misc.Unsafe;
 
 /**
  * A random number generator isolated to the current thread.  Like the
@@ -95,7 +97,9 @@
      * ThreadLocalRandom sequence.  The dual use is a marriage of
      * convenience, but is a simple and efficient way of reducing
      * application-level overhead and footprint of most concurrent
-     * programs.
+     * programs. Even more opportunistically, we also define here
+     * other package-private utilities that access Thread class
+     * fields.
      *
      * Even though this class subclasses java.util.Random, it uses the
      * same basic algorithm as java.util.SplittableRandom.  (See its
@@ -958,6 +962,49 @@
         return r;
     }
 
+    // Support for other package-private ThreadLocal access
+
+    /**
+     * Erases ThreadLocals by nulling out Thread maps.
+     */
+    static final void eraseThreadLocals(Thread thread) {
+        U.putObject(thread, THREADLOCALS, null);
+        U.putObject(thread, INHERITABLETHREADLOCALS, null);
+    }
+
+    static final void setInheritedAccessControlContext(Thread thread,
+                                                       AccessControlContext acc) {
+        U.putObjectRelease(thread, INHERITEDACCESSCONTROLCONTEXT, acc);
+    }
+
+    /**
+     * Returns a new group with the system ThreadGroup (the
+     * topmost, parent-less group) as parent.  Uses Unsafe to
+     * traverse Thread.group and ThreadGroup.parent fields.
+     */
+    static final ThreadGroup createThreadGroup(String name) {
+        if (name == null)
+            throw new NullPointerException();
+        try {
+            long tg = U.objectFieldOffset
+                (Thread.class.getDeclaredField("group"));
+            long gp = U.objectFieldOffset
+                (ThreadGroup.class.getDeclaredField("parent"));
+            ThreadGroup group = (ThreadGroup)
+                U.getObject(Thread.currentThread(), tg);
+            while (group != null) {
+                ThreadGroup parent = (ThreadGroup)U.getObject(group, gp);
+                if (parent == null)
+                    return new ThreadGroup(group, name);
+                group = parent;
+            }
+        } catch (ReflectiveOperationException e) {
+            throw new Error(e);
+        }
+        // fall through if null as cannot-happen safeguard
+        throw new Error("Cannot create ThreadGroup");
+    }
+
     // Serialization support
 
     private static final long serialVersionUID = -5851777807851030925L;
@@ -1022,10 +1069,13 @@
     static final String BAD_SIZE  = "size must be non-negative";
 
     // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long SEED;
     private static final long PROBE;
     private static final long SECONDARY;
+    private static final long THREADLOCALS;
+    private static final long INHERITABLETHREADLOCALS;
+    private static final long INHERITEDACCESSCONTROLCONTEXT;
     static {
         try {
             SEED = U.objectFieldOffset
@@ -1034,6 +1084,12 @@
                 (Thread.class.getDeclaredField("threadLocalRandomProbe"));
             SECONDARY = U.objectFieldOffset
                 (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+            THREADLOCALS = U.objectFieldOffset
+                (Thread.class.getDeclaredField("threadLocals"));
+            INHERITABLETHREADLOCALS = U.objectFieldOffset
+                (Thread.class.getDeclaredField("inheritableThreadLocals"));
+            INHERITEDACCESSCONTROLCONTEXT = U.objectFieldOffset
+                (Thread.class.getDeclaredField("inheritedAccessControlContext"));
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicBoolean.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,27 +35,26 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * A {@code boolean} value that may be updated atomically. See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicBoolean} is used in applications such as atomically
- * updated flags, and cannot be used as a replacement for a
- * {@link java.lang.Boolean}.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicBoolean} is used in
+ * applications such as atomically updated flags, and cannot be used
+ * as a replacement for a {@link java.lang.Boolean}.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicBoolean implements java.io.Serializable {
     private static final long serialVersionUID = 4654671469794556979L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicBoolean.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicBoolean.class, "value", int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -79,7 +78,8 @@
     }
 
     /**
-     * Returns the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -88,40 +88,39 @@
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+    public final boolean compareAndSet(boolean expectedValue, boolean newValue) {
+        return VALUE.compareAndSet(this,
+                                   (expectedValue ? 1 : 0),
+                                   (newValue ? 1 : 0));
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
-     *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public boolean weakCompareAndSet(boolean expect, boolean update) {
-        return U.compareAndSwapInt(this, VALUE,
-                                   (expect ? 1 : 0),
-                                   (update ? 1 : 0));
+    public boolean weakCompareAndSet(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSet(this,
+                                       (expectedValue ? 1 : 0),
+                                       (newValue ? 1 : 0));
     }
 
     /**
-     * Unconditionally sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -130,17 +129,19 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(boolean newValue) {
-        U.putIntRelease(this, VALUE, (newValue ? 1 : 0));
+        VALUE.setRelease(this, (newValue ? 1 : 0));
     }
 
     /**
-     * Atomically sets to the given value and returns the previous value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
@@ -161,4 +162,178 @@
         return Boolean.toString(get());
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getPlain() {
+        return (int)VALUE.get(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(boolean newValue) {
+        VALUE.set(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getOpaque() {
+        return (int)VALUE.getOpaque(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(boolean newValue) {
+        VALUE.setOpaque(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final boolean getAcquire() {
+        return (int)VALUE.getAcquire(this) != 0;
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(boolean newValue) {
+        VALUE.setRelease(this, newValue ? 1 : 0);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchange(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchange(this,
+                                             (expectedValue ? 1 : 0),
+                                             (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchangeAcquire(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchangeAcquire(this,
+                                                    (expectedValue ? 1 : 0),
+                                                    (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final boolean compareAndExchangeRelease(boolean expectedValue, boolean newValue) {
+        return (int)VALUE.compareAndExchangeRelease(this,
+                                                    (expectedValue ? 1 : 0),
+                                                    (newValue ? 1 : 0)) != 0;
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetVolatile(this,
+                                               (expectedValue ? 1 : 0),
+                                               (newValue ? 1 : 0));
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetAcquire(this,
+                                              (expectedValue ? 1 : 0),
+                                              (newValue ? 1 : 0));
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if the current
+     * value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(boolean expectedValue, boolean newValue) {
+        return VALUE.weakCompareAndSetRelease(this,
+                                              (expectedValue ? 1 : 0),
+                                              (newValue ? 1 : 0));
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicInteger.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,32 +35,30 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 
 /**
  * An {@code int} value that may be updated atomically.  See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicInteger} is used in applications such as atomically
- * incremented counters, and cannot be used as a replacement for an
- * {@link java.lang.Integer}. However, this class does extend
- * {@code Number} to allow uniform access by tools and utilities that
- * deal with numerically-based classes.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicInteger} is used in
+ * applications such as atomically incremented counters, and cannot be
+ * used as a replacement for an {@link java.lang.Integer}. However,
+ * this class does extend {@code Number} to allow uniform access by
+ * tools and utilities that deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicInteger extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 6214790243416807050L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicInteger.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicInteger.class, "value", int.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -84,7 +82,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -93,7 +92,8 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -102,108 +102,122 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int newValue) {
-        U.putIntRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final int getAndSet(int newValue) {
-        return U.getAndSetInt(this, VALUE, newValue);
+        return (int)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+    public final boolean compareAndSet(int expectedValue, int newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
-     *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int expect, int update) {
-        return U.compareAndSwapInt(this, VALUE, expect, update);
+    public final boolean weakCompareAndSet(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(1)}.
      *
      * @return the previous value
      */
     public final int getAndIncrement() {
-        return U.getAndAddInt(this, VALUE, 1);
+        return (int)VALUE.getAndAdd(this, 1);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(-1)}.
      *
      * @return the previous value
      */
     public final int getAndDecrement() {
-        return U.getAndAddInt(this, VALUE, -1);
+        return (int)VALUE.getAndAdd(this, -1);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the previous value
      */
     public final int getAndAdd(int delta) {
-        return U.getAndAddInt(this, VALUE, delta);
+        return (int)VALUE.getAndAdd(this, delta);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(1)}.
      *
      * @return the updated value
      */
     public final int incrementAndGet() {
-        return U.getAndAddInt(this, VALUE, 1) + 1;
+        return (int)VALUE.addAndGet(this, 1);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(-1)}.
      *
      * @return the updated value
      */
     public final int decrementAndGet() {
-        return U.getAndAddInt(this, VALUE, -1) - 1;
+        return (int)VALUE.addAndGet(this, -1);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param delta the value to add
      * @return the updated value
      */
     public final int addAndGet(int delta) {
-        return U.getAndAddInt(this, VALUE, delta) + delta;
+        return (int)VALUE.addAndGet(this, delta);
     }
 
     /**
@@ -217,12 +231,14 @@
      * @since 1.8
      */
     public final int getAndUpdate(IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -236,12 +252,14 @@
      * @since 1.8
      */
     public final int updateAndGet(IntUnaryOperator updateFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -260,12 +278,14 @@
      */
     public final int getAndAccumulate(int x,
                                       IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -284,12 +304,14 @@
      */
     public final int accumulateAndGet(int x,
                                       IntBinaryOperator accumulatorFunction) {
-        int prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        int prev = get(), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -301,7 +323,10 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as an {@code int}.
+     * Returns the current value of this {@code AtomicInteger} as an
+     * {@code int},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
+     *
      * Equivalent to {@link #get()}.
      */
     public int intValue() {
@@ -309,8 +334,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code long}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code long} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public long longValue() {
@@ -318,8 +344,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code float}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code float} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
@@ -327,12 +354,175 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicInteger} as a {@code double}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicInteger} as a
+     * {@code double} after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getPlain() {
+        return (int)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getOpaque() {
+        return (int)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final int getAcquire() {
+        return (int)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchange(int expectedValue, int newValue) {
+        return (int)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeAcquire(int expectedValue, int newValue) {
+        return (int)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeRelease(int expectedValue, int newValue) {
+        return (int)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue} if
+     * the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int expectedValue, int newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerArray.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,44 +35,24 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
 
 /**
  * An {@code int} array in which elements may be updated atomically.
- * See the {@link java.util.concurrent.atomic} package
- * specification for description of the properties of atomic
- * variables.
+ * See the {@link VarHandle} specification for descriptions of the
+ * properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicIntegerArray implements java.io.Serializable {
     private static final long serialVersionUID = 2862133569453604235L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(int[].class);
     private final int[] array;
 
-    static {
-        ABASE = U.arrayBaseOffset(int[].class);
-        int scale = U.arrayIndexScale(int[].class);
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicIntegerArray of the given length, with all
      * elements initially zero.
@@ -105,147 +85,155 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
     public final int get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    private int getRaw(long offset) {
-        return U.getIntVolatile(array, offset);
+        return (int)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, int newValue) {
-        U.putIntVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, int newValue) {
-        U.putIntRelease(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * value and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
      * @return the previous value
      */
     public final int getAndSet(int i, int newValue) {
-        return U.getAndSetInt(array, checkedByteOffset(i), newValue);
+        return (int)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int i, int expect, int update) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, int expect, int update) {
-        return U.compareAndSwapInt(array, offset, expect, update);
+    public final boolean compareAndSet(int i, int expectedValue, int newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int i, int expect, int update) {
-        return compareAndSet(i, expect, update);
+    public final boolean weakCompareAndSet(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, 1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final int getAndIncrement(int i) {
-        return getAndAdd(i, 1);
+        return (int)AA.getAndAdd(array, i, 1);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, -1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final int getAndDecrement(int i) {
-        return getAndAdd(i, -1);
+        return (int)AA.getAndAdd(array, i, -1);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the previous value
      */
     public final int getAndAdd(int i, int delta) {
-        return U.getAndAddInt(array, checkedByteOffset(i), delta);
+        return (int)AA.getAndAdd(array, i, delta);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, 1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final int incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return (int)AA.addAndGet(array, i, 1);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, -1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final int decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return (int)AA.addAndGet(array, i, -1);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the updated value
      */
     public final int addAndGet(int i, int delta) {
-        return getAndAdd(i, delta) + delta;
+        return (int)AA.addAndGet(array, i, delta);
     }
 
     /**
@@ -260,13 +248,14 @@
      * @since 1.8
      */
     public final int getAndUpdate(int i, IntUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -281,23 +270,25 @@
      * @since 1.8
      */
     public final int updateAndGet(int i, IntUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsInt(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsInt(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the previous value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
+     * results of applying the given function to the current and given
+     * values, returning the previous value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -307,23 +298,25 @@
      */
     public final int getAndAccumulate(int i, int x,
                                       IntBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the updated value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
+     * results of applying the given function to the current and given
+     * values, returning the updated value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -333,13 +326,14 @@
      */
     public final int accumulateAndGet(int i, int x,
                                       IntBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        int prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsInt(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        int prev = get(i), next = 0;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsInt(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -354,11 +348,190 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
         }
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getPlain(int i) {
+        return (int)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, int newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getOpaque(int i) {
+        return (int)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, int newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final int getAcquire(int i) {
+        return (int)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, int newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchange(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeAcquire(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final int compareAndExchangeRelease(int i, int expectedValue, int newValue) {
+        return (int)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetVolatile(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, int expectedValue, int newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
+    }
+
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java	Mon Jul 18 09:38:08 2016 -0700
@@ -42,6 +42,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.IntBinaryOperator;
 import java.util.function.IntUnaryOperator;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -150,8 +151,8 @@
     public abstract void lazySet(T obj, int newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -367,7 +368,7 @@
      */
     private static final class AtomicIntegerFieldUpdaterImpl<T>
         extends AtomicIntegerFieldUpdater<T> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLong.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,31 +35,30 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 
 /**
  * A {@code long} value that may be updated atomically.  See the
- * {@link java.util.concurrent.atomic} package specification for
- * description of the properties of atomic variables. An
- * {@code AtomicLong} is used in applications such as atomically
- * incremented sequence numbers, and cannot be used as a replacement
- * for a {@link java.lang.Long}. However, this class does extend
- * {@code Number} to allow uniform access by tools and utilities that
- * deal with numerically-based classes.
+ * {@link VarHandle} specification for descriptions of the properties
+ * of atomic accesses. An {@code AtomicLong} is used in applications
+ * such as atomically incremented sequence numbers, and cannot be used
+ * as a replacement for a {@link java.lang.Long}. However, this class
+ * does extend {@code Number} to allow uniform access by tools and
+ * utilities that deal with numerically-based classes.
  *
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicLong extends Number implements java.io.Serializable {
     private static final long serialVersionUID = 1927816293512124184L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
+    private static final VarHandle VALUE;
 
     /**
      * Records whether the underlying JVM supports lockless
-     * compareAndSwap for longs. While the Unsafe.compareAndSwapLong
+     * compareAndSwap for longs. While the intrinsic compareAndSwapLong
      * method works in either case, some constructions should be
      * handled at Java level to avoid locking user-visible locks.
      */
@@ -73,8 +72,8 @@
 
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicLong.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicLong.class, "value", long.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -98,7 +97,8 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
@@ -107,119 +107,132 @@
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
     public final void set(long newValue) {
-        // Use putLongVolatile instead of ordinary volatile store when
-        // using compareAndSwapLong, for sake of some 32bit systems.
-        U.putLongVolatile(this, VALUE, newValue);
+        VALUE.setVolatile(this, newValue);
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(long newValue) {
-        U.putLongRelease(this, VALUE, newValue);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     public final long getAndSet(long newValue) {
-        return U.getAndSetLong(this, VALUE, newValue);
+        return (long)VALUE.getAndSet(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+    public final boolean compareAndSet(long expectedValue, long newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
-     *
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(long expect, long update) {
-        return U.compareAndSwapLong(this, VALUE, expect, update);
+    public final boolean weakCompareAndSet(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(1)}.
      *
      * @return the previous value
      */
     public final long getAndIncrement() {
-        return U.getAndAddLong(this, VALUE, 1L);
+        return (long)VALUE.getAndAdd(this, 1L);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(-1)}.
      *
      * @return the previous value
      */
     public final long getAndDecrement() {
-        return U.getAndAddLong(this, VALUE, -1L);
+        return (long)VALUE.getAndAdd(this, -1L);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param delta the value to add
      * @return the previous value
      */
     public final long getAndAdd(long delta) {
-        return U.getAndAddLong(this, VALUE, delta);
+        return (long)VALUE.getAndAdd(this, delta);
     }
 
     /**
-     * Atomically increments by one the current value.
+     * Atomically increments the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(1)}.
      *
      * @return the updated value
      */
     public final long incrementAndGet() {
-        return U.getAndAddLong(this, VALUE, 1L) + 1L;
+        return (long)VALUE.addAndGet(this, 1L);
     }
 
     /**
-     * Atomically decrements by one the current value.
+     * Atomically decrements the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(-1)}.
      *
      * @return the updated value
      */
     public final long decrementAndGet() {
-        return U.getAndAddLong(this, VALUE, -1L) - 1L;
+        return (long)VALUE.addAndGet(this, -1L);
     }
 
     /**
-     * Atomically adds the given value to the current value.
+     * Atomically adds the given value to the current value,
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param delta the value to add
      * @return the updated value
      */
     public final long addAndGet(long delta) {
-        return U.getAndAddLong(this, VALUE, delta) + delta;
+        return (long)VALUE.addAndGet(this, delta);
     }
 
     /**
@@ -233,12 +246,14 @@
      * @since 1.8
      */
     public final long getAndUpdate(LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -252,12 +267,14 @@
      * @since 1.8
      */
     public final long updateAndGet(LongUnaryOperator updateFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -276,12 +293,14 @@
      */
     public final long getAndAccumulate(long x,
                                        LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -300,12 +319,14 @@
      */
     public final long accumulateAndGet(long x,
                                        LongBinaryOperator accumulatorFunction) {
-        long prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        long prev = get(), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -317,8 +338,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as an {@code int}
-     * after a narrowing primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as an {@code int}
+     * after a narrowing primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.3 Narrowing Primitive Conversions
      */
     public int intValue() {
@@ -326,7 +348,8 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code long}.
+     * Returns the current value of this {@code AtomicLong} as a {@code long},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * Equivalent to {@link #get()}.
      */
     public long longValue() {
@@ -334,8 +357,9 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code float}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as a {@code float}
+     * after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public float floatValue() {
@@ -343,12 +367,175 @@
     }
 
     /**
-     * Returns the value of this {@code AtomicLong} as a {@code double}
-     * after a widening primitive conversion.
+     * Returns the current value of this {@code AtomicLong} as a {@code double}
+     * after a widening primitive conversion,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      * @jls 5.1.2 Widening Primitive Conversions
      */
     public double doubleValue() {
         return (double)get();
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as if the
+     * variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getPlain() {
+        return (long)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(long newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getOpaque() {
+        return (long)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(long newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final long getAcquire() {
+        return (long)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(long newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchange(long expectedValue, long newValue) {
+        return (long)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeAcquire(long expectedValue, long newValue) {
+        return (long)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeRelease(long expectedValue, long newValue) {
+        return (long)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(long expectedValue, long newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongArray.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,43 +35,24 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
 
 /**
  * A {@code long} array in which elements may be updated atomically.
- * See the {@link java.util.concurrent.atomic} package specification
- * for description of the properties of atomic variables.
+ * See the {@link VarHandle} specification for descriptions of the
+ * properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  */
 public class AtomicLongArray implements java.io.Serializable {
     private static final long serialVersionUID = -2308431214976778248L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(long[].class);
     private final long[] array;
 
-    static {
-        ABASE = U.arrayBaseOffset(long[].class);
-        int scale = U.arrayIndexScale(long[].class);
-        if ((scale & (scale - 1)) != 0)
-            throw new Error("array index scale not a power of two");
-        ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicLongArray of the given length, with all
      * elements initially zero.
@@ -104,147 +85,155 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
     public final long get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    private long getRaw(long offset) {
-        return U.getLongVolatile(array, offset);
+        return (long)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, long newValue) {
-        U.putLongVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, long newValue) {
-        U.putLongRelease(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given value
-     * and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
      * @return the previous value
      */
     public final long getAndSet(int i, long newValue) {
-        return U.getAndSetLong(array, checkedByteOffset(i), newValue);
+        return (long)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int i, long expect, long update) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, long expect, long update) {
-        return U.compareAndSwapLong(array, offset, expect, update);
+    public final boolean compareAndSet(int i, long expectedValue, long newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int i, long expect, long update) {
-        return compareAndSet(i, expect, update);
+    public final boolean weakCompareAndSet(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, 1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final long getAndIncrement(int i) {
-        return getAndAdd(i, 1);
+        return (long)AA.getAndAdd(array, i, 1L);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
+     *
+     * <p>Equivalent to {@code getAndAdd(i, -1)}.
      *
      * @param i the index
      * @return the previous value
      */
     public final long getAndDecrement(int i) {
-        return getAndAdd(i, -1);
+        return (long)AA.getAndAdd(array, i, -1L);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAndAdd}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the previous value
      */
     public final long getAndAdd(int i, long delta) {
-        return U.getAndAddLong(array, checkedByteOffset(i), delta);
+        return (long)AA.getAndAdd(array, i, delta);
     }
 
     /**
-     * Atomically increments by one the element at index {@code i}.
+     * Atomically increments the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, 1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final long incrementAndGet(int i) {
-        return getAndAdd(i, 1) + 1;
+        return (long)AA.addAndGet(array, i, 1L);
     }
 
     /**
-     * Atomically decrements by one the element at index {@code i}.
+     * Atomically decrements the value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
+     *
+     * <p>Equivalent to {@code addAndGet(i, -1)}.
      *
      * @param i the index
      * @return the updated value
      */
     public final long decrementAndGet(int i) {
-        return getAndAdd(i, -1) - 1;
+        return (long)AA.addAndGet(array, i, -1L);
     }
 
     /**
-     * Atomically adds the given value to the element at index {@code i}.
+     * Atomically adds the given value to the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#addAndGet}.
      *
      * @param i the index
      * @param delta the value to add
      * @return the updated value
      */
     public long addAndGet(int i, long delta) {
-        return getAndAdd(i, delta) + delta;
+        return (long)AA.addAndGet(array, i, delta);
     }
 
     /**
@@ -259,13 +248,14 @@
      * @since 1.8
      */
     public final long getAndUpdate(int i, LongUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -280,23 +270,25 @@
      * @since 1.8
      */
     public final long updateAndGet(int i, LongUnaryOperator updateFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.applyAsLong(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.applyAsLong(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the previous value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
+     * results of applying the given function to the current and given
+     * values, returning the previous value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -306,23 +298,25 @@
      */
     public final long getAndAccumulate(int i, long x,
                                       LongBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the updated value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
+     * results of applying the given function to the current and given
+     * values, returning the updated value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -332,13 +326,14 @@
      */
     public final long accumulateAndGet(int i, long x,
                                       LongBinaryOperator accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        long prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.applyAsLong(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        long prev = get(i), next = 0L;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.applyAsLong(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -353,11 +348,189 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
         }
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getPlain(int i) {
+        return (long)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, long newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getOpaque(int i) {
+        return (long)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, long newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final long getAcquire(int i) {
+        return (long)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, long newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchange(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeAcquire(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final long compareAndExchangeRelease(int i, long expectedValue, long newValue) {
+        return (long)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetVolatile(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, long expectedValue, long newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java	Mon Jul 18 09:38:08 2016 -0700
@@ -42,6 +42,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.LongBinaryOperator;
 import java.util.function.LongUnaryOperator;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -153,8 +154,8 @@
     public abstract void lazySet(T obj, long newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -366,7 +367,7 @@
     }
 
     private static final class CASUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
@@ -497,7 +498,7 @@
     }
 
     private static final class LockedUpdater<T> extends AtomicLongFieldUpdater<T> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicMarkableReference.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * An {@code AtomicMarkableReference} maintains an object reference
  * along with a mark bit, that can be updated atomically.
@@ -188,20 +191,19 @@
              casPair(current, Pair.of(expectedReference, newMark)));
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
+    // VarHandle mechanics
+    private static final VarHandle PAIR;
     static {
         try {
-            PAIR = U.objectFieldOffset
-                (AtomicMarkableReference.class.getDeclaredField("pair"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PAIR = l.findVarHandle(AtomicMarkableReference.class, "pair",
+                                   Pair.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return PAIR.compareAndSet(this, cmp, val);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReference.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,33 +35,32 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 
 /**
- * An object reference that may be updated atomically. See the {@link
- * java.util.concurrent.atomic} package specification for description
- * of the properties of atomic variables.
+ * An object reference that may be updated atomically.  See the {@link
+ * VarHandle} specification for descriptions of the properties of
+ * atomic accesses.
  * @since 1.5
  * @author Doug Lea
  * @param <V> The type of object referred to by this reference
  */
 public class AtomicReference<V> implements java.io.Serializable {
     private static final long serialVersionUID = -1848883965231344442L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long VALUE;
-
+    private static final VarHandle VALUE;
     static {
         try {
-            VALUE = U.objectFieldOffset
-                (AtomicReference.class.getDeclaredField("value"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            VALUE = l.findVarHandle(AtomicReference.class, "value", Object.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
 
-    private volatile V value;
+    private volatile Object value;
 
     /**
      * Creates a new AtomicReference with the given initial value.
@@ -79,16 +78,19 @@
     }
 
     /**
-     * Gets the current value.
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @return the current value
      */
+    @SuppressWarnings("unchecked")
     public final V get() {
-        return value;
+        return (V)value;
     }
 
     /**
-     * Sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param newValue the new value
      */
@@ -97,52 +99,53 @@
     }
 
     /**
-     * Eventually sets to the given value.
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(V newValue) {
-        U.putObjectRelease(this, VALUE, newValue);
-    }
-
-    /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
-     * @param expect the expected value
-     * @param update the new value
-     * @return {@code true} if successful. False return indicates that
-     * the actual value was not equal to the expected value.
-     */
-    public final boolean compareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+        VALUE.setRelease(this, newValue);
     }
 
     /**
-     * Atomically sets the value to the given updated value
-     * if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
-     * @param expect the expected value
-     * @param update the new value
-     * @return {@code true} if successful
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful. False return indicates that
+     * the actual value was not equal to the expected value.
      */
-    public final boolean weakCompareAndSet(V expect, V update) {
-        return U.compareAndSwapObject(this, VALUE, expect, update);
+    public final boolean compareAndSet(V expectedValue, V newValue) {
+        return VALUE.compareAndSet(this, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets to the given value and returns the old value.
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     */
+    public final boolean weakCompareAndSet(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSet(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param newValue the new value
      * @return the previous value
      */
     @SuppressWarnings("unchecked")
     public final V getAndSet(V newValue) {
-        return (V)U.getAndSetObject(this, VALUE, newValue);
+        return (V)VALUE.getAndSet(this, newValue);
     }
 
     /**
@@ -156,12 +159,14 @@
      * @since 1.8
      */
     public final V getAndUpdate(UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -175,12 +180,14 @@
      * @since 1.8
      */
     public final V updateAndGet(UnaryOperator<V> updateFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = updateFunction.apply(prev);
-        } while (!compareAndSet(prev, next));
-        return next;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -199,12 +206,14 @@
      */
     public final V getAndAccumulate(V x,
                                     BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(prev, next));
-        return prev;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return prev;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -223,12 +232,14 @@
      */
     public final V accumulateAndGet(V x,
                                     BinaryOperator<V> accumulatorFunction) {
-        V prev, next;
-        do {
-            prev = get();
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSet(prev, next));
-        return next;
+        V prev = get(), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(prev, next))
+                return next;
+            haveNext = (prev == (prev = get()));
+        }
     }
 
     /**
@@ -239,4 +250,166 @@
         return String.valueOf(get());
     }
 
+    // jdk9
+
+    /**
+     * Returns the current value, with memory semantics of reading as
+     * if the variable was declared non-{@code volatile}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getPlain() {
+        return (V)VALUE.get(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue}, with memory semantics
+     * of setting as if the variable was declared non-{@code volatile}
+     * and non-{@code final}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(V newValue) {
+        VALUE.set(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getOpaque() {
+        return (V)VALUE.getOpaque(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(V newValue) {
+        VALUE.setOpaque(this, newValue);
+    }
+
+    /**
+     * Returns the current value,
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @return the value
+     * @since 9
+     */
+    public final V getAcquire() {
+        return (V)VALUE.getAcquire(this);
+    }
+
+    /**
+     * Sets the value to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(V newValue) {
+        VALUE.setRelease(this, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchange(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchange(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchangeAcquire(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchangeAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the value to {@code newValue} if the current value,
+     * referred to as the <em>witness value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final V compareAndExchangeRelease(V expectedValue, V newValue) {
+        return (V)VALUE.compareAndExchangeRelease(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetVolatile(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetAcquire(this, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the value to {@code newValue}
+     * if the current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(V expectedValue, V newValue) {
+        return VALUE.weakCompareAndSetRelease(this, expectedValue, newValue);
+    }
+
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceArray.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,54 +35,28 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.lang.reflect.Array;
+import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
 
 /**
  * An array of object references in which elements may be updated
- * atomically.  See the {@link java.util.concurrent.atomic} package
- * specification for description of the properties of atomic
- * variables.
+ * atomically.  See the {@link VarHandle} specification for
+ * descriptions of the properties of atomic accesses.
  * @since 1.5
  * @author Doug Lea
  * @param <E> The base class of elements held in this array
  */
 public class AtomicReferenceArray<E> implements java.io.Serializable {
     private static final long serialVersionUID = -6209656149925076980L;
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long ARRAY;
-    private static final int ABASE;
-    private static final int ASHIFT;
+    private static final VarHandle AA
+        = MethodHandles.arrayElementVarHandle(Object[].class);
     private final Object[] array; // must have exact type Object[]
 
-    static {
-        try {
-            ARRAY = U.objectFieldOffset
-                (AtomicReferenceArray.class.getDeclaredField("array"));
-            ABASE = U.arrayBaseOffset(Object[].class);
-            int scale = U.arrayIndexScale(Object[].class);
-            if ((scale & (scale - 1)) != 0)
-                throw new Error("array index scale not a power of two");
-            ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
-    private long checkedByteOffset(int i) {
-        if (i < 0 || i >= array.length)
-            throw new IndexOutOfBoundsException("index " + i);
-
-        return byteOffset(i);
-    }
-
-    private static long byteOffset(int i) {
-        return ((long) i << ASHIFT) + ABASE;
-    }
-
     /**
      * Creates a new AtomicReferenceArray of the given length, with all
      * elements initially null.
@@ -115,44 +89,44 @@
     }
 
     /**
-     * Gets the current value at position {@code i}.
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getVolatile}.
      *
      * @param i the index
      * @return the current value
      */
+    @SuppressWarnings("unchecked")
     public final E get(int i) {
-        return getRaw(checkedByteOffset(i));
-    }
-
-    @SuppressWarnings("unchecked")
-    private E getRaw(long offset) {
-        return (E) U.getObjectVolatile(array, offset);
+        return (E)AA.getVolatile(array, i);
     }
 
     /**
-     * Sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setVolatile}.
      *
      * @param i the index
      * @param newValue the new value
      */
     public final void set(int i, E newValue) {
-        U.putObjectVolatile(array, checkedByteOffset(i), newValue);
+        AA.setVolatile(array, i, newValue);
     }
 
     /**
-     * Eventually sets the element at position {@code i} to the given value.
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
      *
      * @param i the index
      * @param newValue the new value
      * @since 1.6
      */
     public final void lazySet(int i, E newValue) {
-        U.putObjectRelease(array, checkedByteOffset(i), newValue);
+        AA.setRelease(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * value and returns the old value.
+     * Atomically sets the element at index {@code i} to {@code
+     * newValue} and returns the old value,
+     * with memory effects as specified by {@link VarHandle#getAndSet}.
      *
      * @param i the index
      * @param newValue the new value
@@ -160,42 +134,36 @@
      */
     @SuppressWarnings("unchecked")
     public final E getAndSet(int i, E newValue) {
-        return (E)U.getAndSetObject(array, checkedByteOffset(i), newValue);
+        return (E)AA.getAndSet(array, i, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#compareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful. False return indicates that
      * the actual value was not equal to the expected value.
      */
-    public final boolean compareAndSet(int i, E expect, E update) {
-        return compareAndSetRaw(checkedByteOffset(i), expect, update);
-    }
-
-    private boolean compareAndSetRaw(long offset, E expect, E update) {
-        return U.compareAndSwapObject(array, offset, expect, update);
+    public final boolean compareAndSet(int i, E expectedValue, E newValue) {
+        return AA.compareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
-     * Atomically sets the element at position {@code i} to the given
-     * updated value if the current value {@code ==} the expected value.
-     *
-     * <p><a href="package-summary.html#weakCompareAndSet">May fail
-     * spuriously and does not provide ordering guarantees</a>, so is
-     * only rarely an appropriate alternative to {@code compareAndSet}.
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by {@link VarHandle#weakCompareAndSet}.
      *
      * @param i the index
-     * @param expect the expected value
-     * @param update the new value
+     * @param expectedValue the expected value
+     * @param newValue the new value
      * @return {@code true} if successful
      */
-    public final boolean weakCompareAndSet(int i, E expect, E update) {
-        return compareAndSet(i, expect, update);
+    public final boolean weakCompareAndSet(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSet(array, i, expectedValue, newValue);
     }
 
     /**
@@ -210,13 +178,14 @@
      * @since 1.8
      */
     public final E getAndUpdate(int i, UnaryOperator<E> updateFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -231,23 +200,25 @@
      * @since 1.8
      */
     public final E updateAndGet(int i, UnaryOperator<E> updateFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = updateFunction.apply(prev);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = updateFunction.apply(prev);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the previous value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
+     * results of applying the given function to the current and given
+     * values, returning the previous value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -257,23 +228,25 @@
      */
     public final E getAndAccumulate(int i, E x,
                                     BinaryOperator<E> accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return prev;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return prev;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
      * Atomically updates the element at index {@code i} with the
-     * results of applying the given function to the current and
-     * given values, returning the updated value. The function should
-     * be side-effect-free, since it may be re-applied when attempted
+     * results of applying the given function to the current and given
+     * values, returning the updated value. The function should be
+     * side-effect-free, since it may be re-applied when attempted
      * updates fail due to contention among threads.  The function is
-     * applied with the current value at index {@code i} as its first
-     * argument, and the given update as the second argument.
+     * applied with the current value of the element at index {@code i}
+     * as its first argument, and the given update as the second
+     * argument.
      *
      * @param i the index
      * @param x the update value
@@ -283,13 +256,14 @@
      */
     public final E accumulateAndGet(int i, E x,
                                     BinaryOperator<E> accumulatorFunction) {
-        long offset = checkedByteOffset(i);
-        E prev, next;
-        do {
-            prev = getRaw(offset);
-            next = accumulatorFunction.apply(prev, x);
-        } while (!compareAndSetRaw(offset, prev, next));
-        return next;
+        E prev = get(i), next = null;
+        for (boolean haveNext = false;;) {
+            if (!haveNext)
+                next = accumulatorFunction.apply(prev, x);
+            if (weakCompareAndSetVolatile(i, prev, next))
+                return next;
+            haveNext = (prev == (prev = get(i)));
+        }
     }
 
     /**
@@ -304,7 +278,7 @@
         StringBuilder b = new StringBuilder();
         b.append('[');
         for (int i = 0; ; i++) {
-            b.append(getRaw(byteOffset(i)));
+            b.append(get(i));
             if (i == iMax)
                 return b.append(']').toString();
             b.append(',').append(' ');
@@ -326,7 +300,199 @@
             throw new java.io.InvalidObjectException("Not array type");
         if (a.getClass() != Object[].class)
             a = Arrays.copyOf((Object[])a, Array.getLength(a), Object[].class);
-        U.putObjectVolatile(this, ARRAY, a);
+        Field arrayField = java.security.AccessController.doPrivileged(
+            (java.security.PrivilegedAction<Field>) () -> {
+                try {
+                    Field f = AtomicReferenceArray.class
+                        .getDeclaredField("array");
+                    f.setAccessible(true);
+                    return f;
+                } catch (ReflectiveOperationException e) {
+                    throw new Error(e);
+                }});
+        try {
+            arrayField.set(this, a);
+        } catch (IllegalAccessException e) {
+            throw new Error(e);
+        }
+    }
+
+    // jdk9
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory semantics of reading as if the variable was declared
+     * non-{@code volatile}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getPlain(int i) {
+        return (E)AA.get(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory semantics of setting as if the variable was
+     * declared non-{@code volatile} and non-{@code final}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setPlain(int i, E newValue) {
+        AA.set(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getOpaque}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getOpaque(int i) {
+        return (E)AA.getOpaque(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setOpaque}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setOpaque(int i, E newValue) {
+        AA.setOpaque(array, i, newValue);
+    }
+
+    /**
+     * Returns the current value of the element at index {@code i},
+     * with memory effects as specified by {@link VarHandle#getAcquire}.
+     *
+     * @param i the index
+     * @return the value
+     * @since 9
+     */
+    public final E getAcquire(int i) {
+        return (E)AA.getAcquire(array, i);
+    }
+
+    /**
+     * Sets the element at index {@code i} to {@code newValue},
+     * with memory effects as specified by {@link VarHandle#setRelease}.
+     *
+     * @param i the index
+     * @param newValue the new value
+     * @since 9
+     */
+    public final void setRelease(int i, E newValue) {
+        AA.setRelease(array, i, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchange}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchange(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchange(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchangeAcquire(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchangeAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Atomically sets the element at index {@code i} to {@code newValue}
+     * if the element's current value, referred to as the <em>witness
+     * value</em>, {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#compareAndExchangeRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return the witness value, which will be the same as the
+     * expected value if successful
+     * @since 9
+     */
+    public final E compareAndExchangeRelease(int i, E expectedValue, E newValue) {
+        return (E)AA.compareAndExchangeRelease(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetVolatile}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetVolatile(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetVolatile(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetAcquire}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetAcquire(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetAcquire(array, i, expectedValue, newValue);
+    }
+
+    /**
+     * Possibly atomically sets the element at index {@code i} to
+     * {@code newValue} if the element's current value {@code == expectedValue},
+     * with memory effects as specified by
+     * {@link VarHandle#weakCompareAndSetRelease}.
+     *
+     * @param i the index
+     * @param expectedValue the expected value
+     * @param newValue the new value
+     * @return {@code true} if successful
+     * @since 9
+     */
+    public final boolean weakCompareAndSetRelease(int i, E expectedValue, E newValue) {
+        return AA.weakCompareAndSetRelease(array, i, expectedValue, newValue);
     }
 
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java	Mon Jul 18 09:38:08 2016 -0700
@@ -42,6 +42,7 @@
 import java.security.PrivilegedExceptionAction;
 import java.util.function.BinaryOperator;
 import java.util.function.UnaryOperator;
+import jdk.internal.misc.Unsafe;
 import jdk.internal.reflect.CallerSensitive;
 import jdk.internal.reflect.Reflection;
 
@@ -168,8 +169,8 @@
     public abstract void lazySet(T obj, V newValue);
 
     /**
-     * Gets the current value held in the field of the given object managed
-     * by this updater.
+     * Returns the current value held in the field of the given object
+     * managed by this updater.
      *
      * @param obj An object whose field to get
      * @return the current value
@@ -284,7 +285,7 @@
 
     private static final class AtomicReferenceFieldUpdaterImpl<T,V>
         extends AtomicReferenceFieldUpdater<T,V> {
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+        private static final Unsafe U = Unsafe.getUnsafe();
         private final long offset;
         /**
          * if field is protected, the subclass constructing updater, else
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/AtomicStampedReference.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,9 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
+
 /**
  * An {@code AtomicStampedReference} maintains an object reference
  * along with an integer "stamp", that can be updated atomically.
@@ -188,20 +191,19 @@
              casPair(current, Pair.of(expectedReference, newStamp)));
     }
 
-    // Unsafe mechanics
-
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long PAIR;
+    // VarHandle mechanics
+    private static final VarHandle PAIR;
     static {
         try {
-            PAIR = U.objectFieldOffset
-                (AtomicStampedReference.class.getDeclaredField("pair"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            PAIR = l.findVarHandle(AtomicStampedReference.class, "pair",
+                                   Pair.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
     }
 
     private boolean casPair(Pair<V> cmp, Pair<V> val) {
-        return U.compareAndSwapObject(this, PAIR, cmp, val);
+        return PAIR.compareAndSet(this, cmp, val);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/LongAccumulator.java	Mon Jul 18 09:38:08 2016 -0700
@@ -68,7 +68,7 @@
  * <p>Class {@link LongAdder} provides analogs of the functionality of
  * this class for the common special case of maintaining counts and
  * sums.  The call {@code new LongAdder()} is equivalent to {@code new
- * LongAccumulator((x, y) -> x + y, 0L}.
+ * LongAccumulator((x, y) -> x + y, 0L)}.
  *
  * <p>This class extends {@link Number}, but does <em>not</em> define
  * methods such as {@code equals}, {@code hashCode} and {@code
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/Striped64.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,10 +35,13 @@
 
 package java.util.concurrent.atomic;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.Arrays;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.function.DoubleBinaryOperator;
 import java.util.function.LongBinaryOperator;
+import jdk.internal.misc.Unsafe;
 
 /**
  * A package-local class holding common representation and mechanics
@@ -123,22 +126,21 @@
         volatile long value;
         Cell(long x) { value = x; }
         final boolean cas(long cmp, long val) {
-            return U.compareAndSwapLong(this, VALUE, cmp, val);
+            return VALUE.compareAndSet(this, cmp, val);
         }
         final void reset() {
-            U.putLongVolatile(this, VALUE, 0L);
+            VALUE.setVolatile(this, 0L);
         }
         final void reset(long identity) {
-            U.putLongVolatile(this, VALUE, identity);
+            VALUE.setVolatile(this, identity);
         }
 
-        // Unsafe mechanics
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long VALUE;
+        // VarHandle mechanics
+        private static final VarHandle VALUE;
         static {
             try {
-                VALUE = U.objectFieldOffset
-                    (Cell.class.getDeclaredField("value"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                VALUE = l.findVarHandle(Cell.class, "value", long.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -174,14 +176,14 @@
      * CASes the base field.
      */
     final boolean casBase(long cmp, long val) {
-        return U.compareAndSwapLong(this, BASE, cmp, val);
+        return BASE.compareAndSet(this, cmp, val);
     }
 
     /**
      * CASes the cellsBusy field from 0 to 1 to acquire lock.
      */
     final boolean casCellsBusy() {
-        return U.compareAndSwapInt(this, CELLSBUSY, 0, 1);
+        return CELLSBUSY.compareAndSet(this, 0, 1);
     }
 
     /**
@@ -371,18 +373,16 @@
         }
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long BASE;
-    private static final long CELLSBUSY;
+    // Unsafe and VarHandle mechanics
+    private static final Unsafe U = Unsafe.getUnsafe();
+    private static final VarHandle BASE;
+    private static final VarHandle CELLSBUSY;
     private static final long PROBE;
     static {
         try {
-            BASE = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("base"));
-            CELLSBUSY = U.objectFieldOffset
-                (Striped64.class.getDeclaredField("cellsBusy"));
-
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            BASE = l.findVarHandle(Striped64.class, "base", long.class);
+            CELLSBUSY = l.findVarHandle(Striped64.class, "cellsBusy", int.class);
             PROBE = U.objectFieldOffset
                 (Thread.class.getDeclaredField("threadLocalRandomProbe"));
         } catch (ReflectiveOperationException e) {
--- a/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/atomic/package-info.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,26 +35,10 @@
 
 /**
  * A small toolkit of classes that support lock-free thread-safe
- * programming on single variables.  In essence, the classes in this
- * package extend the notion of {@code volatile} values, fields, and
- * array elements to those that also provide an atomic conditional update
- * operation of the form:
- *
- * <pre> {@code boolean compareAndSet(expectedValue, updateValue);}</pre>
- *
- * <p>This method (which varies in argument types across different
- * classes) atomically sets a variable to the {@code updateValue} if it
- * currently holds the {@code expectedValue}, reporting {@code true} on
- * success.  The classes in this package also contain methods to get and
- * unconditionally set values, as well as a weaker conditional atomic
- * update operation {@code weakCompareAndSet} described below.
- *
- * <p>The specifications of these methods enable implementations to
- * employ efficient machine-level atomic instructions that are available
- * on contemporary processors.  However on some platforms, support may
- * entail some form of internal locking.  Thus the methods are not
- * strictly guaranteed to be non-blocking --
- * a thread may block transiently before performing the operation.
+ * programming on single variables.  Instances of Atomic classes
+ * maintain values that are accessed and updated using methods
+ * otherwise available for fields using associated atomic {@link
+ * java.lang.invoke.VarHandle} operations.
  *
  * <p>Instances of classes
  * {@link java.util.concurrent.atomic.AtomicBoolean},
@@ -92,45 +76,26 @@
  *   return prev; // return next; for transformAndGet
  * }}</pre>
  *
- * <p>The memory effects for accesses and updates of atomics generally
- * follow the rules for volatiles, as stated in
- * <a href="https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.4">
- * Chapter 17 of
- * <cite>The Java&trade; Language Specification</cite></a>:
- *
- * <ul>
- *
- *   <li>{@code get} has the memory effects of reading a
- * {@code volatile} variable.
- *
- *   <li>{@code set} has the memory effects of writing (assigning) a
- * {@code volatile} variable.
+ * <p>These classes are not general purpose replacements for {@code
+ * java.lang.Integer} and related classes.  They do <em>not</em>
+ * define methods such as {@code equals}, {@code hashCode} and {@code
+ * compareTo}.  Because atomic variables are expected to be mutated,
+ * they are poor choices for hash table keys.
  *
- *   <li>{@code lazySet} has the memory effects of writing (assigning)
- *   a {@code volatile} variable except that it permits reorderings with
- *   subsequent (but not previous) memory actions that do not themselves
- *   impose reordering constraints with ordinary non-{@code volatile}
- *   writes.  Among other usage contexts, {@code lazySet} may apply when
- *   nulling out, for the sake of garbage collection, a reference that is
- *   never accessed again.
+ * <p>The
+ * {@link java.util.concurrent.atomic.AtomicIntegerArray},
+ * {@link java.util.concurrent.atomic.AtomicLongArray}, and
+ * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
+ * further extend atomic operation support to arrays of these types.
+ * These classes are also notable in providing {@code volatile} access
+ * semantics for their array elements.
  *
- *   <li>{@code weakCompareAndSet} atomically reads and conditionally
- *   writes a variable but does <em>not</em>
- *   create any happens-before orderings, so provides no guarantees
- *   with respect to previous or subsequent reads and writes of any
- *   variables other than the target of the {@code weakCompareAndSet}.
- *
- *   <li>{@code compareAndSet}
- *   and all other read-and-update operations such as {@code getAndIncrement}
- *   have the memory effects of both reading and
- *   writing {@code volatile} variables.
- * </ul>
- *
- * <p>In addition to classes representing single values, this package
- * contains <em>Updater</em> classes that can be used to obtain
- * {@code compareAndSet} operations on any selected {@code volatile}
- * field of any selected class.
- *
+ * <p>In addition to classes representing single values and arrays,
+ * this package contains <em>Updater</em> classes that can be used to
+ * obtain {@code compareAndSet} and related operations on any selected
+ * {@code volatile} field of any selected class. These classes
+ * predate the introduction of {@link
+ * java.lang.invoke.VarHandle}, and are of more limited use.
  * {@link java.util.concurrent.atomic.AtomicReferenceFieldUpdater},
  * {@link java.util.concurrent.atomic.AtomicIntegerFieldUpdater}, and
  * {@link java.util.concurrent.atomic.AtomicLongFieldUpdater} are
@@ -143,38 +108,6 @@
  * reflection-based setup, less convenient usage, and weaker
  * guarantees.
  *
- * <p>The
- * {@link java.util.concurrent.atomic.AtomicIntegerArray},
- * {@link java.util.concurrent.atomic.AtomicLongArray}, and
- * {@link java.util.concurrent.atomic.AtomicReferenceArray} classes
- * further extend atomic operation support to arrays of these types.
- * These classes are also notable in providing {@code volatile} access
- * semantics for their array elements, which is not supported for
- * ordinary arrays.
- *
- * <p id="weakCompareAndSet">The atomic classes also support method
- * {@code weakCompareAndSet}, which has limited applicability.  On some
- * platforms, the weak version may be more efficient than {@code
- * compareAndSet} in the normal case, but differs in that any given
- * invocation of the {@code weakCompareAndSet} method may return {@code
- * false} <em>spuriously</em> (that is, for no apparent reason).  A
- * {@code false} return means only that the operation may be retried if
- * desired, relying on the guarantee that repeated invocation when the
- * variable holds {@code expectedValue} and no other thread is also
- * attempting to set the variable will eventually succeed.  (Such
- * spurious failures may for example be due to memory contention effects
- * that are unrelated to whether the expected and current values are
- * equal.)  Additionally {@code weakCompareAndSet} does not provide
- * ordering guarantees that are usually needed for synchronization
- * control.  However, the method may be useful for updating counters and
- * statistics when such updates are unrelated to the other
- * happens-before orderings of a program.  When a thread sees an update
- * to an atomic variable caused by a {@code weakCompareAndSet}, it does
- * not necessarily see updates to any <em>other</em> variables that
- * occurred before the {@code weakCompareAndSet}.  This may be
- * acceptable when, for example, updating performance statistics, but
- * rarely otherwise.
- *
  * <p>The {@link java.util.concurrent.atomic.AtomicMarkableReference}
  * class associates a single boolean with a reference.  For example, this
  * bit might be used inside a data structure to mean that the object
@@ -185,29 +118,6 @@
  * used for example, to represent version numbers corresponding to
  * series of updates.
  *
- * <p>Atomic classes are designed primarily as building blocks for
- * implementing non-blocking data structures and related infrastructure
- * classes.  The {@code compareAndSet} method is not a general
- * replacement for locking.  It applies only when critical updates for an
- * object are confined to a <em>single</em> variable.
- *
- * <p>Atomic classes are not general purpose replacements for
- * {@code java.lang.Integer} and related classes.  They do <em>not</em>
- * define methods such as {@code equals}, {@code hashCode} and
- * {@code compareTo}.  (Because atomic variables are expected to be
- * mutated, they are poor choices for hash table keys.)  Additionally,
- * classes are provided only for those types that are commonly useful in
- * intended applications.  For example, there is no atomic class for
- * representing {@code byte}.  In those infrequent cases where you would
- * like to do so, you can use an {@code AtomicInteger} to hold
- * {@code byte} values, and cast appropriately.
- *
- * You can also hold floats using
- * {@link java.lang.Float#floatToRawIntBits} and
- * {@link java.lang.Float#intBitsToFloat} conversions, and doubles using
- * {@link java.lang.Double#doubleToRawLongBits} and
- * {@link java.lang.Double#longBitsToDouble} conversions.
- *
  * @since 1.5
  */
 package java.util.concurrent.atomic;
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
@@ -113,7 +115,7 @@
     protected final void setState(long newState) {
         // Use putLongVolatile instead of ordinary volatile store when
         // using compareAndSwapLong, for sake of some 32bit systems.
-        U.putLongVolatile(this, STATE, newState);
+        STATE.setVolatile(this, newState);
     }
 
     /**
@@ -128,7 +130,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(long expect, long update) {
-        return U.compareAndSwapLong(this, STATE, expect, update);
+        return STATE.compareAndSet(this, expect, update);
     }
 
     // Queuing utilities
@@ -149,7 +151,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return oldTail;
@@ -172,7 +174,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return node;
@@ -1810,28 +1812,17 @@
         }
     }
 
-    /**
-     * Setup to support compareAndSet. We need to natively implement
-     * this here: For the sake of permitting future enhancements, we
-     * cannot explicitly subclass AtomicLong, which would be
-     * efficient and useful otherwise. So, as the lesser of evils, we
-     * natively implement using hotspot intrinsics API. And while we
-     * are at it, we do the same for other CASable fields (which could
-     * otherwise be done with atomic field updaters).
-     */
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
 
     static {
         try {
-            STATE = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (AbstractQueuedLongSynchronizer.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "state", long.class);
+            HEAD = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "head", Node.class);
+            TAIL = l.findVarHandle(AbstractQueuedLongSynchronizer.class, "tail", Node.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -1846,7 +1837,7 @@
      */
     private final void initializeSyncQueue() {
         Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
+        if (HEAD.compareAndSet(this, null, (h = new Node())))
             tail = h;
     }
 
@@ -1854,6 +1845,6 @@
      * CASes tail field.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return TAIL.compareAndSet(this, expect, update);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,11 +35,12 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Date;
 import java.util.concurrent.TimeUnit;
-import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * Provides a framework for implementing blocking locks and related
@@ -506,40 +507,41 @@
         /** Constructor used by addWaiter. */
         Node(Node nextWaiter) {
             this.nextWaiter = nextWaiter;
-            U.putObject(this, THREAD, Thread.currentThread());
+            THREAD.set(this, Thread.currentThread());
         }
 
         /** Constructor used by addConditionWaiter. */
         Node(int waitStatus) {
-            U.putInt(this, WAITSTATUS, waitStatus);
-            U.putObject(this, THREAD, Thread.currentThread());
+            WAITSTATUS.set(this, waitStatus);
+            THREAD.set(this, Thread.currentThread());
         }
 
         /** CASes waitStatus field. */
         final boolean compareAndSetWaitStatus(int expect, int update) {
-            return U.compareAndSwapInt(this, WAITSTATUS, expect, update);
+            return WAITSTATUS.compareAndSet(this, expect, update);
         }
 
         /** CASes next field. */
         final boolean compareAndSetNext(Node expect, Node update) {
-            return U.compareAndSwapObject(this, NEXT, expect, update);
+            return NEXT.compareAndSet(this, expect, update);
+        }
+
+        final void setPrevRelaxed(Node p) {
+            PREV.set(this, p);
         }
 
-        private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-        private static final long NEXT;
-        static final long PREV;
-        private static final long THREAD;
-        private static final long WAITSTATUS;
+        // VarHandle mechanics
+        private static final VarHandle NEXT;
+        private static final VarHandle PREV;
+        private static final VarHandle THREAD;
+        private static final VarHandle WAITSTATUS;
         static {
             try {
-                NEXT = U.objectFieldOffset
-                    (Node.class.getDeclaredField("next"));
-                PREV = U.objectFieldOffset
-                    (Node.class.getDeclaredField("prev"));
-                THREAD = U.objectFieldOffset
-                    (Node.class.getDeclaredField("thread"));
-                WAITSTATUS = U.objectFieldOffset
-                    (Node.class.getDeclaredField("waitStatus"));
+                MethodHandles.Lookup l = MethodHandles.lookup();
+                NEXT = l.findVarHandle(Node.class, "next", Node.class);
+                PREV = l.findVarHandle(Node.class, "prev", Node.class);
+                THREAD = l.findVarHandle(Node.class, "thread", Thread.class);
+                WAITSTATUS = l.findVarHandle(Node.class, "waitStatus", int.class);
             } catch (ReflectiveOperationException e) {
                 throw new Error(e);
             }
@@ -595,7 +597,7 @@
      *         value was not equal to the expected value.
      */
     protected final boolean compareAndSetState(int expect, int update) {
-        return U.compareAndSwapInt(this, STATE, expect, update);
+        return STATE.compareAndSet(this, expect, update);
     }
 
     // Queuing utilities
@@ -616,7 +618,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return oldTail;
@@ -639,7 +641,7 @@
         for (;;) {
             Node oldTail = tail;
             if (oldTail != null) {
-                U.putObject(node, Node.PREV, oldTail);
+                node.setPrevRelaxed(oldTail);
                 if (compareAndSetTail(oldTail, node)) {
                     oldTail.next = node;
                     return node;
@@ -887,7 +889,6 @@
      * @param arg the acquire argument
      * @return {@code true} if interrupted while waiting
      */
-    @ReservedStackAccess
     final boolean acquireQueued(final Node node, int arg) {
         try {
             boolean interrupted = false;
@@ -1220,7 +1221,6 @@
      *        {@link #tryAcquire} but is otherwise uninterpreted and
      *        can represent anything you like.
      */
-    @ReservedStackAccess
     public final void acquire(int arg) {
         if (!tryAcquire(arg) &&
             acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
@@ -1284,7 +1284,6 @@
      *        can represent anything you like.
      * @return the value returned from {@link #tryRelease}
      */
-    @ReservedStackAccess
     public final boolean release(int arg) {
         if (tryRelease(arg)) {
             Node h = head;
@@ -1365,7 +1364,6 @@
      *        and can represent anything you like.
      * @return the value returned from {@link #tryReleaseShared}
      */
-    @ReservedStackAccess
     public final boolean releaseShared(int arg) {
         if (tryReleaseShared(arg)) {
             doReleaseShared();
@@ -2279,28 +2277,17 @@
         }
     }
 
-    /**
-     * Setup to support compareAndSet. We need to natively implement
-     * this here: For the sake of permitting future enhancements, we
-     * cannot explicitly subclass AtomicInteger, which would be
-     * efficient and useful otherwise. So, as the lesser of evils, we
-     * natively implement using hotspot intrinsics API. And while we
-     * are at it, we do the same for other CASable fields (which could
-     * otherwise be done with atomic field updaters).
-     */
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long HEAD;
-    private static final long TAIL;
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle HEAD;
+    private static final VarHandle TAIL;
 
     static {
         try {
-            STATE = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("state"));
-            HEAD = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("head"));
-            TAIL = U.objectFieldOffset
-                (AbstractQueuedSynchronizer.class.getDeclaredField("tail"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(AbstractQueuedSynchronizer.class, "state", int.class);
+            HEAD = l.findVarHandle(AbstractQueuedSynchronizer.class, "head", Node.class);
+            TAIL = l.findVarHandle(AbstractQueuedSynchronizer.class, "tail", Node.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
@@ -2315,7 +2302,7 @@
      */
     private final void initializeSyncQueue() {
         Node h;
-        if (U.compareAndSwapObject(this, HEAD, null, (h = new Node())))
+        if (HEAD.compareAndSet(this, null, (h = new Node())))
             tail = h;
     }
 
@@ -2323,6 +2310,6 @@
      * CASes tail field.
      */
     private final boolean compareAndSetTail(Node expect, Node update) {
-        return U.compareAndSwapObject(this, TAIL, expect, update);
+        return TAIL.compareAndSet(this, expect, update);
     }
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/Condition.java	Mon Jul 18 09:38:08 2016 -0700
@@ -396,7 +396,6 @@
      * re-acquire the lock associated with this condition. When the
      * thread returns it is <em>guaranteed</em> to hold this lock.
      *
-     *
      * <p>If the current thread:
      * <ul>
      * <li>has its interrupted status set on entry to this method; or
@@ -408,7 +407,6 @@
      * case, whether or not the test for interruption occurs before the lock
      * is released.
      *
-     *
      * <p>The return value indicates whether the deadline has elapsed,
      * which can be used as follows:
      * <pre> {@code
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/LockSupport.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,8 @@
 
 package java.util.concurrent.locks;
 
+import jdk.internal.misc.Unsafe;
+
 /**
  * Basic thread blocking primitives for creating locks and other
  * synchronization classes.
@@ -405,16 +407,30 @@
         return r;
     }
 
+    /**
+     * Returns the thread id for the given thread.  We must access
+     * this directly rather than via method Thread.getId() because
+     * getId() is not final, and has been known to be overridden in
+     * ways that do not preserve unique mappings.
+     */
+    static final long getThreadId(Thread thread) {
+        return U.getLongVolatile(thread, TID);
+    }
+
     // Hotspot implementation via intrinsics API
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
+    private static final Unsafe U = Unsafe.getUnsafe();
     private static final long PARKBLOCKER;
     private static final long SECONDARY;
+    private static final long TID;
     static {
         try {
             PARKBLOCKER = U.objectFieldOffset
                 (Thread.class.getDeclaredField("parkBlocker"));
             SECONDARY = U.objectFieldOffset
                 (Thread.class.getDeclaredField("threadLocalRandomSecondarySeed"));
+            TID = U.objectFieldOffset
+                (Thread.class.getDeclaredField("tid"));
+
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReadWriteLock.java	Mon Jul 18 09:38:08 2016 -0700
@@ -79,7 +79,6 @@
  * and measurement will establish whether the use of a read-write lock is
  * suitable for your application.
  *
- *
  * <p>Although the basic operation of a read-write lock is straight-forward,
  * there are many policy decisions that an implementation must make, which
  * may affect the effectiveness of the read-write lock in a given application.
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantLock.java	Mon Jul 18 09:38:08 2016 -0700
@@ -119,12 +119,6 @@
         private static final long serialVersionUID = -5179523762034025860L;
 
         /**
-         * Performs {@link Lock#lock}. The main reason for subclassing
-         * is to allow fast path for nonfair version.
-         */
-        abstract void lock();
-
-        /**
          * Performs non-fair tryLock.  tryAcquire is implemented in
          * subclasses, but both need nonfair try for trylock method.
          */
@@ -201,19 +195,6 @@
      */
     static final class NonfairSync extends Sync {
         private static final long serialVersionUID = 7316153563782823691L;
-
-        /**
-         * Performs lock.  Try immediate barge, backing up to normal
-         * acquire on failure.
-         */
-        @ReservedStackAccess
-        final void lock() {
-            if (compareAndSetState(0, 1))
-                setExclusiveOwnerThread(Thread.currentThread());
-            else
-                acquire(1);
-        }
-
         protected final boolean tryAcquire(int acquires) {
             return nonfairTryAcquire(acquires);
         }
@@ -224,11 +205,6 @@
      */
     static final class FairSync extends Sync {
         private static final long serialVersionUID = -3000897897090466540L;
-
-        final void lock() {
-            acquire(1);
-        }
-
         /**
          * Fair version of tryAcquire.  Don't grant access unless
          * recursive call or no waiters or is first.
@@ -288,7 +264,7 @@
      * at which time the lock hold count is set to one.
      */
     public void lock() {
-        sync.lock();
+        sync.acquire(1);
     }
 
     /**
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java	Mon Jul 18 09:38:08 2016 -0700
@@ -37,6 +37,7 @@
 
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * An implementation of {@link ReadWriteLock} supporting similar
@@ -278,7 +279,7 @@
         static final class HoldCounter {
             int count;          // initially 0
             // Use id, not reference, to avoid garbage retention
-            final long tid = getThreadId(Thread.currentThread());
+            final long tid = LockSupport.getThreadId(Thread.currentThread());
         }
 
         /**
@@ -367,7 +368,7 @@
          * both read and write holds that are all released during a
          * condition wait and re-established in tryAcquire.
          */
-
+        @ReservedStackAccess
         protected final boolean tryRelease(int releases) {
             if (!isHeldExclusively())
                 throw new IllegalMonitorStateException();
@@ -379,6 +380,7 @@
             return free;
         }
 
+        @ReservedStackAccess
         protected final boolean tryAcquire(int acquires) {
             /*
              * Walkthrough:
@@ -411,6 +413,7 @@
             return true;
         }
 
+        @ReservedStackAccess
         protected final boolean tryReleaseShared(int unused) {
             Thread current = Thread.currentThread();
             if (firstReader == current) {
@@ -421,7 +424,8 @@
                     firstReaderHoldCount--;
             } else {
                 HoldCounter rh = cachedHoldCounter;
-                if (rh == null || rh.tid != getThreadId(current))
+                if (rh == null ||
+                    rh.tid != LockSupport.getThreadId(current))
                     rh = readHolds.get();
                 int count = rh.count;
                 if (count <= 1) {
@@ -447,6 +451,7 @@
                 "attempt to unlock read lock, not locked by current thread");
         }
 
+        @ReservedStackAccess
         protected final int tryAcquireShared(int unused) {
             /*
              * Walkthrough:
@@ -479,7 +484,8 @@
                     firstReaderHoldCount++;
                 } else {
                     HoldCounter rh = cachedHoldCounter;
-                    if (rh == null || rh.tid != getThreadId(current))
+                    if (rh == null ||
+                        rh.tid != LockSupport.getThreadId(current))
                         cachedHoldCounter = rh = readHolds.get();
                     else if (rh.count == 0)
                         readHolds.set(rh);
@@ -516,7 +522,8 @@
                     } else {
                         if (rh == null) {
                             rh = cachedHoldCounter;
-                            if (rh == null || rh.tid != getThreadId(current)) {
+                            if (rh == null ||
+                                rh.tid != LockSupport.getThreadId(current)) {
                                 rh = readHolds.get();
                                 if (rh.count == 0)
                                     readHolds.remove();
@@ -537,7 +544,8 @@
                     } else {
                         if (rh == null)
                             rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null ||
+                            rh.tid != LockSupport.getThreadId(current))
                             rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -554,6 +562,7 @@
          * This is identical in effect to tryAcquire except for lack
          * of calls to writerShouldBlock.
          */
+        @ReservedStackAccess
         final boolean tryWriteLock() {
             Thread current = Thread.currentThread();
             int c = getState();
@@ -575,6 +584,7 @@
          * This is identical in effect to tryAcquireShared except for
          * lack of calls to readerShouldBlock.
          */
+        @ReservedStackAccess
         final boolean tryReadLock() {
             Thread current = Thread.currentThread();
             for (;;) {
@@ -593,7 +603,8 @@
                         firstReaderHoldCount++;
                     } else {
                         HoldCounter rh = cachedHoldCounter;
-                        if (rh == null || rh.tid != getThreadId(current))
+                        if (rh == null ||
+                            rh.tid != LockSupport.getThreadId(current))
                             cachedHoldCounter = rh = readHolds.get();
                         else if (rh.count == 0)
                             readHolds.set(rh);
@@ -644,7 +655,7 @@
                 return firstReaderHoldCount;
 
             HoldCounter rh = cachedHoldCounter;
-            if (rh != null && rh.tid == getThreadId(current))
+            if (rh != null && rh.tid == LockSupport.getThreadId(current))
                 return rh.count;
 
             int count = readHolds.get().count;
@@ -1490,26 +1501,4 @@
             "[Write locks = " + w + ", Read locks = " + r + "]";
     }
 
-    /**
-     * Returns the thread id for the given thread.  We must access
-     * this directly rather than via method Thread.getId() because
-     * getId() is not final, and has been known to be overridden in
-     * ways that do not preserve unique mappings.
-     */
-    static final long getThreadId(Thread thread) {
-        return U.getLongVolatile(thread, TID);
-    }
-
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long TID;
-    static {
-        try {
-            TID = U.objectFieldOffset
-                (Thread.class.getDeclaredField("tid"));
-        } catch (ReflectiveOperationException e) {
-            throw new Error(e);
-        }
-    }
-
 }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/locks/StampedLock.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,7 +35,10 @@
 
 package java.util.concurrent.locks;
 
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.util.concurrent.TimeUnit;
+import jdk.internal.vm.annotation.ReservedStackAccess;
 
 /**
  * A capability-based lock with three modes for controlling read/write
@@ -108,6 +111,10 @@
  * into initial unlocked state, so they are not useful for remote
  * locking.
  *
+ * <p>Like {@link java.util.concurrent.Semaphore Semaphore}, but unlike most
+ * {@link Lock} implementations, StampedLocks have no notion of ownership.
+ * Locks acquired in one thread can be released or converted in another.
+ *
  * <p>The scheduling policy of StampedLock does not consistently
  * prefer readers over writers or vice versa.  All "try" methods are
  * best-effort and do not necessarily conform to any scheduling or
@@ -126,7 +133,7 @@
  * in a class that maintains simple two-dimensional points. The sample
  * code illustrates some try/catch conventions even though they are
  * not strictly needed here because no exceptions can occur in their
- * bodies.<br>
+ * bodies.
  *
  * <pre> {@code
  * class Point {
@@ -234,9 +241,7 @@
      * used in the acquire methods to reduce (increasingly expensive)
      * context switching while also avoiding sustained memory
      * thrashing among many threads.  We limit spins to the head of
-     * queue. A thread spin-waits up to SPINS times (where each
-     * iteration decreases spin count with 50% probability) before
-     * blocking. If, upon wakening it fails to obtain lock, and is
+     * queue. If, upon wakening, a thread fails to obtain lock, and is
      * still (or becomes) the first waiting thread (which indicates
      * that some other thread barged and obtained lock), it escalates
      * spins (up to MAX_HEAD_SPINS) to reduce the likelihood of
@@ -252,7 +257,7 @@
      * to normal volatile reads (of "state").  To force orderings of
      * reads before a validation and the validation itself in those
      * cases where this is not already forced, we use
-     * Unsafe.loadFence.
+     * VarHandle.acquireFence.
      *
      * The memory layout keeps lock state and queue pointers together
      * (normally on the same cache line). This usually works well for
@@ -290,7 +295,20 @@
     private static final long ABITS = RBITS | WBIT;
     private static final long SBITS = ~RBITS; // note overlap with ABITS
 
-    // Initial value for lock state; avoid failure value zero
+    /*
+     * 3 stamp modes can be distinguished by examining (m = stamp & ABITS):
+     * write mode: m == WBIT
+     * optimistic read mode: m == 0L (even when read lock is held)
+     * read mode: m > 0L && m <= RFULL (the stamp is a copy of state, but the
+     * read hold count in the stamp is unused other than to determine mode)
+     *
+     * This differs slightly from the encoding of state:
+     * (state & ABITS) == 0L indicates the lock is currently unlocked.
+     * (state & ABITS) == RBITS is a special transient value
+     * indicating spin-locked to manipulate reader bits overflow.
+     */
+
+    /** Initial value for lock state; avoids failure value zero. */
     private static final long ORIGIN = WBIT << 1;
 
     // Special value from cancelled acquire methods so caller can throw IE
@@ -341,25 +359,27 @@
      * Exclusively acquires the lock, blocking if necessary
      * until available.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a write stamp that can be used to unlock or convert mode
      */
+    @ReservedStackAccess
     public long writeLock() {
         long s, next;  // bypass acquireWrite in fully unlocked case only
         return ((((s = state) & ABITS) == 0L &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
+                 STATE.compareAndSet(this, s, next = s + WBIT)) ?
                 next : acquireWrite(false, 0L));
     }
 
     /**
      * Exclusively acquires the lock if it is immediately available.
      *
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a write stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      */
+    @ReservedStackAccess
     public long tryWriteLock() {
         long s, next;
         return ((((s = state) & ABITS) == 0L &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + WBIT)) ?
+                 STATE.compareAndSet(this, s, next = s + WBIT)) ?
                 next : 0L);
     }
 
@@ -371,7 +391,7 @@
      *
      * @param time the maximum time to wait for the lock
      * @param unit the time unit of the {@code time} argument
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a write stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
@@ -399,10 +419,11 @@
      * Behavior under interruption matches that specified
      * for method {@link Lock#lockInterruptibly()}.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a write stamp that can be used to unlock or convert mode
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
      */
+    @ReservedStackAccess
     public long writeLockInterruptibly() throws InterruptedException {
         long next;
         if (!Thread.interrupted() &&
@@ -415,33 +436,34 @@
      * Non-exclusively acquires the lock, blocking if necessary
      * until available.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a read stamp that can be used to unlock or convert mode
      */
+    @ReservedStackAccess
     public long readLock() {
         long s = state, next;  // bypass acquireRead on common uncontended case
         return ((whead == wtail && (s & ABITS) < RFULL &&
-                 U.compareAndSwapLong(this, STATE, s, next = s + RUNIT)) ?
+                 STATE.compareAndSet(this, s, next = s + RUNIT)) ?
                 next : acquireRead(false, 0L));
     }
 
     /**
      * Non-exclusively acquires the lock if it is immediately available.
      *
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a read stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      */
+    @ReservedStackAccess
     public long tryReadLock() {
-        for (;;) {
-            long s, m, next;
-            if ((m = (s = state) & ABITS) == WBIT)
-                return 0L;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
+        long s, m, next;
+        while ((m = (s = state) & ABITS) != WBIT) {
+            if (m < RFULL) {
+                if (STATE.compareAndSet(this, s, next = s + RUNIT))
                     return next;
             }
             else if ((next = tryIncReaderOverflow(s)) != 0L)
                 return next;
         }
+        return 0L;
     }
 
     /**
@@ -452,11 +474,12 @@
      *
      * @param time the maximum time to wait for the lock
      * @param unit the time unit of the {@code time} argument
-     * @return a stamp that can be used to unlock or convert mode,
+     * @return a read stamp that can be used to unlock or convert mode,
      * or zero if the lock is not available
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
      */
+    @ReservedStackAccess
     public long tryReadLock(long time, TimeUnit unit)
         throws InterruptedException {
         long s, m, next, deadline;
@@ -464,7 +487,7 @@
         if (!Thread.interrupted()) {
             if ((m = (s = state) & ABITS) != WBIT) {
                 if (m < RFULL) {
-                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
+                    if (STATE.compareAndSet(this, s, next = s + RUNIT))
                         return next;
                 }
                 else if ((next = tryIncReaderOverflow(s)) != 0L)
@@ -486,10 +509,11 @@
      * Behavior under interruption matches that specified
      * for method {@link Lock#lockInterruptibly()}.
      *
-     * @return a stamp that can be used to unlock or convert mode
+     * @return a read stamp that can be used to unlock or convert mode
      * @throws InterruptedException if the current thread is interrupted
      * before acquiring the lock
      */
+    @ReservedStackAccess
     public long readLockInterruptibly() throws InterruptedException {
         long next;
         if (!Thread.interrupted() &&
@@ -502,7 +526,7 @@
      * Returns a stamp that can later be validated, or zero
      * if exclusively locked.
      *
-     * @return a stamp, or zero if exclusively locked
+     * @return a valid optimistic read stamp, or zero if exclusively locked
      */
     public long tryOptimisticRead() {
         long s;
@@ -522,11 +546,29 @@
      * since issuance of the given stamp; else false
      */
     public boolean validate(long stamp) {
-        U.loadFence();
+        VarHandle.acquireFence();
         return (stamp & SBITS) == (state & SBITS);
     }
 
     /**
+     * Returns an unlocked state, incrementing the version and
+     * avoiding special failure value 0L.
+     *
+     * @param s a write-locked state (or stamp)
+     */
+    private static long unlockWriteState(long s) {
+        return ((s += WBIT) == 0L) ? ORIGIN : s;
+    }
+
+    private long unlockWriteInternal(long s) {
+        long next; WNode h;
+        STATE.setVolatile(this, next = unlockWriteState(s));
+        if ((h = whead) != null && h.status != 0)
+            release(h);
+        return next;
+    }
+
+    /**
      * If the lock state matches the given stamp, releases the
      * exclusive lock.
      *
@@ -534,13 +576,11 @@
      * @throws IllegalMonitorStateException if the stamp does
      * not match the current state of this lock
      */
+    @ReservedStackAccess
     public void unlockWrite(long stamp) {
-        WNode h;
         if (state != stamp || (stamp & WBIT) == 0L)
             throw new IllegalMonitorStateException();
-        U.putLongVolatile(this, STATE, (stamp += WBIT) == 0L ? ORIGIN : stamp);
-        if ((h = whead) != null && h.status != 0)
-            release(h);
+        unlockWriteInternal(stamp);
     }
 
     /**
@@ -551,22 +591,23 @@
      * @throws IllegalMonitorStateException if the stamp does
      * not match the current state of this lock
      */
+    @ReservedStackAccess
     public void unlockRead(long stamp) {
         long s, m; WNode h;
-        for (;;) {
-            if (((s = state) & SBITS) != (stamp & SBITS) ||
-                (stamp & ABITS) == 0L || (m = s & ABITS) == 0L || m == WBIT)
-                throw new IllegalMonitorStateException();
+        while (((s = state) & SBITS) == (stamp & SBITS)
+               && (stamp & RBITS) > 0L
+               && ((m = s & RBITS) > 0L)) {
             if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
+                if (STATE.compareAndSet(this, s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
-                    break;
+                    return;
                 }
             }
             else if (tryDecReaderOverflow(s) != 0L)
-                break;
+                return;
         }
+        throw new IllegalMonitorStateException();
     }
 
     /**
@@ -577,32 +618,12 @@
      * @throws IllegalMonitorStateException if the stamp does
      * not match the current state of this lock
      */
+    @ReservedStackAccess
     public void unlock(long stamp) {
-        long a = stamp & ABITS, m, s; WNode h;
-        while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L)
-                break;
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return;
-            }
-            else if (a == 0L || a >= WBIT)
-                break;
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
-                    if (m == RUNIT && (h = whead) != null && h.status != 0)
-                        release(h);
-                    return;
-                }
-            }
-            else if (tryDecReaderOverflow(s) != 0L)
-                return;
-        }
-        throw new IllegalMonitorStateException();
+        if ((stamp & WBIT) != 0)
+            unlockWrite(stamp);
+        else
+            unlockRead(stamp);
     }
 
     /**
@@ -623,7 +644,7 @@
             if ((m = s & ABITS) == 0L) {
                 if (a != 0L)
                     break;
-                if (U.compareAndSwapLong(this, STATE, s, next = s + WBIT))
+                if (STATE.compareAndSet(this, s, next = s + WBIT))
                     return next;
             }
             else if (m == WBIT) {
@@ -632,8 +653,7 @@
                 return stamp;
             }
             else if (m == RUNIT && a != 0L) {
-                if (U.compareAndSwapLong(this, STATE, s,
-                                         next = s - RUNIT + WBIT))
+                if (STATE.compareAndSet(this, s, next = s - RUNIT + WBIT))
                     return next;
             }
             else
@@ -654,30 +674,32 @@
      * @return a valid read stamp, or zero on failure
      */
     public long tryConvertToReadLock(long stamp) {
-        long a = stamp & ABITS, m, s, next; WNode h;
+        long a, s, next; WNode h;
         while (((s = state) & SBITS) == (stamp & SBITS)) {
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
+            if ((a = stamp & ABITS) >= WBIT) {
+                // write stamp
+                if (s != stamp)
                     break;
-                else if (m < RFULL) {
-                    if (U.compareAndSwapLong(this, STATE, s, next = s + RUNIT))
+                STATE.setVolatile(this, next = unlockWriteState(s) + RUNIT);
+                if ((h = whead) != null && h.status != 0)
+                    release(h);
+                return next;
+            }
+            else if (a == 0L) {
+                // optimistic read stamp
+                if ((s & ABITS) < RFULL) {
+                    if (STATE.compareAndSet(this, s, next = s + RUNIT))
                         return next;
                 }
                 else if ((next = tryIncReaderOverflow(s)) != 0L)
                     return next;
             }
-            else if (m == WBIT) {
-                if (a != m)
+            else {
+                // already a read stamp
+                if ((s & ABITS) == 0L)
                     break;
-                U.putLongVolatile(this, STATE, next = s + (WBIT + RUNIT));
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return next;
+                return stamp;
             }
-            else if (a != 0L && a < WBIT)
-                return stamp;
-            else
-                break;
         }
         return 0L;
     }
@@ -693,29 +715,22 @@
      * @return a valid optimistic read stamp, or zero on failure
      */
     public long tryConvertToOptimisticRead(long stamp) {
-        long a = stamp & ABITS, m, s, next; WNode h;
-        U.loadFence();
-        for (;;) {
-            if (((s = state) & SBITS) != (stamp & SBITS))
-                break;
-            if ((m = s & ABITS) == 0L) {
-                if (a != 0L)
+        long a, m, s, next; WNode h;
+        VarHandle.acquireFence();
+        while (((s = state) & SBITS) == (stamp & SBITS)) {
+            if ((a = stamp & ABITS) >= WBIT) {
+                // write stamp
+                if (s != stamp)
                     break;
-                return s;
+                return unlockWriteInternal(s);
             }
-            else if (m == WBIT) {
-                if (a != m)
-                    break;
-                U.putLongVolatile(this, STATE,
-                                  next = (s += WBIT) == 0L ? ORIGIN : s);
-                if ((h = whead) != null && h.status != 0)
-                    release(h);
-                return next;
-            }
-            else if (a == 0L || a >= WBIT)
+            else if (a == 0L)
+                // already an optimistic read stamp
+                return stamp;
+            else if ((m = s & ABITS) == 0L) // invalid read stamp
                 break;
             else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, next = s - RUNIT)) {
+                if (STATE.compareAndSet(this, s, next = s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return next & SBITS;
@@ -734,12 +749,11 @@
      *
      * @return {@code true} if the lock was held, else false
      */
+    @ReservedStackAccess
     public boolean tryUnlockWrite() {
-        long s; WNode h;
+        long s;
         if (((s = state) & WBIT) != 0L) {
-            U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-            if ((h = whead) != null && h.status != 0)
-                release(h);
+            unlockWriteInternal(s);
             return true;
         }
         return false;
@@ -752,11 +766,12 @@
      *
      * @return {@code true} if the read lock was held, else false
      */
+    @ReservedStackAccess
     public boolean tryUnlockRead() {
         long s, m; WNode h;
         while ((m = (s = state) & ABITS) != 0L && m < WBIT) {
             if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
+                if (STATE.compareAndSet(this, s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
                     return true;
@@ -832,32 +847,30 @@
      * Returns a plain {@link Lock} view of this StampedLock in which
      * the {@link Lock#lock} method is mapped to {@link #readLock},
      * and similarly for other methods. The returned Lock does not
-     * support a {@link Condition}; method {@link
-     * Lock#newCondition()} throws {@code
-     * UnsupportedOperationException}.
+     * support a {@link Condition}; method {@link Lock#newCondition()}
+     * throws {@code UnsupportedOperationException}.
      *
      * @return the lock
      */
     public Lock asReadLock() {
         ReadLockView v;
-        return ((v = readLockView) != null ? v :
-                (readLockView = new ReadLockView()));
+        if ((v = readLockView) != null) return v;
+        return readLockView = new ReadLockView();
     }
 
     /**
      * Returns a plain {@link Lock} view of this StampedLock in which
      * the {@link Lock#lock} method is mapped to {@link #writeLock},
      * and similarly for other methods. The returned Lock does not
-     * support a {@link Condition}; method {@link
-     * Lock#newCondition()} throws {@code
-     * UnsupportedOperationException}.
+     * support a {@link Condition}; method {@link Lock#newCondition()}
+     * throws {@code UnsupportedOperationException}.
      *
      * @return the lock
      */
     public Lock asWriteLock() {
         WriteLockView v;
-        return ((v = writeLockView) != null ? v :
-                (writeLockView = new WriteLockView()));
+        if ((v = writeLockView) != null) return v;
+        return writeLockView = new WriteLockView();
     }
 
     /**
@@ -870,8 +883,8 @@
      */
     public ReadWriteLock asReadWriteLock() {
         ReadWriteLockView v;
-        return ((v = readWriteLockView) != null ? v :
-                (readWriteLockView = new ReadWriteLockView()));
+        if ((v = readWriteLockView) != null) return v;
+        return readWriteLockView = new ReadWriteLockView();
     }
 
     // view classes
@@ -917,35 +930,32 @@
     // Needed because view-class lock methods throw away stamps.
 
     final void unstampedUnlockWrite() {
-        WNode h; long s;
+        long s;
         if (((s = state) & WBIT) == 0L)
             throw new IllegalMonitorStateException();
-        U.putLongVolatile(this, STATE, (s += WBIT) == 0L ? ORIGIN : s);
-        if ((h = whead) != null && h.status != 0)
-            release(h);
+        unlockWriteInternal(s);
     }
 
     final void unstampedUnlockRead() {
-        for (;;) {
-            long s, m; WNode h;
-            if ((m = (s = state) & ABITS) == 0L || m >= WBIT)
-                throw new IllegalMonitorStateException();
-            else if (m < RFULL) {
-                if (U.compareAndSwapLong(this, STATE, s, s - RUNIT)) {
+        long s, m; WNode h;
+        while ((m = (s = state) & RBITS) > 0L) {
+            if (m < RFULL) {
+                if (STATE.compareAndSet(this, s, s - RUNIT)) {
                     if (m == RUNIT && (h = whead) != null && h.status != 0)
                         release(h);
-                    break;
+                    return;
                 }
             }
             else if (tryDecReaderOverflow(s) != 0L)
-                break;
+                return;
         }
+        throw new IllegalMonitorStateException();
     }
 
     private void readObject(java.io.ObjectInputStream s)
         throws java.io.IOException, ClassNotFoundException {
         s.defaultReadObject();
-        U.putLongVolatile(this, STATE, ORIGIN); // reset to unlocked state
+        STATE.setVolatile(this, ORIGIN); // reset to unlocked state
     }
 
     // internals
@@ -961,15 +971,16 @@
     private long tryIncReaderOverflow(long s) {
         // assert (s & ABITS) >= RFULL;
         if ((s & ABITS) == RFULL) {
-            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
+            if (STATE.compareAndSet(this, s, s | RBITS)) {
                 ++readerOverflow;
-                U.putLongVolatile(this, STATE, s);
+                STATE.setVolatile(this, s);
                 return s;
             }
         }
-        else if ((LockSupport.nextSecondarySeed() &
-                  OVERFLOW_YIELD_RATE) == 0)
+        else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
             Thread.yield();
+        else
+            Thread.onSpinWait();
         return 0L;
     }
 
@@ -982,7 +993,7 @@
     private long tryDecReaderOverflow(long s) {
         // assert (s & ABITS) >= RFULL;
         if ((s & ABITS) == RFULL) {
-            if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
+            if (STATE.compareAndSet(this, s, s | RBITS)) {
                 int r; long next;
                 if ((r = readerOverflow) > 0) {
                     readerOverflow = r - 1;
@@ -990,13 +1001,14 @@
                 }
                 else
                     next = s - RUNIT;
-                U.putLongVolatile(this, STATE, next);
+                STATE.setVolatile(this, next);
                 return next;
             }
         }
-        else if ((LockSupport.nextSecondarySeed() &
-                  OVERFLOW_YIELD_RATE) == 0)
+        else if ((LockSupport.nextSecondarySeed() & OVERFLOW_YIELD_RATE) == 0)
             Thread.yield();
+        else
+            Thread.onSpinWait();
         return 0L;
     }
 
@@ -1010,14 +1022,14 @@
     private void release(WNode h) {
         if (h != null) {
             WNode q; Thread w;
-            U.compareAndSwapInt(h, WSTATUS, WAITING, 0);
+            WSTATUS.compareAndSet(h, WAITING, 0);
             if ((q = h.next) == null || q.status == CANCELLED) {
                 for (WNode t = wtail; t != null && t != h; t = t.prev)
                     if (t.status <= 0)
                         q = t;
             }
             if (q != null && (w = q.thread) != null)
-                U.unpark(w);
+                LockSupport.unpark(w);
         }
     }
 
@@ -1035,25 +1047,25 @@
         for (int spins = -1;;) { // spin while enqueuing
             long m, s, ns;
             if ((m = (s = state) & ABITS) == 0L) {
-                if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT))
+                if (STATE.compareAndSet(this, s, ns = s + WBIT))
                     return ns;
             }
             else if (spins < 0)
                 spins = (m == WBIT && wtail == whead) ? SPINS : 0;
             else if (spins > 0) {
-                if (LockSupport.nextSecondarySeed() >= 0)
-                    --spins;
+                --spins;
+                Thread.onSpinWait();
             }
             else if ((p = wtail) == null) { // initialize queue
                 WNode hd = new WNode(WMODE, null);
-                if (U.compareAndSwapObject(this, WHEAD, null, hd))
+                if (WHEAD.weakCompareAndSetVolatile(this, null, hd))
                     wtail = hd;
             }
             else if (node == null)
                 node = new WNode(WMODE, p);
             else if (node.prev != p)
                 node.prev = p;
-            else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
+            else if (WTAIL.weakCompareAndSetVolatile(this, p, node)) {
                 p.next = node;
                 break;
             }
@@ -1067,11 +1079,10 @@
                     spins = HEAD_SPINS;
                 else if (spins < MAX_HEAD_SPINS)
                     spins <<= 1;
-                for (int k = spins;;) { // spin at head
+                for (int k = spins; k > 0; --k) { // spin at head
                     long s, ns;
                     if (((s = state) & ABITS) == 0L) {
-                        if (U.compareAndSwapLong(this, STATE, s,
-                                                 ns = s + WBIT)) {
+                        if (STATE.compareAndSet(this, s, ns = s + WBIT)) {
                             whead = node;
                             node.prev = null;
                             if (wasInterrupted)
@@ -1079,17 +1090,16 @@
                             return ns;
                         }
                     }
-                    else if (LockSupport.nextSecondarySeed() >= 0 &&
-                             --k <= 0)
-                        break;
+                    else
+                        Thread.onSpinWait();
                 }
             }
             else if (h != null) { // help release stale waiters
                 WNode c; Thread w;
                 while ((c = h.cowait) != null) {
-                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
+                    if (WCOWAIT.weakCompareAndSetVolatile(h, c, c.cowait) &&
                         (w = c.thread) != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                 }
             }
             if (whead == h) {
@@ -1098,7 +1108,7 @@
                         (p = np).next = node;   // stale
                 }
                 else if ((ps = p.status) == 0)
-                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
+                    WSTATUS.compareAndSet(p, 0, WAITING);
                 else if (ps == CANCELLED) {
                     if ((pp = p.prev) != null) {
                         node.prev = pp;
@@ -1112,13 +1122,15 @@
                     else if ((time = deadline - System.nanoTime()) <= 0L)
                         return cancelWaiter(node, node, false);
                     Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
                     node.thread = wt;
                     if (p.status < 0 && (p != h || (state & ABITS) != 0L) &&
-                        whead == h && node.prev == p)
-                        U.park(false, time);  // emulate LockSupport.park
+                        whead == h && node.prev == p) {
+                        if (time == 0L)
+                            LockSupport.park(this);
+                        else
+                            LockSupport.parkNanos(this, time);
+                    }
                     node.thread = null;
-                    U.putObject(wt, PARKBLOCKER, null);
                     if (Thread.interrupted()) {
                         if (interruptible)
                             return cancelWaiter(node, node, true);
@@ -1146,7 +1158,7 @@
             if ((h = whead) == (p = wtail)) {
                 for (long m, s, ns;;) {
                     if ((m = (s = state) & ABITS) < RFULL ?
-                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
+                        STATE.compareAndSet(this, s, ns = s + RUNIT) :
                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                         if (wasInterrupted)
                             Thread.currentThread().interrupt();
@@ -1154,8 +1166,8 @@
                     }
                     else if (m >= WBIT) {
                         if (spins > 0) {
-                            if (LockSupport.nextSecondarySeed() >= 0)
-                                --spins;
+                            --spins;
+                            Thread.onSpinWait();
                         }
                         else {
                             if (spins == 0) {
@@ -1170,7 +1182,7 @@
             }
             if (p == null) { // initialize queue
                 WNode hd = new WNode(WMODE, null);
-                if (U.compareAndSwapObject(this, WHEAD, null, hd))
+                if (WHEAD.weakCompareAndSetVolatile(this, null, hd))
                     wtail = hd;
             }
             else if (node == null)
@@ -1178,27 +1190,25 @@
             else if (h == p || p.mode != RMODE) {
                 if (node.prev != p)
                     node.prev = p;
-                else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
+                else if (WTAIL.weakCompareAndSetVolatile(this, p, node)) {
                     p.next = node;
                     break;
                 }
             }
-            else if (!U.compareAndSwapObject(p, WCOWAIT,
-                                             node.cowait = p.cowait, node))
+            else if (!WCOWAIT.compareAndSet(p, node.cowait = p.cowait, node))
                 node.cowait = null;
             else {
                 for (;;) {
                     WNode pp, c; Thread w;
                     if ((h = whead) != null && (c = h.cowait) != null &&
-                        U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
+                        WCOWAIT.compareAndSet(h, c, c.cowait) &&
                         (w = c.thread) != null) // help release
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                     if (h == (pp = p.prev) || h == p || pp == null) {
                         long m, s, ns;
                         do {
                             if ((m = (s = state) & ABITS) < RFULL ?
-                                U.compareAndSwapLong(this, STATE, s,
-                                                     ns = s + RUNIT) :
+                                STATE.compareAndSet(this, s, ns = s + RUNIT) :
                                 (m < WBIT &&
                                  (ns = tryIncReaderOverflow(s)) != 0L)) {
                                 if (wasInterrupted)
@@ -1221,13 +1231,15 @@
                             return cancelWaiter(node, p, false);
                         }
                         Thread wt = Thread.currentThread();
-                        U.putObject(wt, PARKBLOCKER, this);
                         node.thread = wt;
                         if ((h != pp || (state & ABITS) == WBIT) &&
-                            whead == h && p.prev == pp)
-                            U.park(false, time);
+                            whead == h && p.prev == pp) {
+                            if (time == 0L)
+                                LockSupport.park(this);
+                            else
+                                LockSupport.parkNanos(this, time);
+                        }
                         node.thread = null;
-                        U.putObject(wt, PARKBLOCKER, null);
                         if (Thread.interrupted()) {
                             if (interruptible)
                                 return cancelWaiter(node, p, true);
@@ -1248,32 +1260,32 @@
                 for (int k = spins;;) { // spin at head
                     long m, s, ns;
                     if ((m = (s = state) & ABITS) < RFULL ?
-                        U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT) :
+                        STATE.compareAndSet(this, s, ns = s + RUNIT) :
                         (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                         WNode c; Thread w;
                         whead = node;
                         node.prev = null;
                         while ((c = node.cowait) != null) {
-                            if (U.compareAndSwapObject(node, WCOWAIT,
-                                                       c, c.cowait) &&
+                            if (WCOWAIT.compareAndSet(node, c, c.cowait) &&
                                 (w = c.thread) != null)
-                                U.unpark(w);
+                                LockSupport.unpark(w);
                         }
                         if (wasInterrupted)
                             Thread.currentThread().interrupt();
                         return ns;
                     }
-                    else if (m >= WBIT &&
-                             LockSupport.nextSecondarySeed() >= 0 && --k <= 0)
+                    else if (m >= WBIT && --k <= 0)
                         break;
+                    else
+                        Thread.onSpinWait();
                 }
             }
             else if (h != null) {
                 WNode c; Thread w;
                 while ((c = h.cowait) != null) {
-                    if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) &&
+                    if (WCOWAIT.compareAndSet(h, c, c.cowait) &&
                         (w = c.thread) != null)
-                        U.unpark(w);
+                        LockSupport.unpark(w);
                 }
             }
             if (whead == h) {
@@ -1282,7 +1294,7 @@
                         (p = np).next = node;   // stale
                 }
                 else if ((ps = p.status) == 0)
-                    U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
+                    WSTATUS.compareAndSet(p, 0, WAITING);
                 else if (ps == CANCELLED) {
                     if ((pp = p.prev) != null) {
                         node.prev = pp;
@@ -1296,14 +1308,16 @@
                     else if ((time = deadline - System.nanoTime()) <= 0L)
                         return cancelWaiter(node, node, false);
                     Thread wt = Thread.currentThread();
-                    U.putObject(wt, PARKBLOCKER, this);
                     node.thread = wt;
                     if (p.status < 0 &&
                         (p != h || (state & ABITS) == WBIT) &&
-                        whead == h && node.prev == p)
-                        U.park(false, time);
+                        whead == h && node.prev == p) {
+                            if (time == 0L)
+                                LockSupport.park(this);
+                            else
+                                LockSupport.parkNanos(this, time);
+                    }
                     node.thread = null;
-                    U.putObject(wt, PARKBLOCKER, null);
                     if (Thread.interrupted()) {
                         if (interruptible)
                             return cancelWaiter(node, node, true);
@@ -1325,7 +1339,7 @@
      * AbstractQueuedSynchronizer (see its detailed explanation in AQS
      * internal documentation).
      *
-     * @param node if nonnull, the waiter
+     * @param node if non-null, the waiter
      * @param group either node or the group node is cowaiting with
      * @param interrupted if already interrupted
      * @return INTERRUPTED if interrupted or Thread.interrupted, else zero
@@ -1337,7 +1351,7 @@
             // unsplice cancelled nodes from group
             for (WNode p = group, q; (q = p.cowait) != null;) {
                 if (q.status == CANCELLED) {
-                    U.compareAndSwapObject(p, WCOWAIT, q, q.cowait);
+                    WCOWAIT.compareAndSet(p, q, q.cowait);
                     p = group; // restart
                 }
                 else
@@ -1346,7 +1360,7 @@
             if (group == node) {
                 for (WNode r = group.cowait; r != null; r = r.cowait) {
                     if ((w = r.thread) != null)
-                        U.unpark(w);       // wake up uncancelled co-waiters
+                        LockSupport.unpark(w); // wake up uncancelled co-waiters
                 }
                 for (WNode pred = node.prev; pred != null; ) { // unsplice
                     WNode succ, pp;        // find valid successor
@@ -1357,23 +1371,23 @@
                             if (t.status != CANCELLED)
                                 q = t;     // don't link if succ cancelled
                         if (succ == q ||   // ensure accurate successor
-                            U.compareAndSwapObject(node, WNEXT,
-                                                   succ, succ = q)) {
+                            WNEXT.compareAndSet(node, succ, succ = q)) {
                             if (succ == null && node == wtail)
-                                U.compareAndSwapObject(this, WTAIL, node, pred);
+                                WTAIL.compareAndSet(this, node, pred);
                             break;
                         }
                     }
                     if (pred.next == node) // unsplice pred link
-                        U.compareAndSwapObject(pred, WNEXT, node, succ);
+                        WNEXT.compareAndSet(pred, node, succ);
                     if (succ != null && (w = succ.thread) != null) {
+                        // wake up succ to observe new pred
                         succ.thread = null;
-                        U.unpark(w);       // wake up succ to observe new pred
+                        LockSupport.unpark(w);
                     }
                     if (pred.status != CANCELLED || (pp = pred.prev) == null)
                         break;
                     node.prev = pp;        // repeat if new pred wrong/cancelled
-                    U.compareAndSwapObject(pp, WNEXT, pred, succ);
+                    WNEXT.compareAndSet(pp, pred, succ);
                     pred = pp;
                 }
             }
@@ -1397,34 +1411,22 @@
         return (interrupted || Thread.interrupted()) ? INTERRUPTED : 0L;
     }
 
-    // Unsafe mechanics
-    private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe();
-    private static final long STATE;
-    private static final long WHEAD;
-    private static final long WTAIL;
-    private static final long WNEXT;
-    private static final long WSTATUS;
-    private static final long WCOWAIT;
-    private static final long PARKBLOCKER;
-
+    // VarHandle mechanics
+    private static final VarHandle STATE;
+    private static final VarHandle WHEAD;
+    private static final VarHandle WTAIL;
+    private static final VarHandle WNEXT;
+    private static final VarHandle WSTATUS;
+    private static final VarHandle WCOWAIT;
     static {
         try {
-            STATE = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("state"));
-            WHEAD = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("whead"));
-            WTAIL = U.objectFieldOffset
-                (StampedLock.class.getDeclaredField("wtail"));
-
-            WSTATUS = U.objectFieldOffset
-                (WNode.class.getDeclaredField("status"));
-            WNEXT = U.objectFieldOffset
-                (WNode.class.getDeclaredField("next"));
-            WCOWAIT = U.objectFieldOffset
-                (WNode.class.getDeclaredField("cowait"));
-
-            PARKBLOCKER = U.objectFieldOffset
-                (Thread.class.getDeclaredField("parkBlocker"));
+            MethodHandles.Lookup l = MethodHandles.lookup();
+            STATE = l.findVarHandle(StampedLock.class, "state", long.class);
+            WHEAD = l.findVarHandle(StampedLock.class, "whead", WNode.class);
+            WTAIL = l.findVarHandle(StampedLock.class, "wtail", WNode.class);
+            WSTATUS = l.findVarHandle(WNode.class, "status", int.class);
+            WNEXT = l.findVarHandle(WNode.class, "next", WNode.class);
+            WCOWAIT = l.findVarHandle(WNode.class, "cowait", WNode.class);
         } catch (ReflectiveOperationException e) {
             throw new Error(e);
         }
--- a/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.base/share/classes/java/util/concurrent/package-info.java	Mon Jul 18 09:38:08 2016 -0700
@@ -262,7 +262,6 @@
  *
  * </ul>
  *
- *
  * The methods of all classes in {@code java.util.concurrent} and its
  * subpackages extend these guarantees to higher-level
  * synchronization.  In particular:
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.nio.ByteBuffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncSSLDelegate.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.Closeable;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferConsumer.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ByteBufferGenerator.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/CharsetToolkit.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.nio.ByteBuffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.net.InetSocketAddress;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ContinuationFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/DataFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ErrorFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ErrorFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.security.AccessControlContext;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/FrameReader.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,8 +1,28 @@
 /*
- * To change this license header, choose License Headers in Project Properties.
- * To change this template file, choose Tools | Templates
- * and open the template in the editor.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.nio.ByteBuffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/GoAwayFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.util.Iterator;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HeadersFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeadersFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Frame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import javax.net.ssl.SSLContext;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.Closeable;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.util.Collections;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.net.URI;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -178,7 +178,7 @@
      */
     RawChannel rawChannel() throws IOException {
         if (rawchan == null) {
-            rawchan = new RawChannel(request.client(), connection);
+            rawchan = new RawChannelImpl(request.client(), connection);
         }
         return rawchan;
     }
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ImmutableHeaders.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.util.Locale;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/OutgoingHeaders.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 /**
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PingFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PriorityFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/PushPromiseFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Queue.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Queue.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,151 +20,43 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.nio.channels.ByteChannel;
-import java.nio.channels.GatheringByteChannel;
-import java.nio.channels.SelectableChannel;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.SocketChannel;
 
-//
-// Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
-// (SocketChannel) but is connected to a Selector and an ExecutorService for
-// invoking the send and receive callbacks. Also includes SSL processing.
-//
-final class RawChannel implements ByteChannel, GatheringByteChannel {
+/*
+ * I/O abstraction used to implement WebSocket.
+ */
+public interface RawChannel {
 
-    private final HttpClientImpl client;
-    private final HttpConnection connection;
+    interface RawEvent {
 
-    private interface RawEvent {
-
-        /**
-         * must return the selector interest op flags OR'd.
+        /*
+         * Must return the selector interest op flags.
          */
         int interestOps();
 
-        /**
-         * called when event occurs.
+        /*
+         * Called when event occurs.
          */
         void handle();
     }
 
-    interface NonBlockingEvent extends RawEvent {
-    }
-
-    RawChannel(HttpClientImpl client, HttpConnection connection)
-                                                throws IOException {
-        this.client = client;
-        this.connection = connection;
-        SocketChannel chan = connection.channel();
-        client.cancelRegistration(chan);
-        chan.configureBlocking(false);
-    }
-
-    SocketChannel socketChannel() {
-        return connection.channel();
-    }
-
-    ByteBuffer getRemaining() {
-        return connection.getRemaining();
-    }
-
-    private class RawAsyncEvent extends AsyncEvent {
-
-        private final RawEvent re;
-
-        RawAsyncEvent(RawEvent re) {
-            super(AsyncEvent.BLOCKING); // BLOCKING & !REPEATING
-            this.re = re;
-        }
-
-        RawAsyncEvent(RawEvent re, int flags) {
-            super(flags);
-            this.re = re;
-        }
-
-        @Override
-        public SelectableChannel channel() {
-            return connection.channel();
-        }
-
-        // must return the selector interest op flags OR'd
-        @Override
-        public int interestOps() {
-            return re.interestOps();
-        }
-
-        // called when event occurs
-        @Override
-        public void handle() {
-            re.handle();
-        }
-
-        @Override
-        public void abort() { }
-    }
-
-    private class NonBlockingRawAsyncEvent extends RawAsyncEvent {
-
-        NonBlockingRawAsyncEvent(RawEvent re) {
-            super(re, 0); // !BLOCKING & !REPEATING
-        }
-    }
-
     /*
      * Register given event whose callback will be called once only.
      * (i.e. register new event for each callback)
      */
-    public void registerEvent(RawEvent event) throws IOException {
-        if (!(event instanceof NonBlockingEvent)) {
-            throw new InternalError();
-        }
-        if ((event.interestOps() & SelectionKey.OP_READ) != 0
-                && connection.buffer.hasRemaining()) {
-            // FIXME: a hack to deal with leftovers from previous reads into an
-            // internal buffer (works in conjunction with change in
-            // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer)
-            connection.channel().configureBlocking(false);
-            event.handle();
-        } else {
-            client.registerEvent(new NonBlockingRawAsyncEvent(event));
-        }
-    }
+    void registerEvent(RawEvent event) throws IOException;
 
-    @Override
-    public int read(ByteBuffer dst) throws IOException {
-        assert !connection.channel().isBlocking();
-        return connection.read(dst);
-    }
+    int read(ByteBuffer dst) throws IOException;
 
-    @Override
-    public boolean isOpen() {
-        return connection.isOpen();
-    }
-
-    @Override
-    public void close() throws IOException {
-        connection.close();
-    }
+    long write(ByteBuffer[] src, int offset, int len) throws IOException;
 
-    @Override
-    public long write(ByteBuffer[] src) throws IOException {
-        return connection.write(src, 0, src.length);
-    }
+    boolean isOpen();
 
-    @Override
-    public long write(ByteBuffer[] src, int offset, int len)
-            throws IOException {
-        return connection.write(src, offset, len);
-    }
-
-    @Override
-    public int write(ByteBuffer src) throws IOException {
-        return (int) connection.write(src);
-    }
+    void close() throws IOException;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannelImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package java.net.http;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+
+/*
+ * Each RawChannel corresponds to a TCP connection (SocketChannel) but is
+ * connected to a Selector and an ExecutorService for invoking the send and
+ * receive callbacks. Also includes SSL processing.
+ */
+final class RawChannelImpl implements RawChannel {
+
+    private final HttpClientImpl client;
+    private final HttpConnection connection;
+
+    RawChannelImpl(HttpClientImpl client, HttpConnection connection)
+            throws IOException {
+        this.client = client;
+        this.connection = connection;
+        SocketChannel chan = connection.channel();
+        client.cancelRegistration(chan);
+        chan.configureBlocking(false);
+    }
+
+    private class NonBlockingRawAsyncEvent extends AsyncEvent {
+
+        private final RawEvent re;
+
+        NonBlockingRawAsyncEvent(RawEvent re) {
+            super(0); // !BLOCKING & !REPEATING
+            this.re = re;
+        }
+
+        @Override
+        public SelectableChannel channel() {
+            return connection.channel();
+        }
+
+        @Override
+        public int interestOps() {
+            return re.interestOps();
+        }
+
+        @Override
+        public void handle() {
+            re.handle();
+        }
+
+        @Override
+        public void abort() { }
+    }
+
+    @Override
+    public void registerEvent(RawEvent event) throws IOException {
+        if ((event.interestOps() & SelectionKey.OP_READ) != 0
+                && connection.buffer.hasRemaining()) {
+            // FIXME: a hack to deal with leftovers from previous reads into an
+            // internal buffer (works in conjunction with change in
+            // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer)
+            connection.channel().configureBlocking(false);
+            event.handle();
+        } else {
+            client.registerEvent(new NonBlockingRawAsyncEvent(event));
+        }
+    }
+
+    @Override
+    public int read(ByteBuffer dst) throws IOException {
+        assert !connection.channel().isBlocking();
+        return connection.read(dst);
+    }
+
+    @Override
+    public long write(ByteBuffer[] src, int offset, int len) throws IOException {
+        return connection.write(src, offset, len);
+    }
+
+    @Override
+    public boolean isOpen() {
+        return connection.isOpen();
+    }
+
+    @Override
+    public void close() throws IOException {
+        connection.close();
+    }
+}
--- a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResetFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/SettingsFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import sun.net.NetProperties;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WS.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WS.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSBuilder.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSBuilder.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.net.URI;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSCharsetToolkit.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSCharsetToolkit.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -20,7 +20,9 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
+
 package java.net.http;
 
 import java.nio.ByteBuffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposable.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSDisposable.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 interface WSDisposable {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.nio.ByteBuffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSFrameConsumer.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.net.http.WSFrame.Opcode;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageConsumer.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.net.http.WebSocket.CloseCode;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageSender.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSMessageSender.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.net.http.WSFrame.HeaderBuilder;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSOpeningHandshake.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.UncheckedIOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSOutgoingMessage.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSOutgoingMessage.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.nio.ByteBuffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSProtocolException.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSProtocolException.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,3 +1,28 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
 package java.net.http;
 
 import java.net.http.WebSocket.CloseCode;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSReceiver.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
@@ -53,7 +54,7 @@
     private final Supplier<WSShared<ByteBuffer>> buffersSupplier =
             new WSSharedPool<>(() -> ByteBuffer.allocateDirect(32768), 2);
     private final RawChannel channel;
-    private final RawChannel.NonBlockingEvent channelEvent;
+    private final RawChannel.RawEvent channelEvent;
     private final WSSignalHandler handler;
     private final AtomicLong demand = new AtomicLong();
     private final AtomicBoolean readable = new AtomicBoolean();
@@ -251,8 +252,8 @@
         assert newDemand >= 0 : newDemand;
     }
 
-    private RawChannel.NonBlockingEvent createChannelEvent() {
-        return new RawChannel.NonBlockingEvent() {
+    private RawChannel.RawEvent createChannelEvent() {
+        return new RawChannel.RawEvent() {
 
             @Override
             public int interestOps() {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSShared.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSShared.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.nio.Buffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSSharedPool.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSSharedPool.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.nio.Buffer;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSSignalHandler.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSSignalHandler.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.util.concurrent.Executor;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSTransmitter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.net.http.WSOutgoingMessage.Binary;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSUtils.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSUtils.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.net.URI;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WSWriter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WSWriter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,20 +1,20 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General  License version 2 only, as
+ * 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  License
+ * 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  License version
+ * 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.
  *
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
@@ -60,7 +61,7 @@
 final class WSWriter {
 
     private final RawChannel channel;
-    private final RawChannel.NonBlockingEvent writeReadinessHandler;
+    private final RawChannel.RawEvent writeReadinessHandler;
     private final Consumer<Throwable> completionCallback;
     private ByteBuffer[] buffers;
     private int offset;
@@ -110,8 +111,8 @@
         return -1;
     }
 
-    private RawChannel.NonBlockingEvent createHandler() {
-        return new RawChannel.NonBlockingEvent() {
+    private RawChannel.RawEvent createHandler() {
+        return new RawChannel.RawEvent() {
 
             @Override
             public int interestOps() {
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocket.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 import java.io.IOException;
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WebSocketHandshakeException.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WebSocketHandshakeException.java	Mon Jul 18 09:38:08 2016 -0700
@@ -22,6 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 package java.net.http;
 
 /**
--- a/jdk/src/java.httpclient/share/classes/java/net/http/WindowUpdateFrame.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/java/net/http/WindowUpdateFrame.java	Mon Jul 18 09:38:08 2016 -0700
@@ -20,6 +20,7 @@
  *
  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  * or visit www.oracle.com if you need additional information or have any
+ * questions.
  */
 
 package java.net.http;
--- a/jdk/src/java.httpclient/share/classes/module-info.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/java.httpclient/share/classes/module-info.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java	Mon Jul 18 09:38:08 2016 -0700
@@ -54,7 +54,7 @@
    }
    ...
 
-   HttpServer server = HttpServer.create(new InetSocketAddress(8000));
+   HttpServer server = HttpServer.create(new InetSocketAddress(8000), 0);
    server.createContext("/applications/myapp", new MyHandler());
    server.setExecutor(null); // creates a default executor
    server.start();
--- a/jdk/test/java/lang/ProcessBuilder/Zombies.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/lang/ProcessBuilder/Zombies.java	Mon Jul 18 09:38:08 2016 -0700
@@ -24,6 +24,7 @@
 /*
  * @test
  * @bug 6474073
+ * @key intermittent
  * @summary Make sure zombies don't get created on Unix
  * @author Martin Buchholz
  */
--- a/jdk/test/java/lang/invoke/LoopCombinatorLongSignatureTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/lang/invoke/LoopCombinatorLongSignatureTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -39,6 +39,11 @@
  * If a loop with an excessive amount of clauses is created, so that the number of parameters to the resulting loop
  * handle exceeds the allowed maximum, an IAE must be signalled. The test is run first in LambdaForm interpretation mode
  * and then in default mode, wherein bytecode generation falls back to LFI mode due to excessively long methods.
+ * <p>
+ * By default, the test run only checks whether loop handle construction succeeds and fails. If executing the generated
+ * loops is desired, this should be indicated by setting the {@code java.lang.invoke.LoopCombinatorLongSignatureTest.RUN}
+ * environment variable to {@code true}. This is disabled by default as it considerably increases the time needed to run
+ * the test.
  */
 public class LoopCombinatorLongSignatureTest {
 
@@ -51,13 +56,15 @@
     static final int ARG_LIMIT = 254; // for internal reasons, this is the maximum allowed number of arguments
 
     public static void main(String[] args) {
+        boolean run = Boolean.parseBoolean(
+                System.getProperty("java.lang.invoke.LoopCombinatorLongSignatureTest.RUN", "false"));
         for (int loopArgs = 0; loopArgs < 2; ++loopArgs) {
-            testLongSignature(loopArgs, false);
-            testLongSignature(loopArgs, true);
+            testLongSignature(loopArgs, false, run);
+            testLongSignature(loopArgs, true, run);
         }
     }
 
-    static void testLongSignature(int loopArgs, boolean excessive) {
+    static void testLongSignature(int loopArgs, boolean excessive, boolean run) {
         int nClauses = ARG_LIMIT - loopArgs + (excessive ? 1 : 0);
 
         System.out.print((excessive ? "(EXCESSIVE)" : "(LONG     )") + " arguments: " + loopArgs + ", clauses: " + nClauses + " -> ");
@@ -78,7 +85,7 @@
             MethodHandle loop = MethodHandles.loop(clauses);
             if (excessive) {
                 throw new AssertionError("loop construction should have failed");
-            } else {
+            } else if (run) {
                 int r;
                 if (loopArgs == 0) {
                     r = (int) loop.invoke();
@@ -88,6 +95,8 @@
                     r = (int) loop.invokeWithArguments(args);
                 }
                 System.out.println("SUCCEEDED (OK) -> " + r);
+            } else {
+                System.out.println("SUCCEEDED (OK)");
             }
         } catch (IllegalArgumentException iae) {
             if (excessive) {
--- a/jdk/test/java/net/httpclient/whitebox/java.httpclient/java/net/http/SelectorTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/net/httpclient/whitebox/java.httpclient/java/net/http/SelectorTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -78,7 +78,7 @@
 
             final RawChannel chan = getARawChannel(port);
 
-            chan.registerEvent(new RawChannel.NonBlockingEvent() {
+            chan.registerEvent(new RawChannel.RawEvent() {
                 @Override
                 public int interestOps() {
                     return SelectionKey.OP_READ;
@@ -95,7 +95,7 @@
                 }
             });
 
-            chan.registerEvent(new RawChannel.NonBlockingEvent() {
+            chan.registerEvent(new RawChannel.RawEvent() {
                 @Override
                 public int interestOps() {
                     return SelectionKey.OP_WRITE;
@@ -111,7 +111,7 @@
                         ByteBuffer bb = ByteBuffer.wrap(TestServer.INPUT);
                         counter.incrementAndGet();
                         try {
-                            chan.write(bb);
+                            chan.write(new ByteBuffer[]{bb}, 0, 1);
                         } catch (IOException e) {
                             throw new UncheckedIOException(e);
                         }
--- a/jdk/test/java/nio/file/WatchService/DeleteInterference.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/nio/file/WatchService/DeleteInterference.java	Mon Jul 18 09:38:08 2016 -0700
@@ -32,6 +32,7 @@
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.WatchService;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
@@ -49,7 +50,8 @@
      * directory.
      */
     public static void main(String[] args) throws Exception {
-        Path dir = Files.createTempDirectory("DeleteInterference");
+        Path testDir = Paths.get(System.getProperty("test.dir", "."));
+        Path dir = Files.createTempDirectory(testDir, "DeleteInterference");
         ExecutorService pool = Executors.newCachedThreadPool();
         try {
             Future<?> task1 = pool.submit(() -> openAndCloseWatcher(dir));
@@ -58,7 +60,6 @@
             task2.get();
         } finally {
             pool.shutdown();
-            deleteFileTree(dir);
         }
     }
 
--- a/jdk/test/java/nio/file/WatchService/LotsOfCancels.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/nio/file/WatchService/LotsOfCancels.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,11 +27,11 @@
  *    an outstanding I/O operation on directory completes after the
  *    directory has been closed
  */
-
 import java.nio.file.ClosedWatchServiceException;
 import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.nio.file.WatchKey;
 import java.nio.file.WatchService;
 import static java.nio.file.StandardWatchEventKinds.*;
@@ -50,8 +50,8 @@
         // one to bash on cancel, the other to poll the events
         ExecutorService pool = Executors.newCachedThreadPool();
         try {
-            Path top = Files.createTempDirectory("LotsOfCancels");
-            top.toFile().deleteOnExit();
+            Path testDir = Paths.get(System.getProperty("test.dir", "."));
+            Path top = Files.createTempDirectory(testDir, "LotsOfCancels");
             for (int i=1; i<=16; i++) {
                 Path dir = Files.createDirectory(top.resolve("dir-" + i));
                 WatchService watcher = FileSystems.getDefault().newWatchService();
@@ -114,6 +114,4 @@
             failed = true;
         }
     }
-
 }
-
--- a/jdk/test/java/util/concurrent/tck/Atomic8Test.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/Atomic8Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -179,7 +179,7 @@
      * result of supplied function
      */
     public void testReferenceGetAndUpdate() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(one);
         assertEquals(new Integer(1), a.getAndUpdate(Atomic8Test::addInteger17));
         assertEquals(new Integer(18), a.getAndUpdate(Atomic8Test::addInteger17));
         assertEquals(new Integer(35), a.get());
@@ -190,7 +190,7 @@
      * returns result.
      */
     public void testReferenceUpdateAndGet() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(one);
         assertEquals(new Integer(18), a.updateAndGet(Atomic8Test::addInteger17));
         assertEquals(new Integer(35), a.updateAndGet(Atomic8Test::addInteger17));
         assertEquals(new Integer(35), a.get());
@@ -201,7 +201,7 @@
      * with supplied function.
      */
     public void testReferenceGetAndAccumulate() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(one);
         assertEquals(new Integer(1), a.getAndAccumulate(2, Atomic8Test::sumInteger));
         assertEquals(new Integer(3), a.getAndAccumulate(3, Atomic8Test::sumInteger));
         assertEquals(new Integer(6), a.get());
@@ -212,7 +212,7 @@
      * returns result.
      */
     public void testReferenceAccumulateAndGet() {
-        AtomicReference<Integer> a = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> a = new AtomicReference<>(one);
         assertEquals(new Integer(7), a.accumulateAndGet(6, Atomic8Test::sumInteger));
         assertEquals(new Integer(10), a.accumulateAndGet(3, Atomic8Test::sumInteger));
         assertEquals(new Integer(10), a.get());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicBoolean9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicBoolean9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicBoolean9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getPlain());
+        ai.set(false);
+        assertEquals(false, ai.getPlain());
+        ai.set(true);
+        assertEquals(true, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getOpaque());
+        ai.set(false);
+        assertEquals(false, ai.getOpaque());
+        ai.set(true);
+        assertEquals(true, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.getAcquire());
+        ai.set(false);
+        assertEquals(false, ai.getAcquire());
+        ai.set(true);
+        assertEquals(true, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.get());
+        ai.setPlain(false);
+        assertEquals(false, ai.get());
+        ai.setPlain(true);
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.get());
+        ai.setOpaque(false);
+        assertEquals(false, ai.get());
+        ai.setOpaque(true);
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.get());
+        ai.setRelease(false);
+        assertEquals(false, ai.get());
+        ai.setRelease(true);
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.compareAndExchange(true, false));
+        assertEquals(false, ai.compareAndExchange(false, false));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchange(true, true));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchange(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.compareAndExchangeAcquire(true, false));
+        assertEquals(false, ai.compareAndExchangeAcquire(false, false));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeAcquire(true, true));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeAcquire(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        assertEquals(true, ai.compareAndExchangeRelease(true, false));
+        assertEquals(false, ai.compareAndExchangeRelease(false, false));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeRelease(true, true));
+        assertEquals(false, ai.get());
+        assertEquals(false, ai.compareAndExchangeRelease(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSetVolatile(true, false));
+        do {} while (!ai.weakCompareAndSetVolatile(false, false));
+        assertEquals(false, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSetAcquire(true, false));
+        do {} while (!ai.weakCompareAndSetAcquire(false, false));
+        assertEquals(false, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(false, true));
+        assertEquals(true, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicBoolean ai = new AtomicBoolean(true);
+        do {} while (!ai.weakCompareAndSetRelease(true, false));
+        do {} while (!ai.weakCompareAndSetRelease(false, false));
+        assertEquals(false, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(false, true));
+        assertEquals(true, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicInteger9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicInteger9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicInteger9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getPlain());
+        ai.set(2);
+        assertEquals(2, ai.getPlain());
+        ai.set(-3);
+        assertEquals(-3, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getOpaque());
+        ai.set(2);
+        assertEquals(2, ai.getOpaque());
+        ai.set(-3);
+        assertEquals(-3, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.getAcquire());
+        ai.set(2);
+        assertEquals(2, ai.getAcquire());
+        ai.set(-3);
+        assertEquals(-3, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.setPlain(2);
+        assertEquals(2, ai.get());
+        ai.setPlain(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.setOpaque(2);
+        assertEquals(2, ai.get());
+        ai.setOpaque(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.get());
+        ai.setRelease(2);
+        assertEquals(2, ai.get());
+        ai.setRelease(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.compareAndExchange(1, 2));
+        assertEquals(2, ai.compareAndExchange(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.compareAndExchangeAcquire(1, 2));
+        assertEquals(2, ai.compareAndExchangeAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicInteger ai = new AtomicInteger(1);
+        assertEquals(1, ai.compareAndExchangeRelease(1, 2));
+        assertEquals(2, ai.compareAndExchangeRelease(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSetVolatile(1, 2));
+        do {} while (!ai.weakCompareAndSetVolatile(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSetAcquire(1, 2));
+        do {} while (!ai.weakCompareAndSetAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicInteger ai = new AtomicInteger(1);
+        do {} while (!ai.weakCompareAndSetRelease(1, 2));
+        do {} while (!ai.weakCompareAndSetRelease(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicIntegerArray9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicIntegerArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicIntegerArray9Test extends JSR166TestCase {
+
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicIntegerArray9Test.class);
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            final int j = index;
+            final Runnable[] tasks = {
+                () -> aa.getPlain(j),
+                () -> aa.getOpaque(j),
+                () -> aa.getAcquire(j),
+                () -> aa.setPlain(j, 1),
+                () -> aa.setOpaque(j, 1),
+                () -> aa.setRelease(j, 1),
+                () -> aa.compareAndExchange(j, 1, 2),
+                () -> aa.compareAndExchangeAcquire(j, 1, 2),
+                () -> aa.compareAndExchangeRelease(j, 1, 2),
+                () -> aa.weakCompareAndSetVolatile(j, 1, 2),
+                () -> aa.weakCompareAndSetAcquire(j, 1, 2),
+                () -> aa.weakCompareAndSetRelease(j, 1, 2),
+            };
+
+            assertThrows(IndexOutOfBoundsException.class, tasks);
+        }
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getPlain(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getPlain(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getPlain(i));
+        }
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getOpaque(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getOpaque(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getOpaque(i));
+        }
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAcquire(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getAcquire(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getAcquire(i));
+        }
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setPlain(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setPlain(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setPlain(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setOpaque(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setOpaque(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setOpaque(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setRelease(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setRelease(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setRelease(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchange(i, 1, 2));
+            assertEquals(2, aa.compareAndExchange(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeAcquire(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeRelease(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetVolatile(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetVolatile(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetVolatile(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetAcquire(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicIntegerArray aa = new AtomicIntegerArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetRelease(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicLong9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLong9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLong9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getPlain());
+        ai.set(2);
+        assertEquals(2, ai.getPlain());
+        ai.set(-3);
+        assertEquals(-3, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getOpaque());
+        ai.set(2);
+        assertEquals(2, ai.getOpaque());
+        ai.set(-3);
+        assertEquals(-3, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.getAcquire());
+        ai.set(2);
+        assertEquals(2, ai.getAcquire());
+        ai.set(-3);
+        assertEquals(-3, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.setPlain(2);
+        assertEquals(2, ai.get());
+        ai.setPlain(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.setOpaque(2);
+        assertEquals(2, ai.get());
+        ai.setOpaque(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.get());
+        ai.setRelease(2);
+        assertEquals(2, ai.get());
+        ai.setRelease(-3);
+        assertEquals(-3, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.compareAndExchange(1, 2));
+        assertEquals(2, ai.compareAndExchange(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchange(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.compareAndExchangeAcquire(1, 2));
+        assertEquals(2, ai.compareAndExchangeAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicLong ai = new AtomicLong(1);
+        assertEquals(1, ai.compareAndExchangeRelease(1, 2));
+        assertEquals(2, ai.compareAndExchangeRelease(2, -4));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-5, 7));
+        assertEquals(-4, ai.get());
+        assertEquals(-4, ai.compareAndExchangeRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSetVolatile(1, 2));
+        do {} while (!ai.weakCompareAndSetVolatile(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSetAcquire(1, 2));
+        do {} while (!ai.weakCompareAndSetAcquire(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicLong ai = new AtomicLong(1);
+        do {} while (!ai.weakCompareAndSetRelease(1, 2));
+        do {} while (!ai.weakCompareAndSetRelease(2, -4));
+        assertEquals(-4, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(-4, 7));
+        assertEquals(7, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicLongArray9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicLongArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicLongArray9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicLongArray9Test.class);
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            final int j = index;
+            final Runnable[] tasks = {
+                () -> aa.getPlain(j),
+                () -> aa.getOpaque(j),
+                () -> aa.getAcquire(j),
+                () -> aa.setPlain(j, 1),
+                () -> aa.setOpaque(j, 1),
+                () -> aa.setRelease(j, 1),
+                () -> aa.compareAndExchange(j, 1, 2),
+                () -> aa.compareAndExchangeAcquire(j, 1, 2),
+                () -> aa.compareAndExchangeRelease(j, 1, 2),
+                () -> aa.weakCompareAndSetVolatile(j, 1, 2),
+                () -> aa.weakCompareAndSetAcquire(j, 1, 2),
+                () -> aa.weakCompareAndSetRelease(j, 1, 2),
+            };
+
+            assertThrows(IndexOutOfBoundsException.class, tasks);
+        }
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getPlain(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getPlain(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getPlain(i));
+        }
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getOpaque(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getOpaque(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getOpaque(i));
+        }
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.getAcquire(i));
+            aa.set(i, 2);
+            assertEquals(2, aa.getAcquire(i));
+            aa.set(i, -3);
+            assertEquals(-3, aa.getAcquire(i));
+        }
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setPlain(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setPlain(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setPlain(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setOpaque(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setOpaque(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setOpaque(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setRelease(i, 1);
+            assertEquals(1, aa.get(i));
+            aa.setRelease(i, 2);
+            assertEquals(2, aa.get(i));
+            aa.setRelease(i, -3);
+            assertEquals(-3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchange(i, 1, 2));
+            assertEquals(2, aa.compareAndExchange(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchange(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeAcquire(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            assertEquals(1, aa.compareAndExchangeRelease(i, 1, 2));
+            assertEquals(2, aa.compareAndExchangeRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i,-5, 7));
+            assertEquals(-4, aa.get(i));
+            assertEquals(-4, aa.compareAndExchangeRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetVolatile(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetVolatile(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetVolatile(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetAcquire(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetAcquire(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetAcquire(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicLongArray aa = new AtomicLongArray(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, 1);
+            do {} while (!aa.weakCompareAndSetRelease(i, 1, 2));
+            do {} while (!aa.weakCompareAndSetRelease(i, 2, -4));
+            assertEquals(-4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetRelease(i, -4, 7));
+            assertEquals(7, aa.get(i));
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicReference9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,203 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicReference9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicReference9Test.class);
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.getPlain());
+        ai.set(two);
+        assertEquals(two, ai.getPlain());
+        ai.set(m3);
+        assertEquals(m3, ai.getPlain());
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.getOpaque());
+        ai.set(two);
+        assertEquals(two, ai.getOpaque());
+        ai.set(m3);
+        assertEquals(m3, ai.getOpaque());
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.getAcquire());
+        ai.set(two);
+        assertEquals(two, ai.getAcquire());
+        ai.set(m3);
+        assertEquals(m3, ai.getAcquire());
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.get());
+        ai.setPlain(two);
+        assertEquals(two, ai.get());
+        ai.setPlain(m3);
+        assertEquals(m3, ai.get());
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.get());
+        ai.setOpaque(two);
+        assertEquals(two, ai.get());
+        ai.setOpaque(m3);
+        assertEquals(m3, ai.get());
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.get());
+        ai.setRelease(two);
+        assertEquals(two, ai.get());
+        ai.setRelease(m3);
+        assertEquals(m3, ai.get());
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.compareAndExchange(one, two));
+        assertEquals(two, ai.compareAndExchange(two, m4));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchange(m5, seven));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchange(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.compareAndExchangeAcquire(one, two));
+        assertEquals(two, ai.compareAndExchangeAcquire(two, m4));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeAcquire(m5, seven));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeAcquire(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        assertEquals(one, ai.compareAndExchangeRelease(one, two));
+        assertEquals(two, ai.compareAndExchangeRelease(two, m4));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeRelease(m5, seven));
+        assertEquals(m4, ai.get());
+        assertEquals(m4, ai.compareAndExchangeRelease(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        do {} while (!ai.weakCompareAndSetVolatile(one, two));
+        do {} while (!ai.weakCompareAndSetVolatile(two, m4));
+        assertEquals(m4, ai.get());
+        do {} while (!ai.weakCompareAndSetVolatile(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        do {} while (!ai.weakCompareAndSetAcquire(one, two));
+        do {} while (!ai.weakCompareAndSetAcquire(two, m4));
+        assertEquals(m4, ai.get());
+        do {} while (!ai.weakCompareAndSetAcquire(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
+        do {} while (!ai.weakCompareAndSetRelease(one, two));
+        do {} while (!ai.weakCompareAndSetRelease(two, m4));
+        assertEquals(m4, ai.get());
+        do {} while (!ai.weakCompareAndSetRelease(m4, seven));
+        assertEquals(seven, ai.get());
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArray9Test.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,266 @@
+/*
+ * 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.
+ */
+
+/*
+ * This file is available under and governed by the GNU General Public
+ * License version 2 only, as published by the Free Software Foundation.
+ * However, the following notice accompanied the original version of this
+ * file:
+ *
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/publicdomain/zero/1.0/
+ */
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicReferenceArray;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AtomicReferenceArray9Test extends JSR166TestCase {
+    public static void main(String[] args) {
+        main(suite(), args);
+    }
+    public static Test suite() {
+        return new TestSuite(AtomicReferenceArray9Test.class);
+    }
+
+    /**
+     * get and set for out of bound indices throw IndexOutOfBoundsException
+     */
+    public void testIndexing() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int index : new int[] { -1, SIZE }) {
+            final int j = index;
+            final Runnable[] tasks = {
+                () -> aa.getPlain(j),
+                () -> aa.getOpaque(j),
+                () -> aa.getAcquire(j),
+                () -> aa.setPlain(j, null),
+                () -> aa.setOpaque(j, null),
+                () -> aa.setRelease(j, null),
+                () -> aa.compareAndExchange(j, null, null),
+                () -> aa.compareAndExchangeAcquire(j, null, null),
+                () -> aa.compareAndExchangeRelease(j, null, null),
+                () -> aa.weakCompareAndSetVolatile(j, null, null),
+                () -> aa.weakCompareAndSetAcquire(j, null, null),
+                () -> aa.weakCompareAndSetRelease(j, null, null),
+            };
+
+            assertThrows(IndexOutOfBoundsException.class, tasks);
+        }
+    }
+
+    /**
+     * getPlain returns the last value set
+     */
+    public void testGetPlainSet() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.getPlain(i));
+            aa.set(i, two);
+            assertEquals(two, aa.getPlain(i));
+            aa.set(i, m3);
+            assertEquals(m3, aa.getPlain(i));
+        }
+    }
+
+    /**
+     * getOpaque returns the last value set
+     */
+    public void testGetOpaqueSet() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.getOpaque(i));
+            aa.set(i, two);
+            assertEquals(two, aa.getOpaque(i));
+            aa.set(i, m3);
+            assertEquals(m3, aa.getOpaque(i));
+        }
+    }
+
+    /**
+     * getAcquire returns the last value set
+     */
+    public void testGetAcquireSet() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.getAcquire(i));
+            aa.set(i, two);
+            assertEquals(two, aa.getAcquire(i));
+            aa.set(i, m3);
+            assertEquals(m3, aa.getAcquire(i));
+        }
+    }
+
+    /**
+     * get returns the last value setPlain
+     */
+    public void testGetSetPlain() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setPlain(i, one);
+            assertEquals(one, aa.get(i));
+            aa.setPlain(i, two);
+            assertEquals(two, aa.get(i));
+            aa.setPlain(i, m3);
+            assertEquals(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setOpaque
+     */
+    public void testGetSetOpaque() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setOpaque(i, one);
+            assertEquals(one, aa.get(i));
+            aa.setOpaque(i, two);
+            assertEquals(two, aa.get(i));
+            aa.setOpaque(i, m3);
+            assertEquals(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * get returns the last value setRelease
+     */
+    public void testGetSetRelease() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.setRelease(i, one);
+            assertEquals(one, aa.get(i));
+            aa.setRelease(i, two);
+            assertEquals(two, aa.get(i));
+            aa.setRelease(i, m3);
+            assertEquals(m3, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchange succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchange() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.compareAndExchange(i, one, two));
+            assertEquals(two, aa.compareAndExchange(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchange(i,m5, seven));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchange(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeAcquire succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeAcquire() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.compareAndExchangeAcquire(i, one, two));
+            assertEquals(two, aa.compareAndExchangeAcquire(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeAcquire(i,m5, seven));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeAcquire(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * compareAndExchangeRelease succeeds in changing value if equal to
+     * expected else fails
+     */
+    public void testCompareAndExchangeRelease() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            assertEquals(one, aa.compareAndExchangeRelease(i, one, two));
+            assertEquals(two, aa.compareAndExchangeRelease(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeRelease(i,m5, seven));
+            assertEquals(m4, aa.get(i));
+            assertEquals(m4, aa.compareAndExchangeRelease(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetVolatile succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetVolatile() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            do {} while (!aa.weakCompareAndSetVolatile(i, one, two));
+            do {} while (!aa.weakCompareAndSetVolatile(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetVolatile(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetAcquire succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetAcquire() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            do {} while (!aa.weakCompareAndSetAcquire(i, one, two));
+            do {} while (!aa.weakCompareAndSetAcquire(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetAcquire(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+    /**
+     * repeated weakCompareAndSetRelease succeeds in changing value when equal
+     * to expected
+     */
+    public void testWeakCompareAndSetRelease() {
+        AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<>(SIZE);
+        for (int i = 0; i < SIZE; i++) {
+            aa.set(i, one);
+            do {} while (!aa.weakCompareAndSetRelease(i, one, two));
+            do {} while (!aa.weakCompareAndSetRelease(i, two, m4));
+            assertEquals(m4, aa.get(i));
+            do {} while (!aa.weakCompareAndSetRelease(i, m4, seven));
+            assertEquals(seven, aa.get(i));
+        }
+    }
+
+}
--- a/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceArrayTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -243,4 +243,5 @@
         AtomicReferenceArray<Integer> aa = new AtomicReferenceArray<Integer>(a);
         assertEquals(Arrays.toString(a), aa.toString());
     }
+
 }
--- a/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/AtomicReferenceTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -161,7 +161,7 @@
      * toString returns current value.
      */
     public void testToString() {
-        AtomicReference<Integer> ai = new AtomicReference<Integer>(one);
+        AtomicReference<Integer> ai = new AtomicReference<>(one);
         assertEquals(one.toString(), ai.toString());
         ai.set(two);
         assertEquals(two.toString(), ai.toString());
--- a/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/CompletableFutureTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -57,6 +57,7 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.ForkJoinPool;
 import java.util.concurrent.ForkJoinTask;
+import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.TimeoutException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -486,62 +487,68 @@
     class FailingSupplier extends CheckedAction
         implements Supplier<Integer>
     {
-        FailingSupplier(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingSupplier(ExecutionMode m) { super(m); ex = new CFException(); }
         public Integer get() {
             invoked();
-            throw new CFException();
+            throw ex;
         }
     }
 
     class FailingConsumer extends CheckedIntegerAction
         implements Consumer<Integer>
     {
-        FailingConsumer(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingConsumer(ExecutionMode m) { super(m); ex = new CFException(); }
         public void accept(Integer x) {
             invoked();
             value = x;
-            throw new CFException();
+            throw ex;
         }
     }
 
     class FailingBiConsumer extends CheckedIntegerAction
         implements BiConsumer<Integer, Integer>
     {
-        FailingBiConsumer(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingBiConsumer(ExecutionMode m) { super(m); ex = new CFException(); }
         public void accept(Integer x, Integer y) {
             invoked();
             value = subtract(x, y);
-            throw new CFException();
+            throw ex;
         }
     }
 
     class FailingFunction extends CheckedIntegerAction
         implements Function<Integer, Integer>
     {
-        FailingFunction(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingFunction(ExecutionMode m) { super(m); ex = new CFException(); }
         public Integer apply(Integer x) {
             invoked();
             value = x;
-            throw new CFException();
+            throw ex;
         }
     }
 
     class FailingBiFunction extends CheckedIntegerAction
         implements BiFunction<Integer, Integer, Integer>
     {
-        FailingBiFunction(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingBiFunction(ExecutionMode m) { super(m); ex = new CFException(); }
         public Integer apply(Integer x, Integer y) {
             invoked();
             value = subtract(x, y);
-            throw new CFException();
+            throw ex;
         }
     }
 
     class FailingRunnable extends CheckedAction implements Runnable {
-        FailingRunnable(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingRunnable(ExecutionMode m) { super(m); ex = new CFException(); }
         public void run() {
             invoked();
-            throw new CFException();
+            throw ex;
         }
     }
 
@@ -561,11 +568,21 @@
     class FailingCompletableFutureFunction extends CheckedIntegerAction
         implements Function<Integer, CompletableFuture<Integer>>
     {
-        FailingCompletableFutureFunction(ExecutionMode m) { super(m); }
+        final CFException ex;
+        FailingCompletableFutureFunction(ExecutionMode m) { super(m); ex = new CFException(); }
         public CompletableFuture<Integer> apply(Integer x) {
             invoked();
             value = x;
-            throw new CFException();
+            throw ex;
+        }
+    }
+
+    static class CountingRejectingExecutor implements Executor {
+        final RejectedExecutionException ex = new RejectedExecutionException();
+        final AtomicInteger count = new AtomicInteger(0);
+        public void execute(Runnable r) {
+            count.getAndIncrement();
+            throw ex;
         }
     }
 
@@ -1249,10 +1266,22 @@
     {
         final FailingRunnable r = new FailingRunnable(m);
         final CompletableFuture<Void> f = m.runAsync(r);
-        checkCompletedWithWrappedCFException(f);
+        checkCompletedWithWrappedException(f, r.ex);
         r.assertInvoked();
     }}
 
+    public void testRunAsync_rejectingExecutor() {
+        CountingRejectingExecutor e = new CountingRejectingExecutor();
+        try {
+            CompletableFuture.runAsync(() -> {}, e);
+            shouldThrow();
+        } catch (Throwable t) {
+            assertSame(e.ex, t);
+        }
+
+        assertEquals(1, e.count.get());
+    }
+
     /**
      * supplyAsync completes with result of supplier
      */
@@ -1283,10 +1312,22 @@
     {
         FailingSupplier r = new FailingSupplier(m);
         CompletableFuture<Integer> f = m.supplyAsync(r);
-        checkCompletedWithWrappedCFException(f);
+        checkCompletedWithWrappedException(f, r.ex);
         r.assertInvoked();
     }}
 
+    public void testSupplyAsync_rejectingExecutor() {
+        CountingRejectingExecutor e = new CountingRejectingExecutor();
+        try {
+            CompletableFuture.supplyAsync(() -> null, e);
+            shouldThrow();
+        } catch (Throwable t) {
+            assertSame(e.ex, t);
+        }
+
+        assertEquals(1, e.count.get());
+    }
+
     // seq completion methods
 
     /**
@@ -1405,12 +1446,12 @@
         final CompletableFuture<Void> h4 = m.runAfterBoth(f, f, rs[4]);
         final CompletableFuture<Void> h5 = m.runAfterEither(f, f, rs[5]);
 
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
-        checkCompletedWithWrappedCFException(h4);
-        checkCompletedWithWrappedCFException(h5);
+        checkCompletedWithWrappedException(h0, rs[0].ex);
+        checkCompletedWithWrappedException(h1, rs[1].ex);
+        checkCompletedWithWrappedException(h2, rs[2].ex);
+        checkCompletedWithWrappedException(h3, rs[3].ex);
+        checkCompletedWithWrappedException(h4, rs[4].ex);
+        checkCompletedWithWrappedException(h5, rs[5].ex);
         checkCompletedNormally(f, v1);
     }}
 
@@ -1509,10 +1550,10 @@
         final CompletableFuture<Integer> h2 = m.thenApply(f, rs[2]);
         final CompletableFuture<Integer> h3 = m.applyToEither(f, f, rs[3]);
 
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h0, rs[0].ex);
+        checkCompletedWithWrappedException(h1, rs[1].ex);
+        checkCompletedWithWrappedException(h2, rs[2].ex);
+        checkCompletedWithWrappedException(h3, rs[3].ex);
         checkCompletedNormally(f, v1);
     }}
 
@@ -1611,10 +1652,10 @@
         final CompletableFuture<Void> h2 = m.thenAccept(f, rs[2]);
         final CompletableFuture<Void> h3 = m.acceptEither(f, f, rs[3]);
 
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h0, rs[0].ex);
+        checkCompletedWithWrappedException(h1, rs[1].ex);
+        checkCompletedWithWrappedException(h2, rs[2].ex);
+        checkCompletedWithWrappedException(h3, rs[3].ex);
         checkCompletedNormally(f, v1);
     }}
 
@@ -1776,9 +1817,9 @@
         assertTrue(snd.complete(w2));
         final CompletableFuture<Integer> h3 = m.thenCombine(f, g, r3);
 
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h1, r1.ex);
+        checkCompletedWithWrappedException(h2, r2.ex);
+        checkCompletedWithWrappedException(h3, r3.ex);
         r1.assertInvoked();
         r2.assertInvoked();
         r3.assertInvoked();
@@ -1940,9 +1981,9 @@
         assertTrue(snd.complete(w2));
         final CompletableFuture<Void> h3 = m.thenAcceptBoth(f, g, r3);
 
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h1, r1.ex);
+        checkCompletedWithWrappedException(h2, r2.ex);
+        checkCompletedWithWrappedException(h3, r3.ex);
         r1.assertInvoked();
         r2.assertInvoked();
         r3.assertInvoked();
@@ -2104,9 +2145,9 @@
         assertTrue(snd.complete(w2));
         final CompletableFuture<Void> h3 = m.runAfterBoth(f, g, r3);
 
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h1, r1.ex);
+        checkCompletedWithWrappedException(h2, r2.ex);
+        checkCompletedWithWrappedException(h3, r3.ex);
         r1.assertInvoked();
         r2.assertInvoked();
         r3.assertInvoked();
@@ -2396,10 +2437,10 @@
         f.complete(v1);
         final CompletableFuture<Integer> h2 = m.applyToEither(f, g, rs[2]);
         final CompletableFuture<Integer> h3 = m.applyToEither(g, f, rs[3]);
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h0, rs[0].ex);
+        checkCompletedWithWrappedException(h1, rs[1].ex);
+        checkCompletedWithWrappedException(h2, rs[2].ex);
+        checkCompletedWithWrappedException(h3, rs[3].ex);
         for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
 
         g.complete(v2);
@@ -2408,10 +2449,10 @@
         final CompletableFuture<Integer> h4 = m.applyToEither(f, g, rs[4]);
         final CompletableFuture<Integer> h5 = m.applyToEither(g, f, rs[5]);
 
-        checkCompletedWithWrappedCFException(h4);
+        checkCompletedWithWrappedException(h4, rs[4].ex);
         assertTrue(Objects.equals(v1, rs[4].value) ||
                    Objects.equals(v2, rs[4].value));
-        checkCompletedWithWrappedCFException(h5);
+        checkCompletedWithWrappedException(h5, rs[5].ex);
         assertTrue(Objects.equals(v1, rs[5].value) ||
                    Objects.equals(v2, rs[5].value));
 
@@ -2655,10 +2696,10 @@
         f.complete(v1);
         final CompletableFuture<Void> h2 = m.acceptEither(f, g, rs[2]);
         final CompletableFuture<Void> h3 = m.acceptEither(g, f, rs[3]);
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h0, rs[0].ex);
+        checkCompletedWithWrappedException(h1, rs[1].ex);
+        checkCompletedWithWrappedException(h2, rs[2].ex);
+        checkCompletedWithWrappedException(h3, rs[3].ex);
         for (int i = 0; i < 4; i++) rs[i].assertValue(v1);
 
         g.complete(v2);
@@ -2667,10 +2708,10 @@
         final CompletableFuture<Void> h4 = m.acceptEither(f, g, rs[4]);
         final CompletableFuture<Void> h5 = m.acceptEither(g, f, rs[5]);
 
-        checkCompletedWithWrappedCFException(h4);
+        checkCompletedWithWrappedException(h4, rs[4].ex);
         assertTrue(Objects.equals(v1, rs[4].value) ||
                    Objects.equals(v2, rs[4].value));
-        checkCompletedWithWrappedCFException(h5);
+        checkCompletedWithWrappedException(h5, rs[5].ex);
         assertTrue(Objects.equals(v1, rs[5].value) ||
                    Objects.equals(v2, rs[5].value));
 
@@ -2686,6 +2727,7 @@
         for (ExecutionMode m : ExecutionMode.values())
         for (Integer v1 : new Integer[] { 1, null })
         for (Integer v2 : new Integer[] { 2, null })
+        for (boolean pushNop : new boolean[] { true, false })
     {
         final CompletableFuture<Integer> f = new CompletableFuture<>();
         final CompletableFuture<Integer> g = new CompletableFuture<>();
@@ -2698,6 +2740,10 @@
         checkIncomplete(h1);
         rs[0].assertNotInvoked();
         rs[1].assertNotInvoked();
+        if (pushNop) {          // ad hoc test of intra-completion interference
+            m.thenRun(f, () -> {});
+            m.thenRun(g, () -> {});
+        }
         f.complete(v1);
         checkCompletedNormally(h0, null);
         checkCompletedNormally(h1, null);
@@ -2910,16 +2956,16 @@
         assertTrue(f.complete(v1));
         final CompletableFuture<Void> h2 = m.runAfterEither(f, g, rs[2]);
         final CompletableFuture<Void> h3 = m.runAfterEither(g, f, rs[3]);
-        checkCompletedWithWrappedCFException(h0);
-        checkCompletedWithWrappedCFException(h1);
-        checkCompletedWithWrappedCFException(h2);
-        checkCompletedWithWrappedCFException(h3);
+        checkCompletedWithWrappedException(h0, rs[0].ex);
+        checkCompletedWithWrappedException(h1, rs[1].ex);
+        checkCompletedWithWrappedException(h2, rs[2].ex);
+        checkCompletedWithWrappedException(h3, rs[3].ex);
         for (int i = 0; i < 4; i++) rs[i].assertInvoked();
         assertTrue(g.complete(v2));
         final CompletableFuture<Void> h4 = m.runAfterEither(f, g, rs[4]);
         final CompletableFuture<Void> h5 = m.runAfterEither(g, f, rs[5]);
-        checkCompletedWithWrappedCFException(h4);
-        checkCompletedWithWrappedCFException(h5);
+        checkCompletedWithWrappedException(h4, rs[4].ex);
+        checkCompletedWithWrappedException(h5, rs[5].ex);
 
         checkCompletedNormally(f, v1);
         checkCompletedNormally(g, v2);
@@ -2980,7 +3026,7 @@
         final CompletableFuture<Integer> g = m.thenCompose(f, r);
         if (createIncomplete) assertTrue(f.complete(v1));
 
-        checkCompletedWithWrappedCFException(g);
+        checkCompletedWithWrappedException(g, r.ex);
         checkCompletedNormally(f, v1);
     }}
 
@@ -3089,7 +3135,7 @@
         }
     }
 
-    public void testAllOf_backwards() throws Exception {
+    public void testAllOf_normal_backwards() throws Exception {
         for (int k = 1; k < 10; k++) {
             CompletableFuture<Integer>[] fs
                 = (CompletableFuture<Integer>[]) new CompletableFuture[k];
@@ -3337,6 +3383,151 @@
     }
 
     /**
+     * Test submissions to an executor that rejects all tasks.
+     */
+    public void testRejectingExecutor() {
+        for (Integer v : new Integer[] { 1, null })
+    {
+        final CountingRejectingExecutor e = new CountingRejectingExecutor();
+
+        final CompletableFuture<Integer> complete = CompletableFuture.completedFuture(v);
+        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
+
+        List<CompletableFuture<?>> futures = new ArrayList<>();
+
+        List<CompletableFuture<Integer>> srcs = new ArrayList<>();
+        srcs.add(complete);
+        srcs.add(incomplete);
+
+        for (CompletableFuture<Integer> src : srcs) {
+            List<CompletableFuture<?>> fs = new ArrayList<>();
+            fs.add(src.thenRunAsync(() -> {}, e));
+            fs.add(src.thenAcceptAsync((z) -> {}, e));
+            fs.add(src.thenApplyAsync((z) -> z, e));
+
+            fs.add(src.thenCombineAsync(src, (x, y) -> x, e));
+            fs.add(src.thenAcceptBothAsync(src, (x, y) -> {}, e));
+            fs.add(src.runAfterBothAsync(src, () -> {}, e));
+
+            fs.add(src.applyToEitherAsync(src, (z) -> z, e));
+            fs.add(src.acceptEitherAsync(src, (z) -> {}, e));
+            fs.add(src.runAfterEitherAsync(src, () -> {}, e));
+
+            fs.add(src.thenComposeAsync((z) -> null, e));
+            fs.add(src.whenCompleteAsync((z, t) -> {}, e));
+            fs.add(src.handleAsync((z, t) -> null, e));
+
+            for (CompletableFuture<?> future : fs) {
+                if (src.isDone())
+                    checkCompletedWithWrappedException(future, e.ex);
+                else
+                    checkIncomplete(future);
+            }
+            futures.addAll(fs);
+        }
+
+        {
+            List<CompletableFuture<?>> fs = new ArrayList<>();
+
+            fs.add(complete.thenCombineAsync(incomplete, (x, y) -> x, e));
+            fs.add(incomplete.thenCombineAsync(complete, (x, y) -> x, e));
+
+            fs.add(complete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
+            fs.add(incomplete.thenAcceptBothAsync(complete, (x, y) -> {}, e));
+
+            fs.add(complete.runAfterBothAsync(incomplete, () -> {}, e));
+            fs.add(incomplete.runAfterBothAsync(complete, () -> {}, e));
+
+            for (CompletableFuture<?> future : fs)
+                checkIncomplete(future);
+            futures.addAll(fs);
+        }
+
+        {
+            List<CompletableFuture<?>> fs = new ArrayList<>();
+
+            fs.add(complete.applyToEitherAsync(incomplete, (z) -> z, e));
+            fs.add(incomplete.applyToEitherAsync(complete, (z) -> z, e));
+
+            fs.add(complete.acceptEitherAsync(incomplete, (z) -> {}, e));
+            fs.add(incomplete.acceptEitherAsync(complete, (z) -> {}, e));
+
+            fs.add(complete.runAfterEitherAsync(incomplete, () -> {}, e));
+            fs.add(incomplete.runAfterEitherAsync(complete, () -> {}, e));
+
+            for (CompletableFuture<?> future : fs)
+                checkCompletedWithWrappedException(future, e.ex);
+            futures.addAll(fs);
+        }
+
+        incomplete.complete(v);
+
+        for (CompletableFuture<?> future : futures)
+            checkCompletedWithWrappedException(future, e.ex);
+
+        assertEquals(futures.size(), e.count.get());
+    }}
+
+    /**
+     * Test submissions to an executor that rejects all tasks, but
+     * should never be invoked because the dependent future is
+     * explicitly completed.
+     */
+    public void testRejectingExecutorNeverInvoked() {
+        for (Integer v : new Integer[] { 1, null })
+    {
+        final CountingRejectingExecutor e = new CountingRejectingExecutor();
+
+        final CompletableFuture<Integer> complete = CompletableFuture.completedFuture(v);
+        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
+
+        List<CompletableFuture<?>> futures = new ArrayList<>();
+
+        List<CompletableFuture<Integer>> srcs = new ArrayList<>();
+        srcs.add(complete);
+        srcs.add(incomplete);
+
+        List<CompletableFuture<?>> fs = new ArrayList<>();
+        fs.add(incomplete.thenRunAsync(() -> {}, e));
+        fs.add(incomplete.thenAcceptAsync((z) -> {}, e));
+        fs.add(incomplete.thenApplyAsync((z) -> z, e));
+
+        fs.add(incomplete.thenCombineAsync(incomplete, (x, y) -> x, e));
+        fs.add(incomplete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
+        fs.add(incomplete.runAfterBothAsync(incomplete, () -> {}, e));
+
+        fs.add(incomplete.applyToEitherAsync(incomplete, (z) -> z, e));
+        fs.add(incomplete.acceptEitherAsync(incomplete, (z) -> {}, e));
+        fs.add(incomplete.runAfterEitherAsync(incomplete, () -> {}, e));
+
+        fs.add(incomplete.thenComposeAsync((z) -> null, e));
+        fs.add(incomplete.whenCompleteAsync((z, t) -> {}, e));
+        fs.add(incomplete.handleAsync((z, t) -> null, e));
+
+        fs.add(complete.thenCombineAsync(incomplete, (x, y) -> x, e));
+        fs.add(incomplete.thenCombineAsync(complete, (x, y) -> x, e));
+
+        fs.add(complete.thenAcceptBothAsync(incomplete, (x, y) -> {}, e));
+        fs.add(incomplete.thenAcceptBothAsync(complete, (x, y) -> {}, e));
+
+        fs.add(complete.runAfterBothAsync(incomplete, () -> {}, e));
+        fs.add(incomplete.runAfterBothAsync(complete, () -> {}, e));
+
+        for (CompletableFuture<?> future : fs)
+            checkIncomplete(future);
+
+        for (CompletableFuture<?> future : fs)
+            future.complete(null);
+
+        incomplete.complete(v);
+
+        for (CompletableFuture<?> future : fs)
+            checkCompletedNormally(future, null);
+
+        assertEquals(0, e.count.get());
+    }}
+
+    /**
      * toCompletableFuture returns this CompletableFuture.
      */
     public void testToCompletableFuture() {
@@ -3659,12 +3850,25 @@
     //--- tests of implementation details; not part of official tck ---
 
     Object resultOf(CompletableFuture<?> f) {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                System.setSecurityManager(null);
+            } catch (SecurityException giveUp) {
+                return "Reflection not available";
+            }
+        }
+
         try {
             java.lang.reflect.Field resultField
                 = CompletableFuture.class.getDeclaredField("result");
             resultField.setAccessible(true);
             return resultField.get(f);
-        } catch (Throwable t) { throw new AssertionError(t); }
+        } catch (Throwable t) {
+            throw new AssertionError(t);
+        } finally {
+            if (sm != null) System.setSecurityManager(sm);
+        }
     }
 
     public void testExceptionPropagationReusesResultObject() {
@@ -3675,33 +3879,44 @@
         final CompletableFuture<Integer> v42 = CompletableFuture.completedFuture(42);
         final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
 
+        final Runnable noopRunnable = new Noop(m);
+        final Consumer<Integer> noopConsumer = new NoopConsumer(m);
+        final Function<Integer, Integer> incFunction = new IncFunction(m);
+
         List<Function<CompletableFuture<Integer>, CompletableFuture<?>>> funs
             = new ArrayList<>();
 
-        funs.add((y) -> m.thenRun(y, new Noop(m)));
-        funs.add((y) -> m.thenAccept(y, new NoopConsumer(m)));
-        funs.add((y) -> m.thenApply(y, new IncFunction(m)));
-
-        funs.add((y) -> m.runAfterEither(y, incomplete, new Noop(m)));
-        funs.add((y) -> m.acceptEither(y, incomplete, new NoopConsumer(m)));
-        funs.add((y) -> m.applyToEither(y, incomplete, new IncFunction(m)));
-
-        funs.add((y) -> m.runAfterBoth(y, v42, new Noop(m)));
+        funs.add((y) -> m.thenRun(y, noopRunnable));
+        funs.add((y) -> m.thenAccept(y, noopConsumer));
+        funs.add((y) -> m.thenApply(y, incFunction));
+
+        funs.add((y) -> m.runAfterEither(y, incomplete, noopRunnable));
+        funs.add((y) -> m.acceptEither(y, incomplete, noopConsumer));
+        funs.add((y) -> m.applyToEither(y, incomplete, incFunction));
+
+        funs.add((y) -> m.runAfterBoth(y, v42, noopRunnable));
+        funs.add((y) -> m.runAfterBoth(v42, y, noopRunnable));
         funs.add((y) -> m.thenAcceptBoth(y, v42, new SubtractAction(m)));
+        funs.add((y) -> m.thenAcceptBoth(v42, y, new SubtractAction(m)));
         funs.add((y) -> m.thenCombine(y, v42, new SubtractFunction(m)));
+        funs.add((y) -> m.thenCombine(v42, y, new SubtractFunction(m)));
 
         funs.add((y) -> m.whenComplete(y, (Integer r, Throwable t) -> {}));
 
         funs.add((y) -> m.thenCompose(y, new CompletableFutureInc(m)));
 
-        funs.add((y) -> CompletableFuture.allOf(new CompletableFuture<?>[] {y, v42}));
-        funs.add((y) -> CompletableFuture.anyOf(new CompletableFuture<?>[] {y, incomplete}));
+        funs.add((y) -> CompletableFuture.allOf(y));
+        funs.add((y) -> CompletableFuture.allOf(y, v42));
+        funs.add((y) -> CompletableFuture.allOf(v42, y));
+        funs.add((y) -> CompletableFuture.anyOf(y));
+        funs.add((y) -> CompletableFuture.anyOf(y, incomplete));
+        funs.add((y) -> CompletableFuture.anyOf(incomplete, y));
 
         for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                  fun : funs) {
             CompletableFuture<Integer> f = new CompletableFuture<>();
             f.completeExceptionally(ex);
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
+            CompletableFuture<Integer> src = m.thenApply(f, incFunction);
             checkCompletedWithWrappedException(src, ex);
             CompletableFuture<?> dep = fun.apply(src);
             checkCompletedWithWrappedException(dep, ex);
@@ -3711,7 +3926,7 @@
         for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                  fun : funs) {
             CompletableFuture<Integer> f = new CompletableFuture<>();
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
+            CompletableFuture<Integer> src = m.thenApply(f, incFunction);
             CompletableFuture<?> dep = fun.apply(src);
             f.completeExceptionally(ex);
             checkCompletedWithWrappedException(src, ex);
@@ -3725,7 +3940,7 @@
             CompletableFuture<Integer> f = new CompletableFuture<>();
             f.cancel(mayInterruptIfRunning);
             checkCancelled(f);
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
+            CompletableFuture<Integer> src = m.thenApply(f, incFunction);
             checkCompletedWithWrappedCancellationException(src);
             CompletableFuture<?> dep = fun.apply(src);
             checkCompletedWithWrappedCancellationException(dep);
@@ -3736,7 +3951,7 @@
         for (Function<CompletableFuture<Integer>, CompletableFuture<?>>
                  fun : funs) {
             CompletableFuture<Integer> f = new CompletableFuture<>();
-            CompletableFuture<Integer> src = m.thenApply(f, new IncFunction(m));
+            CompletableFuture<Integer> src = m.thenApply(f, incFunction);
             CompletableFuture<?> dep = fun.apply(src);
             f.cancel(mayInterruptIfRunning);
             checkCancelled(f);
@@ -3747,7 +3962,7 @@
     }}
 
     /**
-     * Minimal completion stages throw UOE for all non-CompletionStage methods
+     * Minimal completion stages throw UOE for most non-CompletionStage methods
      */
     public void testMinimalCompletionStage_minimality() {
         if (!testImplementationDetails) return;
@@ -3776,8 +3991,10 @@
             .filter((method) -> !permittedMethodSignatures.contains(toSignature.apply(method)))
             .collect(Collectors.toList());
 
-        CompletionStage<Integer> minimalStage =
-            new CompletableFuture<Integer>().minimalCompletionStage();
+        List<CompletionStage<Integer>> stages = new ArrayList<>();
+        stages.add(new CompletableFuture<Integer>().minimalCompletionStage());
+        stages.add(CompletableFuture.completedStage(1));
+        stages.add(CompletableFuture.failedStage(new CFException()));
 
         List<Method> bugs = new ArrayList<>();
         for (Method method : allMethods) {
@@ -3793,20 +4010,22 @@
                 else if (parameterTypes[i] == long.class)
                     args[i] = 0L;
             }
-            try {
-                method.invoke(minimalStage, args);
-                bugs.add(method);
+            for (CompletionStage<Integer> stage : stages) {
+                try {
+                    method.invoke(stage, args);
+                    bugs.add(method);
+                }
+                catch (java.lang.reflect.InvocationTargetException expected) {
+                    if (! (expected.getCause() instanceof UnsupportedOperationException)) {
+                        bugs.add(method);
+                        // expected.getCause().printStackTrace();
+                    }
+                }
+                catch (ReflectiveOperationException bad) { throw new Error(bad); }
             }
-            catch (java.lang.reflect.InvocationTargetException expected) {
-                if (! (expected.getCause() instanceof UnsupportedOperationException)) {
-                    bugs.add(method);
-                    // expected.getCause().printStackTrace();
-                }
-            }
-            catch (ReflectiveOperationException bad) { throw new Error(bad); }
         }
         if (!bugs.isEmpty())
-            throw new Error("Methods did not throw UOE: " + bugs.toString());
+            throw new Error("Methods did not throw UOE: " + bugs);
     }
 
     static class Monad {
@@ -3955,12 +4174,33 @@
                                  Monad.plus(godot, Monad.unit(5L)));
     }
 
+    /** Test long recursive chains of CompletableFutures with cascading completions */
+    public void testRecursiveChains() throws Throwable {
+        for (ExecutionMode m : ExecutionMode.values())
+        for (boolean addDeadEnds : new boolean[] { true, false })
+    {
+        final int val = 42;
+        final int n = expensiveTests ? 1_000 : 2;
+        CompletableFuture<Integer> head = new CompletableFuture<>();
+        CompletableFuture<Integer> tail = head;
+        for (int i = 0; i < n; i++) {
+            if (addDeadEnds) m.thenApply(tail, v -> v + 1);
+            tail = m.thenApply(tail, v -> v + 1);
+            if (addDeadEnds) m.applyToEither(tail, tail, v -> v + 1);
+            tail = m.applyToEither(tail, tail, v -> v + 1);
+            if (addDeadEnds) m.thenCombine(tail, tail, (v, w) -> v + 1);
+            tail = m.thenCombine(tail, tail, (v, w) -> v + 1);
+        }
+        head.complete(val);
+        assertEquals(val + 3 * n, (int) tail.join());
+    }}
+
     /**
      * A single CompletableFuture with many dependents.
      * A demo of scalability - runtime is O(n).
      */
     public void testManyDependents() throws Throwable {
-        final int n = 1_000;
+        final int n = expensiveTests ? 1_000_000 : 10;
         final CompletableFuture<Void> head = new CompletableFuture<>();
         final CompletableFuture<Void> complete = CompletableFuture.completedFuture((Void)null);
         final AtomicInteger count = new AtomicInteger(0);
@@ -3987,6 +4227,78 @@
         assertEquals(5 * 3 * n, count.get());
     }
 
+    /** ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck */
+    public void testCoCompletionGarbageRetention() throws Throwable {
+        final int n = expensiveTests ? 1_000_000 : 10;
+        final CompletableFuture<Integer> incomplete = new CompletableFuture<>();
+        CompletableFuture<Integer> f;
+        for (int i = 0; i < n; i++) {
+            f = new CompletableFuture<>();
+            f.runAfterEither(incomplete, () -> {});
+            f.complete(null);
+
+            f = new CompletableFuture<>();
+            f.acceptEither(incomplete, (x) -> {});
+            f.complete(null);
+
+            f = new CompletableFuture<>();
+            f.applyToEither(incomplete, (x) -> x);
+            f.complete(null);
+
+            f = new CompletableFuture<>();
+            CompletableFuture.anyOf(new CompletableFuture<?>[] { f, incomplete });
+            f.complete(null);
+        }
+
+        for (int i = 0; i < n; i++) {
+            f = new CompletableFuture<>();
+            incomplete.runAfterEither(f, () -> {});
+            f.complete(null);
+
+            f = new CompletableFuture<>();
+            incomplete.acceptEither(f, (x) -> {});
+            f.complete(null);
+
+            f = new CompletableFuture<>();
+            incomplete.applyToEither(f, (x) -> x);
+            f.complete(null);
+
+            f = new CompletableFuture<>();
+            CompletableFuture.anyOf(new CompletableFuture<?>[] { incomplete, f });
+            f.complete(null);
+        }
+    }
+
+    /*
+     * Tests below currently fail in stress mode due to memory retention.
+     * ant -Dvmoptions=-Xmx8m -Djsr166.expensiveTests=true -Djsr166.tckTestClass=CompletableFutureTest tck
+     */
+
+    /** Checks for garbage retention with anyOf. */
+    public void testAnyOfGarbageRetention() throws Throwable {
+        for (Integer v : new Integer[] { 1, null })
+    {
+        final int n = expensiveTests ? 100_000 : 10;
+        CompletableFuture<Integer>[] fs
+            = (CompletableFuture<Integer>[]) new CompletableFuture<?>[100];
+        for (int i = 0; i < fs.length; i++)
+            fs[i] = new CompletableFuture<>();
+        fs[fs.length - 1].complete(v);
+        for (int i = 0; i < n; i++)
+            checkCompletedNormally(CompletableFuture.anyOf(fs), v);
+    }}
+
+    /** Checks for garbage retention with allOf. */
+    public void testCancelledAllOfGarbageRetention() throws Throwable {
+        final int n = expensiveTests ? 100_000 : 10;
+        CompletableFuture<Integer>[] fs
+            = (CompletableFuture<Integer>[]) new CompletableFuture<?>[100];
+        for (int i = 0; i < fs.length; i++)
+            fs[i] = new CompletableFuture<>();
+        for (int i = 0; i < n; i++)
+            assertTrue(CompletableFuture.allOf(fs).cancel(false));
+    }
+
 //     static <U> U join(CompletionStage<U> stage) {
 //         CompletableFuture<U> f = new CompletableFuture<>();
 //         stage.whenComplete((v, ex) -> {
--- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java	Mon Jul 18 09:38:08 2016 -0700
@@ -548,6 +548,13 @@
         // Java9+ test classes
         if (atLeastJava9()) {
             String[] java9TestClassNames = {
+                "AtomicBoolean9Test",
+                "AtomicInteger9Test",
+                "AtomicIntegerArray9Test",
+                "AtomicLong9Test",
+                "AtomicLongArray9Test",
+                "AtomicReference9Test",
+                "AtomicReferenceArray9Test",
                 "ExecutorCompletionService9Test",
             };
             addNamedTestClasses(suite, java9TestClassNames);
@@ -975,7 +982,11 @@
         }
     }
 
-    /** Like Runnable, but with the freedom to throw anything */
+    /**
+     * Like Runnable, but with the freedom to throw anything.
+     * junit folks had the same idea:
+     * http://junit.org/junit5/docs/snapshot/api/org/junit/gen5/api/Executable.html
+     */
     interface Action { public void run() throws Throwable; }
 
     /**
@@ -1006,6 +1017,15 @@
      * Uninteresting threads are filtered out.
      */
     static void dumpTestThreads() {
+        SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            try {
+                System.setSecurityManager(null);
+            } catch (SecurityException giveUp) {
+                return;
+            }
+        }
+
         ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
         System.err.println("------ stacktrace dump start ------");
         for (ThreadInfo info : threadMXBean.dumpAllThreads(true, true)) {
@@ -1023,6 +1043,8 @@
             System.err.print(info);
         }
         System.err.println("------ stacktrace dump end ------");
+
+        if (sm != null) System.setSecurityManager(sm);
     }
 
     /**
--- a/jdk/test/java/util/concurrent/tck/StampedLockTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/jdk/test/java/util/concurrent/tck/StampedLockTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -745,28 +745,41 @@
     public void testTryConvertToOptimisticRead() throws InterruptedException {
         StampedLock lock = new StampedLock();
         long s, p;
-        s = 0L;
-        assertFalse((p = lock.tryConvertToOptimisticRead(s)) != 0L);
+        assertEquals(0L, lock.tryConvertToOptimisticRead(0L));
+
         assertTrue((s = lock.tryOptimisticRead()) != 0L);
-        assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
+        assertEquals(s, lock.tryConvertToOptimisticRead(s));
+        assertTrue(lock.validate(s));
+
+        assertTrue((p = lock.readLock()) != 0L);
+        assertTrue((s = lock.tryOptimisticRead()) != 0L);
+        assertEquals(s, lock.tryConvertToOptimisticRead(s));
+        assertTrue(lock.validate(s));
+        lock.unlockRead(p);
+
         assertTrue((s = lock.writeLock()) != 0L);
         assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
         assertTrue(lock.validate(p));
+
         assertTrue((s = lock.readLock()) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
         assertTrue(lock.validate(p));
+
         assertTrue((s = lock.tryWriteLock()) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
         assertTrue(lock.validate(p));
+
         assertTrue((s = lock.tryReadLock()) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
         assertTrue(lock.validate(p));
+
         assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
         assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
         assertTrue(lock.validate(p));
+
         assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToOptimisticRead(s)) != 0L);
@@ -780,39 +793,67 @@
     public void testTryConvertToReadLock() throws InterruptedException {
         StampedLock lock = new StampedLock();
         long s, p;
-        s = 0L;
-        assertFalse((p = lock.tryConvertToReadLock(s)) != 0L);
+
+        assertFalse((p = lock.tryConvertToReadLock(0L)) != 0L);
+
         assertTrue((s = lock.tryOptimisticRead()) != 0L);
         assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
+        assertTrue(lock.isReadLocked());
+        assertEquals(1, lock.getReadLockCount());
         lock.unlockRead(p);
+
+        assertTrue((s = lock.tryOptimisticRead()) != 0L);
+        lock.readLock();
+        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
+        assertTrue(lock.isReadLocked());
+        assertEquals(2, lock.getReadLockCount());
+        lock.unlockRead(p);
+        lock.unlockRead(p);
+
         assertTrue((s = lock.writeLock()) != 0L);
         assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertTrue(lock.isReadLocked());
+        assertEquals(1, lock.getReadLockCount());
         lock.unlockRead(p);
+
         assertTrue((s = lock.readLock()) != 0L);
         assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
+        assertEquals(s, lock.tryConvertToReadLock(s));
+        assertTrue(lock.validate(s));
+        assertTrue(lock.isReadLocked());
+        assertEquals(1, lock.getReadLockCount());
+        lock.unlockRead(s);
+
         assertTrue((s = lock.tryWriteLock()) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertEquals(1, lock.getReadLockCount());
         lock.unlockRead(p);
+
         assertTrue((s = lock.tryReadLock()) != 0L);
         assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
+        assertEquals(s, lock.tryConvertToReadLock(s));
+        assertTrue(lock.validate(s));
+        assertTrue(lock.isReadLocked());
+        assertEquals(1, lock.getReadLockCount());
+        lock.unlockRead(s);
+
         assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
         assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertTrue(lock.isReadLocked());
+        assertEquals(1, lock.getReadLockCount());
         lock.unlockRead(p);
+
         assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
         assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToReadLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockRead(p);
+        assertEquals(s, lock.tryConvertToReadLock(s));
+        assertTrue(lock.validate(s));
+        assertTrue(lock.isReadLocked());
+        assertEquals(1, lock.getReadLockCount());
+        lock.unlockRead(s);
     }
 
     /**
@@ -822,38 +863,52 @@
     public void testTryConvertToWriteLock() throws InterruptedException {
         StampedLock lock = new StampedLock();
         long s, p;
-        s = 0L;
-        assertFalse((p = lock.tryConvertToWriteLock(s)) != 0L);
+
+        assertFalse((p = lock.tryConvertToWriteLock(0L)) != 0L);
+
         assertTrue((s = lock.tryOptimisticRead()) != 0L);
         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
+        assertTrue(lock.isWriteLocked());
         lock.unlockWrite(p);
+
         assertTrue((s = lock.writeLock()) != 0L);
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
+        assertEquals(s, lock.tryConvertToWriteLock(s));
+        assertTrue(lock.validate(s));
+        assertTrue(lock.isWriteLocked());
+        lock.unlockWrite(s);
+
         assertTrue((s = lock.readLock()) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertTrue(lock.isWriteLocked());
         lock.unlockWrite(p);
+
         assertTrue((s = lock.tryWriteLock()) != 0L);
         assertTrue(lock.validate(s));
-        assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
-        assertTrue(lock.validate(p));
-        lock.unlockWrite(p);
+        assertEquals(s, lock.tryConvertToWriteLock(s));
+        assertTrue(lock.validate(s));
+        assertTrue(lock.isWriteLocked());
+        lock.unlockWrite(s);
+
         assertTrue((s = lock.tryReadLock()) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertTrue(lock.isWriteLocked());
         lock.unlockWrite(p);
+
         assertTrue((s = lock.tryWriteLock(100L, MILLISECONDS)) != 0L);
         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertTrue(lock.isWriteLocked());
         lock.unlockWrite(p);
+
         assertTrue((s = lock.tryReadLock(100L, MILLISECONDS)) != 0L);
         assertTrue(lock.validate(s));
         assertTrue((p = lock.tryConvertToWriteLock(s)) != 0L);
         assertTrue(lock.validate(p));
+        assertTrue(lock.isWriteLocked());
         lock.unlockWrite(p);
     }
 
@@ -903,4 +958,124 @@
         assertTrue(lock.tryLock());
     }
 
+    /**
+     * Lock.newCondition throws UnsupportedOperationException
+     */
+    public void testLockViewsDoNotSupportConditions() {
+        StampedLock sl = new StampedLock();
+        assertThrows(UnsupportedOperationException.class,
+                     () -> sl.asWriteLock().newCondition(),
+                     () -> sl.asReadLock().newCondition(),
+                     () -> sl.asReadWriteLock().writeLock().newCondition(),
+                     () -> sl.asReadWriteLock().readLock().newCondition());
+    }
+
+    /**
+     * Passing optimistic read stamps to unlock operations result in
+     * IllegalMonitorStateException
+     */
+    public void testCannotUnlockOptimisticReadStamps() {
+        Runnable[] actions = {
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryOptimisticRead();
+                assertTrue(stamp != 0);
+                sl.unlockRead(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryOptimisticRead();
+                sl.unlock(stamp);
+            },
+
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryOptimisticRead();
+                sl.writeLock();
+                sl.unlock(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryOptimisticRead();
+                sl.readLock();
+                sl.unlockRead(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryOptimisticRead();
+                sl.readLock();
+                sl.unlock(stamp);
+            },
+
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+                assertTrue(stamp != 0);
+                sl.writeLock();
+                sl.unlockWrite(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+                sl.writeLock();
+                sl.unlock(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+                sl.readLock();
+                sl.unlockRead(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.writeLock());
+                sl.readLock();
+                sl.unlock(stamp);
+            },
+
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+                assertTrue(stamp != 0);
+                sl.writeLock();
+                sl.unlockWrite(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+                sl.writeLock();
+                sl.unlock(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+                sl.readLock();
+                sl.unlockRead(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                sl.readLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+                assertTrue(stamp != 0);
+                sl.readLock();
+                sl.unlockRead(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+                sl.readLock();
+                sl.unlock(stamp);
+            },
+            () -> {
+                StampedLock sl = new StampedLock();
+                sl.readLock();
+                long stamp = sl.tryConvertToOptimisticRead(sl.readLock());
+                sl.readLock();
+                sl.unlock(stamp);
+            },
+        };
+
+        assertThrows(IllegalMonitorStateException.class, actions);
+    }
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/sun/net/www/protocol/http/NULLTargetInfoTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8151788
+ * @summary NullPointerException from ntlm.Client.type3
+ * @modules java.base/com.sun.security.ntlm
+ * @run main NULLTargetInfoTest
+ */
+import com.sun.security.ntlm.Client;
+
+public class NULLTargetInfoTest {
+
+    public static void main(String[] args) throws Exception {
+        Client c = new Client(null, "host", "user", "domain", "pass".toCharArray());
+        c.type1();
+        // this input does have the 0x800000 bit(NTLMSSP_NEGOTIATE_TARGET_INFO) set
+        // but after offset 40 all eight bytes are all zero which means there is no
+        // security buffer for target info.
+        byte[] type2 = hex(
+                "4E 54 4C 4D 53 53 50 00 02 00 00 00 00 00 00 00"
+                + "00 00 00 00 05 82 89 00 0B 87 81 B6 2D 6E 8B C1"
+                + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00");
+        byte[] nonce = new byte[10];
+        c.type3(type2, nonce);
+    }
+
+    private static byte[] hex(String str) {
+        str = str.replaceAll("\\s", "");
+        byte[] response = new byte[str.length() / 2];
+        int index = 0;
+        for (int i = 0; i < str.length(); i += 2) {
+            response[index++] = Integer.valueOf(str.substring(i, i + 2), 16).byteValue();
+        }
+        return response;
+    }
+}
--- a/langtools/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -369,3 +369,4 @@
 26aa3caa778eab1c931910149c414783ee83bce7 jdk-9+124
 2d65e127e93d5ff0df61bf78e57d7f46a2f1edeb jdk-9+125
 ea4eea2997b9e2f26cd7965839921710ff4065c8 jdk-9+126
+a42768b48cb0c5af9063e12093975baeeca3b5fa jdk-9+127
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/make/src/classes/build/tools/listjdkinternals/ListJDKInternals.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.listjdkinternals;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.lang.module.ModuleDescriptor;
+import java.lang.module.ModuleFinder;
+import java.lang.module.ModuleReference;
+import java.net.URI;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+
+/**
+ * Run this tool to generate the JDK internal APIs in the previous releases
+ * including platform-specific internal APIs.
+ */
+public class ListJDKInternals {
+    // Filter non-interesting JAR files
+    private final static List<String> excludes = Arrays.asList(
+        "deploy.jar",
+        "javaws.jar",
+        "plugin.jar",
+        "cldrdata.jar",
+        "localedata.jar"
+    );
+    private static void usage() {
+        System.out.println("ListJDKInternals [-o <outfile>] <javaHome> [<javaHome>]*");
+    }
+
+    private static final Set<String> EXPORTED_PACKAGES = new HashSet<>();
+
+    public static void main(String... args) throws IOException {
+        List<Path> paths = new ArrayList<>();
+        Path outFile = null;
+        int i=0;
+        while (i < args.length) {
+            String arg = args[i++];
+            if (arg.equals("-o")) {
+                outFile = Paths.get(args[i++]);
+            } else {
+                Path p = Paths.get(arg);
+                if (Files.notExists(p))
+                    throw new IllegalArgumentException(p + " not exist");
+                paths.add(p);
+            }
+        }
+        if (paths.isEmpty()) {
+            usage();
+            System.exit(1);
+        }
+
+        // Get the exported APIs from the current JDK releases
+        Path javaHome = Paths.get(System.getProperty("java.home"));
+        ModuleFinder.ofSystem().findAll()
+            .stream()
+            .map(ModuleReference::descriptor)
+            .filter(md -> !md.name().equals("jdk.unsupported"))
+            .map(ModuleDescriptor::exports)
+            .flatMap(Set::stream)
+            .filter(exp -> !exp.isQualified())
+            .map(ModuleDescriptor.Exports::source)
+            .forEach(EXPORTED_PACKAGES::add);
+
+        ListJDKInternals listJDKInternals = new ListJDKInternals(paths);
+        if (outFile != null) {
+            try (OutputStream out = Files.newOutputStream(outFile);
+                 PrintStream pw = new PrintStream(out)) {
+                listJDKInternals.write(pw);
+            }
+        } else {
+            listJDKInternals.write(System.out);
+        }
+    }
+
+    private final Set<String> packages = new HashSet<>();
+    ListJDKInternals(List<Path> dirs) throws IOException {
+        for (Path p : dirs) {
+            packages.addAll(list(p));
+        }
+    }
+
+    private void write(PrintStream pw) {
+        pw.println("# This file is auto-generated by ListJDKInternals tool on " +
+                   LocalDateTime.now().toString());
+        packages.stream().sorted()
+                .forEach(pw::println);
+    }
+
+    private Set<String> list(Path javaHome) throws IOException {
+        Path jrt = javaHome.resolve("lib").resolve("modules");
+        Path jre = javaHome.resolve("jre");
+
+        if (Files.exists(jrt)) {
+            return listModularRuntime(javaHome);
+        } else if (Files.exists(jre.resolve("lib").resolve("rt.jar"))) {
+            return listLegacyRuntime(javaHome);
+        }
+        throw new IllegalArgumentException("invalid " + javaHome);
+    }
+
+    private Set<String> listModularRuntime(Path javaHome) throws IOException {
+        Map<String, String> env = new HashMap<>();
+        env.put("java.home", javaHome.toString());
+        FileSystem fs = FileSystems.newFileSystem(URI.create("jrt:/"), env);
+        Path root = fs.getPath("packages");
+        return Files.walk(root, 1)
+                    .map(Path::getFileName)
+                    .map(Path::toString)
+                    .filter(pn -> !EXPORTED_PACKAGES.contains(pn))
+                    .collect(Collectors.toSet());
+    }
+
+    private Set<String> listLegacyRuntime(Path javaHome) throws IOException {
+        List<Path> dirs = new ArrayList<>();
+        Path jre = javaHome.resolve("jre");
+        Path lib = javaHome.resolve("lib");
+
+        dirs.add(jre.resolve("lib"));
+        dirs.add(jre.resolve("lib").resolve("ext"));
+        dirs.add(lib.resolve("tools.jar"));
+        dirs.add(lib.resolve("jconsole.jar"));
+        Set<String> packages = new HashSet<>();
+        for (Path d : dirs) {
+            Files.find(d, 1, (Path p, BasicFileAttributes attr)
+                    -> p.getFileName().toString().endsWith(".jar") &&
+                       !excludes.contains(p.getFileName().toString()))
+                .map(ListJDKInternals::walkJarFile)
+                .flatMap(Set::stream)
+                .filter(pn -> !EXPORTED_PACKAGES.contains(pn))
+                .forEach(packages::add);
+        }
+        return packages;
+    }
+
+    static Set<String> walkJarFile(Path jarfile) {
+        try (JarFile jf = new JarFile(jarfile.toFile())) {
+            return jf.stream()
+                     .map(JarEntry::getName)
+                     .filter(n -> n.endsWith(".class"))
+                     .map(ListJDKInternals::toPackage)
+                .collect(Collectors.toSet());
+        } catch (IOException e) {
+            throw new UncheckedIOException(e);
+        }
+    }
+
+    static String toPackage(String name) {
+        int i = name.lastIndexOf('/');
+        if (i < 0) {
+            System.err.format("Warning: unnamed package %s%n", name);
+        }
+        return i >= 0 ? name.substring(0, i).replace("/", ".") : "";
+    }
+}
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1152,10 +1152,6 @@
         case TYP:
             if (sym.isLocal()) {
                 mask = LocalClassFlags;
-                if (sym.name.isEmpty()) { // Anonymous class
-                    // JLS: Anonymous classes are final.
-                    implicit |= FINAL;
-                }
                 if ((sym.owner.flags_field & STATIC) == 0 &&
                     (flags & ENUM) != 0)
                     log.error(pos, "enums.must.be.static");
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1040,7 +1040,6 @@
             inner.markAbstractIfNeeded(types);
             char flags = (char) adjustFlags(inner.flags_field);
             if ((flags & INTERFACE) != 0) flags |= ABSTRACT; // Interfaces are always ABSTRACT
-            if (inner.name.isEmpty()) flags &= ~FINAL; // Anonymous class: unset FINAL flag
             flags &= ~STRICTFP; //inner classes should not have the strictfp flag set.
             if (dumpInnerClassModifiers) {
                 PrintWriter pw = log.getWriter(Log.WriterKind.ERROR);
@@ -1679,7 +1678,6 @@
             if ((flags & PROTECTED) != 0) flags |= PUBLIC;
             flags = flags & ClassFlags & ~STRICTFP;
             if ((flags & INTERFACE) == 0) flags |= ACC_SUPER;
-            if (c.isInner() && c.name.isEmpty()) flags &= ~FINAL;
         }
 
         if (dumpClassModifiers) {
--- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DCTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -578,7 +578,7 @@
         public final String signature;
 
         // The following are not directly exposed through ReferenceTree
-        // use DocTrees.getElement(TreePath,ReferenceTree)
+        // use DocTrees.getElement(DocTreePath)
         public final JCTree qualifierExpression;
         public final Name memberName;
         public final List<JCTree> paramTypes;
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AnnotationTypeWriterImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -458,17 +458,6 @@
     }
 
     /**
-     * Add gap between navigation bar elements.
-     *
-     * @param liNav the content tree to which the gap will be added
-     */
-    protected void addNavGap(Content liNav) {
-        liNav.addContent(getSpace());
-        liNav.addContent("|");
-        liNav.addContent(getSpace());
-    }
-
-    /**
      * {@inheritDoc}
      */
     @Override
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -764,17 +764,6 @@
     }
 
     /**
-     * Add gap between navigation bar elements.
-     *
-     * @param liNav the content tree to which the gap will be added
-     */
-    protected void addNavGap(Content liNav) {
-        liNav.addContent(getSpace());
-        liNav.addContent("|");
-        liNav.addContent(getSpace());
-    }
-
-    /**
      * Return the TypeElement being documented.
      *
      * @return the TypeElement being documented.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -908,6 +908,17 @@
     }
 
     /**
+     * Add gap between navigation bar elements.
+     *
+     * @param liNav the content tree to which the gap will be added
+     */
+    protected void addNavGap(Content liNav) {
+        liNav.addContent(getSpace());
+        liNav.addContent("|");
+        liNav.addContent(getSpace());
+    }
+
+    /**
      * Get summary table header.
      *
      * @param header the header for the table
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ModuleWriterImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -26,23 +26,28 @@
 package jdk.javadoc.internal.doclets.formats.html;
 
 import java.io.*;
+import java.util.ArrayList;
+import java.util.EnumMap;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 import javax.lang.model.element.ModuleElement;
+import javax.lang.model.element.ModuleElement.DirectiveKind;
 import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
 
 import com.sun.source.doctree.DocTree;
-
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlConstants;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag;
 import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree;
 import jdk.javadoc.internal.doclets.formats.html.markup.RawHtml;
+import jdk.javadoc.internal.doclets.formats.html.markup.StringContent;
 import jdk.javadoc.internal.doclets.toolkit.Content;
 import jdk.javadoc.internal.doclets.toolkit.ModuleSummaryWriter;
 import jdk.javadoc.internal.doclets.toolkit.util.CommentHelper;
 import jdk.javadoc.internal.doclets.toolkit.util.DocPaths;
+import jdk.javadoc.internal.doclets.toolkit.util.DocletAbortException;
 
 /**
  * Class to generate file for each module contents in the right-hand
@@ -74,17 +79,25 @@
      */
     protected ModuleElement mdle;
 
+    private final Map<ModuleElement.DirectiveKind, List<ModuleElement.Directive>> directiveMap
+            = new EnumMap<>(ModuleElement.DirectiveKind.class);
+
     /**
      * The HTML tree for main tag.
      */
     protected HtmlTree mainTree = HtmlTree.MAIN();
 
     /**
+     * The HTML tree for section tag.
+     */
+    protected HtmlTree sectionTree = HtmlTree.SECTION();
+
+    /**
      * Constructor to construct ModuleWriter object and to generate
      * "moduleName-summary.html" file.
      *
      * @param configuration the configuration of the doclet.
-     * @param module        Module under consideration.
+     * @param mdle        Module under consideration.
      * @param prevModule   Previous module in the sorted array.
      * @param nextModule   Next module in the sorted array.
      */
@@ -95,10 +108,13 @@
         this.prevModule = prevModule;
         this.nextModule = nextModule;
         this.mdle = mdle;
+        generateDirectiveMap();
     }
 
     /**
-     * {@inheritDoc}
+     * Get the module header.
+     *
+     * @param heading the heading for the section
      */
     public Content getModuleHeader(String heading) {
         HtmlTree bodyTree = getBody(true, getWindowTitle(mdle.getQualifiedName().toString()));
@@ -127,7 +143,7 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Get the content header.
      */
     public Content getContentHeader() {
         HtmlTree div = new HtmlTree(HtmlTag.DIV);
@@ -136,7 +152,7 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Get the summary section header.
      */
     public Content getSummaryHeader() {
         HtmlTree li = new HtmlTree(HtmlTag.LI);
@@ -145,7 +161,9 @@
     }
 
     /**
-     * {@inheritDoc}
+     * Get the summary tree.
+     *
+     * @param summaryContentTree the content tree to be added to the summary tree.
      */
     public Content getSummaryTree(Content summaryContentTree) {
         HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, summaryContentTree);
@@ -153,18 +171,315 @@
     }
 
     /**
+     * Generate the directive map for the directives on the module.
+     */
+    public void generateDirectiveMap() {
+        for (ModuleElement.Directive d : mdle.getDirectives()) {
+            if (directiveMap.containsKey(d.getKind())) {
+                List<ModuleElement.Directive> dir = directiveMap.get(d.getKind());
+                dir.add(d);
+                directiveMap.put(d.getKind(), dir);
+            } else {
+                List<ModuleElement.Directive> dir = new ArrayList<>();
+                dir.add(d);
+                directiveMap.put(d.getKind(), dir);
+            }
+        }
+    }
+
+    /**
+     * Add the summary header.
+     *
+     * @param startMarker the marker comment
+     * @param markerAnchor the marker anchor for the section
+     * @param heading the heading for the section
+     * @param htmltree the content tree to which the information is added
+     */
+    public void addSummaryHeader(Content startMarker, SectionName markerAnchor, Content heading, Content htmltree) {
+        htmltree.addContent(startMarker);
+        htmltree.addContent(getMarkerAnchor(markerAnchor));
+        htmltree.addContent(HtmlTree.HEADING(HtmlTag.H3, heading));
+    }
+
+    /**
+     * Add the summary for the module.
+     *
+     * @param text the table caption
+     * @param tableSummary the summary for the table
+     * @param htmltree the content tree to which the table will be added
+     * @param tableStyle the table style
+     * @param tableHeader the table header
+     * @param dirs the list of module directives
+     */
+    public void addSummary(String text, String tableSummary, Content htmltree, HtmlStyle tableStyle,
+            List<String> tableHeader, List<ModuleElement.Directive> dirs) {
+        Content table = (configuration.isOutputHtml5())
+                ? HtmlTree.TABLE(tableStyle, getTableCaption(new RawHtml(text)))
+                : HtmlTree.TABLE(tableStyle, tableSummary, getTableCaption(new RawHtml(text)));
+        table.addContent(getSummaryTableHeader(tableHeader, "col"));
+        Content tbody = new HtmlTree(HtmlTag.TBODY);
+        addList(dirs, tbody);
+        table.addContent(tbody);
+        htmltree.addContent(table);
+    }
+
+    /**
+     * Add the list of directives for the module.
+     *
+     * @param dirs the list of module directives
+     * @params tbody the content tree to which the list is added
+     */
+    public void addList(List<ModuleElement.Directive> dirs, Content tbody) {
+        boolean altColor = true;
+        for (ModuleElement.Directive direct : dirs) {
+            DirectiveKind kind = direct.getKind();
+            switch (kind) {
+                case REQUIRES:
+                    addRequiresList((ModuleElement.RequiresDirective) direct, tbody, altColor);
+                    break;
+                case EXPORTS:
+                    addExportedPackagesList((ModuleElement.ExportsDirective) direct, tbody, altColor);
+                    break;
+                case USES:
+                    addUsesList((ModuleElement.UsesDirective) direct, tbody, altColor);
+                    break;
+                case PROVIDES:
+                    addProvidesList((ModuleElement.ProvidesDirective) direct, tbody, altColor);
+                    break;
+                default:
+                    throw new AssertionError("unknown directive kind: " + kind);
+            }
+            altColor = !altColor;
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addModulesSummary(Content summaryContentTree) {
+        List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.REQUIRES);
+        if (dirs != null && !dirs.isEmpty()) {
+            HtmlTree li = new HtmlTree(HtmlTag.LI);
+            li.addStyle(HtmlStyle.blockList);
+            addSummaryHeader(HtmlConstants.START_OF_MODULES_SUMMARY, SectionName.MODULES,
+                    getResource("doclet.navModules"), li);
+            String text = configuration.getText("doclet.Requires_Summary");
+            String tableSummary = configuration.getText("doclet.Member_Table_Summary",
+                    configuration.getText("doclet.Requires_Summary"),
+                    configuration.getText("doclet.modules"));
+            addRequiresSummary(text, tableSummary, dirs, li);
+            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
+            summaryContentTree.addContent(ul);
+        }
+    }
+
+    /**
+     * Add the requires summary for the module.
+     *
+     * @param text the table caption
+     * @param tableSummary the summary for the table
+     * @param dirs the list of module directives
+     * @param htmltree the content tree to which the table will be added
+     */
+    public void addRequiresSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
+            Content htmltree) {
+        addSummary(text, tableSummary, htmltree, HtmlStyle.requiresSummary, requiresTableHeader, dirs);
+    }
+
+    /**
+     * Add the requires directive list for the module.
+     *
+     * @param direct the requires directive
+     * @param tbody the content tree to which the directive will be added
+     * @param altColor true if altColor style should be used or false if rowColor style should be used
+     */
+    public void addRequiresList(ModuleElement.RequiresDirective direct, Content tbody, boolean altColor) {
+        ModuleElement m = direct.getDependency();
+        Content moduleLinkContent = getModuleLink(m, new StringContent(m.getQualifiedName().toString()));
+        Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, moduleLinkContent);
+        HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
+        tdSummary.addStyle(HtmlStyle.colLast);
+        addSummaryComment(m, tdSummary);
+        HtmlTree tr = HtmlTree.TR(tdPackage);
+        tr.addContent(tdSummary);
+        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+        tbody.addContent(tr);
+    }
+
+    /**
      * {@inheritDoc}
      */
-    public void addPackagesSummary(Set<PackageElement> packages, String text,
-            String tableSummary, Content summaryContentTree) {
-        Content table = (configuration.isOutputHtml5())
-                ? HtmlTree.TABLE(HtmlStyle.overviewSummary, getTableCaption(new RawHtml(text)))
-                : HtmlTree.TABLE(HtmlStyle.overviewSummary, tableSummary, getTableCaption(new RawHtml(text)));
-        table.addContent(getSummaryTableHeader(packageTableHeader, "col"));
-        Content tbody = new HtmlTree(HtmlTag.TBODY);
-        addPackagesList(packages, tbody);
-        table.addContent(tbody);
-        summaryContentTree.addContent(table);
+    public void addPackagesSummary(Content summaryContentTree) {
+        List<ModuleElement.Directive> dirs = directiveMap.get(DirectiveKind.EXPORTS);
+        if (dirs != null && !dirs.isEmpty()) {
+            HtmlTree li = new HtmlTree(HtmlTag.LI);
+            li.addStyle(HtmlStyle.blockList);
+            addSummaryHeader(HtmlConstants.START_OF_PACKAGES_SUMMARY, SectionName.PACKAGES,
+                    getResource("doclet.navPackages"), li);
+            String text = configuration.getText("doclet.Exported_Packages_Summary");
+            String tableSummary = configuration.getText("doclet.Member_Table_Summary",
+                    configuration.getText("doclet.Exported_Packages_Summary"),
+                    configuration.getText("doclet.packages"));
+            addExportedPackagesSummary(text, tableSummary, dirs, li);
+            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
+            summaryContentTree.addContent(ul);
+        }
+    }
+
+    /**
+     * Add the exported packages summary for the module.
+     *
+     * @param text the table caption
+     * @param tableSummary the summary for the table
+     * @param dirs the list of module directives
+     * @param htmltree the content tree to which the table will be added
+     */
+    public void addExportedPackagesSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
+            Content htmltree) {
+        addSummary(text, tableSummary, htmltree, HtmlStyle.packagesSummary, exportedPackagesTableHeader, dirs);
+    }
+
+    /**
+     * Add the exported packages list for the module.
+     *
+     * @param direct the requires directive
+     * @param tbody the content tree to which the directive will be added
+     * @param altColor true if altColor style should be used or false if rowColor style should be used
+     */
+    public void addExportedPackagesList(ModuleElement.ExportsDirective direct, Content tbody, boolean altColor) {
+        PackageElement pkg = direct.getPackage();
+        Content pkgLinkContent = getPackageLink(pkg, new StringContent(utils.getPackageName(pkg)));
+        Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, pkgLinkContent);
+        HtmlTree tdModules = new HtmlTree(HtmlTag.TD);
+        tdModules.addStyle(HtmlStyle.colSecond);
+        List<? extends ModuleElement> targetModules = direct.getTargetModules();
+        if (targetModules != null) {
+            List<? extends ModuleElement> mElements = direct.getTargetModules();
+            for (int i = 0; i < mElements.size(); i++) {
+                if (i > 0) {
+                    tdModules.addContent(new HtmlTree(HtmlTag.BR));
+                }
+                ModuleElement m = mElements.get(i);
+                tdModules.addContent(new StringContent(m.getQualifiedName().toString()));
+            }
+        } else {
+            tdModules.addContent(configuration.getText("doclet.All_Modules"));
+        }
+        HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
+        tdSummary.addStyle(HtmlStyle.colLast);
+        addSummaryComment(pkg, tdSummary);
+        HtmlTree tr = HtmlTree.TR(tdPackage);
+        tr.addContent(tdModules);
+        tr.addContent(tdSummary);
+        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+        tbody.addContent(tr);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public void addServicesSummary(Content summaryContentTree) {
+        List<ModuleElement.Directive> usesDirs = directiveMap.get(DirectiveKind.USES);
+        List<ModuleElement.Directive> providesDirs = directiveMap.get(DirectiveKind.PROVIDES);
+        if ((usesDirs != null && !usesDirs.isEmpty()) || (providesDirs != null && !providesDirs.isEmpty())) {
+            HtmlTree li = new HtmlTree(HtmlTag.LI);
+            li.addStyle(HtmlStyle.blockList);
+            addSummaryHeader(HtmlConstants.START_OF_SERVICES_SUMMARY, SectionName.SERVICES,
+                    getResource("doclet.navServices"), li);
+            String text;
+            String tableSummary;
+            if (usesDirs != null && !usesDirs.isEmpty()) {
+                text = configuration.getText("doclet.Uses_Summary");
+                tableSummary = configuration.getText("doclet.Member_Table_Summary",
+                        configuration.getText("doclet.Uses_Summary"),
+                        configuration.getText("doclet.types"));
+                addUsesSummary(text, tableSummary, usesDirs, li);
+            }
+            if (providesDirs != null && !providesDirs.isEmpty()) {
+                text = configuration.getText("doclet.Provides_Summary");
+                tableSummary = configuration.getText("doclet.Member_Table_Summary",
+                        configuration.getText("doclet.Provides_Summary"),
+                        configuration.getText("doclet.types"));
+                addProvidesSummary(text, tableSummary, providesDirs, li);
+            }
+            HtmlTree ul = HtmlTree.UL(HtmlStyle.blockList, li);
+            summaryContentTree.addContent(ul);
+        }
+    }
+
+    /**
+     * Add the uses summary for the module.
+     *
+     * @param text the table caption
+     * @param tableSummary the summary for the table
+     * @param dirs the list of module directives
+     * @param htmltree the content tree to which the table will be added
+     */
+    public void addUsesSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
+            Content htmltree) {
+        addSummary(text, tableSummary, htmltree, HtmlStyle.usesSummary, usesTableHeader, dirs);
+    }
+
+    /**
+     * Add the uses list for the module.
+     *
+     * @param direct the requires directive
+     * @param tbody the content tree to which the directive will be added
+     * @param altColor true if altColor style should be used or false if rowColor style should be used
+     */
+    public void addUsesList(ModuleElement.UsesDirective direct, Content tbody, boolean altColor) {
+        TypeElement type = direct.getService();
+        Content typeLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, type));
+        Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, typeLinkContent);
+        HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
+        tdSummary.addStyle(HtmlStyle.colLast);
+        addSummaryComment(type, tdSummary);
+        HtmlTree tr = HtmlTree.TR(tdPackage);
+        tr.addContent(tdSummary);
+        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+        tbody.addContent(tr);
+    }
+
+    /**
+     * Add the provides summary for the module.
+     *
+     * @param text the table caption
+     * @param tableSummary the summary for the table
+     * @param dirs the list of module directives
+     * @param htmltree the content tree to which the table will be added
+     */
+    public void addProvidesSummary(String text, String tableSummary, List<ModuleElement.Directive> dirs,
+            Content htmltree) {
+        addSummary(text, tableSummary, htmltree, HtmlStyle.providesSummary, providesTableHeader, dirs);
+    }
+
+    /**
+     * Add the exported packages list for the module.
+     *
+     * @param direct the requires directive
+     * @param tbody the content tree to which the directive will be added
+     * @param altColor true if altColor style should be used or false if rowColor style should be used
+     */
+    public void addProvidesList(ModuleElement.ProvidesDirective direct, Content tbody, boolean altColor) {
+        TypeElement impl = direct.getImplementation();
+        TypeElement srv = direct.getService();
+        Content implLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, impl));
+        Content srvLinkContent = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.PACKAGE, srv));
+        HtmlTree tdType = HtmlTree.TD(HtmlStyle.colFirst, srvLinkContent);
+        tdType.addContent(new HtmlTree(HtmlTag.BR));
+        tdType.addContent("(");
+        HtmlTree implSpan = HtmlTree.SPAN(HtmlStyle.implementationLabel, getResource("doclet.Implementation"));
+        tdType.addContent(implSpan);
+        tdType.addContent(getSpace());
+        tdType.addContent(implLinkContent);
+        tdType.addContent(")");
+        HtmlTree tdDesc = new HtmlTree(HtmlTag.TD);
+        tdDesc.addStyle(HtmlStyle.colLast);
+        addSummaryComment(srv, tdDesc);
+        HtmlTree tr = HtmlTree.TR(tdType);
+        tr.addContent(tdDesc);
+        tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
+        tbody.addContent(tr);
     }
 
     /**
@@ -196,29 +511,56 @@
     }
 
     /**
-     * Adds list of packages in the package summary table. Generate link to each package.
+     * Add summary details to the navigation bar.
      *
-     * @param packages Packages to which link is to be generated
-     * @param tbody the documentation tree to which the list will be added
+     * @param subDiv the content tree to which the summary detail links will be added
+     */
+    protected void addSummaryDetailLinks(Content subDiv) {
+        try {
+            Content div = HtmlTree.DIV(getNavSummaryLinks());
+            subDiv.addContent(div);
+        } catch (Exception e) {
+            throw new DocletAbortException(e);
+        }
+    }
+
+    /**
+     * Get summary links for navigation bar.
+     *
+     * @return the content tree for the navigation summary links
      */
-    protected void addPackagesList(Set<PackageElement> packages, Content tbody) {
-        boolean altColor = true;
-        for (PackageElement pkg : packages) {
-            if (pkg != null && !pkg.isUnnamed()) {
-                if (!(configuration.nodeprecated && utils.isDeprecated(pkg))) {
-                    Content packageLinkContent = getPackageLink(pkg, getPackageName(pkg));
-                    Content tdPackage = HtmlTree.TD(HtmlStyle.colFirst, packageLinkContent);
-                    HtmlTree tdSummary = new HtmlTree(HtmlTag.TD);
-                    tdSummary.addStyle(HtmlStyle.colLast);
-                    addSummaryComment(pkg, tdSummary);
-                    HtmlTree tr = HtmlTree.TR(tdPackage);
-                    tr.addContent(tdSummary);
-                    tr.addStyle(altColor ? HtmlStyle.altColor : HtmlStyle.rowColor);
-                    tbody.addContent(tr);
-                }
-            }
-            altColor = !altColor;
-        }
+    protected Content getNavSummaryLinks() throws Exception {
+        Content li = HtmlTree.LI(moduleSubNavLabel);
+        li.addContent(getSpace());
+        Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li);
+        Content liNav = new HtmlTree(HtmlTag.LI);
+        liNav.addContent(!utils.getBody(mdle).isEmpty() && !configuration.nocomment
+                ? getHyperLink(SectionName.MODULE_DESCRIPTION, getResource("doclet.navModuleDescription"))
+                : getResource("doclet.navModuleDescription"));
+        addNavGap(liNav);
+        liNav.addContent(showDirectives(DirectiveKind.REQUIRES)
+                ? getHyperLink(SectionName.MODULES, getResource("doclet.navModules"))
+                : getResource("doclet.navModules"));
+        addNavGap(liNav);
+        liNav.addContent(showDirectives(DirectiveKind.EXPORTS)
+                ? getHyperLink(SectionName.PACKAGES, getResource("doclet.navPackages"))
+                : getResource("doclet.navPackages"));
+        addNavGap(liNav);
+        liNav.addContent((showDirectives(DirectiveKind.USES) || showDirectives(DirectiveKind.PROVIDES))
+                ? getHyperLink(SectionName.SERVICES, getResource("doclet.navServices"))
+                : getResource("doclet.navServices"));
+        ulNav.addContent(liNav);
+        return ulNav;
+    }
+
+    /**
+     * Return true if the directive should be displayed.
+     *
+     * @param dirKind the kind of directive for the module
+     * @return true if the directive should be displayed
+     */
+    private boolean showDirectives(DirectiveKind dirKind) {
+        return directiveMap.get(dirKind) != null && !directiveMap.get(dirKind).isEmpty();
     }
 
     /**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/SectionName.java	Mon Jul 18 09:38:08 2016 -0700
@@ -54,6 +54,9 @@
     METHODS_INHERITANCE("methods.inherited.from.class."),
     METHOD_SUMMARY("method.summary"),
     MODULE_DESCRIPTION("module.description"),
+    MODULES("modules.summary"),
+    PACKAGES("packages.summary"),
+    SERVICES("services.summary"),
     NAVBAR_BOTTOM("navbar.bottom"),
     NAVBAR_BOTTOM_FIRSTROW("navbar.bottom.firstrow"),
     NAVBAR_TOP("navbar.top"),
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlConstants.java	Mon Jul 18 09:38:08 2016 -0700
@@ -70,6 +70,24 @@
             new Comment("============ MODULE DESCRIPTION ===========");
 
     /**
+     * Marker to identify start of modules summary.
+     */
+    public static final Content START_OF_MODULES_SUMMARY =
+            new Comment("============ MODULES SUMMARY ===========");
+
+    /**
+     * Marker to identify start of packages summary.
+     */
+    public static final Content START_OF_PACKAGES_SUMMARY =
+            new Comment("============ PACKAGES SUMMARY ===========");
+
+    /**
+     * Marker to identify start of services summary.
+     */
+    public static final Content START_OF_SERVICES_SUMMARY =
+            new Comment("============ SERVICES SUMMARY ===========");
+
+    /**
      * Marker to identify start of class data.
      */
     public static final Content START_OF_CLASS_DATA =
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java	Mon Jul 18 09:38:08 2016 -0700
@@ -49,6 +49,7 @@
     colFirst,
     colLast,
     colOne,
+    colSecond,
     constantsSummary,
     constantValuesContainer,
     contentContainer,
@@ -65,6 +66,7 @@
     header,
     horizontal,
     footer,
+    implementationLabel,
     indexContainer,
     indexNav,
     inheritance,
@@ -87,7 +89,10 @@
     overviewSummary,
     packageHierarchyLabel,
     packageLabelInClass,
+    packagesSummary,
     paramLabel,
+    providesSummary,
+    requiresSummary,
     returnLabel,
     rightContainer,
     rightIframe,
@@ -111,5 +116,6 @@
     typeNameLabel,
     typeNameLink,
     typeSummary,
-    useSummary
+    useSummary,
+    usesSummary
 }
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -77,6 +77,26 @@
     protected final List<String> packageTableHeader;
 
     /**
+     * Header for tables displaying modules and description..
+     */
+    protected final List<String> requiresTableHeader;
+
+    /**
+     * Header for tables displaying packages and description..
+     */
+    protected final List<String> exportedPackagesTableHeader;
+
+    /**
+     * Header for tables displaying types and description..
+     */
+    protected final List<String> usesTableHeader;
+
+    /**
+     * Header for tables displaying types and description..
+     */
+    protected final List<String> providesTableHeader;
+
+    /**
      * Summary for use tables displaying class and package use.
      */
     protected final String useTableSummary;
@@ -108,6 +128,8 @@
 
     public final Content detailLabel;
 
+    public final Content moduleSubNavLabel;
+
     public final Content framesLabel;
 
     public final Content noframesLabel;
@@ -192,6 +214,19 @@
         packageTableHeader = new ArrayList<>();
         packageTableHeader.add(configuration.getText("doclet.Package"));
         packageTableHeader.add(configuration.getText("doclet.Description"));
+        requiresTableHeader = new ArrayList<>();
+        requiresTableHeader.add(configuration.getText("doclet.Module"));
+        requiresTableHeader.add(configuration.getText("doclet.Description"));
+        exportedPackagesTableHeader = new ArrayList<>();
+        exportedPackagesTableHeader.add(configuration.getText("doclet.Package"));
+        exportedPackagesTableHeader.add(configuration.getText("doclet.Module"));
+        exportedPackagesTableHeader.add(configuration.getText("doclet.Description"));
+        usesTableHeader = new ArrayList<>();
+        usesTableHeader.add(configuration.getText("doclet.Type"));
+        usesTableHeader.add(configuration.getText("doclet.Description"));
+        providesTableHeader = new ArrayList<>();
+        providesTableHeader.add(configuration.getText("doclet.Type"));
+        providesTableHeader.add(configuration.getText("doclet.Description"));
         useTableSummary = configuration.getText("doclet.Use_Table_Summary",
                 configuration.getText("doclet.packages"));
         modifierTypeHeader = configuration.getText("doclet.0_and_1",
@@ -208,6 +243,7 @@
         nextclassLabel = getNonBreakResource("doclet.Next_Class");
         summaryLabel = getResource("doclet.Summary");
         detailLabel = getResource("doclet.Detail");
+        moduleSubNavLabel = getResource("doclet.Module_Sub_Nav");
         framesLabel = getResource("doclet.Frames");
         noframesLabel = getNonBreakResource("doclet.No_Frames");
         treeLabel = getResource("doclet.Tree");
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties	Mon Jul 18 09:38:08 2016 -0700
@@ -31,6 +31,11 @@
 doclet.Href_Class_Or_Interface_Title=class or interface in {0}
 doclet.Summary=Summary:
 doclet.Detail=Detail:
+doclet.Module_Sub_Nav=Module:
+doclet.navModuleDescription=Description
+doclet.navModules=Modules
+doclet.navPackages=Packages
+doclet.navServices=Services
 doclet.navNested=Nested
 doclet.navAnnotationTypeOptionalMember=Optional
 doclet.navAnnotationTypeRequiredMember=Required
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/ModuleSummaryWriter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -91,15 +91,25 @@
     public abstract void addModuleTags(Content moduleContentTree);
 
     /**
-     * Adds the table of packages to the documentation tree.
+     * Adds the modules summary to the documentation tree.
      *
-     * @param packages the set of packages that should be added.
-     * @param label the label for this table.
-     * @param tableSummary the summary string for the table
      * @param summaryContentTree the content tree to which the summary will be added
      */
-    public abstract void addPackagesSummary(Set<PackageElement> packages, String label,
-            String tableSummary, Content summaryContentTree);
+    public abstract void addModulesSummary(Content summaryContentTree);
+
+    /**
+     * Adds the packages summary to the documentation tree.
+     *
+     * @param summaryContentTree the content tree to which the summary will be added
+     */
+    public abstract void addPackagesSummary(Content summaryContentTree);
+
+    /**
+     * Adds the services summary to the documentation tree.
+     *
+     * @param summaryContentTree the content tree to which the summary will be added
+     */
+    public abstract void addServicesSummary(Content summaryContentTree);
 
     /**
      * Adds the module content tree to the documentation tree.
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/builders/ModuleSummaryBuilder.java	Mon Jul 18 09:38:08 2016 -0700
@@ -167,23 +167,34 @@
     }
 
     /**
-     * Build the module package summary.
+     * Build the modules summary.
      *
      * @param node the XML element that specifies which components to document
      * @param summaryContentTree the content tree to which the summaries will
      *                           be added
      */
-    public void buildPackageSummary(XMLNode node, Content summaryContentTree) {
-        Set<PackageElement> packages = configuration.modulePackages.get(mdle);
-        if (!packages.isEmpty()) {
-            String packageTableSummary
-                    = configuration.getText("doclet.Member_Table_Summary",
-                            configuration.getText("doclet.Package_Summary"),
-                            configuration.getText("doclet.packages"));
-            moduleWriter.addPackagesSummary(
-                    packages, configuration.getText("doclet.Package_Summary"),
-                    packageTableSummary, summaryContentTree);
+    public void buildModulesSummary(XMLNode node, Content summaryContentTree) {
+        moduleWriter.addModulesSummary(summaryContentTree);
+    }
+
+    /**
+     * Build the package summary.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param summaryContentTree the content tree to which the summaries will be added
+     */
+    public void buildPackagesSummary(XMLNode node, Content summaryContentTree) {
+        moduleWriter.addPackagesSummary(summaryContentTree);
         }
+
+    /**
+     * Build the services summary.
+     *
+     * @param node the XML element that specifies which components to document
+     * @param summaryContentTree the content tree to which the summaries will be added
+     */
+    public void buildServicesSummary(XMLNode node, Content summaryContentTree) {
+        moduleWriter.addServicesSummary(summaryContentTree);
     }
 
     /**
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclet.xml	Mon Jul 18 09:38:08 2016 -0700
@@ -33,7 +33,9 @@
             <ModuleDescription/>
             <ModuleTags/>
             <Summary>
-                <PackageSummary/>
+                <ModulesSummary/>
+                <PackagesSummary/>
+                <ServicesSummary/>
             </Summary>
         </Content>
     </ModuleDoc>
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties	Mon Jul 18 09:38:08 2016 -0700
@@ -69,6 +69,10 @@
 doclet.tag_misuse=Tag {0} cannot be used in {1} documentation.  It can only be used in the following types of documentation: {2}.
 doclet.javafx_tag_misuse=Tags @propertyGetter, @propertySetter and @propertyDescription can only be used in JavaFX properties getters and setters.
 doclet.Package_Summary=Package Summary
+doclet.Requires_Summary=Requires
+doclet.Exported_Packages_Summary=Exported Packages
+doclet.Uses_Summary=Uses
+doclet.Provides_Summary=Provides
 doclet.Module_Summary=Module Summary
 doclet.Interface_Summary=Interface Summary
 doclet.Annotation_Types_Summary=Annotation Types Summary
@@ -93,6 +97,7 @@
 doclet.Packages=Packages
 doclet.packages=packages
 doclet.modules=modules
+doclet.types=types
 doclet.All_Classes=All Classes
 doclet.All_Superinterfaces=All Superinterfaces:
 doclet.All_Implemented_Interfaces=All Implemented Interfaces:
@@ -170,6 +175,7 @@
 doclet.subinterfaces=subinterfaces
 doclet.Modifier=Modifier
 doclet.Type=Type
+doclet.Implementation=Implementation:
 doclet.Types=Types
 doclet.Members=Members
 doclet.SearchTags=SearchTags
--- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css	Mon Jul 18 09:38:08 2016 -0700
@@ -412,18 +412,20 @@
 /*
 Table styles
 */
-.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary {
+.overviewSummary, .memberSummary, .typeSummary, .useSummary, .constantsSummary, .deprecatedSummary,
+.requiresSummary, .packagesSummary, .providesSummary, .usesSummary {
     width:100%;
     border-spacing:0;
     border-left:1px solid #EEE; 
     border-right:1px solid #EEE; 
     border-bottom:1px solid #EEE; 
 }
-.overviewSummary, .memberSummary  {
+.overviewSummary, .memberSummary, .requiresSummary, .packagesSummary, .providesSummary, .usesSummary  {
     padding:0px;
 }
 .overviewSummary caption, .memberSummary caption, .typeSummary caption,
-.useSummary caption, .constantsSummary caption, .deprecatedSummary caption {
+.useSummary caption, .constantsSummary caption, .deprecatedSummary caption,
+.requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption {
     position:relative;
     text-align:left;
     background-repeat:no-repeat;
@@ -439,16 +441,26 @@
 }
 .overviewSummary caption a:link, .memberSummary caption a:link, .typeSummary caption a:link,
 .useSummary caption a:link, .constantsSummary caption a:link, .deprecatedSummary caption a:link,
+.requiresSummary caption a:link, .packagesSummary caption a:link, providesSummary caption a:link,
+.usesSummary caption a:link,
 .overviewSummary caption a:hover, .memberSummary caption a:hover, .typeSummary caption a:hover,
 .useSummary caption a:hover, .constantsSummary caption a:hover, .deprecatedSummary caption a:hover,
+.requiresSummary caption a:hover, .packagesSummary caption a:hover, providesSummary caption a:hover,
+.usesSummary caption a:hover,
 .overviewSummary caption a:active, .memberSummary caption a:active, .typeSummary caption a:active,
 .useSummary caption a:active, .constantsSummary caption a:active, .deprecatedSummary caption a:active,
+.requiresSummary caption a:active, .packagesSummary caption a:active, providesSummary caption a:active,
+.usesSummary caption a:active,
 .overviewSummary caption a:visited, .memberSummary caption a:visited, .typeSummary caption a:visited,
-.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited {
+.useSummary caption a:visited, .constantsSummary caption a:visited, .deprecatedSummary caption a:visited
+.requiresSummary caption a:visited, .packagesSummary caption a:visited, providesSummary caption a:visited,
+.usesSummary caption a:visited {
     color:#FFFFFF;
 }
 .overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,
-.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {
+.useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span,
+.requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span,
+.usesSummary caption span {
     white-space:nowrap;
     padding-top:5px;
     padding-left:12px;
@@ -491,7 +503,8 @@
     display:inline;
 }
 .overviewSummary .tabEnd, .memberSummary .tabEnd, .typeSummary .tabEnd,
-.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd {
+.useSummary .tabEnd, .constantsSummary .tabEnd, .deprecatedSummary .tabEnd,
+.requiresSummary .tabEnd, .packagesSummary .tabEnd, .providesSummary .tabEnd, .usesSummary .tabEnd {
     display:none;
     width:5px;
     position:relative;
@@ -516,18 +529,19 @@
 
 }
 .overviewSummary td, .memberSummary td, .typeSummary td,
-.useSummary td, .constantsSummary td, .deprecatedSummary td {
+.useSummary td, .constantsSummary td, .deprecatedSummary td,
+.requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td {
     text-align:left;
     padding:0px 0px 12px 10px;
 }
-th.colOne, th.colFirst, th.colLast, .useSummary th, .constantsSummary th,
-td.colOne, td.colFirst, td.colLast, .useSummary td, .constantsSummary td{
+th.colOne, th.colFirst, th.colSecond, th.colLast, .useSummary th, .constantsSummary th, .packagesSummary th,
+td.colOne, td.colFirst, td.colSecond, td.colLast, .useSummary td, .constantsSummary td {
     vertical-align:top;
     padding-right:0px;
     padding-top:8px;
     padding-bottom:3px;
 }
-th.colFirst, th.colLast, th.colOne, .constantsSummary th {
+th.colFirst, th.colSecond, th.colLast, th.colOne, .constantsSummary th, .packagesSummary th {
     background:#dee3e9;
     text-align:left;
     padding:8px 3px 3px 7px;
@@ -539,10 +553,19 @@
 td.colLast, th.colLast {
     font-size:13px;
 }
-td.colOne, th.colOne {
+td.colOne, th.colOne, .constantsSummary th, .packagesSummary th {
+    font-size:13px;
+}
+.providesSummary th.colFirst, .providesSummary th.colLast, .providesSummary td.colFirst,
+.providesSummary td.colLast {
+    white-space:normal;
+    width:50%;
     font-size:13px;
 }
 .overviewSummary td.colFirst, .overviewSummary th.colFirst,
+.requiresSummary td.colFirst, .requiresSummary th.colFirst,
+.packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th,
+.usesSummary td.colFirst, .usesSummary th.colFirst,
 .useSummary td.colFirst, .useSummary th.colFirst,
 .overviewSummary td.colOne, .overviewSummary th.colOne,
 .memberSummary td.colFirst, .memberSummary th.colFirst,
@@ -551,7 +574,7 @@
     width:25%;
     vertical-align:top;
 }
-td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
+td.colOne a:link, td.colOne a:active, td.colOne a:visited, td.colOne a:hover, td.colFirst a:link, td.colFirst a:active, td.colFirst a:visited, td.colFirst a:hover, td.colSecond a:link, td.colSecond a:active, td.colSecond a:visited, td.colSecond a:hover, td.colLast a:link, td.colLast a:active, td.colLast a:visited, td.colLast a:hover, .constantValuesContainer td a:link, .constantValuesContainer td a:active, .constantValuesContainer td a:visited, .constantValuesContainer td a:hover {
     font-weight:bold;
 }
 .tableSubHeadingColor {
@@ -611,7 +634,7 @@
     margin:3px 10px 2px 0px;
     color:#474747;
 }
-.deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink,
+.deprecatedLabel, .descfrmTypeLabel, .implementationLabel, .memberNameLabel, .memberNameLink,
 .moduleLabelInClass, .overrideSpecifyLabel, .packageLabelInClass,
 .packageHierarchyLabel, .paramLabel, .returnLabel, .seeLabel, .simpleTagLabel,
 .throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink {
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Analyzer.java	Mon Jul 18 09:38:08 2016 -0700
@@ -25,20 +25,19 @@
 
 package com.sun.tools.jdeps;
 
-import static com.sun.tools.jdeps.JdepsConfiguration.*;
+import com.sun.tools.classfile.Dependency.Location;
 
-import com.sun.tools.classfile.Dependency.Location;
+import java.io.BufferedReader;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.UncheckedIOException;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.MissingResourceException;
 import java.util.Objects;
-import java.util.Optional;
-import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -369,35 +368,29 @@
         }
     }
 
-    static final JdkInternals REMOVED_JDK_INTERNALS = new JdkInternals();
+    static final Jdk8Internals REMOVED_JDK_INTERNALS = new Jdk8Internals();
 
-    static class JdkInternals extends Module {
-        private final String BUNDLE = "com.sun.tools.jdeps.resources.jdkinternals";
-
-        private final Set<String> jdkinternals;
-        private final Set<String> jdkUnsupportedClasses;
-        private JdkInternals() {
+    static class Jdk8Internals extends Module {
+        private final String JDK8_INTERNALS = "/com/sun/tools/jdeps/resources/jdk8_internals.txt";
+        private final Set<String> jdk8Internals;
+        private Jdk8Internals() {
             super("JDK removed internal API");
-
-            try {
-                ResourceBundle rb = ResourceBundle.getBundle(BUNDLE);
-                this.jdkinternals = rb.keySet();
-            } catch (MissingResourceException e) {
-                throw new InternalError("Cannot find jdkinternals resource bundle");
+            try (InputStream in = JdepsTask.class.getResourceAsStream(JDK8_INTERNALS);
+                 BufferedReader reader = new BufferedReader(new InputStreamReader(in))) {
+                this.jdk8Internals = reader.lines()
+                                          .filter(ln -> !ln.startsWith("#"))
+                                          .collect(Collectors.toSet());
+            } catch (IOException e) {
+                throw new UncheckedIOException(e);
             }
-
-            this.jdkUnsupportedClasses = getUnsupportedClasses();
         }
 
         public boolean contains(Location location) {
-            if (jdkUnsupportedClasses.contains(location.getName() + ".class")) {
-                return false;
-            }
-
             String cn = location.getClassName();
             int i = cn.lastIndexOf('.');
             String pn = i > 0 ? cn.substring(0, i) : "";
-            return jdkinternals.contains(cn) || jdkinternals.contains(pn);
+
+            return jdk8Internals.contains(pn);
         }
 
         @Override
@@ -414,25 +407,5 @@
         public boolean isExported(String pn) {
             return false;
         }
-
-        private Set<String> getUnsupportedClasses() {
-            // jdk.unsupported may not be observable
-            Optional<Module> om = Profile.FULL_JRE.findModule(JDK_UNSUPPORTED);
-            if (om.isPresent()) {
-                return om.get().reader().entries();
-            }
-
-            // find from local run-time image
-            SystemModuleFinder system = new SystemModuleFinder();
-            if (system.find(JDK_UNSUPPORTED).isPresent()) {
-                try {
-                    return system.getClassReader(JDK_UNSUPPORTED).entries();
-                } catch (IOException e) {
-                    throw new UncheckedIOException(e);
-                }
-            }
-
-            return Collections.emptySet();
-        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdk8_internals.txt	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,1029 @@
+# This file is auto-generated by ListJDKInternals tool on 2016-07-12T16:13:20.303865
+apple.applescript
+apple.laf
+apple.launcher
+apple.security
+com.apple.concurrent
+com.apple.eawt
+com.apple.eawt.event
+com.apple.eio
+com.apple.laf
+com.apple.laf.resources
+com.oracle.jrockit.jfr
+com.oracle.jrockit.jfr.client
+com.oracle.jrockit.jfr.management
+com.oracle.security.ucrypto
+com.oracle.util
+com.oracle.webservices.internal.api
+com.oracle.webservices.internal.api.databinding
+com.oracle.webservices.internal.api.message
+com.oracle.webservices.internal.impl.encoding
+com.oracle.webservices.internal.impl.internalspi.encoding
+com.oracle.xmlns.internal.webservices.jaxws_databinding
+com.sun.accessibility.internal.resources
+com.sun.activation.registries
+com.sun.awt
+com.sun.beans
+com.sun.beans.decoder
+com.sun.beans.editors
+com.sun.beans.finder
+com.sun.beans.infos
+com.sun.beans.util
+com.sun.codemodel.internal
+com.sun.codemodel.internal.fmt
+com.sun.codemodel.internal.util
+com.sun.codemodel.internal.writer
+com.sun.corba.se.impl.activation
+com.sun.corba.se.impl.copyobject
+com.sun.corba.se.impl.corba
+com.sun.corba.se.impl.dynamicany
+com.sun.corba.se.impl.encoding
+com.sun.corba.se.impl.interceptors
+com.sun.corba.se.impl.io
+com.sun.corba.se.impl.ior
+com.sun.corba.se.impl.ior.iiop
+com.sun.corba.se.impl.javax.rmi
+com.sun.corba.se.impl.javax.rmi.CORBA
+com.sun.corba.se.impl.legacy.connection
+com.sun.corba.se.impl.logging
+com.sun.corba.se.impl.monitoring
+com.sun.corba.se.impl.naming.cosnaming
+com.sun.corba.se.impl.naming.namingutil
+com.sun.corba.se.impl.naming.pcosnaming
+com.sun.corba.se.impl.oa
+com.sun.corba.se.impl.oa.poa
+com.sun.corba.se.impl.oa.toa
+com.sun.corba.se.impl.orb
+com.sun.corba.se.impl.orbutil
+com.sun.corba.se.impl.orbutil.closure
+com.sun.corba.se.impl.orbutil.concurrent
+com.sun.corba.se.impl.orbutil.fsm
+com.sun.corba.se.impl.orbutil.graph
+com.sun.corba.se.impl.orbutil.threadpool
+com.sun.corba.se.impl.presentation.rmi
+com.sun.corba.se.impl.protocol
+com.sun.corba.se.impl.protocol.giopmsgheaders
+com.sun.corba.se.impl.resolver
+com.sun.corba.se.impl.transport
+com.sun.corba.se.impl.util
+com.sun.corba.se.internal.CosNaming
+com.sun.corba.se.internal.Interceptors
+com.sun.corba.se.internal.POA
+com.sun.corba.se.internal.corba
+com.sun.corba.se.internal.iiop
+com.sun.corba.se.org.omg.CORBA
+com.sun.corba.se.pept.broker
+com.sun.corba.se.pept.encoding
+com.sun.corba.se.pept.protocol
+com.sun.corba.se.pept.transport
+com.sun.corba.se.spi.activation
+com.sun.corba.se.spi.activation.InitialNameServicePackage
+com.sun.corba.se.spi.activation.LocatorPackage
+com.sun.corba.se.spi.activation.RepositoryPackage
+com.sun.corba.se.spi.copyobject
+com.sun.corba.se.spi.encoding
+com.sun.corba.se.spi.extension
+com.sun.corba.se.spi.ior
+com.sun.corba.se.spi.ior.iiop
+com.sun.corba.se.spi.legacy.connection
+com.sun.corba.se.spi.legacy.interceptor
+com.sun.corba.se.spi.logging
+com.sun.corba.se.spi.monitoring
+com.sun.corba.se.spi.oa
+com.sun.corba.se.spi.orb
+com.sun.corba.se.spi.orbutil.closure
+com.sun.corba.se.spi.orbutil.fsm
+com.sun.corba.se.spi.orbutil.proxy
+com.sun.corba.se.spi.orbutil.threadpool
+com.sun.corba.se.spi.presentation.rmi
+com.sun.corba.se.spi.protocol
+com.sun.corba.se.spi.resolver
+com.sun.corba.se.spi.servicecontext
+com.sun.corba.se.spi.transport
+com.sun.crypto.provider
+com.sun.demo.jvmti.hprof
+com.sun.deploy.uitoolkit.impl.fx
+com.sun.deploy.uitoolkit.impl.fx.ui
+com.sun.deploy.uitoolkit.impl.fx.ui.resources
+com.sun.glass.events
+com.sun.glass.events.mac
+com.sun.glass.ui
+com.sun.glass.ui.delegate
+com.sun.glass.ui.gtk
+com.sun.glass.ui.mac
+com.sun.glass.ui.win
+com.sun.glass.utils
+com.sun.image.codec.jpeg
+com.sun.imageio.plugins.bmp
+com.sun.imageio.plugins.common
+com.sun.imageio.plugins.gif
+com.sun.imageio.plugins.jpeg
+com.sun.imageio.plugins.png
+com.sun.imageio.plugins.wbmp
+com.sun.imageio.spi
+com.sun.imageio.stream
+com.sun.istack.internal
+com.sun.istack.internal.localization
+com.sun.istack.internal.logging
+com.sun.istack.internal.tools
+com.sun.java.accessibility
+com.sun.java.accessibility.util.java.awt
+com.sun.java.browser.dom
+com.sun.java.browser.net
+com.sun.java.swing
+com.sun.java.swing.plaf.gtk
+com.sun.java.swing.plaf.gtk.resources
+com.sun.java.swing.plaf.motif
+com.sun.java.swing.plaf.motif.resources
+com.sun.java.swing.plaf.nimbus
+com.sun.java.swing.plaf.windows
+com.sun.java.swing.plaf.windows.resources
+com.sun.java.util.jar.pack
+com.sun.java_cup.internal.runtime
+com.sun.javafx
+com.sun.javafx.animation
+com.sun.javafx.applet
+com.sun.javafx.application
+com.sun.javafx.beans
+com.sun.javafx.beans.event
+com.sun.javafx.binding
+com.sun.javafx.charts
+com.sun.javafx.collections
+com.sun.javafx.css
+com.sun.javafx.css.converters
+com.sun.javafx.css.parser
+com.sun.javafx.cursor
+com.sun.javafx.effect
+com.sun.javafx.embed
+com.sun.javafx.event
+com.sun.javafx.font
+com.sun.javafx.font.coretext
+com.sun.javafx.font.directwrite
+com.sun.javafx.font.freetype
+com.sun.javafx.font.t2k
+com.sun.javafx.fxml
+com.sun.javafx.fxml.builder
+com.sun.javafx.fxml.expression
+com.sun.javafx.geom
+com.sun.javafx.geom.transform
+com.sun.javafx.geometry
+com.sun.javafx.iio
+com.sun.javafx.iio.bmp
+com.sun.javafx.iio.common
+com.sun.javafx.iio.gif
+com.sun.javafx.iio.ios
+com.sun.javafx.iio.jpeg
+com.sun.javafx.iio.png
+com.sun.javafx.image
+com.sun.javafx.image.impl
+com.sun.javafx.jmx
+com.sun.javafx.logging
+com.sun.javafx.media
+com.sun.javafx.menu
+com.sun.javafx.perf
+com.sun.javafx.print
+com.sun.javafx.property
+com.sun.javafx.property.adapter
+com.sun.javafx.robot
+com.sun.javafx.robot.impl
+com.sun.javafx.runtime
+com.sun.javafx.runtime.async
+com.sun.javafx.runtime.eula
+com.sun.javafx.scene
+com.sun.javafx.scene.control
+com.sun.javafx.scene.control.behavior
+com.sun.javafx.scene.control.skin
+com.sun.javafx.scene.control.skin.resources
+com.sun.javafx.scene.input
+com.sun.javafx.scene.layout.region
+com.sun.javafx.scene.paint
+com.sun.javafx.scene.shape
+com.sun.javafx.scene.text
+com.sun.javafx.scene.transform
+com.sun.javafx.scene.traversal
+com.sun.javafx.scene.web
+com.sun.javafx.scene.web.behavior
+com.sun.javafx.scene.web.skin
+com.sun.javafx.sg.prism
+com.sun.javafx.sg.prism.web
+com.sun.javafx.stage
+com.sun.javafx.text
+com.sun.javafx.tk
+com.sun.javafx.tk.quantum
+com.sun.javafx.util
+com.sun.javafx.webkit
+com.sun.javafx.webkit.drt
+com.sun.javafx.webkit.prism
+com.sun.javafx.webkit.prism.theme
+com.sun.javafx.webkit.theme
+com.sun.jmx.defaults
+com.sun.jmx.interceptor
+com.sun.jmx.mbeanserver
+com.sun.jmx.remote.internal
+com.sun.jmx.remote.protocol.iiop
+com.sun.jmx.remote.protocol.rmi
+com.sun.jmx.remote.security
+com.sun.jmx.remote.util
+com.sun.jmx.snmp
+com.sun.jmx.snmp.IPAcl
+com.sun.jmx.snmp.agent
+com.sun.jmx.snmp.daemon
+com.sun.jmx.snmp.defaults
+com.sun.jmx.snmp.internal
+com.sun.jmx.snmp.mpm
+com.sun.jmx.snmp.tasks
+com.sun.jndi.cosnaming
+com.sun.jndi.dns
+com.sun.jndi.ldap
+com.sun.jndi.ldap.ext
+com.sun.jndi.ldap.pool
+com.sun.jndi.ldap.sasl
+com.sun.jndi.rmi.registry
+com.sun.jndi.toolkit.corba
+com.sun.jndi.toolkit.ctx
+com.sun.jndi.toolkit.dir
+com.sun.jndi.toolkit.url
+com.sun.jndi.url.corbaname
+com.sun.jndi.url.dns
+com.sun.jndi.url.iiop
+com.sun.jndi.url.iiopname
+com.sun.jndi.url.ldap
+com.sun.jndi.url.ldaps
+com.sun.jndi.url.rmi
+com.sun.management.jmx
+com.sun.media.jfxmedia
+com.sun.media.jfxmedia.control
+com.sun.media.jfxmedia.effects
+com.sun.media.jfxmedia.events
+com.sun.media.jfxmedia.locator
+com.sun.media.jfxmedia.logging
+com.sun.media.jfxmedia.track
+com.sun.media.jfxmediaimpl
+com.sun.media.jfxmediaimpl.platform
+com.sun.media.jfxmediaimpl.platform.gstreamer
+com.sun.media.jfxmediaimpl.platform.ios
+com.sun.media.jfxmediaimpl.platform.java
+com.sun.media.jfxmediaimpl.platform.osx
+com.sun.media.sound
+com.sun.naming.internal
+com.sun.net.ssl
+com.sun.net.ssl.internal.ssl
+com.sun.net.ssl.internal.www.protocol.https
+com.sun.nio.file
+com.sun.nio.zipfs
+com.sun.openpisces
+com.sun.org.apache.bcel.internal
+com.sun.org.apache.bcel.internal.classfile
+com.sun.org.apache.bcel.internal.generic
+com.sun.org.apache.bcel.internal.util
+com.sun.org.apache.regexp.internal
+com.sun.org.apache.xalan.internal
+com.sun.org.apache.xalan.internal.extensions
+com.sun.org.apache.xalan.internal.lib
+com.sun.org.apache.xalan.internal.res
+com.sun.org.apache.xalan.internal.templates
+com.sun.org.apache.xalan.internal.utils
+com.sun.org.apache.xalan.internal.xslt
+com.sun.org.apache.xalan.internal.xsltc
+com.sun.org.apache.xalan.internal.xsltc.cmdline
+com.sun.org.apache.xalan.internal.xsltc.cmdline.getopt
+com.sun.org.apache.xalan.internal.xsltc.compiler
+com.sun.org.apache.xalan.internal.xsltc.compiler.util
+com.sun.org.apache.xalan.internal.xsltc.dom
+com.sun.org.apache.xalan.internal.xsltc.runtime
+com.sun.org.apache.xalan.internal.xsltc.runtime.output
+com.sun.org.apache.xalan.internal.xsltc.trax
+com.sun.org.apache.xalan.internal.xsltc.util
+com.sun.org.apache.xerces.internal.dom
+com.sun.org.apache.xerces.internal.dom.events
+com.sun.org.apache.xerces.internal.impl
+com.sun.org.apache.xerces.internal.impl.dtd
+com.sun.org.apache.xerces.internal.impl.dtd.models
+com.sun.org.apache.xerces.internal.impl.dv
+com.sun.org.apache.xerces.internal.impl.dv.dtd
+com.sun.org.apache.xerces.internal.impl.dv.util
+com.sun.org.apache.xerces.internal.impl.dv.xs
+com.sun.org.apache.xerces.internal.impl.io
+com.sun.org.apache.xerces.internal.impl.msg
+com.sun.org.apache.xerces.internal.impl.validation
+com.sun.org.apache.xerces.internal.impl.xpath
+com.sun.org.apache.xerces.internal.impl.xpath.regex
+com.sun.org.apache.xerces.internal.impl.xs
+com.sun.org.apache.xerces.internal.impl.xs.identity
+com.sun.org.apache.xerces.internal.impl.xs.models
+com.sun.org.apache.xerces.internal.impl.xs.opti
+com.sun.org.apache.xerces.internal.impl.xs.traversers
+com.sun.org.apache.xerces.internal.impl.xs.util
+com.sun.org.apache.xerces.internal.jaxp
+com.sun.org.apache.xerces.internal.jaxp.datatype
+com.sun.org.apache.xerces.internal.jaxp.validation
+com.sun.org.apache.xerces.internal.parsers
+com.sun.org.apache.xerces.internal.util
+com.sun.org.apache.xerces.internal.utils
+com.sun.org.apache.xerces.internal.xinclude
+com.sun.org.apache.xerces.internal.xni
+com.sun.org.apache.xerces.internal.xni.grammars
+com.sun.org.apache.xerces.internal.xni.parser
+com.sun.org.apache.xerces.internal.xpointer
+com.sun.org.apache.xerces.internal.xs
+com.sun.org.apache.xerces.internal.xs.datatypes
+com.sun.org.apache.xml.internal.dtm
+com.sun.org.apache.xml.internal.dtm.ref
+com.sun.org.apache.xml.internal.dtm.ref.dom2dtm
+com.sun.org.apache.xml.internal.dtm.ref.sax2dtm
+com.sun.org.apache.xml.internal.res
+com.sun.org.apache.xml.internal.resolver
+com.sun.org.apache.xml.internal.resolver.helpers
+com.sun.org.apache.xml.internal.resolver.readers
+com.sun.org.apache.xml.internal.resolver.tools
+com.sun.org.apache.xml.internal.security
+com.sun.org.apache.xml.internal.security.algorithms
+com.sun.org.apache.xml.internal.security.algorithms.implementations
+com.sun.org.apache.xml.internal.security.c14n
+com.sun.org.apache.xml.internal.security.c14n.helper
+com.sun.org.apache.xml.internal.security.c14n.implementations
+com.sun.org.apache.xml.internal.security.encryption
+com.sun.org.apache.xml.internal.security.exceptions
+com.sun.org.apache.xml.internal.security.keys
+com.sun.org.apache.xml.internal.security.keys.content
+com.sun.org.apache.xml.internal.security.keys.content.keyvalues
+com.sun.org.apache.xml.internal.security.keys.content.x509
+com.sun.org.apache.xml.internal.security.keys.keyresolver
+com.sun.org.apache.xml.internal.security.keys.keyresolver.implementations
+com.sun.org.apache.xml.internal.security.keys.storage
+com.sun.org.apache.xml.internal.security.keys.storage.implementations
+com.sun.org.apache.xml.internal.security.signature
+com.sun.org.apache.xml.internal.security.signature.reference
+com.sun.org.apache.xml.internal.security.transforms
+com.sun.org.apache.xml.internal.security.transforms.implementations
+com.sun.org.apache.xml.internal.security.transforms.params
+com.sun.org.apache.xml.internal.security.utils
+com.sun.org.apache.xml.internal.security.utils.resolver
+com.sun.org.apache.xml.internal.security.utils.resolver.implementations
+com.sun.org.apache.xml.internal.serialize
+com.sun.org.apache.xml.internal.serializer
+com.sun.org.apache.xml.internal.serializer.utils
+com.sun.org.apache.xml.internal.utils
+com.sun.org.apache.xml.internal.utils.res
+com.sun.org.apache.xpath.internal
+com.sun.org.apache.xpath.internal.axes
+com.sun.org.apache.xpath.internal.compiler
+com.sun.org.apache.xpath.internal.domapi
+com.sun.org.apache.xpath.internal.functions
+com.sun.org.apache.xpath.internal.jaxp
+com.sun.org.apache.xpath.internal.objects
+com.sun.org.apache.xpath.internal.operations
+com.sun.org.apache.xpath.internal.patterns
+com.sun.org.apache.xpath.internal.res
+com.sun.org.glassfish.external.amx
+com.sun.org.glassfish.external.arc
+com.sun.org.glassfish.external.probe.provider
+com.sun.org.glassfish.external.probe.provider.annotations
+com.sun.org.glassfish.external.statistics
+com.sun.org.glassfish.external.statistics.annotations
+com.sun.org.glassfish.external.statistics.impl
+com.sun.org.glassfish.gmbal
+com.sun.org.glassfish.gmbal.util
+com.sun.org.omg.CORBA
+com.sun.org.omg.CORBA.ValueDefPackage
+com.sun.org.omg.CORBA.portable
+com.sun.org.omg.SendingContext
+com.sun.org.omg.SendingContext.CodeBasePackage
+com.sun.pisces
+com.sun.prism
+com.sun.prism.d3d
+com.sun.prism.es2
+com.sun.prism.image
+com.sun.prism.impl
+com.sun.prism.impl.packrect
+com.sun.prism.impl.paint
+com.sun.prism.impl.ps
+com.sun.prism.impl.shape
+com.sun.prism.j2d
+com.sun.prism.j2d.paint
+com.sun.prism.j2d.print
+com.sun.prism.paint
+com.sun.prism.ps
+com.sun.prism.shader
+com.sun.prism.shape
+com.sun.prism.sw
+com.sun.rmi.rmid
+com.sun.rowset
+com.sun.rowset.internal
+com.sun.rowset.providers
+com.sun.scenario
+com.sun.scenario.animation
+com.sun.scenario.animation.shared
+com.sun.scenario.effect
+com.sun.scenario.effect.impl
+com.sun.scenario.effect.impl.es2
+com.sun.scenario.effect.impl.hw
+com.sun.scenario.effect.impl.hw.d3d
+com.sun.scenario.effect.impl.prism
+com.sun.scenario.effect.impl.prism.ps
+com.sun.scenario.effect.impl.prism.sw
+com.sun.scenario.effect.impl.state
+com.sun.scenario.effect.impl.sw
+com.sun.scenario.effect.impl.sw.java
+com.sun.scenario.effect.impl.sw.sse
+com.sun.scenario.effect.light
+com.sun.security.cert.internal.x509
+com.sun.security.ntlm
+com.sun.security.sasl
+com.sun.security.sasl.digest
+com.sun.security.sasl.gsskerb
+com.sun.security.sasl.ntlm
+com.sun.security.sasl.util
+com.sun.swing.internal.plaf.basic.resources
+com.sun.swing.internal.plaf.metal.resources
+com.sun.swing.internal.plaf.synth.resources
+com.sun.tools.classfile
+com.sun.tools.corba.se.idl
+com.sun.tools.corba.se.idl.constExpr
+com.sun.tools.corba.se.idl.som.cff
+com.sun.tools.corba.se.idl.som.idlemit
+com.sun.tools.corba.se.idl.toJavaPortable
+com.sun.tools.doclets.formats.html
+com.sun.tools.doclets.formats.html.markup
+com.sun.tools.doclets.formats.html.resources
+com.sun.tools.doclets.internal.toolkit
+com.sun.tools.doclets.internal.toolkit.builders
+com.sun.tools.doclets.internal.toolkit.resources
+com.sun.tools.doclets.internal.toolkit.taglets
+com.sun.tools.doclets.internal.toolkit.util
+com.sun.tools.doclets.internal.toolkit.util.links
+com.sun.tools.doclint
+com.sun.tools.doclint.resources
+com.sun.tools.example.debug.expr
+com.sun.tools.example.debug.tty
+com.sun.tools.extcheck
+com.sun.tools.hat
+com.sun.tools.hat.internal.model
+com.sun.tools.hat.internal.oql
+com.sun.tools.hat.internal.parser
+com.sun.tools.hat.internal.server
+com.sun.tools.hat.internal.util
+com.sun.tools.internal.jxc
+com.sun.tools.internal.jxc.ap
+com.sun.tools.internal.jxc.api
+com.sun.tools.internal.jxc.api.impl.j2s
+com.sun.tools.internal.jxc.gen.config
+com.sun.tools.internal.jxc.model.nav
+com.sun.tools.internal.ws
+com.sun.tools.internal.ws.api
+com.sun.tools.internal.ws.api.wsdl
+com.sun.tools.internal.ws.processor
+com.sun.tools.internal.ws.processor.generator
+com.sun.tools.internal.ws.processor.model
+com.sun.tools.internal.ws.processor.model.exporter
+com.sun.tools.internal.ws.processor.model.java
+com.sun.tools.internal.ws.processor.model.jaxb
+com.sun.tools.internal.ws.processor.modeler
+com.sun.tools.internal.ws.processor.modeler.annotation
+com.sun.tools.internal.ws.processor.modeler.wsdl
+com.sun.tools.internal.ws.processor.util
+com.sun.tools.internal.ws.resources
+com.sun.tools.internal.ws.spi
+com.sun.tools.internal.ws.util
+com.sun.tools.internal.ws.util.xml
+com.sun.tools.internal.ws.wscompile
+com.sun.tools.internal.ws.wscompile.plugin.at_generated
+com.sun.tools.internal.ws.wsdl.document
+com.sun.tools.internal.ws.wsdl.document.http
+com.sun.tools.internal.ws.wsdl.document.jaxws
+com.sun.tools.internal.ws.wsdl.document.mime
+com.sun.tools.internal.ws.wsdl.document.schema
+com.sun.tools.internal.ws.wsdl.document.soap
+com.sun.tools.internal.ws.wsdl.framework
+com.sun.tools.internal.ws.wsdl.parser
+com.sun.tools.internal.xjc
+com.sun.tools.internal.xjc.addon.accessors
+com.sun.tools.internal.xjc.addon.at_generated
+com.sun.tools.internal.xjc.addon.code_injector
+com.sun.tools.internal.xjc.addon.episode
+com.sun.tools.internal.xjc.addon.locator
+com.sun.tools.internal.xjc.addon.sync
+com.sun.tools.internal.xjc.api
+com.sun.tools.internal.xjc.api.impl.s2j
+com.sun.tools.internal.xjc.api.util
+com.sun.tools.internal.xjc.generator.annotation.spec
+com.sun.tools.internal.xjc.generator.bean
+com.sun.tools.internal.xjc.generator.bean.field
+com.sun.tools.internal.xjc.generator.util
+com.sun.tools.internal.xjc.model
+com.sun.tools.internal.xjc.model.nav
+com.sun.tools.internal.xjc.outline
+com.sun.tools.internal.xjc.reader
+com.sun.tools.internal.xjc.reader.dtd
+com.sun.tools.internal.xjc.reader.dtd.bindinfo
+com.sun.tools.internal.xjc.reader.gbind
+com.sun.tools.internal.xjc.reader.internalizer
+com.sun.tools.internal.xjc.reader.relaxng
+com.sun.tools.internal.xjc.reader.xmlschema
+com.sun.tools.internal.xjc.reader.xmlschema.bindinfo
+com.sun.tools.internal.xjc.reader.xmlschema.ct
+com.sun.tools.internal.xjc.reader.xmlschema.parser
+com.sun.tools.internal.xjc.runtime
+com.sun.tools.internal.xjc.util
+com.sun.tools.internal.xjc.writer
+com.sun.tools.javac.api
+com.sun.tools.javac.code
+com.sun.tools.javac.comp
+com.sun.tools.javac.file
+com.sun.tools.javac.jvm
+com.sun.tools.javac.main
+com.sun.tools.javac.model
+com.sun.tools.javac.nio
+com.sun.tools.javac.parser
+com.sun.tools.javac.processing
+com.sun.tools.javac.resources
+com.sun.tools.javac.sym
+com.sun.tools.javac.tree
+com.sun.tools.javac.util
+com.sun.tools.javadoc.api
+com.sun.tools.javadoc.resources
+com.sun.tools.javah
+com.sun.tools.javah.resources
+com.sun.tools.javap
+com.sun.tools.javap.resources
+com.sun.tools.jdeps
+com.sun.tools.jdeps.resources
+com.sun.tools.jdi
+com.sun.tools.jdi.resources
+com.sun.tools.script.shell
+com.sun.tracing
+com.sun.tracing.dtrace
+com.sun.webkit
+com.sun.webkit.dom
+com.sun.webkit.event
+com.sun.webkit.graphics
+com.sun.webkit.network
+com.sun.webkit.network.about
+com.sun.webkit.network.data
+com.sun.webkit.perf
+com.sun.webkit.plugin
+com.sun.webkit.text
+com.sun.xml.internal.bind
+com.sun.xml.internal.bind.annotation
+com.sun.xml.internal.bind.api
+com.sun.xml.internal.bind.api.impl
+com.sun.xml.internal.bind.marshaller
+com.sun.xml.internal.bind.unmarshaller
+com.sun.xml.internal.bind.util
+com.sun.xml.internal.bind.v2
+com.sun.xml.internal.bind.v2.bytecode
+com.sun.xml.internal.bind.v2.model.annotation
+com.sun.xml.internal.bind.v2.model.core
+com.sun.xml.internal.bind.v2.model.impl
+com.sun.xml.internal.bind.v2.model.nav
+com.sun.xml.internal.bind.v2.model.runtime
+com.sun.xml.internal.bind.v2.model.util
+com.sun.xml.internal.bind.v2.runtime
+com.sun.xml.internal.bind.v2.runtime.output
+com.sun.xml.internal.bind.v2.runtime.property
+com.sun.xml.internal.bind.v2.runtime.reflect
+com.sun.xml.internal.bind.v2.runtime.reflect.opt
+com.sun.xml.internal.bind.v2.runtime.unmarshaller
+com.sun.xml.internal.bind.v2.schemagen
+com.sun.xml.internal.bind.v2.schemagen.episode
+com.sun.xml.internal.bind.v2.schemagen.xmlschema
+com.sun.xml.internal.bind.v2.util
+com.sun.xml.internal.dtdparser
+com.sun.xml.internal.fastinfoset
+com.sun.xml.internal.fastinfoset.algorithm
+com.sun.xml.internal.fastinfoset.alphabet
+com.sun.xml.internal.fastinfoset.dom
+com.sun.xml.internal.fastinfoset.org.apache.xerces.util
+com.sun.xml.internal.fastinfoset.sax
+com.sun.xml.internal.fastinfoset.stax
+com.sun.xml.internal.fastinfoset.stax.events
+com.sun.xml.internal.fastinfoset.stax.factory
+com.sun.xml.internal.fastinfoset.stax.util
+com.sun.xml.internal.fastinfoset.tools
+com.sun.xml.internal.fastinfoset.util
+com.sun.xml.internal.fastinfoset.vocab
+com.sun.xml.internal.messaging.saaj
+com.sun.xml.internal.messaging.saaj.client.p2p
+com.sun.xml.internal.messaging.saaj.packaging.mime
+com.sun.xml.internal.messaging.saaj.packaging.mime.internet
+com.sun.xml.internal.messaging.saaj.packaging.mime.util
+com.sun.xml.internal.messaging.saaj.soap
+com.sun.xml.internal.messaging.saaj.soap.dynamic
+com.sun.xml.internal.messaging.saaj.soap.impl
+com.sun.xml.internal.messaging.saaj.soap.name
+com.sun.xml.internal.messaging.saaj.soap.ver1_1
+com.sun.xml.internal.messaging.saaj.soap.ver1_2
+com.sun.xml.internal.messaging.saaj.util
+com.sun.xml.internal.messaging.saaj.util.transform
+com.sun.xml.internal.org.jvnet.fastinfoset
+com.sun.xml.internal.org.jvnet.fastinfoset.sax
+com.sun.xml.internal.org.jvnet.fastinfoset.sax.helpers
+com.sun.xml.internal.org.jvnet.fastinfoset.stax
+com.sun.xml.internal.org.jvnet.mimepull
+com.sun.xml.internal.org.jvnet.staxex
+com.sun.xml.internal.rngom.ast.builder
+com.sun.xml.internal.rngom.ast.om
+com.sun.xml.internal.rngom.ast.util
+com.sun.xml.internal.rngom.binary
+com.sun.xml.internal.rngom.binary.visitor
+com.sun.xml.internal.rngom.digested
+com.sun.xml.internal.rngom.dt
+com.sun.xml.internal.rngom.dt.builtin
+com.sun.xml.internal.rngom.nc
+com.sun.xml.internal.rngom.parse
+com.sun.xml.internal.rngom.parse.compact
+com.sun.xml.internal.rngom.parse.host
+com.sun.xml.internal.rngom.parse.xml
+com.sun.xml.internal.rngom.util
+com.sun.xml.internal.rngom.xml.sax
+com.sun.xml.internal.rngom.xml.util
+com.sun.xml.internal.stream
+com.sun.xml.internal.stream.buffer
+com.sun.xml.internal.stream.buffer.sax
+com.sun.xml.internal.stream.buffer.stax
+com.sun.xml.internal.stream.dtd
+com.sun.xml.internal.stream.dtd.nonvalidating
+com.sun.xml.internal.stream.events
+com.sun.xml.internal.stream.util
+com.sun.xml.internal.stream.writers
+com.sun.xml.internal.txw2
+com.sun.xml.internal.txw2.annotation
+com.sun.xml.internal.txw2.output
+com.sun.xml.internal.ws
+com.sun.xml.internal.ws.addressing
+com.sun.xml.internal.ws.addressing.model
+com.sun.xml.internal.ws.addressing.policy
+com.sun.xml.internal.ws.addressing.v200408
+com.sun.xml.internal.ws.api
+com.sun.xml.internal.ws.api.addressing
+com.sun.xml.internal.ws.api.client
+com.sun.xml.internal.ws.api.config.management
+com.sun.xml.internal.ws.api.config.management.policy
+com.sun.xml.internal.ws.api.databinding
+com.sun.xml.internal.ws.api.fastinfoset
+com.sun.xml.internal.ws.api.ha
+com.sun.xml.internal.ws.api.handler
+com.sun.xml.internal.ws.api.message
+com.sun.xml.internal.ws.api.message.saaj
+com.sun.xml.internal.ws.api.message.stream
+com.sun.xml.internal.ws.api.model
+com.sun.xml.internal.ws.api.model.soap
+com.sun.xml.internal.ws.api.model.wsdl
+com.sun.xml.internal.ws.api.model.wsdl.editable
+com.sun.xml.internal.ws.api.pipe
+com.sun.xml.internal.ws.api.pipe.helper
+com.sun.xml.internal.ws.api.policy
+com.sun.xml.internal.ws.api.policy.subject
+com.sun.xml.internal.ws.api.server
+com.sun.xml.internal.ws.api.streaming
+com.sun.xml.internal.ws.api.wsdl.parser
+com.sun.xml.internal.ws.api.wsdl.writer
+com.sun.xml.internal.ws.assembler
+com.sun.xml.internal.ws.assembler.dev
+com.sun.xml.internal.ws.assembler.jaxws
+com.sun.xml.internal.ws.binding
+com.sun.xml.internal.ws.client
+com.sun.xml.internal.ws.client.dispatch
+com.sun.xml.internal.ws.client.sei
+com.sun.xml.internal.ws.commons.xmlutil
+com.sun.xml.internal.ws.config.management.policy
+com.sun.xml.internal.ws.config.metro.dev
+com.sun.xml.internal.ws.config.metro.util
+com.sun.xml.internal.ws.db
+com.sun.xml.internal.ws.db.glassfish
+com.sun.xml.internal.ws.developer
+com.sun.xml.internal.ws.dump
+com.sun.xml.internal.ws.encoding
+com.sun.xml.internal.ws.encoding.fastinfoset
+com.sun.xml.internal.ws.encoding.policy
+com.sun.xml.internal.ws.encoding.soap
+com.sun.xml.internal.ws.encoding.soap.streaming
+com.sun.xml.internal.ws.encoding.xml
+com.sun.xml.internal.ws.fault
+com.sun.xml.internal.ws.handler
+com.sun.xml.internal.ws.message
+com.sun.xml.internal.ws.message.jaxb
+com.sun.xml.internal.ws.message.saaj
+com.sun.xml.internal.ws.message.source
+com.sun.xml.internal.ws.message.stream
+com.sun.xml.internal.ws.model
+com.sun.xml.internal.ws.model.soap
+com.sun.xml.internal.ws.model.wsdl
+com.sun.xml.internal.ws.org.objectweb.asm
+com.sun.xml.internal.ws.policy
+com.sun.xml.internal.ws.policy.jaxws
+com.sun.xml.internal.ws.policy.jaxws.spi
+com.sun.xml.internal.ws.policy.privateutil
+com.sun.xml.internal.ws.policy.sourcemodel
+com.sun.xml.internal.ws.policy.sourcemodel.attach
+com.sun.xml.internal.ws.policy.sourcemodel.wspolicy
+com.sun.xml.internal.ws.policy.spi
+com.sun.xml.internal.ws.policy.subject
+com.sun.xml.internal.ws.protocol.soap
+com.sun.xml.internal.ws.protocol.xml
+com.sun.xml.internal.ws.resources
+com.sun.xml.internal.ws.runtime.config
+com.sun.xml.internal.ws.server
+com.sun.xml.internal.ws.server.provider
+com.sun.xml.internal.ws.server.sei
+com.sun.xml.internal.ws.spi
+com.sun.xml.internal.ws.spi.db
+com.sun.xml.internal.ws.streaming
+com.sun.xml.internal.ws.transport
+com.sun.xml.internal.ws.transport.http
+com.sun.xml.internal.ws.transport.http.client
+com.sun.xml.internal.ws.transport.http.server
+com.sun.xml.internal.ws.util
+com.sun.xml.internal.ws.util.exception
+com.sun.xml.internal.ws.util.pipe
+com.sun.xml.internal.ws.util.xml
+com.sun.xml.internal.ws.wsdl
+com.sun.xml.internal.ws.wsdl.parser
+com.sun.xml.internal.ws.wsdl.writer
+com.sun.xml.internal.ws.wsdl.writer.document
+com.sun.xml.internal.ws.wsdl.writer.document.http
+com.sun.xml.internal.ws.wsdl.writer.document.soap
+com.sun.xml.internal.ws.wsdl.writer.document.soap12
+com.sun.xml.internal.ws.wsdl.writer.document.xsd
+com.sun.xml.internal.xsom
+com.sun.xml.internal.xsom.impl
+com.sun.xml.internal.xsom.impl.parser
+com.sun.xml.internal.xsom.impl.parser.state
+com.sun.xml.internal.xsom.impl.scd
+com.sun.xml.internal.xsom.impl.util
+com.sun.xml.internal.xsom.parser
+com.sun.xml.internal.xsom.util
+com.sun.xml.internal.xsom.visitor
+java.awt.dnd.peer
+java.awt.peer
+javafx.embed.swt
+jdk
+jdk.internal.cmm
+jdk.internal.dynalink
+jdk.internal.dynalink.beans
+jdk.internal.dynalink.linker
+jdk.internal.dynalink.support
+jdk.internal.instrumentation
+jdk.internal.org.objectweb.asm
+jdk.internal.org.objectweb.asm.commons
+jdk.internal.org.objectweb.asm.signature
+jdk.internal.org.objectweb.asm.tree
+jdk.internal.org.objectweb.asm.tree.analysis
+jdk.internal.org.objectweb.asm.util
+jdk.internal.org.xml.sax
+jdk.internal.org.xml.sax.helpers
+jdk.internal.util.xml
+jdk.internal.util.xml.impl
+jdk.jfr.events
+jdk.management.resource.internal
+jdk.management.resource.internal.inst
+jdk.nashorn.internal
+jdk.nashorn.internal.codegen
+jdk.nashorn.internal.codegen.types
+jdk.nashorn.internal.ir
+jdk.nashorn.internal.ir.annotations
+jdk.nashorn.internal.ir.debug
+jdk.nashorn.internal.ir.visitor
+jdk.nashorn.internal.lookup
+jdk.nashorn.internal.objects
+jdk.nashorn.internal.objects.annotations
+jdk.nashorn.internal.parser
+jdk.nashorn.internal.runtime
+jdk.nashorn.internal.runtime.arrays
+jdk.nashorn.internal.runtime.events
+jdk.nashorn.internal.runtime.linker
+jdk.nashorn.internal.runtime.logging
+jdk.nashorn.internal.runtime.options
+jdk.nashorn.internal.runtime.regexp
+jdk.nashorn.internal.runtime.regexp.joni
+jdk.nashorn.internal.runtime.regexp.joni.ast
+jdk.nashorn.internal.runtime.regexp.joni.constants
+jdk.nashorn.internal.runtime.regexp.joni.encoding
+jdk.nashorn.internal.runtime.regexp.joni.exception
+jdk.nashorn.internal.scripts
+jdk.nashorn.tools
+oracle.jrockit.jfr
+oracle.jrockit.jfr.events
+oracle.jrockit.jfr.jdkevents
+oracle.jrockit.jfr.jdkevents.throwabletransform
+oracle.jrockit.jfr.openmbean
+oracle.jrockit.jfr.parser
+oracle.jrockit.jfr.settings
+oracle.jrockit.jfr.tools
+org.jcp.xml.dsig.internal
+org.jcp.xml.dsig.internal.dom
+org.omg.stub.javax.management.remote.rmi
+org.relaxng.datatype
+org.relaxng.datatype.helpers
+sun.applet
+sun.applet.resources
+sun.audio
+sun.awt
+sun.awt.X11
+sun.awt.datatransfer
+sun.awt.dnd
+sun.awt.event
+sun.awt.geom
+sun.awt.im
+sun.awt.image
+sun.awt.image.codec
+sun.awt.motif
+sun.awt.resources
+sun.awt.shell
+sun.awt.util
+sun.awt.windows
+sun.corba
+sun.dc
+sun.dc.path
+sun.dc.pr
+sun.font
+sun.instrument
+sun.invoke
+sun.invoke.anon
+sun.invoke.empty
+sun.invoke.util
+sun.io
+sun.java2d
+sun.java2d.cmm
+sun.java2d.cmm.kcms
+sun.java2d.cmm.lcms
+sun.java2d.d3d
+sun.java2d.jules
+sun.java2d.loops
+sun.java2d.opengl
+sun.java2d.pipe
+sun.java2d.pipe.hw
+sun.java2d.pisces
+sun.java2d.windows
+sun.java2d.x11
+sun.java2d.xr
+sun.jvmstat.monitor
+sun.jvmstat.monitor.event
+sun.jvmstat.monitor.remote
+sun.jvmstat.perfdata.monitor
+sun.jvmstat.perfdata.monitor.protocol.file
+sun.jvmstat.perfdata.monitor.protocol.local
+sun.jvmstat.perfdata.monitor.protocol.rmi
+sun.jvmstat.perfdata.monitor.v1_0
+sun.jvmstat.perfdata.monitor.v2_0
+sun.launcher
+sun.launcher.resources
+sun.lwawt
+sun.lwawt.macosx
+sun.management
+sun.management.counter
+sun.management.counter.perf
+sun.management.jdp
+sun.management.jmxremote
+sun.management.resources
+sun.management.snmp
+sun.management.snmp.jvminstr
+sun.management.snmp.jvmmib
+sun.management.snmp.util
+sun.misc
+sun.misc.resources
+sun.net
+sun.net.dns
+sun.net.ftp
+sun.net.ftp.impl
+sun.net.httpserver
+sun.net.idn
+sun.net.sdp
+sun.net.smtp
+sun.net.spi
+sun.net.spi.nameservice
+sun.net.spi.nameservice.dns
+sun.net.util
+sun.net.www
+sun.net.www.content.audio
+sun.net.www.content.image
+sun.net.www.content.text
+sun.net.www.http
+sun.net.www.protocol.file
+sun.net.www.protocol.ftp
+sun.net.www.protocol.http
+sun.net.www.protocol.http.logging
+sun.net.www.protocol.http.ntlm
+sun.net.www.protocol.http.spnego
+sun.net.www.protocol.https
+sun.net.www.protocol.jar
+sun.net.www.protocol.mailto
+sun.net.www.protocol.netdoc
+sun.nio
+sun.nio.ch
+sun.nio.ch.sctp
+sun.nio.cs
+sun.nio.cs.ext
+sun.nio.fs
+sun.print
+sun.print.resources
+sun.reflect
+sun.reflect.annotation
+sun.reflect.generics.factory
+sun.reflect.generics.parser
+sun.reflect.generics.reflectiveObjects
+sun.reflect.generics.repository
+sun.reflect.generics.scope
+sun.reflect.generics.tree
+sun.reflect.generics.visitor
+sun.reflect.misc
+sun.rmi.log
+sun.rmi.registry
+sun.rmi.rmic
+sun.rmi.rmic.iiop
+sun.rmi.rmic.newrmic
+sun.rmi.rmic.newrmic.jrmp
+sun.rmi.runtime
+sun.rmi.server
+sun.rmi.transport
+sun.rmi.transport.proxy
+sun.rmi.transport.tcp
+sun.security.acl
+sun.security.action
+sun.security.ec
+sun.security.internal.interfaces
+sun.security.internal.spec
+sun.security.jca
+sun.security.jgss
+sun.security.jgss.krb5
+sun.security.jgss.spi
+sun.security.jgss.spnego
+sun.security.jgss.wrapper
+sun.security.krb5
+sun.security.krb5.internal
+sun.security.krb5.internal.ccache
+sun.security.krb5.internal.crypto
+sun.security.krb5.internal.crypto.dk
+sun.security.krb5.internal.ktab
+sun.security.krb5.internal.rcache
+sun.security.krb5.internal.tools
+sun.security.krb5.internal.util
+sun.security.mscapi
+sun.security.pkcs
+sun.security.pkcs10
+sun.security.pkcs11
+sun.security.pkcs11.wrapper
+sun.security.pkcs12
+sun.security.provider
+sun.security.provider.certpath
+sun.security.provider.certpath.ldap
+sun.security.provider.certpath.ssl
+sun.security.rsa
+sun.security.smartcardio
+sun.security.ssl
+sun.security.ssl.krb5
+sun.security.timestamp
+sun.security.tools
+sun.security.tools.jarsigner
+sun.security.tools.keytool
+sun.security.tools.policytool
+sun.security.util
+sun.security.validator
+sun.security.x509
+sun.swing
+sun.swing.icon
+sun.swing.plaf
+sun.swing.plaf.synth
+sun.swing.plaf.windows
+sun.swing.table
+sun.swing.text
+sun.swing.text.html
+sun.text
+sun.text.bidi
+sun.text.normalizer
+sun.text.resources
+sun.text.resources.en
+sun.tools.asm
+sun.tools.attach
+sun.tools.jar
+sun.tools.jar.resources
+sun.tools.java
+sun.tools.javac
+sun.tools.jcmd
+sun.tools.jconsole
+sun.tools.jconsole.inspector
+sun.tools.jinfo
+sun.tools.jmap
+sun.tools.jps
+sun.tools.jstack
+sun.tools.jstat
+sun.tools.jstatd
+sun.tools.native2ascii
+sun.tools.native2ascii.resources
+sun.tools.serialver
+sun.tools.tree
+sun.tools.util
+sun.tracing
+sun.tracing.dtrace
+sun.usagetracker
+sun.util
+sun.util.calendar
+sun.util.cldr
+sun.util.locale
+sun.util.locale.provider
+sun.util.logging
+sun.util.logging.resources
+sun.util.resources
+sun.util.resources.en
+sun.util.spi
+sun.util.xml
--- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties	Mon Jul 18 09:38:08 2016 -0700
@@ -28,7 +28,7 @@
 sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
 sun.tools.jar=Use java.util.jar or jar tool @since 1.2
 # Internal APIs removed in JDK 9
-com.apple.eawt=Use java.awt.desktop and JEP 272 @since 9
+com.apple.eawt=Use java.awt.Desktop and JEP 272 @since 9
 com.apple.concurrent=Removed. See https://bugs.openjdk.java.net/browse/JDK-8148187
 com.sun.image.codec.jpeg=Use javax.imageio @since 1.4
 sun.awt.image.codec=Use javax.imageio @since 1.4
--- a/langtools/test/ProblemList.txt	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/ProblemList.txt	Mon Jul 18 09:38:08 2016 -0700
@@ -27,9 +27,6 @@
 #
 # javadoc
 
-com/sun/javadoc/testTypeAnnotations/TestTypeAnnotations.java                    8006735    generic-all    output type annotations in javadoc
-com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java                            8013406    generic-all    Test cases fail in javadoc test TestSmoke.java
-
 jdk/javadoc/tool/6176978/T6176978.java                                          8152049    generic-all    no longer applicable, should delete
 jdk/javadoc/tool/InlineTagsWithBraces.java                                      8152050    generic-all    API, re-evaluate @bold, @maybe causes doclint to throw up.
 jdk/javadoc/tool/LangVers.java                                                  8152051    generic-all    API, re-evaluate, unsure of this test.
--- a/langtools/test/com/sun/javadoc/testTypeAnnotations/TestTypeAnnotations.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/com/sun/javadoc/testTypeAnnotations/TestTypeAnnotations.java	Mon Jul 18 09:38:08 2016 -0700
@@ -28,7 +28,6 @@
  * @author   Bhavesh Patel
  * @library  ../lib
  * @modules jdk.javadoc
- * @ignore 8006735 output type annotations in javadoc
  * @build    JavadocTester
  * @run main TestTypeAnnotations
  */
--- a/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/com/sun/javadoc/typeAnnotations/smoke/TestSmoke.java	Mon Jul 18 09:38:08 2016 -0700
@@ -29,7 +29,6 @@
  * @author   Mahmood Ali <mali>
  * @library  ../../lib
  * @modules jdk.javadoc
- * @ignore
  * @build    JavadocTester
  * @run main TestSmoke
  */
--- a/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testModules/TestModules.java	Mon Jul 18 09:38:08 2016 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8154119 8154262 8156077 8157987
+ * @bug 8154119 8154262 8156077 8157987 8154261
  * @summary Test modules support in javadoc.
  * @author bpatel
  * @library ../lib
@@ -110,6 +110,17 @@
         testModuleTags();
     }
 
+    @Test
+    void test7() {
+        javadoc("-d", "out-moduleSummary", "-use",
+                "-modulesourcepath", testSrc,
+                "-addmods", "module1,module2",
+                "testpkgmdl1", "testpkgmdl2", "testpkg2mdl2");
+        checkExit(Exit.OK);
+        testModuleSummary();
+        testNegatedModuleSummary();
+    }
+
    @Test
     void test8() {
         javadoc("-d", "out-html5-nomodule", "-html5", "-use",
@@ -139,12 +150,16 @@
                 "<div class=\"contentContainer\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
-                + "<table class=\"overviewSummary\" summary=\"Package Summary table, listing packages, and an explanation\">");
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<!-- ============ MODULES SUMMARY =========== -->");
         checkOutput("module2-summary.html", found,
                 "<div class=\"contentContainer\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
-                + "<table class=\"overviewSummary\" summary=\"Package Summary table, listing packages, and an explanation\">");
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<!-- ============ MODULES SUMMARY =========== -->");
     }
 
     void testHtml5Description(boolean found) {
@@ -171,12 +186,16 @@
                 "<div class=\"contentContainer\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
-                + "<table class=\"overviewSummary\">");
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<!-- ============ MODULES SUMMARY =========== -->");
         checkOutput("module2-summary.html", found,
                 "<div class=\"contentContainer\">\n"
                 + "<ul class=\"blockList\">\n"
                 + "<li class=\"blockList\">\n"
-                + "<table class=\"overviewSummary\">");
+                + "<ul class=\"blockList\">\n"
+                + "<li class=\"blockList\">\n"
+                + "<!-- ============ MODULES SUMMARY =========== -->");
     }
 
     void testModuleLink() {
@@ -313,4 +332,114 @@
                 + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
                 + "</tr>");
     }
+
+    void testModuleSummary() {
+        checkOutput("module1-summary.html", true,
+                "<ul class=\"subNavList\">\n"
+                + "<li>Module:&nbsp;</li>\n"
+                + "<li><a href=\"#module.description\">Description</a>&nbsp;|&nbsp;<a "
+                + "href=\"#modules.summary\">Modules</a>&nbsp;|&nbsp;<a href=\"#packages.summary\">"
+                + "Packages</a>&nbsp;|&nbsp;Services</li>\n"
+                + "</ul>");
+        checkOutput("module1-summary.html", true,
+                "<!-- ============ MODULES SUMMARY =========== -->\n"
+                + "<a name=\"modules.summary\">\n"
+                + "<!--   -->\n"
+                + "</a>");
+        checkOutput("module1-summary.html", true,
+                "<tr class=\"altColor\">\n"
+                + "<td class=\"colFirst\"><a href=\"testpkgmdl1/package-summary.html\">testpkgmdl1</a></td>\n"
+                + "<td class=\"colSecond\">All Modules</td>\n"
+                + "<td class=\"colLast\">&nbsp;</td>\n"
+                + "</tr>");
+        checkOutput("module1-summary.html", true,
+                "<!-- ============ PACKAGES SUMMARY =========== -->\n"
+                + "<a name=\"packages.summary\">\n"
+                + "<!--   -->\n"
+                + "</a>");
+        checkOutput("module1-summary.html", true,
+                "<tr class=\"rowColor\">\n"
+                + "<td class=\"colFirst\"><a href=\"module2-summary.html\">module2</a></td>\n"
+                + "<td class=\"colLast\">\n"
+                + "<div class=\"block\">This is a test description for the module2 module.</div>\n"
+                + "</td>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<li><a href=\"#module.description\">Description</a>&nbsp;|&nbsp;<a "
+                + "href=\"#modules.summary\">Modules</a>&nbsp;|&nbsp;<a href=\"#packages.summary\">"
+                + "Packages</a>&nbsp;|&nbsp;<a href=\"#services.summary\">Services</a></li>");
+        checkOutput("module2-summary.html", true,
+                "<!-- ============ MODULES SUMMARY =========== -->\n"
+                + "<a name=\"modules.summary\">\n"
+                + "<!--   -->\n"
+                + "</a>");
+        checkOutput("module2-summary.html", true,
+                "<tr class=\"rowColor\">\n"
+                + "<td class=\"colFirst\">testpkg2mdl2</td>\n"
+                + "<td class=\"colSecond\">module1</td>\n"
+                + "<td class=\"colLast\">&nbsp;</td>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<!-- ============ PACKAGES SUMMARY =========== -->\n"
+                + "<a name=\"packages.summary\">\n"
+                + "<!--   -->\n"
+                + "</a>");
+        checkOutput("module2-summary.html", true,
+                "<tr class=\"altColor\">\n"
+                + "<td class=\"colFirst\"><a href=\"java.base-summary.html\">java.base</a></td>\n"
+                + "<td class=\"colLast\">&nbsp;</td>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<!-- ============ SERVICES SUMMARY =========== -->\n"
+                + "<a name=\"services.summary\">\n"
+                + "<!--   -->\n"
+                + "</a>");
+        checkOutput("module2-summary.html", true,
+                "<tr class=\"altColor\">\n"
+                + "<td class=\"colFirst\"><a href=\"testpkgmdl2/TestClassInModule2.html\" "
+                + "title=\"class in testpkgmdl2\">TestClassInModule2</a></td>\n"
+                + "<td class=\"colLast\">&nbsp;</td>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<tr class=\"altColor\">\n"
+                + "<td class=\"colFirst\">testpkg2mdl2.TestInterfaceInModule2<br>(<span "
+                + "class=\"implementationLabel\">Implementation:</span>&nbsp;<a "
+                + "href=\"testpkgmdl2/TestClassInModule2.html\" title=\"class in testpkgmdl2\">"
+                + "TestClassInModule2</a>)</td>\n"
+                + "<td class=\"colLast\">&nbsp;</td>\n"
+                + "</tr");
+        checkOutput("module2-summary.html", true,
+                "<caption><span>Exported Packages</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">Package</th>\n"
+                + "<th scope=\"col\">Module</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<caption><span>Requires</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">Module</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<caption><span>Uses</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">Type</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
+                + "</tr>");
+        checkOutput("module2-summary.html", true,
+                "<caption><span>Provides</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
+                + "<tr>\n"
+                + "<th class=\"colFirst\" scope=\"col\">Type</th>\n"
+                + "<th class=\"colLast\" scope=\"col\">Description</th>\n"
+                + "</tr>");
+    }
+
+    void testNegatedModuleSummary() {
+        checkOutput("module1-summary.html", false,
+                "<!-- ============ SERVICES SUMMARY =========== -->\n"
+                + "<a name=\"services.summary\">\n"
+                + "<!--   -->\n"
+                + "</a>");
+    }
 }
--- a/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/module-info.java	Mon Jul 18 09:38:08 2016 -0700
@@ -28,4 +28,10 @@
   */
 module module2 {
     exports testpkgmdl2;
+
+    exports testpkg2mdl2 to module1;
+
+    uses testpkgmdl2.TestClassInModule2;
+
+    provides testpkg2mdl2.TestInterfaceInModule2 with testpkgmdl2.TestClassInModule2;
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkg2mdl2/TestInterfaceInModule2.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package testpkg2mdl2;
+
+public interface TestInterfaceInModule2 {
+    void testMethod();
+}
--- a/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testModules/module2/testpkgmdl2/TestClassInModule2.java	Mon Jul 18 09:38:08 2016 -0700
@@ -24,5 +24,8 @@
  */
 package testpkgmdl2;
 
-public class TestClassInModule2 {
+import testpkg2mdl2.TestInterfaceInModule2;
+
+public class TestClassInModule2 implements TestInterfaceInModule2 {
+    void testMethod() {}
 }
--- a/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/jdk/javadoc/doclet/testStylesheet/TestStylesheet.java	Mon Jul 18 09:38:08 2016 -0700
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461
+ * @bug      4494033 7028815 7052425 8007338 8023608 8008164 8016549 8072461 8154261
  * @summary  Run tests on doclet stylesheet.
  * @author   jamieh
  * @library  ../lib
@@ -81,7 +81,8 @@
                 + "    list-style-type:disc;\n"
                 + "}",
                 ".overviewSummary caption, .memberSummary caption, .typeSummary caption,\n"
-                + ".useSummary caption, .constantsSummary caption, .deprecatedSummary caption {\n"
+                + ".useSummary caption, .constantsSummary caption, .deprecatedSummary caption,\n"
+                + ".requiresSummary caption, .packagesSummary caption, .providesSummary caption, .usesSummary caption {\n"
                 + "    position:relative;\n"
                 + "    text-align:left;\n"
                 + "    background-repeat:no-repeat;\n"
@@ -96,7 +97,9 @@
                 + "    white-space:pre;\n"
                 + "}",
                 ".overviewSummary caption span, .memberSummary caption span, .typeSummary caption span,\n"
-                + ".useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span {\n"
+                + ".useSummary caption span, .constantsSummary caption span, .deprecatedSummary caption span,\n"
+                + ".requiresSummary caption span, .packagesSummary caption span, .providesSummary caption span,\n"
+                + ".usesSummary caption span {\n"
                 + "    white-space:nowrap;\n"
                 + "    padding-top:5px;\n"
                 + "    padding-left:12px;\n"
@@ -132,6 +135,9 @@
                 + "}",
                 // Test the formatting styles for proper content display in use and constant values pages.
                 ".overviewSummary td.colFirst, .overviewSummary th.colFirst,\n"
+                + ".requiresSummary td.colFirst, .requiresSummary th.colFirst,\n"
+                + ".packagesSummary td.colFirst, .packagesSummary td.colSecond, .packagesSummary th.colFirst, .packagesSummary th,\n"
+                + ".usesSummary td.colFirst, .usesSummary th.colFirst,\n"
                 + ".useSummary td.colFirst, .useSummary th.colFirst,\n"
                 + ".overviewSummary td.colOne, .overviewSummary th.colOne,\n"
                 + ".memberSummary td.colFirst, .memberSummary th.colFirst,\n"
@@ -141,7 +147,8 @@
                 + "    vertical-align:top;\n"
                 + "}",
                 ".overviewSummary td, .memberSummary td, .typeSummary td,\n"
-                + ".useSummary td, .constantsSummary td, .deprecatedSummary td {\n"
+                + ".useSummary td, .constantsSummary td, .deprecatedSummary td,\n"
+                + ".requiresSummary td, .packagesSummary td, .providesSummary td, .usesSummary td {\n"
                 + "    text-align:left;\n"
                 + "    padding:0px 0px 12px 10px;\n"
                 + "}",
--- a/langtools/test/jdk/jshell/KullaCompletenessStressTest.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/jdk/jshell/KullaCompletenessStressTest.java	Mon Jul 18 09:38:08 2016 -0700
@@ -37,10 +37,6 @@
 public class KullaCompletenessStressTest extends CompletenessStressTest {
     @Override
     public File[] getDirectoriesToTest() {
-        return new File[]{ getKullaSourceDirectory() };
-    }
-
-    public File getKullaSourceDirectory() {
         String src = System.getProperty("test.src");
         File file;
         if (src == null) {
@@ -48,6 +44,11 @@
         } else {
             file = new File(src, "../../../src/jdk.jshell/share/classes");
         }
-        return file;
+        if (!file.exists()) {
+            System.out.println("jdk.jshell sources are not exist. Test has been skipped. Path: " + file.toString());
+            return new File[]{};
+        }else {
+            return new File[]{file};
+        }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/AnonymousClass/AnonymousClassFlags.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8161013
+ * @summary Verify that anonymous class binaries have the correct flags set
+ * @modules jdk.jdeps/com.sun.tools.classfile
+ * @run main AnonymousClassFlags
+ */
+
+import java.util.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import com.sun.tools.classfile.*;
+import static com.sun.tools.classfile.AccessFlags.*;
+
+public class AnonymousClassFlags {
+    public static void main(String[] args) throws Exception {
+        new AnonymousClassFlags().test(System.getProperty("test.classes", "."));
+    }
+
+    /** Maps names of anonymous classes to their expected inner_class_access_flags */
+    private static Map<String, Integer> anonClasses = new LinkedHashMap<>();
+
+    // ******* TEST CASES ********
+
+    static Object o1 = new Object() {
+        { anonClasses.put(getClass().getName(), 0); }
+    };
+
+    static void staticMethod() {
+        Object o2 = new Object() {
+            { anonClasses.put(getClass().getName(), 0); }
+        };
+    }
+
+    static {
+        staticMethod();
+
+        Object o3 = new Object() {
+            { anonClasses.put(getClass().getName(), 0); }
+        };
+    }
+
+    Object o4 = new Object() {
+        { anonClasses.put(getClass().getName(), 0); }
+    };
+
+    void instanceMethod() {
+        Object o5 = new Object() {
+            { anonClasses.put(getClass().getName(), 0); }
+        };
+    }
+
+    {
+        instanceMethod();
+
+        Object o6 = new Object() {
+            { anonClasses.put(getClass().getName(), 0); }
+        };
+    }
+
+    // ******* TEST IMPLEMENTATION ********
+
+    void test(String classesDir) throws Exception {
+        staticMethod();
+        instanceMethod();
+
+        Path outerFile = Paths.get(classesDir, getClass().getName() + ".class");
+        ClassFile outerClass = ClassFile.read(outerFile);
+        for (Map.Entry<String,Integer> entry : anonClasses.entrySet()) {
+            Path innerFile = Paths.get(classesDir, entry.getKey() + ".class");
+            ClassFile innerClass = ClassFile.read(innerFile);
+            String name = entry.getKey();
+            int expected = entry.getValue();
+            assertInnerFlags(outerClass, name, expected);
+            assertClassFlags(innerClass, name, expected);
+            assertInnerFlags(innerClass, name, expected);
+        }
+    }
+
+    static void assertClassFlags(ClassFile classFile, String name, int expected) {
+        int mask = ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT |
+                   ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM;
+        int classExpected = (expected & mask) | ACC_SUPER;
+        int classActual = classFile.access_flags.flags;
+        if (classActual != classExpected) {
+            throw new AssertionError("Incorrect access_flags for class " + name +
+                                     ": expected=" + classExpected + ", actual=" + classActual);
+        }
+
+    }
+
+    static void assertInnerFlags(ClassFile classFile, String name, int expected) throws ConstantPoolException {
+        int innerActual = lookupInnerFlags(classFile, name).flags;
+        if (innerActual != expected) {
+            throw new AssertionError("Incorrect inner_class_access_flags for class " + name +
+                                     " in class " + classFile.getName() +
+                                     ": expected=" + expected + ", actual=" + innerActual);
+        }
+    }
+
+    private static AccessFlags lookupInnerFlags(ClassFile classFile, String innerName) throws ConstantPoolException {
+        InnerClasses_attribute inners = (InnerClasses_attribute) classFile.getAttribute("InnerClasses");
+        if (inners == null) {
+            throw new AssertionError("InnerClasses attribute missing in class " + classFile.getName());
+        }
+        for (InnerClasses_attribute.Info info : inners.classes) {
+            String entryName = info.getInnerClassInfo(classFile.constant_pool).getName();
+            if (innerName.equals(entryName)) {
+                return info.inner_class_access_flags;
+            }
+        }
+        throw new AssertionError("No InnerClasses entry in class " + classFile.getName() + " for class " + innerName);
+    }
+
+}
--- a/langtools/test/tools/javac/cast/6219964/T6219964.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/tools/javac/cast/6219964/T6219964.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,8 +1,8 @@
 /*
  * @test    /nodynamiccopyright/
- * @bug     6219964
- * @summary Compiler allows illegal cast of anonymous inner class
- * @compile/fail/ref=T6219964.out -XDrawDiagnostics  T6219964.java
+ * @bug     6219964 8161013
+ * @summary Anonymous class types are not final
+ * @compile T6219964.java
  */
 
 public class T6219964 {
--- a/langtools/test/tools/javac/cast/6219964/T6219964.out	Fri Jul 15 09:05:36 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,2 +0,0 @@
-T6219964.java:13:27: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: compiler.misc.anonymous.class: java.lang.Object, T6219964.I)
-1 error
--- a/langtools/test/tools/jdeps/jdkinternals/RemovedJDKInternals.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/tools/jdeps/jdkinternals/RemovedJDKInternals.java	Mon Jul 18 09:38:08 2016 -0700
@@ -71,7 +71,7 @@
         assertTrue(CompilerUtils.compile(codecSrc, codecDest));
 
         // patch jdk.unsupported and set -cp to codec types
-        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src"),
+        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "p"),
                                          CLASSES_DIR,
                                          "-Xpatch:jdk.unsupported=" + patchDir,
                                          "-cp", codecDest.toString()));
--- a/langtools/test/tools/jdeps/jdkinternals/ShowReplacement.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/langtools/test/tools/jdeps/jdkinternals/ShowReplacement.java	Mon Jul 18 09:38:08 2016 -0700
@@ -59,14 +59,17 @@
     public void compileAll() throws Exception {
         CompilerUtils.cleanDir(CLASSES_DIR);
 
-        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "p"),
+        Path tmp = Paths.get("tmp");
+        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "apple"), tmp));
+        assertTrue(CompilerUtils.compile(Paths.get(TEST_SRC, "src", "q"),
                                          CLASSES_DIR,
+                                         "-cp", tmp.toString(),
                                          "-XaddExports:java.base/sun.security.util=ALL-UNNAMED"));
     }
 
     @Test
     public void withReplacement() {
-        Path file = Paths.get("p", "WithRepl.class");
+        Path file = Paths.get("q", "WithRepl.class");
         String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.resolve(file).toString());
         int i = 0;
         while (!output[i].contains("Suggested Replacement")) {
@@ -90,9 +93,29 @@
         }
     }
 
+    /*
+     * A JDK internal class has been removed while its package still exists.
+     */
     @Test
     public void noReplacement() {
-        Path file = Paths.get("p", "NoRepl.class");
+        Path file = Paths.get("q", "NoRepl.class");
+        String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.resolve(file).toString());
+        int i = 0;
+        // expect no replacement
+        while (i < output.length && !output[i].contains("Suggested Replacement")) {
+            i++;
+        }
+
+        // no replacement
+        assertEquals(output.length-i, 0);
+    }
+
+    /*
+     * A JDK internal package has been removed.
+     */
+    @Test
+    public void removedPackage() {
+        Path file = Paths.get("q", "RemovedPackage.class");
         String[] output = JdepsUtil.jdeps("-jdkinternals", CLASSES_DIR.resolve(file).toString());
         int i = 0;
         // expect no replacement
--- a/langtools/test/tools/jdeps/jdkinternals/p/NoRepl.java	Fri Jul 15 09:05:36 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package p;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import sun.security.util.DerEncoder;
-
-public class NoRepl implements DerEncoder {
-    public void derEncode(OutputStream out) throws IOException {
-        throw new IOException();
-    }
-}
--- a/langtools/test/tools/jdeps/jdkinternals/p/WithRepl.java	Fri Jul 15 09:05:36 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package p;
-
-import sun.security.util.HostnameChecker;
-
-public class WithRepl {
-   public static void main(String[] argv) throws Exception {
-        HostnameChecker hc = HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP);
-   }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/jdkinternals/src/apple/applescript/AppleScriptEngine.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+
+package apple.applescript;
+
+import javax.script.ScriptEngine;
+
+public interface AppleScriptEngine extends ScriptEngine {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/jdkinternals/src/q/NoRepl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package q;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import sun.security.util.DerEncoder;
+
+public class NoRepl implements DerEncoder {
+    public void derEncode(OutputStream out) throws IOException {
+        throw new IOException();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/jdkinternals/src/q/RemovedPackage.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package q;
+
+import apple.applescript.AppleScriptEngine;
+
+public class RemovedPackage {
+    AppleScriptEngine scriptEngine;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/jdeps/jdkinternals/src/q/WithRepl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package q;
+
+import sun.security.util.HostnameChecker;
+
+public class WithRepl {
+   public static void main(String[] argv) throws Exception {
+        HostnameChecker hc = HostnameChecker.getInstance(HostnameChecker.TYPE_LDAP);
+   }
+}
--- a/make/CompileJavaModules.gmk	Fri Jul 15 09:05:36 2016 -0700
+++ b/make/CompileJavaModules.gmk	Mon Jul 18 09:38:08 2016 -0700
@@ -409,6 +409,8 @@
 
 ################################################################################
 
+jdk.jdeps_COPY := .txt
+
 jdk.jdeps_CLEAN_FILES := $(wildcard \
     $(JDK_TOPDIR)/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/*.properties \
     $(JDK_TOPDIR)/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/*.properties)
--- a/make/Javadoc.gmk	Fri Jul 15 09:05:36 2016 -0700
+++ b/make/Javadoc.gmk	Mon Jul 18 09:38:08 2016 -0700
@@ -424,7 +424,7 @@
 	@($(call COMMON_JAVADOCFLAGS) ; \
           $(call COMMON_JAVADOCTAGS) ; \
           $(call OptionOnly,-Xdoclint:reference) ; \
-          $(call OptionOnly,-Xdoclint/package:-org.omg.*) ; \
+          $(call OptionOnly,-Xdoclint/package:-org.omg.*$(COMMA)jdk.internal.logging.*) ; \
           $(call OptionPair,-system,none) ; \
 	  $(call OptionPair,-modulesourcepath,$(RELEASEDOCS_MODULESOURCEPATH)) ; \
 	  $(call OptionPair,-addmods,$(COREAPI_MODULES)) ; \
--- a/make/common/MakeBase.gmk	Fri Jul 15 09:05:36 2016 -0700
+++ b/make/common/MakeBase.gmk	Mon Jul 18 09:38:08 2016 -0700
@@ -801,15 +801,20 @@
 # of the build in case of failure. The  command line itself is stored in a file,
 # and also logged to stdout if the LOG=cmdlines option has been given.
 #
+# NOTE: If the command redirects stdout, the caller needs to wrap it in a
+# subshell (by adding parentheses around it), otherwise the redirect to the
+# subshell tee process will create a race condition where the target file may
+# not be fully written when the make recipe is done.
+#
 # Param 1 - The path to base the name of the log file / command line file on
 # Param 2 - The command to run
 ExecuteWithLog = \
   $(call LogCmdlines, Exececuting: [$(strip $2)]) \
   $(call WriteFile, $2, $(strip $1).cmdline) \
-  ( ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \
+  ( $(strip $2) > >($(TEE) $(strip $1).log) 2> >($(TEE) $(strip $1).log >&2) || \
       ( exitcode=$(DOLLAR)? && \
       $(CP) $(strip $1).log $(MAKESUPPORT_OUTPUTDIR)/failure-logs/$(subst /,_,$(patsubst $(BUILD_OUTPUT)/%,%,$(strip $1))).log && \
-      exit $(DOLLAR)exitcode ) ) && wait )
+      exit $(DOLLAR)exitcode ) )
 
 ################################################################################
 # Find lib dir for module
--- a/make/common/Modules.gmk	Fri Jul 15 09:05:36 2016 -0700
+++ b/make/common/Modules.gmk	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 #
 # This code is free software; you can redistribute it and/or modify it
@@ -71,7 +71,6 @@
 
 # to be deprivileged
 BOOT_MODULES += \
-    java.smartcardio \
     jdk.naming.rmi \
     #
 
@@ -104,6 +103,7 @@
 PLATFORM_MODULES += \
     java.compiler \
     java.scripting \
+    java.smartcardio \
     java.sql \
     java.sql.rowset \
     jdk.accessibility \
--- a/nashorn/.hgtags	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/.hgtags	Mon Jul 18 09:38:08 2016 -0700
@@ -360,3 +360,4 @@
 5d68f5155dded7efec7d5aca5d631caa7ee1042b jdk-9+124
 a32d419d73fe881a935b567c57dab9bfe3ed5f92 jdk-9+125
 ee90c69a18409533df8f7b602044bf966a28381a jdk-9+126
+ff07be6106fa56b72c163244f45a3ecb4c995564 jdk-9+127
--- a/nashorn/make/project.properties	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/make/project.properties	Mon Jul 18 09:38:08 2016 -0700
@@ -35,7 +35,9 @@
 javac.source=1.9
 javac.target=1.9
 
-javadoc.option=-tag "implSpec:a:Implementation Requirements:"
+javadoc.option=\
+    -tag "implSpec:a:Implementation Requirements:"\
+    -tag "implNote:a:Implementation Note:"
 
 # nashorn version information
 nashorn.version=0.1
--- a/nashorn/samples/prettyprinter.js	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/samples/prettyprinter.js	Mon Jul 18 09:38:08 2016 -0700
@@ -209,7 +209,7 @@
         }
         print("function ");
         if (func.name) {
-            print(func.name);
+            print(func.name.name);
         }
         printFunctionBody(func, extra, end);
         if (funcDecl) {
@@ -608,7 +608,7 @@
 
          visitVariable: function(node, extra) {
              indent();
-             print("var " + node.name);
+             print("var " + node.binding.name);
              var init = node.initializer;
              if (init) {
                  print(" = ");
--- a/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/NashornCompleter.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/NashornCompleter.java	Mon Jul 18 09:38:08 2016 -0700
@@ -439,6 +439,10 @@
             args.add("-strict");
         }
 
+        if (env._es6) {
+            args.add("--language=es6");
+        }
+
         return Parser.create(args.toArray(new String[0]));
     }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CatchTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CatchTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -38,11 +38,11 @@
  */
 public interface CatchTree extends Tree {
     /**
-     * Returns the catch parameter identifier of the exception caught.
+     * Returns the catch parameter identifier or parameter binding pattern of the exception caught.
      *
-     * @return the catch parameter identifier
+     * @return the catch parameter identifier or parameter binding pattern
      */
-    IdentifierTree getParameter();
+    ExpressionTree getParameter();
 
     /**
      * Returns the code block of this catch block.
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CatchTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CatchTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -28,12 +28,12 @@
 import jdk.nashorn.internal.ir.CatchNode;
 
 final class CatchTreeImpl extends TreeImpl implements CatchTree {
-    private final IdentifierTree param;
+    private final ExpressionTree param;
     private final BlockTree block;
     private final ExpressionTree condition;
 
     CatchTreeImpl(final CatchNode node,
-            final IdentifierTree param,
+            final ExpressionTree param,
             final BlockTree block,
             final ExpressionTree condition) {
         super(node);
@@ -48,7 +48,7 @@
     }
 
     @Override
-    public IdentifierTree getParameter() {
+    public ExpressionTree getParameter() {
         return param;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ClassDeclarationTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A tree node that represents a <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions">class declaration</a>.
+ *
+ * @since 9
+ */
+public interface ClassDeclarationTree extends StatementTree {
+
+    /**
+     * Class identifier.
+     *
+     * @return the class identifier
+     */
+    IdentifierTree getName();
+
+    /**
+     * The expression of the {@code extends} clause. Optional.
+     *
+     * @return the class heritage
+     */
+    ExpressionTree getClassHeritage();
+
+    /**
+     * Get the constructor method definition.
+     *
+     * @return the constructor
+     */
+    PropertyTree getConstructor();
+
+    /**
+     * Get other property definitions except for the constructor.
+     *
+     * @return the class elements
+     */
+    List<? extends PropertyTree> getClassElements();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ClassDeclarationTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+import jdk.nashorn.internal.ir.VarNode;
+
+final class ClassDeclarationTreeImpl extends StatementTreeImpl implements ClassDeclarationTree {
+
+    private final IdentifierTree name;
+    private final ExpressionTree classHeritage;
+    private final PropertyTree constructor;
+    private final List<? extends PropertyTree> classElements;
+
+    ClassDeclarationTreeImpl(final VarNode node, final IdentifierTree name,
+            final ExpressionTree classHeritage, final PropertyTree constructor,
+            final List<? extends PropertyTree> classElements) {
+        super(node);
+        this.name = name;
+        this.classHeritage = classHeritage;
+        this.constructor = constructor;
+        this.classElements = classElements;
+    }
+
+    @Override
+    public Tree.Kind getKind() {
+        return Tree.Kind.CLASS;
+    }
+
+    @Override
+    public IdentifierTree getName() {
+        return name;
+    }
+
+    @Override
+    public ExpressionTree getClassHeritage() {
+        return classHeritage;
+    }
+
+    @Override
+    public PropertyTree getConstructor() {
+        return constructor;
+    }
+
+    @Override
+    public List<? extends PropertyTree> getClassElements() {
+        return classElements;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitClassDeclaration(this, data);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ClassExpressionTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A tree node that represents a <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-class-definitions">class expression</a>.
+ *
+ * @since 9
+ */
+public interface ClassExpressionTree extends ExpressionTree {
+    /**
+     * Class identifier. Optional.
+     *
+     * @return the class identifier
+     */
+    IdentifierTree getName();
+
+    /**
+     * The expression of the {@code extends} clause. Optional.
+     *
+     * @return the class heritage
+     */
+    ExpressionTree getClassHeritage();
+
+    /**
+     * Get the constructor method definition.
+     *
+     * @return the constructor
+     */
+    PropertyTree getConstructor();
+
+    /**
+     * Get other property definitions except for the constructor.
+     *
+     * @return the class elements
+     */
+    List<? extends PropertyTree> getClassElements();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ClassExpressionTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+import jdk.nashorn.internal.ir.ClassNode;
+
+final class ClassExpressionTreeImpl extends ExpressionTreeImpl implements ClassExpressionTree {
+
+    private final IdentifierTree name;
+    private final ExpressionTree classHeritage;
+    private final PropertyTree constructor;
+    private final List<? extends PropertyTree> classElements;
+
+    ClassExpressionTreeImpl(final ClassNode cn, final IdentifierTree name,
+            final ExpressionTree classHeritage, final PropertyTree constructor,
+            final List<? extends PropertyTree> classElements) {
+        super(cn);
+        this.name = name;
+        this.classHeritage = classHeritage;
+        this.constructor = constructor;
+        this.classElements = classElements;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.CLASS_EXPRESSION;
+    }
+
+    @Override
+    public IdentifierTree getName() {
+        return name;
+    }
+
+    @Override
+    public ExpressionTree getClassHeritage() {
+        return classHeritage;
+    }
+
+    @Override
+    public PropertyTree getConstructor() {
+        return constructor;
+    }
+
+    @Override
+    public List<? extends PropertyTree> getClassElements() {
+        return classElements;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitClassExpression(this, data);
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompilationUnitTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompilationUnitTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -62,4 +62,12 @@
      * @return the line map for this compilation unit
      */
     LineMap getLineMap();
+
+    /**
+     * Return the {@link ModuleTree} associated with this compilation unit. This is null,
+     * if there is no module information from this compilation unit.
+     *
+     * @return the Module info or null
+     */
+    ModuleTree getModule();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompilationUnitTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/CompilationUnitTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -32,13 +32,18 @@
     implements CompilationUnitTree {
     private final FunctionNode funcNode;
     private final List<? extends Tree> elements;
+    private final ModuleTree module;
 
     CompilationUnitTreeImpl(final FunctionNode node,
-            final List<? extends Tree> elements) {
+            final List<? extends Tree> elements,
+            final ModuleTree module) {
         super(node);
         this.funcNode = node;
-        assert funcNode.getKind() == FunctionNode.Kind.SCRIPT : "script function expected";
+        assert funcNode.getKind() == FunctionNode.Kind.SCRIPT ||
+                funcNode.getKind() == FunctionNode.Kind.MODULE :
+                "script or module function expected";
         this.elements = elements;
+        this.module = module;
     }
 
     @Override
@@ -67,6 +72,11 @@
     }
 
     @Override
+    public ModuleTree getModule() {
+        return module;
+    }
+
+    @Override
     public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitCompilationUnit(this, data);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/DestructuringDeclTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+import jdk.nashorn.internal.ir.ExpressionStatement;
+import jdk.nashorn.internal.parser.TokenType;
+
+// This implementation of VariableTree represents a destructuring declaration
+final class DestructuringDeclTreeImpl extends StatementTreeImpl
+        implements VariableTree {
+
+    private final TokenType declType;
+    private final ExpressionTree lhs;
+    private final ExpressionTree init;
+
+    DestructuringDeclTreeImpl(ExpressionStatement exprStat, final ExpressionTree lhs, final ExpressionTree init) {
+        super(exprStat);
+        assert exprStat.destructuringDeclarationType() != null : "expecting a destructuring decl. statement";
+
+        this.declType = exprStat.destructuringDeclarationType();
+        this.lhs = lhs;
+        this.init = init;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.VARIABLE;
+    }
+
+    @Override
+    public ExpressionTree getBinding() {
+        return lhs;
+    }
+
+    @Override
+    public ExpressionTree getInitializer() {
+        return init;
+    }
+
+    @Override
+    public boolean isConst() {
+        return declType == TokenType.CONST;
+    }
+
+    @Override
+    public boolean isLet() {
+        return declType == TokenType.LET;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitVariable(this, data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ExportEntryTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A Tree node for export entry in <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-modules">Module information</a>.
+ */
+public interface ExportEntryTree extends Tree {
+    /**
+     * Returns the entry's export name.
+     *
+     * @return the export name
+     */
+    public IdentifierTree getExportName();
+
+    /**
+     * Returns the entry's module request.
+     *
+     * @return the module request
+     */
+    public IdentifierTree getModuleRequest();
+
+    /**
+     * Returns the entry's import name.
+     *
+     * @return the import name
+     */
+    public IdentifierTree getImportName();
+
+    /**
+     * Returns the entry's local name.
+     *
+     * @return the local name
+     */
+    public IdentifierTree getLocalName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ExportEntryTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.Module;
+import static jdk.nashorn.api.tree.ModuleTreeImpl.identOrNull;
+
+final class ExportEntryTreeImpl extends TreeImpl implements ExportEntryTree {
+    private final long startPos, endPos;
+    private final IdentifierTree exportName;
+    private final IdentifierTree moduleRequest;
+    private final IdentifierTree importName;
+    private final IdentifierTree localName;
+
+    private ExportEntryTreeImpl(final long startPos, final long endPos,
+            IdentifierTree exportName,
+            IdentifierTree moduleRequest,
+            IdentifierTree importName,
+            IdentifierTree localName) {
+        super(null); // no underlying Node!
+        this.startPos = startPos;
+        this.endPos = endPos;
+        this.exportName = exportName;
+        this.moduleRequest = moduleRequest;
+        this.importName = importName;
+        this.localName = localName;
+    }
+
+    private static ExportEntryTreeImpl createExportEntry(Module.ExportEntry entry) {
+        return new ExportEntryTreeImpl(entry.getStartPosition(),
+                entry.getEndPosition(),
+                identOrNull(entry.getExportName()),
+                identOrNull(entry.getModuleRequest()),
+                identOrNull(entry.getImportName()),
+                identOrNull(entry.getLocalName()));
+    }
+
+    static List<ExportEntryTreeImpl> createExportList(List<Module.ExportEntry> exportList) {
+        return exportList.stream().
+            map(ExportEntryTreeImpl::createExportEntry).
+            collect(Collectors.toList());
+    }
+
+    @Override
+    public Kind getKind() {
+        return Tree.Kind.EXPORT_ENTRY;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitExportEntry(this, data);
+    }
+
+    @Override
+    public long getStartPosition() {
+        return startPos;
+    }
+
+    @Override
+    public long getEndPosition() {
+        return endPos;
+    }
+
+    @Override
+    public IdentifierTree getExportName() {
+        return exportName;
+    }
+
+    @Override
+    public IdentifierTree getModuleRequest() {
+        return moduleRequest;
+    }
+
+    @Override
+    public IdentifierTree getImportName() {
+        return importName;
+    }
+
+    @Override
+    public IdentifierTree getLocalName() {
+        return localName;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForOfLoopTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+/**
+ * A tree node for <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-for-in-and-for-of-statements">for..of statement</a>.
+ *
+ * For example:
+ * <pre>
+ *   for ( <em>variable</em> of <em>expression</em> )
+ *       <em>statement</em>
+ * </pre>
+ *
+ * @since 9
+ */
+public interface ForOfLoopTree extends LoopTree {
+    /**
+     * The for..in left hand side expression.
+     *
+     * @return the left hand side expression
+     */
+    ExpressionTree getVariable();
+
+    /**
+     * The object or array being whose properties are iterated.
+     *
+     * @return the object or array expression being iterated
+     */
+    ExpressionTree getExpression();
+
+    /**
+     * The statement contained in this for..in statement.
+     *
+     * @return the statement
+     */
+    @Override
+    StatementTree getStatement();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ForOfLoopTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import jdk.nashorn.internal.ir.ForNode;
+
+final class ForOfLoopTreeImpl extends StatementTreeImpl implements ForOfLoopTree {
+    private final ExpressionTree lhsExpr;
+    private final ExpressionTree expr;
+    private final StatementTree stat;
+
+    ForOfLoopTreeImpl(final ForNode node,
+            final ExpressionTree lhsExpr,
+            final ExpressionTree expr,
+            final StatementTree stat) {
+        super(node);
+        assert node.isForIn() : "for ..in expected";
+        this.lhsExpr = lhsExpr;
+        this.expr = expr;
+        this.stat = stat;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.FOR_IN_LOOP;
+    }
+
+    @Override
+    public ExpressionTree getVariable() {
+        return lhsExpr;
+    }
+
+    @Override
+    public ExpressionTree getExpression() {
+        return expr;
+    }
+
+    @Override
+    public StatementTree getStatement() {
+        return stat;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitForOfLoop(this, data);
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 import java.util.List;
 
 /**
- * A tree node for a function declaration.
+ * A tree node for a <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-function-definitions">function declaration</a>.
  *
  * For example:
  * <pre>
@@ -37,6 +37,12 @@
  *      <em>body</em>
  * </pre>
  *
+ * <pre>
+ *   <em>function*</em> <em>name</em>
+ *      ( <em>parameters</em> )
+ *      <em>body</em>
+ * </pre>
+ *
  * @since 9
  */
 public interface FunctionDeclarationTree extends StatementTree {
@@ -45,7 +51,7 @@
      *
      * @return name the function declared
      */
-    String getName();
+    IdentifierTree getName();
 
     /**
      * Returns the parameters of this function.
@@ -67,4 +73,11 @@
      * @return true if this function is strict
      */
     boolean isStrict();
+
+    /**
+     * Is this a generator function?
+     *
+     * @return true if this is a generator function
+     */
+    boolean isGenerator();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionDeclarationTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,7 +32,7 @@
 final class FunctionDeclarationTreeImpl extends StatementTreeImpl
     implements FunctionDeclarationTree {
     private final FunctionNode funcNode;
-    private final String funcName;
+    private final IdentifierTree funcName;
     private final List<? extends ExpressionTree> params;
     private final BlockTree body;
 
@@ -43,7 +43,7 @@
         assert node.getInit() instanceof FunctionNode : "function expected";
         funcNode = (FunctionNode)node.getInit();
         assert funcNode.isDeclared() : "function declaration expected";
-        funcName = funcNode.isAnonymous()? null : node.getName().getName();
+        funcName = funcNode.isAnonymous()? null : new IdentifierTreeImpl(node.getName());
         this.params = params;
         this.body = body;
     }
@@ -54,7 +54,7 @@
     }
 
     @Override
-    public String getName() {
+    public IdentifierTree getName() {
         return funcName;
     }
 
@@ -74,6 +74,11 @@
     }
 
     @Override
+    public boolean isGenerator() {
+        return funcNode.getKind() == FunctionNode.Kind.GENERATOR;
+    }
+
+    @Override
     public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitFunctionDeclaration(this, data);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionExpressionTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionExpressionTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,7 +28,7 @@
 import java.util.List;
 
 /**
- * A tree node for a function expression.
+ * A tree node for <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-function-defining-expressions">function expressions</a> including <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-arrow-function-definitions">arrow functions</a>.
  *
  * For example:
  * <pre>
@@ -37,6 +37,10 @@
  *      <em>body</em>
  * </pre>
  *
+ * <pre>
+ *   <em>var</em> func = <em>(x) =&gt; x+1</em>
+ * </pre>
+ *
  * @since 9
  */
 public interface FunctionExpressionTree extends ExpressionTree {
@@ -45,7 +49,7 @@
      *
      * @return name the function declared
      */
-    String getName();
+    IdentifierTree getName();
 
     /**
      * Returns the parameters of this function.
@@ -55,11 +59,13 @@
     List<? extends ExpressionTree> getParameters();
 
     /**
-     * Returns the body of code of this function.
+     * Returns the body of this function. This may be a {@link BlockTree} when this
+     * function has a block body. This is an {@link ExpressionTree} when the function body
+     * is a concise expression as in an expression arrow, or in an expression closure.
      *
-     * @return the body of code
+     * @return the body of this function
      */
-    BlockTree getBody();
+    Tree getBody();
 
     /**
      * Is this a strict function?
@@ -67,4 +73,18 @@
      * @return true if this function is strict
      */
     boolean isStrict();
+
+    /**
+     * Is this a arrow function?
+     *
+     * @return true if this is a arrow function
+     */
+    boolean isArrow();
+
+    /**
+     * Is this a generator function?
+     *
+     * @return true if this is a generator function
+     */
+    boolean isGenerator();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionExpressionTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/FunctionExpressionTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,9 +31,9 @@
 final class FunctionExpressionTreeImpl extends ExpressionTreeImpl
     implements FunctionExpressionTree {
     private final FunctionNode funcNode;
-    private final String funcName;
+    private final IdentifierTree funcName;
     private final List<? extends ExpressionTree> params;
-    private final BlockTree body;
+    private final Tree body;
 
     FunctionExpressionTreeImpl(final FunctionNode node,
             final List<? extends ExpressionTree> params,
@@ -46,11 +46,17 @@
         if (node.isAnonymous() || kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
             funcName = null;
         } else {
-            funcName = node.getIdent().getName();
+            funcName = new IdentifierTreeImpl(node.getIdent());
         }
 
         this.params = params;
-        this.body = body;
+        if (node.getFlag(FunctionNode.HAS_EXPRESSION_BODY)) {
+            StatementTree first = body.getStatements().get(0);
+            assert first instanceof ReturnTree : "consise func. expression should have a return statement";
+            this.body = ((ReturnTree)first).getExpression();
+        } else {
+            this.body = body;
+        }
     }
 
     @Override
@@ -59,7 +65,7 @@
     }
 
     @Override
-    public String getName() {
+    public IdentifierTree getName() {
         return funcName;
     }
 
@@ -69,7 +75,7 @@
     }
 
     @Override
-    public BlockTree getBody() {
+    public Tree getBody() {
         return body;
     }
 
@@ -79,6 +85,16 @@
     }
 
     @Override
+    public boolean isArrow() {
+        return funcNode.getKind() == FunctionNode.Kind.ARROW;
+    }
+
+    @Override
+    public boolean isGenerator() {
+        return funcNode.getKind() == FunctionNode.Kind.GENERATOR;
+    }
+
+    @Override
     public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitFunctionExpression(this, data);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IRTranslator.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
@@ -35,6 +36,7 @@
 import jdk.nashorn.internal.ir.CallNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ClassNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.DebuggerNode;
 import jdk.nashorn.internal.ir.EmptyNode;
@@ -56,6 +58,7 @@
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.TemplateLiteral;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
@@ -87,11 +90,14 @@
             return null;
         }
 
-        assert (node.getKind() == FunctionNode.Kind.SCRIPT) : "script function expected";
+        assert node.getKind() == FunctionNode.Kind.SCRIPT ||
+                node.getKind() == FunctionNode.Kind.MODULE :
+                "script or module function expected";
 
         final Block body = node.getBody();
         return new CompilationUnitTreeImpl(node,
-                translateStats(body != null? getOrderedStatements(body.getStatements()) : null));
+                translateStats(body != null? getOrderedStatements(body.getStatements()) : null),
+                translateModule(node));
     }
 
     @Override
@@ -184,8 +190,15 @@
 
     @Override
     public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
-        curStat = new ExpressionStatementTreeImpl(expressionStatement,
+        if (expressionStatement.destructuringDeclarationType() != null) {
+            ExpressionTree expr = translateExpr(expressionStatement.getExpression());
+            assert expr instanceof AssignmentTree : "destructuring decl. statement does not have assignment";
+            AssignmentTree assign = (AssignmentTree)expr;
+            curStat = new DestructuringDeclTreeImpl(expressionStatement, assign.getVariable(), assign.getExpression());
+        } else {
+            curStat = new ExpressionStatementTreeImpl(expressionStatement,
                 translateExpr(expressionStatement.getExpression()));
+        }
         return false;
     }
 
@@ -209,6 +222,11 @@
                     translateExpr(forNode.getInit()),
                     translateExpr(forNode.getModify()),
                     translateBlock(forNode.getBody()));
+        } else if (forNode.isForOf()) {
+            curStat = new ForOfLoopTreeImpl(forNode,
+                    translateExpr(forNode.getInit()),
+                    translateExpr(forNode.getModify()),
+                    translateBlock(forNode.getBody()));
         } else {
             curStat = new ForLoopTreeImpl(forNode,
                     translateExpr(forNode.getInit()),
@@ -224,8 +242,7 @@
     public boolean enterFunctionNode(final FunctionNode functionNode) {
         assert !functionNode.isDeclared() || functionNode.isAnonymous() : "should not reach here for function declaration";
 
-        final List<? extends ExpressionTree> paramTrees
-                    = translateExprs(functionNode.getParameters());
+        final List<? extends ExpressionTree> paramTrees = translateParameters(functionNode);
         final BlockTree blockTree = (BlockTree) translateBlock(functionNode.getBody(), true);
         curExpr = new FunctionExpressionTreeImpl(functionNode, paramTrees, blockTree);
 
@@ -291,14 +308,7 @@
     @Override
     public boolean enterObjectNode(final ObjectNode objectNode) {
         final List<PropertyNode> propNodes = objectNode.getElements();
-        final List<PropertyTreeImpl> propTrees = new ArrayList<>(propNodes.size());
-        for (final PropertyNode propNode : propNodes) {
-            propTrees.add(new PropertyTreeImpl(propNode,
-                    translateExpr(propNode.getKey()),
-                    translateExpr(propNode.getValue()),
-                    (FunctionExpressionTree) translateExpr(propNode.getGetter()),
-                    (FunctionExpressionTree) translateExpr(propNode.getSetter())));
-        }
+        final List<? extends PropertyTree> propTrees = translateProperties(propNodes);
         curExpr = new ObjectLiteralTreeImpl(objectNode, propTrees);
         return false;
     }
@@ -347,6 +357,12 @@
     }
 
     @Override
+    public boolean enterTemplateLiteral(final TemplateLiteral templateLiteral) {
+        curExpr = new TemplateLiteralTreeImpl(templateLiteral, translateExprs(templateLiteral.getExpressions()));
+        return false;
+    }
+
+    @Override
     public boolean enterTernaryNode(final TernaryNode ternaryNode) {
         curExpr = new ConditionalExpressionTreeImpl(ternaryNode,
                 translateExpr(ternaryNode.getTest()),
@@ -386,6 +402,14 @@
         if (unaryNode.isTokenType(TokenType.NEW)) {
             curExpr = new NewTreeImpl(unaryNode,
                     translateExpr(unaryNode.getExpression()));
+        } else if (unaryNode.isTokenType(TokenType.YIELD) ||
+                unaryNode.isTokenType(TokenType.YIELD_STAR)) {
+            curExpr = new YieldTreeImpl(unaryNode,
+                    translateExpr(unaryNode.getExpression()));
+        } else if (unaryNode.isTokenType(TokenType.SPREAD_ARGUMENT) ||
+                unaryNode.isTokenType(TokenType.SPREAD_ARRAY)) {
+            curExpr = new SpreadTreeImpl(unaryNode,
+                    translateExpr(unaryNode.getExpression()));
         } else {
             curExpr = new UnaryTreeImpl(unaryNode,
                     translateExpr(unaryNode.getExpression()));
@@ -399,12 +423,19 @@
         if (initNode instanceof FunctionNode && ((FunctionNode)initNode).isDeclared()) {
             final FunctionNode funcNode = (FunctionNode) initNode;
 
-            final List<? extends ExpressionTree> paramTrees
-                    = translateExprs(funcNode.getParameters());
+            final List<? extends ExpressionTree> paramTrees = translateParameters(funcNode);
             final BlockTree blockTree = (BlockTree) translateBlock(funcNode.getBody(), true);
             curStat = new FunctionDeclarationTreeImpl(varNode, paramTrees, blockTree);
+        } else if (initNode instanceof ClassNode && ((ClassNode)initNode).isStatement()) {
+            final ClassNode classNode = (ClassNode) initNode;
+
+            curStat = new ClassDeclarationTreeImpl(varNode,
+                    translateIdent(classNode.getIdent()),
+                    translateExpr(classNode.getClassHeritage()),
+                    translateProperty(classNode.getConstructor()),
+                    translateProperties(classNode.getClassElements()));
         } else {
-            curStat = new VariableTreeImpl(varNode, translateExpr(initNode));
+            curStat = new VariableTreeImpl(varNode, translateIdent(varNode.getName()), translateExpr(initNode));
         }
 
         return false;
@@ -433,6 +464,25 @@
         return false;
     }
 
+    /**
+     * Callback for entering a ClassNode
+     *
+     * @param  classNode  the node
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    @Override
+    public boolean enterClassNode(final ClassNode classNode) {
+        assert !classNode.isStatement(): "should not reach here for class declaration";
+
+        curExpr = new ClassExpressionTreeImpl(classNode,
+            translateIdent(classNode.getIdent()),
+            translateExpr(classNode.getClassHeritage()),
+            translateProperty(classNode.getConstructor()),
+            translateProperties(classNode.getClassElements()));
+
+        return false;
+    }
+
     private StatementTree translateBlock(final Block blockNode) {
         return translateBlock(blockNode, false);
     }
@@ -493,6 +543,24 @@
         return statTrees;
     }
 
+    private List<? extends ExpressionTree> translateParameters(final FunctionNode func) {
+        Map<IdentNode, Expression> paramExprs = func.getParameterExpressions();
+        if (paramExprs != null) {
+            List<IdentNode> params = func.getParameters();
+            final List<ExpressionTreeImpl> exprTrees = new ArrayList<>(params.size());
+            for (final IdentNode ident : params) {
+                Expression expr = paramExprs.containsKey(ident)? paramExprs.get(ident) : ident;
+                curExpr = null;
+                expr.accept(this);
+                assert curExpr != null;
+                exprTrees.add(curExpr);
+            }
+            return exprTrees;
+        } else {
+            return translateExprs(func.getParameters());
+        }
+    }
+
     private List<? extends ExpressionTree> translateExprs(final List<? extends Expression> exprs) {
         if (exprs == null) {
             return null;
@@ -532,4 +600,25 @@
     private static IdentifierTree translateIdent(final IdentNode ident) {
         return new IdentifierTreeImpl(ident);
     }
+
+    private List<? extends PropertyTree> translateProperties(final List<PropertyNode> propNodes) {
+        final List<PropertyTree> propTrees = new ArrayList<>(propNodes.size());
+        for (final PropertyNode propNode : propNodes) {
+            propTrees.add(translateProperty(propNode));
+        }
+        return propTrees;
+    }
+
+    private PropertyTree translateProperty(final PropertyNode propNode) {
+        return new PropertyTreeImpl(propNode,
+                    translateExpr(propNode.getKey()),
+                    translateExpr(propNode.getValue()),
+                    (FunctionExpressionTree) translateExpr(propNode.getGetter()),
+                    (FunctionExpressionTree) translateExpr(propNode.getSetter()));
+    }
+
+    private ModuleTree translateModule(final FunctionNode func) {
+        return func.getKind() == FunctionNode.Kind.MODULE?
+            ModuleTreeImpl.create(func) : null;
+    }
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IdentifierTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IdentifierTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -42,4 +42,46 @@
      * @return the name of this identifier
      */
     String getName();
+
+    /**
+     * Is this a rest parameter for a function or rest elements of an array?
+     *
+     * @return true if this is a rest parameter
+     */
+    boolean isRestParameter();
+
+    /**
+     * Is this super identifier?
+     *
+     * @return true if this is super identifier
+     */
+    boolean isSuper();
+
+    /**
+     * Is this 'this' identifier?
+     *
+     * @return true if this is 'this' identifier
+     */
+    boolean isThis();
+
+    /**
+     * Is this "*" used in module export entry?
+     *
+     * @return true if this "*" used in module export entry?
+     */
+    boolean isStar();
+
+    /**
+     * Is this "default" used in module export entry?
+     *
+     * @return true if this 'default' used in module export entry?
+     */
+    boolean isDefault();
+
+    /**
+     * Is this "*default*" used in module export entry?
+     *
+     * @return true if this '*default*' used in module export entry?
+     */
+    boolean isStarDefaultStar();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IdentifierTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/IdentifierTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -27,6 +27,7 @@
 package jdk.nashorn.api.tree;
 
 import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.Module;
 
 final class IdentifierTreeImpl extends ExpressionTreeImpl implements IdentifierTree {
     private final String name;
@@ -47,6 +48,37 @@
     }
 
     @Override
+    public boolean isRestParameter() {
+        return ((IdentNode)node).isRestParameter();
+    }
+
+    @Override
+    public boolean isSuper() {
+        final IdentNode ident = (IdentNode)node;
+        return ident.isDirectSuper() || "super".equals(ident.getName());
+    }
+
+    @Override
+    public boolean isThis() {
+        return "this".equals(((IdentNode)node).getName());
+    }
+
+    @Override
+    public boolean isStar() {
+        return Module.STAR_NAME.equals(((IdentNode)node).getName());
+    }
+
+    @Override
+    public boolean isDefault() {
+        return Module.DEFAULT_NAME.equals(((IdentNode)node).getName());
+    }
+
+    @Override
+    public boolean isStarDefaultStar() {
+        return Module.DEFAULT_EXPORT_BINDING_NAME.equals(((IdentNode)node).getName());
+    }
+
+    @Override
     public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitIdentifier(this, data);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ImportEntryTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A Tree node for import entry of <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-modules">Module information</a>.
+ */
+public interface ImportEntryTree extends Tree {
+    /**
+     * Returns the entry's module request.
+     *
+     * @return the module request
+     */
+    public IdentifierTree getModuleRequest();
+
+    /**
+     * Returns the entry's import name.
+     *
+     * @return the import name
+     */
+    public IdentifierTree getImportName();
+
+    /**
+     * Returns the entry's local name.
+     *
+     * @return the local name
+     */
+    public IdentifierTree getLocalName();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ImportEntryTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.Module;
+import static jdk.nashorn.api.tree.ModuleTreeImpl.identOrNull;
+
+final class ImportEntryTreeImpl extends TreeImpl implements ImportEntryTree {
+    private final long startPos, endPos;
+    private final IdentifierTree moduleRequest;
+    private final IdentifierTree importName;
+    private final IdentifierTree localName;
+
+    private ImportEntryTreeImpl(final long startPos, final long endPos,
+            IdentifierTree moduleRequest,
+            IdentifierTree importName,
+            IdentifierTree localName) {
+        super(null); // No underlying Node!
+        this.startPos = startPos;
+        this.endPos = endPos;
+        this.moduleRequest = moduleRequest;
+        this.importName = importName;
+        this.localName = localName;
+    }
+
+    private static ImportEntryTreeImpl createImportEntry(Module.ImportEntry entry) {
+        return new ImportEntryTreeImpl(entry.getStartPosition(),
+                entry.getEndPosition(),
+                identOrNull(entry.getModuleRequest()),
+                identOrNull(entry.getImportName()),
+                identOrNull(entry.getLocalName()));
+    }
+
+    static List<ImportEntryTreeImpl> createImportList(List<Module.ImportEntry> importList) {
+        return importList.stream().
+            map(ImportEntryTreeImpl::createImportEntry).
+            collect(Collectors.toList());
+    }
+
+    @Override
+    public Kind getKind() {
+        return Tree.Kind.IMPORT_ENTRY;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitImportEntry(this, data);
+    }
+
+    @Override
+    public long getStartPosition() {
+        return startPos;
+    }
+
+    @Override
+    public long getEndPosition() {
+        return endPos;
+    }
+
+    @Override
+    public IdentifierTree getModuleRequest() {
+        return moduleRequest;
+    }
+
+    @Override
+    public IdentifierTree getImportName() {
+        return importName;
+    }
+
+    @Override
+    public IdentifierTree getLocalName() {
+        return localName;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ModuleTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A Tree node for <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-modules">Module information</a>.
+ */
+public interface ModuleTree extends Tree {
+    /**
+     * Returns the list of import entries.
+     *
+     * @return the import entries
+     */
+    public List<? extends ImportEntryTree> getImportEntries();
+
+    /**
+     * Returns the list of local export entries.
+     *
+     * @return the local export entries
+     */
+    public List<? extends ExportEntryTree> getLocalExportEntries();
+
+    /**
+     * Returns the list of indirect export entries.
+     *
+     * @return the indirect export entries
+     */
+    public List<? extends ExportEntryTree> getIndirectExportEntries();
+
+    /**
+     * Returns the list of star export entries.
+     *
+     * @return the star export entries
+     */
+    public List<? extends ExportEntryTree> getStarExportEntries();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ModuleTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.Module;
+import static jdk.nashorn.api.tree.ExportEntryTreeImpl.createExportList;
+import static jdk.nashorn.api.tree.ImportEntryTreeImpl.createImportList;
+
+final class ModuleTreeImpl extends TreeImpl implements ModuleTree {
+
+    private final Module mod;
+    private final List<? extends ImportEntryTree> imports;
+    private final List<? extends ExportEntryTree> localExports;
+    private final List<? extends ExportEntryTree> indirectExports;
+    private final List<? extends ExportEntryTree> starExports;
+
+    private ModuleTreeImpl(final FunctionNode func,
+            final List<? extends ImportEntryTree> imports,
+            final List<? extends ExportEntryTree> localExports,
+            final List<? extends ExportEntryTree> indirectExports,
+            final List<? extends ExportEntryTree> starExports) {
+        super(func);
+        assert func.getKind() == FunctionNode.Kind.MODULE : "module function node expected";
+        this.mod = func.getModule();
+        this.imports = imports;
+        this.localExports = localExports;
+        this.indirectExports = indirectExports;
+        this.starExports = starExports;
+    }
+
+    static ModuleTreeImpl create(final FunctionNode func) {
+        final Module mod = func.getModule();
+        return new ModuleTreeImpl(func,
+            createImportList(mod.getImportEntries()),
+            createExportList(mod.getLocalExportEntries()),
+            createExportList(mod.getIndirectExportEntries()),
+            createExportList(mod.getStarExportEntries()));
+    }
+
+    @Override
+    public Kind getKind() {
+        return Tree.Kind.MODULE;
+    }
+
+    @Override
+    public List<? extends ImportEntryTree> getImportEntries() {
+        return imports;
+    }
+
+    @Override
+    public List<? extends ExportEntryTree> getLocalExportEntries() {
+        return localExports;
+    }
+
+    @Override
+    public List<? extends ExportEntryTree> getIndirectExportEntries() {
+        return indirectExports;
+    }
+
+    @Override
+    public List<? extends ExportEntryTree> getStarExportEntries() {
+        return starExports;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitModule(this, data);
+    }
+
+    static IdentifierTree identOrNull(final IdentNode node) {
+        return node != null? new IdentifierTreeImpl(node) : null;
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/Parser.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/Parser.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,6 +130,8 @@
      * <dt>"--no-syntax-extensions" or "-nse"</dt><dd>disable ECMAScript syntax extensions</dd>
      * <dt>"-scripting"</dt><dd>enable scripting mode extensions</dd>
      * <dt>"-strict"</dt><dd>enable ECMAScript strict mode</dd>
+     * <dt>"--language=es6"</dt><dd>enable ECMAScript 6 parsing mode</dd>
+     * <dt>"--es6-module"</dt><dd>enable ECMAScript 6 module parsing mode. This option implies --language=es6</dd>
      * </dl>
      *
      * @throws NullPointerException if options array or any of its element is null
@@ -148,6 +150,8 @@
                 case "-nse":
                 case "-scripting":
                 case "-strict":
+                case "--language=es6":
+                case "--es6-module":
                     break;
                 default:
                     throw new IllegalArgumentException(opt);
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/ParserImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,6 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-
 package jdk.nashorn.api.tree;
 
 import java.io.File;
@@ -31,6 +30,7 @@
 import java.io.Reader;
 import java.net.URL;
 import java.nio.file.Path;
+import java.util.Arrays;
 import java.util.Map;
 import java.util.Objects;
 import jdk.nashorn.api.scripting.NashornException;
@@ -47,51 +47,94 @@
 final class ParserImpl implements Parser {
 
     private final ScriptEnvironment env;
+    private final boolean moduleMode;
 
     ParserImpl(final String... args) throws IllegalArgumentException {
-       Objects.requireNonNull(args);
-       Options options = new Options("nashorn");
-       options.process(args);
-       this.env = new ScriptEnvironment(options,
-               new PrintWriter(System.out), new PrintWriter(System.err));
+        Objects.requireNonNull(args);
+
+        // handle the parser specific "--es6-module" option
+        boolean seenModuleOption = false;
+        for (int idx = 0; idx < args.length; idx++) {
+            final String opt = args[idx];
+            if (opt.equals("--es6-module")) {
+                seenModuleOption = true;
+                /*
+                 * Nashorn parser does not understand parser API specific
+                 * option. This option implies --language=es6. So, we change
+                 * the option to --language=es6. Note that if user specified
+                 * --language=es6 explicitly, that is okay. Nashorn tolerates
+                 * repeated options!
+                 */
+                args[idx] = "--language=es6";
+                break;
+            }
+        }
+        this.moduleMode = seenModuleOption;
+
+        // append "--parse-only to signal to the Nashorn that it
+        // is being used in "parse only" mode.
+        String[] newArgs = Arrays.copyOf(args, args.length + 1, String[].class);
+        newArgs[args.length] = "--parse-only";
+        Options options = new Options("nashorn");
+        options.process(newArgs);
+        this.env = new ScriptEnvironment(options,
+                new PrintWriter(System.out), new PrintWriter(System.err));
     }
 
     @Override
     public CompilationUnitTree parse(final File file, final DiagnosticListener listener) throws IOException, NashornException {
+        if (moduleMode) {
+            return parseModule(file, listener);
+        }
         final Source src = Source.sourceFor(Objects.requireNonNull(file).getName(), file);
         return translate(makeParser(src, listener).parse());
     }
 
     @Override
     public CompilationUnitTree parse(final Path path, final DiagnosticListener listener) throws IOException, NashornException {
+        if (moduleMode) {
+            return parseModule(path, listener);
+        }
         final Source src = Source.sourceFor(Objects.requireNonNull(path).toString(), path);
         return translate(makeParser(src, listener).parse());
     }
 
     @Override
     public CompilationUnitTree parse(final URL url, final DiagnosticListener listener) throws IOException, NashornException {
+        if (moduleMode) {
+            return parseModule(url, listener);
+        }
         final Source src = Source.sourceFor(url.toString(), url);
         return translate(makeParser(src, listener).parse());
     }
 
     @Override
     public CompilationUnitTree parse(final String name, final Reader reader, final DiagnosticListener listener) throws IOException, NashornException {
+        if (moduleMode) {
+            return parseModule(name, reader, listener);
+        }
         final Source src = Source.sourceFor(Objects.requireNonNull(name), Objects.requireNonNull(reader));
         return translate(makeParser(src, listener).parse());
     }
 
     @Override
     public CompilationUnitTree parse(final String name, final String code, final DiagnosticListener listener) throws NashornException {
+        if (moduleMode) {
+            return parseModule(name, code, listener);
+        }
         final Source src = Source.sourceFor(name, code);
         return translate(makeParser(src, listener).parse());
     }
 
     @Override
     public CompilationUnitTree parse(final ScriptObjectMirror scriptObj, final DiagnosticListener listener) throws NashornException {
-        final Map<?,?> map = Objects.requireNonNull(scriptObj);
+        if (moduleMode) {
+            return parseModule(scriptObj, listener);
+        }
+        final Map<?, ?> map = Objects.requireNonNull(scriptObj);
         if (map.containsKey("script") && map.containsKey("name")) {
             final String script = JSType.toString(map.get("script"));
-            final String name   = JSType.toString(map.get("name"));
+            final String name = JSType.toString(map.get("name"));
             final Source src = Source.sourceFor(name, script);
             return translate(makeParser(src, listener).parse());
         } else {
@@ -99,12 +142,55 @@
         }
     }
 
+    private CompilationUnitTree parseModule(File file, DiagnosticListener listener) throws IOException, NashornException {
+        final Source src = Source.sourceFor(Objects.requireNonNull(file).getName(), file);
+        return makeModule(src, listener);
+    }
+
+    private CompilationUnitTree parseModule(Path path, DiagnosticListener listener) throws IOException, NashornException {
+        final Source src = Source.sourceFor(Objects.requireNonNull(path).toString(), path);
+        return makeModule(src, listener);
+    }
+
+    private CompilationUnitTree parseModule(URL url, DiagnosticListener listener) throws IOException, NashornException {
+        final Source src = Source.sourceFor(url.toString(), url);
+        return makeModule(src, listener);
+    }
+
+    private CompilationUnitTree parseModule(String name, Reader reader, DiagnosticListener listener) throws IOException, NashornException {
+        final Source src = Source.sourceFor(Objects.requireNonNull(name), Objects.requireNonNull(reader));
+        return makeModule(src, listener);
+    }
+
+    private CompilationUnitTree parseModule(String name, String code, DiagnosticListener listener) throws NashornException {
+        final Source src = Source.sourceFor(name, code);
+        return makeModule(src, listener);
+    }
+
+    private CompilationUnitTree parseModule(ScriptObjectMirror scriptObj, DiagnosticListener listener) throws NashornException {
+        final Map<?, ?> map = Objects.requireNonNull(scriptObj);
+        if (map.containsKey("script") && map.containsKey("name")) {
+            final String script = JSType.toString(map.get("script"));
+            final String name = JSType.toString(map.get("name"));
+            final Source src = Source.sourceFor(name, script);
+            return makeModule(src, listener);
+        } else {
+            throw new IllegalArgumentException("can't find 'script' and 'name' properties");
+        }
+    }
+
+    private CompilationUnitTree makeModule(Source src, DiagnosticListener listener) {
+        final FunctionNode modFunc = makeParser(src, listener).parseModule(src.getName());
+        return new IRTranslator().translate(modFunc);
+    }
+
     private jdk.nashorn.internal.parser.Parser makeParser(final Source source, final DiagnosticListener listener) {
-        final ErrorManager errMgr = listener != null? new ListenerErrorManager(listener) : new Context.ThrowErrorManager();
+        final ErrorManager errMgr = listener != null ? new ListenerErrorManager(listener) : new Context.ThrowErrorManager();
         return new jdk.nashorn.internal.parser.Parser(env, source, errMgr);
     }
 
     private static class ListenerErrorManager extends ErrorManager {
+
         private final DiagnosticListener listener;
 
         ListenerErrorManager(final DiagnosticListener listener) {
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/PropertyTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/PropertyTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,4 +60,18 @@
      * @return the getter function of the property
      */
     public FunctionExpressionTree getSetter();
+
+    /**
+     * Is this a class static property?
+     *
+     * @return true if this is a static property
+     */
+    public boolean isStatic();
+
+    /**
+     * Is this a computed property?
+     *
+     * @return true if this is a computed property
+     */
+    public boolean isComputed();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/PropertyTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/PropertyTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@
     private final ExpressionTree value;
     private final FunctionExpressionTree getter;
     private final FunctionExpressionTree setter;
+    private final boolean isStatic, isComputed;
+
     PropertyTreeImpl(final PropertyNode node,
             final ExpressionTree key,
             final ExpressionTree value,
@@ -42,6 +44,8 @@
         this.value  = value;
         this.getter = getter;
         this.setter = setter;
+        this.isStatic = node.isStatic();
+        this.isComputed = node.isComputed();
     }
 
     @Override
@@ -70,6 +74,16 @@
     }
 
     @Override
+    public boolean isStatic() {
+        return isStatic;
+    }
+
+    @Override
+    public boolean isComputed() {
+        return isComputed;
+    }
+
+    @Override
     public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitProperty(this, data);
     }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/RegExpLiteralTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/RegExpLiteralTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -30,7 +30,7 @@
  *
  * @since 9
  */
-public interface RegExpLiteralTree extends Tree {
+public interface RegExpLiteralTree extends ExpressionTree {
     /**
      * Regular expression pattern to match.
      *
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SimpleTreeVisitorES5_1.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SimpleTreeVisitorES5_1.java	Mon Jul 18 09:38:08 2016 -0700
@@ -61,6 +61,45 @@
         return null;
     }
 
+    /**
+     * Visits a {@code ModuleTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitModule(ModuleTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
+    /**
+     * Visits an {@code ExportEntryTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitExportEntry(ExportEntryTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
+    /**
+     * Visits an {@code ImportEntryTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitImportEntry(ImportEntryTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
     @Override
     public R visitBinary(final BinaryTree node, final P r) {
         node.getLeftOperand().accept(this, r);
@@ -105,6 +144,32 @@
         return null;
     }
 
+    /**
+     * Visits a {@code ClassDeclarationTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitClassDeclaration(ClassDeclarationTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
+    /**
+     * Visits a {@code ClassExpressionTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitClassExpression(ClassExpressionTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
     @Override
     public R visitConditionalExpression(final ConditionalExpressionTree node, final P r) {
         node.getCondition().accept(this, r);
@@ -173,6 +238,19 @@
         return null;
     }
 
+    /**
+     * Visits a {@code ForOfLoopTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitForOfLoop(ForOfLoopTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
     @Override
     public R visitFunctionCall(final FunctionCallTree node, final P r) {
         node.getFunctionSelect().accept(this, r);
@@ -305,11 +383,37 @@
         return null;
     }
 
+    /**
+     * Visits a {@code TemplateLiteralTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitTemplateLiteral(TemplateLiteralTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
     @Override
     public R visitEmptyStatement(final EmptyStatementTree node, final P r) {
         return null;
     }
 
+    /**
+     * Visits a {@code SpreadTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
+    @Override
+    public R visitSpread(SpreadTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
     @Override
     public R visitSwitch(final SwitchTree node, final P r) {
         node.getExpression().accept(this, r);
@@ -382,9 +486,36 @@
         return null;
     }
 
+    /**
+     * Visits a {@code YieldTree} tree by calling {@code
+     * visitUnknown}.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return the result of {@code visitUnknown}
+     */
     @Override
-    public R visitUnknown(final Tree node, final P r) {
+    public R visitYield(YieldTree node, P p) {
+        return visitUnknown(node, p);
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @implSpec The default implementation of this method in {@code
+     * SimpleTreeVisitorES5_1} will always throw {@code
+     * UnknownTypeException}. This behavior is not required of a
+     * subclass.
+     *
+     * @param node  {@inheritDoc}
+     * @param p  {@inheritDoc}
+     * @return abnormal return by throwing exception always
+     * @throws UnknownTreeException
+     *  a visitor implementation may optionally throw this exception
+     */
+    @Override
+    public R visitUnknown(final Tree node, final P p) {
         // unknown in ECMAScript 5.1 edition
-        throw new UnknownTreeException(node, r);
+        throw new UnknownTreeException(node, p);
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SimpleTreeVisitorES6.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A simple implementation of the TreeVisitor for ECMAScript edition 6.
+ *
+ * <p>The visit methods corresponding to ES 6 language constructs walk the
+ * "components" of the given tree by calling accept method passing the
+ * current visitor and the additional parameter.
+ *
+ * <p>For constructs introduced in later versions, {@code visitUnknown}
+ * is called instead which throws {@link UnknownTreeException}.
+ *
+ * <p> Methods in this class may be overridden subject to their
+ * general contract.  Note that annotating methods in concrete
+ * subclasses with {@link java.lang.Override @Override} will help
+ * ensure that methods are overridden as intended.
+ *
+ * @param <R> the return type of this visitor's methods.  Use {@link
+ *            Void} for visitors that do not need to return results.
+ * @param <P> the type of the additional parameter to this visitor's
+ *            methods.  Use {@code Void} for visitors that do not need an
+ *            additional parameter.
+ */
+public class SimpleTreeVisitorES6<R, P> extends SimpleTreeVisitorES5_1<R, P> {
+    @Override
+    public R visitCompilationUnit(final CompilationUnitTree node, final P r) {
+        final ModuleTree mod = node.getModule();
+        if (mod != null) {
+            mod.accept(this, r);
+        }
+        return super.visitCompilationUnit(node, r);
+    }
+
+    /**
+     * Visit Module tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitModule(ModuleTree node, P p) {
+        node.getImportEntries().forEach(e -> visitImportEntry(e, p));
+        node.getLocalExportEntries().forEach(e -> visitExportEntry(e, p));
+        node.getIndirectExportEntries().forEach(e -> visitExportEntry(e, p));
+        node.getStarExportEntries().forEach(e -> visitExportEntry(e, p));
+        return null;
+    }
+
+    /**
+     * Visit Module ExportEntry tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitExportEntry(ExportEntryTree node, P p) {
+        return null;
+    }
+
+    /**
+     * Visit Module ImportEntry tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitImportEntry(ImportEntryTree node, P p) {
+        return null;
+    }
+
+   /**
+    * Visit class statement tree.
+    *
+    * @param node node being visited
+    * @param p extra parameter passed to the visitor
+    * @return value from the visitor
+    */
+    @Override
+    public R visitClassDeclaration(ClassDeclarationTree node, P p) {
+        node.getName().accept(this, p);
+        final ExpressionTree heritage = node.getClassHeritage();
+        if (heritage != null) {
+            heritage.accept(this, p);
+        }
+        final PropertyTree constructor = node.getConstructor();
+        if (constructor != null) {
+            constructor.accept(this, p);
+        }
+        final List<? extends PropertyTree> elements = node.getClassElements();
+        if (elements != null) {
+            for (PropertyTree prop : elements) {
+                prop.accept(this, p);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Visit class expression tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitClassExpression(ClassExpressionTree node, P p) {
+        node.getName().accept(this, p);
+        final ExpressionTree heritage = node.getClassHeritage();
+        if (heritage != null) {
+            heritage.accept(this, p);
+        }
+        final PropertyTree constructor = node.getConstructor();
+        if (constructor != null) {
+            constructor.accept(this, p);
+        }
+        final List<? extends PropertyTree> elements = node.getClassElements();
+        if (elements != null) {
+            for (PropertyTree prop : elements) {
+                prop.accept(this, p);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Visit for..of statement tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitForOfLoop(final ForOfLoopTree node, final P p) {
+        node.getVariable().accept(this, p);
+        node.getExpression().accept(this, p);
+        final StatementTree stat = node.getStatement();
+        if (stat != null) {
+            stat.accept(this, p);
+        }
+        return null;
+    }
+
+    /**
+     * Visit 'yield' expression tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitYield(YieldTree node, P p) {
+        node.getExpression().accept(this, p);
+        return null;
+    }
+
+    /**
+     * Visit 'spread' expression tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    @Override
+    public R visitSpread(SpreadTree node, P p) {
+        node.getExpression().accept(this, p);
+        return null;
+    }
+
+   /**
+    * Visit template literal tree.
+    *
+    * @param node node being visited
+    * @param p extra parameter passed to the visitor
+    * @return value from the visitor
+    */
+    @Override
+    public R visitTemplateLiteral(TemplateLiteralTree node, P p) {
+        final List<? extends ExpressionTree> expressions = node.getExpressions();
+        for (ExpressionTree expr : expressions) {
+            expr.accept(this, p);
+        }
+        return null;
+    }
+
+    @Override
+    public R visitVariable(final VariableTree node, final P r) {
+        final ExpressionTree expr = node.getBinding();
+        if (expr != null) {
+            expr.accept(this, r);
+        }
+        super.visitVariable(node, r);
+        return null;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SpreadTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+/**
+ *  A tree node for spread operator in array elements, function call arguments.
+ */
+public interface SpreadTree extends ExpressionTree {
+    /**
+     * Returns the expression that is being spread.
+     *
+     * @return The expression that is being spread.
+     */
+    ExpressionTree getExpression();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/SpreadTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import jdk.nashorn.internal.ir.Expression;
+
+final class SpreadTreeImpl extends ExpressionTreeImpl
+        implements SpreadTree {
+
+    private final ExpressionTree expr;
+
+    SpreadTreeImpl(final Expression exprNode, final ExpressionTree expr) {
+        super(exprNode);
+        this.expr = expr;
+    }
+
+    @Override
+    public Tree.Kind getKind() {
+        return Tree.Kind.SPREAD;
+    }
+
+    @Override
+    public ExpressionTree getExpression() {
+        return expr;
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitSpread(this, data);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TemplateLiteralTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+
+/**
+ * A tree node for <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-template-literals">template literal strings</a>.
+ *
+ * For example:
+ * <pre>
+ * `This is a String with ${computed} values in it`
+ * </pre>
+ *
+ * @since 9
+ *
+ */
+public interface TemplateLiteralTree extends ExpressionTree {
+    /**
+     * Returns the list of expressions in this template string
+     *
+     * @return the list of expressions in this template string
+     */
+    List<? extends ExpressionTree> getExpressions();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TemplateLiteralTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+import java.util.List;
+import jdk.nashorn.internal.ir.Expression;
+
+final class TemplateLiteralTreeImpl extends ExpressionTreeImpl
+        implements TemplateLiteralTree {
+
+    private final List<? extends ExpressionTree> expressions;
+
+    TemplateLiteralTreeImpl(Expression node, List<? extends ExpressionTree> expressions) {
+        super(node);
+        this.expressions = expressions;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.TEMPLATE_LITERAL;
+    }
+
+    @Override
+    public List<? extends ExpressionTree> getExpressions() {
+        return expressions;
+    }
+
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitTemplateLiteral(this, data);
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/Tree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/Tree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,16 @@
         BREAK(BreakTree.class),
 
         /**
+         * Used for instances of {@link ClassDeclarationTree}.
+         */
+        CLASS(ClassDeclarationTree.class),
+
+        /**
+         * Used for instances of {@link ClassExpressionTree}.
+         */
+        CLASS_EXPRESSION(ClassExpressionTree.class),
+
+        /**
          * Used for instances of {@link CaseTree}.
          */
         CASE(CaseTree.class),
@@ -150,6 +160,21 @@
         LABELED_STATEMENT(LabeledStatementTree.class),
 
         /**
+         * Used for instances of {@link ModuleTree}.
+         */
+        MODULE(ModuleTree.class),
+
+        /**
+         * Used for instances of {@link ExportEntryTree}.
+         */
+        EXPORT_ENTRY(ExportEntryTree.class),
+
+        /**
+         * Used for instances of {@link ImportEntryTree}.
+         */
+        IMPORT_ENTRY(ImportEntryTree.class),
+
+        /**
          * Used for instances of {@link FunctionDeclarationTree}.
          */
         FUNCTION(FunctionDeclarationTree.class),
@@ -185,6 +210,11 @@
         REGEXP_LITERAL(RegExpLiteralTree.class),
 
         /**
+         * Used for instances of {@link TemplateLiteralTree}.
+         */
+        TEMPLATE_LITERAL(TemplateLiteralTree.class),
+
+        /**
          * Used for instances of {@link ReturnTree}.
          */
         RETURN(ReturnTree.class),
@@ -286,7 +316,7 @@
 
         /**
          * Used for instances of {@link UnaryTree} representing logical
-         * void operator {@code typeof}.
+         * void operator {@code void}.
          */
         VOID(UnaryTree.class),
 
@@ -495,6 +525,18 @@
         OR_ASSIGNMENT(CompoundAssignmentTree.class),
 
         /**
+         * Used for instances of {@link SpreadTree} representing
+         * spread "operator" for arrays and function call arguments.
+         */
+        SPREAD(SpreadTree.class),
+
+        /**
+         * Used for instances of {@link YieldTree} representing (generator)
+         * yield expression {@code yield expr}.
+         */
+        YIELD(YieldTree.class),
+
+        /**
          * Used for instances of {@link LiteralTree} representing
          * a number literal expression of type {@code double}.
          */
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -137,10 +137,15 @@
                 return Kind.BITWISE_COMPLEMENT;
             case DELETE:
                 return Kind.DELETE;
+            case SPREAD_ARRAY:
+            case SPREAD_ARGUMENT:
+                return Kind.SPREAD;
             case TYPEOF:
                 return Kind.TYPEOF;
             case VOID:
                 return Kind.VOID;
+            case YIELD:
+                return Kind.YIELD;
             case IN:
                 return Kind.IN;
             case INSTANCEOF:
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeVisitor.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/TreeVisitor.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -118,6 +118,24 @@
     R visitCatch(CatchTree node, P p);
 
     /**
+     * Visit class statement tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitClassDeclaration(ClassDeclarationTree node, P p);
+
+    /**
+     * Visit class expression tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitClassExpression(ClassExpressionTree node, P p);
+
+    /**
      * Visit conditional expression tree.
      *
      * @param node node being visited
@@ -190,6 +208,15 @@
     R visitForInLoop(ForInLoopTree node, P p);
 
     /**
+     * Visit for..of statement tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitForOfLoop(ForOfLoopTree node, P p);
+
+    /**
      * Visit function call expression tree.
      *
      * @param node node being visited
@@ -216,7 +243,7 @@
      */
     R visitFunctionExpression(FunctionExpressionTree node, P p);
 
-        /**
+    /**
      * Visit identifier tree.
      *
      * @param node node being visited
@@ -334,6 +361,15 @@
     R visitRegExpLiteral(RegExpLiteralTree node, P p);
 
     /**
+     * Visit template literal tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitTemplateLiteral(TemplateLiteralTree node, P p);
+
+    /**
      * Visit an empty statement tree.
      *
      * @param node node being visited
@@ -343,6 +379,15 @@
     R visitEmptyStatement(EmptyStatementTree node, P p);
 
     /**
+     * Visit 'spread' expression tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitSpread(SpreadTree node, P p);
+
+    /**
      * Visit 'switch' statement tree.
      *
      * @param node node being visited
@@ -370,6 +415,33 @@
     R visitCompilationUnit(CompilationUnitTree node, P p);
 
     /**
+     * Visit Module tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitModule(ModuleTree node, P p);
+
+    /**
+     * Visit Module ExportEntry tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitExportEntry(ExportEntryTree node, P p);
+
+    /**
+     * Visit Module ImportEntry tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitImportEntry(ImportEntryTree node, P p);
+
+    /**
      * Visit 'try' statement tree.
      *
      * @param node node being visited
@@ -424,6 +496,15 @@
     R visitWith(WithTree node, P p);
 
     /**
+     * Visit 'yield' expression tree.
+     *
+     * @param node node being visited
+     * @param p extra parameter passed to the visitor
+     * @return value from the visitor
+     */
+    R visitYield(YieldTree node, P p);
+
+    /**
      * Visit unknown expression/statement tree. This fallback will be
      * called if new Tree subtypes are introduced in future. A specific
      * implementation may throw {{@linkplain UnknownTreeException unknown tree exception}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/VariableTree.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/VariableTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,22 +26,26 @@
 package jdk.nashorn.api.tree;
 
 /**
- * A tree node for a variable declaration.
+ * A tree node for a <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-variable-statement">variable declaration statement</a>.
  *
  * For example:
  * <pre>
- *   <em>var</em> <em>name</em> <em>initializer</em> ;
+ *   <em>var</em> <em>name</em> [ <em>initializer</em> ] ;
+ *   <em>var</em> <em>binding_pattern</em> [ <em>initializer</em> ];
  * </pre>
  *
  * @since 9
  */
 public interface VariableTree extends StatementTree {
     /**
-     * Returns the name of this variable.
+     * Returns the binding of this declaration. This is an {@link IdentifierTree}
+     * for a binding identifier case (simple variable declaration).
+     * This is an {@link ObjectLiteralTree} or a {@link ArrayLiteralTree} for a
+     * destructuring declaration.
      *
-     * @return the name of this variable
+     * @return the binding expression of this declaration
      */
-    String getName();
+    ExpressionTree getBinding();
 
     /**
      * Returns the initial value expression for this variable. This is
@@ -50,4 +54,18 @@
      * @return the initial value expression
      */
     ExpressionTree getInitializer();
+
+    /**
+     * Is this a const declaration?
+     *
+     * @return true if this is a const declaration
+     */
+    boolean isConst();
+
+    /**
+     * Is this a let declaration?
+     *
+     * @return true if this is a let declaration
+     */
+    boolean isLet();
 }
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/VariableTreeImpl.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/VariableTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,12 +28,12 @@
 import jdk.nashorn.internal.ir.VarNode;
 
 final class VariableTreeImpl extends StatementTreeImpl implements VariableTree {
-    private final String name;
+    private final IdentifierTree ident;
     private final ExpressionTree init;
 
-    VariableTreeImpl(final VarNode node, final ExpressionTree init) {
+    VariableTreeImpl(final VarNode node, final IdentifierTree ident, final ExpressionTree init) {
         super(node);
-        this.name = node.getName().getName();
+        this.ident = ident;
         this.init = init;
     }
 
@@ -43,8 +43,8 @@
     }
 
     @Override
-    public String getName() {
-        return name;
+    public ExpressionTree getBinding() {
+        return ident;
     }
 
     @Override
@@ -53,6 +53,16 @@
     }
 
     @Override
+    public boolean isConst() {
+        return ((VarNode)node).isConst();
+    }
+
+    @Override
+    public boolean isLet() {
+        return ((VarNode)node).isLet();
+    }
+
+    @Override
     public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
         return visitor.visitVariable(this, data);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/YieldTree.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.api.tree;
+
+/**
+ *  A tree node for <a href="http://www.ecma-international.org/ecma-262/6.0/#sec-generator-function-definitions">yield expressions</a> used in generator functions.
+ *
+ * For example:
+ * <pre>
+ * <em>function*</em> id(){
+ *     var index = 0;
+ *     while(index &lt; 10)
+ *         <em>yield index++;</em>
+ * }
+ * </pre>
+ *
+ * @since 9
+ */
+public interface YieldTree extends ExpressionTree {
+    /**
+     * Returns the expression that is yielded.
+     *
+     * @return The expression that is yielded.
+     */
+    ExpressionTree getExpression();
+
+    /**
+     * Is this a yield * expression in a generator function?
+     *
+     * For example:
+     * <pre>
+     * function* id(){
+     *     yield 1;
+     *     <em>yield * anotherGeneratorFunc();</em>
+     *     yield 10;
+     * }
+     * </pre>
+     *
+     *
+     * @return true if this is a yield * expression
+     */
+    boolean isStar();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/tree/YieldTreeImpl.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.nashorn.api.tree;
+
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.parser.TokenType;
+
+final class YieldTreeImpl extends ExpressionTreeImpl
+        implements YieldTree {
+
+    private final ExpressionTree expr;
+
+    YieldTreeImpl(final Expression exprNode, final ExpressionTree expr) {
+        super(exprNode);
+        this.expr = expr;
+    }
+
+    @Override
+    public Kind getKind() {
+        return Kind.YIELD;
+    }
+
+    @Override
+    public ExpressionTree getExpression() {
+        return expr;
+    }
+
+    @Override
+    public boolean isStar() {
+        return ((UnaryNode) node).isTokenType(TokenType.YIELD_STAR);
+    }
+
+    @Override
+    public <R,D> R accept(final TreeVisitor<R,D> visitor, final D data) {
+        return visitor.visitYield(this, data);
+    }
+}
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/codegen/SplitIntoFunctions.java	Mon Jul 18 09:38:08 2016 -0700
@@ -167,6 +167,7 @@
                 createIdent(name),
                 originalFn.getName() + "$" + name,
                 isProgram ? Collections.singletonList(createReturnParamIdent()) : Collections.<IdentNode>emptyList(),
+                null,
                 FunctionNode.Kind.NORMAL,
                 // We only need IS_SPLIT conservatively, in case it contains any array units so that we force
                 // the :callee's existence, to force :scope to never be in a slot lower than 2. This is actually
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ClassNode.java	Mon Jul 18 09:38:08 2016 -0700
@@ -42,6 +42,7 @@
     private final PropertyNode constructor;
     private final List<PropertyNode> classElements;
     private final int line;
+    private final boolean isStatement;
 
     /**
      * Constructor.
@@ -53,15 +54,17 @@
      * @param classHeritage class heritage
      * @param constructor constructor
      * @param classElements class elements
+     * @param isStatement is this a statement or an expression?
      */
     public ClassNode(final int line, final long token, final int finish, final IdentNode ident, final Expression classHeritage, final PropertyNode constructor,
-                     final List<PropertyNode> classElements) {
+                     final List<PropertyNode> classElements, final boolean isStatement) {
         super(token, finish);
         this.line = line;
         this.ident = ident;
         this.classHeritage = classHeritage;
         this.constructor = constructor;
         this.classElements = classElements;
+        this.isStatement = isStatement;
     }
 
     /**
@@ -101,6 +104,15 @@
     }
 
     /**
+     * Returns if this class was a statement or an expression
+     *
+     * @return true if this class was a statement
+     */
+    public boolean isStatement() {
+        return isStatement;
+    }
+
+    /**
      * Returns the line number.
      *
      * @return the line number
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionStatement.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/ExpressionStatement.java	Mon Jul 18 09:38:08 2016 -0700
@@ -27,6 +27,7 @@
 
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
 
 /**
  * IR representation for executing bare expressions. Basically, an expression
@@ -39,6 +40,23 @@
 
     /** Expression to execute. */
     private final Expression expression;
+    private final TokenType destructuringDecl;
+
+    /**
+     * Constructor
+     *
+     * @param lineNumber line number
+     * @param token      token
+     * @param finish     finish
+     * @param expression the expression to execute
+     * @param destructuringDecl does this statement represent a destructuring declaration?
+     */
+    public ExpressionStatement(final int lineNumber, final long token, final int finish,
+            final Expression expression, final TokenType destructuringDecl) {
+        super(lineNumber, token, finish);
+        this.expression = expression;
+        this.destructuringDecl = destructuringDecl;
+    }
 
     /**
      * Constructor
@@ -49,13 +67,13 @@
      * @param expression the expression to execute
      */
     public ExpressionStatement(final int lineNumber, final long token, final int finish, final Expression expression) {
-        super(lineNumber, token, finish);
-        this.expression = expression;
+        this(lineNumber, token, finish, expression, null);
     }
 
     private ExpressionStatement(final ExpressionStatement expressionStatement, final Expression expression) {
         super(expressionStatement);
         this.expression = expression;
+        this.destructuringDecl = null;
     }
 
     @Override
@@ -81,6 +99,15 @@
     }
 
     /**
+     * Return declaration type if this expression statement is a destructuring declaration
+     *
+     * @return declaration type (LET, VAR, CONST) if destructuring declaration, null otherwise.
+     */
+    public TokenType destructuringDeclarationType() {
+        return destructuringDecl;
+    }
+
+    /**
      * Reset the expression to be executed
      * @param expression the expression
      * @return new or same execute node
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/FunctionNode.java	Mon Jul 18 09:38:08 2016 -0700
@@ -35,6 +35,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
@@ -106,6 +107,9 @@
     /** List of parameters. */
     private final List<IdentNode> parameters;
 
+    /** Map of ES6 function parameter expressions. */
+    private final Map<IdentNode, Expression> parameterExpressions;
+
     /** First token of function. **/
     private final long firstToken;
 
@@ -242,6 +246,9 @@
     /** Does this function use new.target? */
     public static final int ES6_USES_NEW_TARGET         = 1 << 25;
 
+    /** Does this function have expression as its body? */
+    public static final int HAS_EXPRESSION_BODY         = 1 << 26;
+
     /** Does this function or any nested functions contain an eval? */
     private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
 
@@ -306,6 +313,7 @@
      * @param ident      the identifier
      * @param name       the name of the function
      * @param parameters parameter list
+     * @param paramExprs the ES6 function parameter expressions
      * @param kind       kind of function as in {@link FunctionNode.Kind}
      * @param flags      initial flags
      * @param body       body of the function
@@ -324,6 +332,7 @@
         final IdentNode ident,
         final String name,
         final List<IdentNode> parameters,
+        final Map<IdentNode, Expression> paramExprs,
         final FunctionNode.Kind kind,
         final int flags,
         final Block body,
@@ -338,6 +347,7 @@
         this.name             = name;
         this.kind             = kind;
         this.parameters       = parameters;
+        this.parameterExpressions = paramExprs;
         this.firstToken       = firstToken;
         this.lastToken        = lastToken;
         this.namespace        = namespace;
@@ -375,6 +385,7 @@
         this.lastToken        = lastToken;
         this.body             = body;
         this.parameters       = parameters;
+        this.parameterExpressions = functionNode.parameterExpressions;
         this.thisProperties   = thisProperties;
         this.rootClass        = rootClass;
         this.source           = source;
@@ -977,6 +988,15 @@
     }
 
     /**
+     * Get the ES6 style parameter expressions of this function. This may be null.
+     *
+     * @return a Map of parameter IdentNode to Expression node (for ES6 parameter expressions)
+     */
+    public Map<IdentNode, Expression> getParameterExpressions() {
+        return parameterExpressions;
+    }
+
+    /**
      * Return the number of parameters to this function
      * @return the number of parameters
      */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/TemplateLiteral.java	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.Collections;
+import java.util.List;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * Represents ES6 template string expression. Note that this Node class is used
+ * only in "parse only" mode. In evaluation mode, Parser directly folds template
+ * literal as string concatenation. Parser API uses this node to represent ES6
+ * template literals "as is" rather than as a String concatenation.
+ */
+public final class TemplateLiteral extends Expression {
+    private static final long serialVersionUID = 1L;
+    private final List<Expression> exprs;
+
+    public TemplateLiteral(final List<Expression> exprs) {
+        super(exprs.get(0).getToken(), exprs.get(exprs.size() - 1).finish);
+        this.exprs = exprs;
+    }
+
+    @Override
+    public Type getType() {
+        return Type.STRING;
+    }
+
+    @Override
+    public Node accept(NodeVisitor<? extends LexicalContext> visitor) {
+        if (visitor.enterTemplateLiteral(this)) {
+            return visitor.leaveTemplateLiteral(this);
+        }
+
+        return this;
+    }
+
+    @Override
+    public void toString(StringBuilder sb, boolean printType) {
+        for (Expression expr : exprs) {
+            sb.append(expr);
+        }
+    }
+
+    /**
+     * The list of expressions that are part of this template literal.
+     *
+     * @return the list of expressions that are part of this template literal.
+     */
+    public List<Expression> getExpressions() {
+        return Collections.unmodifiableList(exprs);
+    }
+}
\ No newline at end of file
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/ir/visitor/NodeVisitor.java	Mon Jul 18 09:38:08 2016 -0700
@@ -59,6 +59,7 @@
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.SplitReturn;
 import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.TemplateLiteral;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
@@ -738,6 +739,26 @@
     }
 
     /**
+     * Callback for entering a TemplateLiteral (used only in --parse-only mode)
+     *
+     * @param  templateLiteral the node
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    public boolean enterTemplateLiteral(final TemplateLiteral templateLiteral) {
+        return enterDefault(templateLiteral);
+    }
+
+    /**
+     * Callback for leaving a TemplateLiteral (used only in --parse-only mode)
+     *
+     * @param  templateLiteral the node
+     * @return processed node, which will replace the original one, or the original node
+     */
+    public Node leaveTemplateLiteral(final TemplateLiteral templateLiteral) {
+        return leaveDefault(templateLiteral);
+    }
+
+    /**
      * Callback for entering a TernaryNode
      *
      * @param  ternaryNode the node
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/Parser.java	Mon Jul 18 09:38:08 2016 -0700
@@ -127,6 +127,7 @@
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.TemplateLiteral;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
@@ -545,7 +546,7 @@
         sb.append(ident.getName());
 
         final String name = namespace.uniqueName(sb.toString());
-        assert parentFunction != null || name.equals(PROGRAM.symbolName()) : "name = " + name;
+        assert parentFunction != null || kind == FunctionNode.Kind.MODULE || name.equals(PROGRAM.symbolName()) : "name = " + name;
 
         int flags = 0;
         if (isStrictMode) {
@@ -575,6 +576,7 @@
                 ident,
                 function.getName(),
                 parameters,
+                function.getParameterExpressions(),
                 kind,
                 function.getFlags(),
                 body,
@@ -623,19 +625,6 @@
     }
 
     /**
-     * Get the statements in a case clause.
-     */
-    private List<Statement> caseStatementList() {
-        final ParserContextBlockNode newBlock = newBlock();
-        try {
-            statementList();
-        } finally {
-            restoreBlock(newBlock);
-        }
-        return newBlock.getStatements();
-    }
-
-    /**
      * Get all the statements generated by a single statement.
      * @return Statements.
      */
@@ -855,17 +844,6 @@
         });
     }
 
-    private static Expression newBinaryExpression(final long op, final Expression lhs, final Expression rhs) {
-        final TokenType opType = Token.descType(op);
-
-        // Build up node.
-        if (BinaryNode.isLogical(opType)) {
-            return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
-        }
-        return new BinaryNode(op, lhs, rhs);
-    }
-
-
     /**
      * Reduce increment/decrement to simpler operations.
      * @param firstToken First token.
@@ -1268,7 +1246,7 @@
             className = getIdent();
         }
 
-        return classTail(classLineNumber, classToken, className);
+        return classTail(classLineNumber, classToken, className, isStatement);
     }
 
     private static final class ClassElementKey {
@@ -1317,7 +1295,8 @@
      *   static MethodDefinition[?Yield]
      *   ;
      */
-    private ClassNode classTail(final int classLineNumber, final long classToken, final IdentNode className) {
+    private ClassNode classTail(final int classLineNumber, final long classToken,
+            final IdentNode className, final boolean isStatement) {
         final boolean oldStrictMode = isStrictMode;
         isStrictMode = true;
         try {
@@ -1399,7 +1378,7 @@
             }
 
             classElements.trimToSize();
-            return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements);
+            return new ClassNode(classLineNumber, classToken, finish, className, classHeritage, constructor, classElements, isStatement);
         } finally {
             isStrictMode = oldStrictMode;
         }
@@ -1601,6 +1580,9 @@
     private List<Expression> variableDeclarationList(final TokenType varType, final boolean isStatement, final int sourceOrder) {
         // VAR tested in caller.
         assert varType == VAR || varType == LET || varType == CONST;
+        final int varLine = line;
+        final long varToken = token;
+
         next();
 
         final List<Expression> bindings = new ArrayList<>();
@@ -1613,9 +1595,6 @@
 
         Expression missingAssignment = null;
         while (true) {
-            // Get starting token.
-            final int  varLine  = line;
-            final long varToken = token;
             // Get name of var.
             if (type == YIELD && inGeneratorFunction()) {
                 expect(IDENT);
@@ -1627,10 +1606,14 @@
             if (isDestructuring) {
                 final int finalVarFlags = varFlags;
                 verifyDestructuringBindingPattern(binding, new Consumer<IdentNode>() {
+                    @Override
                     public void accept(final IdentNode identNode) {
                         verifyIdent(identNode, contextString);
-                        final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
-                        appendStatement(var);
+                        if (!env._parse_only) {
+                            // don't bother adding a variable if we are just parsing!
+                            final VarNode var = new VarNode(varLine, varToken, sourceOrder, identNode.getFinish(), identNode.setIsDeclaredHere(), null, finalVarFlags);
+                            appendStatement(var);
+                        }
                     }
                 });
             }
@@ -1682,7 +1665,7 @@
                 assert init != null || !isStatement;
                 binding = init == null ? binding : verifyAssignment(Token.recast(varToken, ASSIGN), binding, init);
                 if (isStatement) {
-                    appendStatement(new ExpressionStatement(varLine, binding.getToken(), finish, binding));
+                    appendStatement(new ExpressionStatement(varLine, binding.getToken(), finish, binding, varType));
                 } else if (init == null) {
                     if (missingAssignment == null) {
                         missingAssignment = binding;
@@ -1748,7 +1731,8 @@
      * Verify destructuring variable declaration binding pattern and extract bound variable declarations.
      */
     private void verifyDestructuringBindingPattern(final Expression pattern, final Consumer<IdentNode> identifierCallback) {
-        assert pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
+        assert (pattern instanceof BinaryNode && ((BinaryNode)pattern).isTokenType(ASSIGN)) ||
+                pattern instanceof ObjectNode || pattern instanceof LiteralNode.ArrayLiteralNode;
         pattern.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
@@ -1857,9 +1841,8 @@
         // Get expression and add as statement.
         final Expression expression = expression();
 
-        ExpressionStatement expressionStatement = null;
         if (expression != null) {
-            expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
+            ExpressionStatement expressionStatement = new ExpressionStatement(expressionLine, expressionToken, finish, expression);
             appendStatement(expressionStatement);
         } else {
             expect(null);
@@ -2625,6 +2608,10 @@
                 final long catchToken = token;
                 next();
                 expect(LPAREN);
+
+                // FIXME: ES6 catch parameter can be a BindingIdentifier or a BindingPattern
+                // We need to generalize this here!
+                // http://www.ecma-international.org/ecma-262/6.0/
                 final IdentNode exception = getIdent();
 
                 // ECMA 12.4.1 strict mode restrictions
@@ -4021,12 +4008,18 @@
 
                     ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
                     if (currentFunction != null) {
-                        // desugar to: param = (param === undefined) ? initializer : param;
-                        // possible alternative: if (param === undefined) param = initializer;
-                        BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
-                        TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
-                        BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
-                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                        if (env._parse_only) {
+                            // keep what is seen in source "as is" and save it as parameter expression
+                            BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, initializer);
+                            currentFunction.addParameterExpression(ident, assignment);
+                        } else {
+                            // desugar to: param = (param === undefined) ? initializer : param;
+                            // possible alternative: if (param === undefined) param = initializer;
+                            BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                            TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                            BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
+                            lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                        }
                     }
                 }
 
@@ -4050,16 +4043,31 @@
 
                     // binding pattern with initializer. desugar to: (param === undefined) ? initializer : param
                     Expression initializer = assignmentExpression(false);
-                    // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
-                    BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
-                    value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+
+                    if (env._parse_only) {
+                        // we don't want the synthetic identifier in parse only mode
+                        value = initializer;
+                    } else {
+                        // TODO initializer must not contain yield expression if yield=true (i.e. this is generator function's parameter list)
+                        BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                        value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                    }
                 }
 
                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
                 if (currentFunction != null) {
                     // destructuring assignment
                     BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), pattern, value);
-                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    if (env._parse_only) {
+                        // in parse-only mode, represent source tree "as is"
+                        if (ident.isDefaultParameter()) {
+                            currentFunction.addParameterExpression(ident, assignment);
+                        } else {
+                            currentFunction.addParameterExpression(ident, pattern);
+                        }
+                    } else {
+                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    }
                 }
             }
             parameters.add(ident);
@@ -4077,7 +4085,9 @@
                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
                 if (currentFunction != null) {
                     // declare function-scope variables for destructuring bindings
-                    lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
+                    if (!env._parse_only) {
+                        lc.getFunctionBody(currentFunction).appendStatement(new VarNode(paramLine, Token.recast(paramToken, VAR), pattern.getFinish(), identNode, null));
+                    }
                     // detect duplicate bounds names in parameter list
                     currentFunction.addParameterBinding(identNode);
                     currentFunction.setSimpleParameterList(false);
@@ -4136,6 +4146,7 @@
                 // the note below for reasoning on skipping happening before instead of after RBRACE for
                 // details).
                 if (parseBody) {
+                    functionNode.setFlag(FunctionNode.HAS_EXPRESSION_BODY);
                     final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
                     appendStatement(returnNode);
                 }
@@ -4305,7 +4316,7 @@
     }
 
     private RuntimeNode referenceError(final Expression lhs, final Expression rhs, final boolean earlyError) {
-        if (earlyError) {
+        if (env._parse_only || earlyError) {
             throw error(JSErrorType.REFERENCE_ERROR, AbstractParser.message("invalid.lvalue"), lhs.getToken());
         }
         final ArrayList<Expression> args = new ArrayList<>();
@@ -4838,10 +4849,14 @@
 
                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
                 if (currentFunction != null) {
-                    BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
-                    TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
-                    BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
-                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    if (env._parse_only) {
+                        currentFunction.addParameterExpression(ident, param);
+                    } else {
+                        BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                        TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                        BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), ident, value);
+                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    }
 
                     currentFunction.addParameterBinding(ident);
                     currentFunction.setSimpleParameterList(false);
@@ -4855,10 +4870,14 @@
 
                 ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
                 if (currentFunction != null) {
-                    BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
-                    TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
-                    BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
-                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    if (env._parse_only) {
+                        currentFunction.addParameterExpression(ident, param);
+                    } else {
+                        BinaryNode test = new BinaryNode(Token.recast(paramToken, EQ_STRICT), ident, newUndefinedLiteral(paramToken, finish));
+                        TernaryNode value = new TernaryNode(Token.recast(paramToken, TERNARY), test, new JoinPredecessorExpression(initializer), new JoinPredecessorExpression(ident));
+                        BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, value);
+                        lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                    }
                 }
                 return ident;
             }
@@ -4872,8 +4891,12 @@
 
             ParserContextFunctionNode currentFunction = lc.getCurrentFunction();
             if (currentFunction != null) {
-                BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
-                lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                if (env._parse_only) {
+                    currentFunction.addParameterExpression(ident, param);
+                } else {
+                    BinaryNode assignment = new BinaryNode(Token.recast(paramToken, ASSIGN), param, ident);
+                    lc.getFunctionBody(currentFunction).appendStatement(new ExpressionStatement(paramLine, assignment.getToken(), assignment.getFinish(), assignment));
+                }
             }
             return ident;
         }
@@ -4982,20 +5005,37 @@
             return literal;
         }
 
-        Expression concat = literal;
-        TokenType lastLiteralType;
-        do {
-            final Expression expression = expression();
-            if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
-                throw error(AbstractParser.message("unterminated.template.expression"), token);
-            }
-            concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
-            lastLiteralType = type;
-            lastLiteralToken = token;
-            literal = getLiteral();
-            concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
-        } while (lastLiteralType == TEMPLATE_MIDDLE);
-        return concat;
+        if (env._parse_only) {
+            List<Expression> exprs = new ArrayList<>();
+            exprs.add(literal);
+            TokenType lastLiteralType;
+            do {
+                final Expression expression = expression();
+                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
+                    throw error(AbstractParser.message("unterminated.template.expression"), token);
+                }
+                exprs.add(expression);
+                lastLiteralType = type;
+                literal = getLiteral();
+                exprs.add(literal);
+            } while (lastLiteralType == TEMPLATE_MIDDLE);
+            return new TemplateLiteral(exprs);
+        } else {
+            Expression concat = literal;
+            TokenType lastLiteralType;
+            do {
+                final Expression expression = expression();
+                if (type != TEMPLATE_MIDDLE && type != TEMPLATE_TAIL) {
+                    throw error(AbstractParser.message("unterminated.template.expression"), token);
+                }
+                concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, expression);
+                lastLiteralType = type;
+                lastLiteralToken = token;
+                literal = getLiteral();
+                concat = new BinaryNode(Token.recast(lastLiteralToken, TokenType.ADD), concat, literal);
+            } while (lastLiteralType == TEMPLATE_MIDDLE);
+            return concat;
+        }
     }
 
     /**
--- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/parser/ParserContextFunctionNode.java	Mon Jul 18 09:38:08 2016 -0700
@@ -24,9 +24,12 @@
  */
 package jdk.nashorn.internal.parser;
 
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
 import jdk.nashorn.internal.codegen.Namespace;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.Module;
@@ -70,6 +73,7 @@
     private Module module;
 
     private int debugFlags;
+    private Map<IdentNode, Expression> parameterExpressions;
 
     /**
      * @param token The token for the function
@@ -170,6 +174,22 @@
     }
 
     /**
+     * Return ES6 function parameter expressions
+     *
+     * @return ES6 function parameter expressions
+     */
+    public Map<IdentNode, Expression> getParameterExpressions() {
+        return parameterExpressions;
+    }
+
+    void addParameterExpression(IdentNode ident, Expression node) {
+        if (parameterExpressions == null) {
+            parameterExpressions = new HashMap<>();
+        }
+        parameterExpressions.put(ident, node);
+    }
+
+    /**
      * Set last token
      * @param token New last token
      */
--- a/nashorn/test/script/basic/JDK-8075207.js	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/basic/JDK-8075207.js	Mon Jul 18 09:38:08 2016 -0700
@@ -61,7 +61,7 @@
 Assert.assertTrue(stats.get(2) instanceof VariableTree);
 
 var print_hello = stats.get(1);
-Assert.assertEquals(print_hello.name, "print_hello");
+Assert.assertEquals(print_hello.name.name, "print_hello");
 var print_hello_stats = print_hello.body.statements;
 Assert.assertTrue(print_hello_stats.get(0) instanceof VariableTree);
 Assert.assertTrue(print_hello_stats.get(1) instanceof ExpressionStatementTree);
--- a/nashorn/test/script/basic/JDK-8075448.js	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/basic/JDK-8075448.js	Mon Jul 18 09:38:08 2016 -0700
@@ -44,6 +44,6 @@
 var stats = ast.sourceElements;
 
 Assert.assertTrue(stats[0] instanceof VariableTree);
-Assert.assertEquals(stats[0].name, "i");
+Assert.assertEquals(stats[0].binding.name, "i");
 Assert.assertTrue(stats[1] instanceof ForLoopTree);
 
--- a/nashorn/test/script/basic/es6/let-const-switch.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/basic/es6/let-const-switch.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -1,12 +1,12 @@
-1
-2
-0
-1
-2
-0
-SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:25 Unsupported let declaration in unprotected switch statement
-switch (x) { case 0: let x = 1; }
-                         ^
-SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:27 Unsupported const declaration in unprotected switch statement
-switch (x) { case 0: const x = 1; }
-                           ^
+1
+2
+0
+1
+2
+0
+SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:21 Unsupported let declaration in unprotected switch statement
+switch (x) { case 0: let x = 1; }
+                     ^
+SyntaxError: test/script/basic/es6/let-const-switch.js#34:8<eval>:1:21 Unsupported const declaration in unprotected switch statement
+switch (x) { case 0: const x = 1; }
+                     ^
--- a/nashorn/test/script/nosecurity/parserapi.js	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/parserapi.js	Mon Jul 18 09:38:08 2016 -0700
@@ -62,6 +62,26 @@
     var result = {};
     for (var i in obj) {
         var val = obj[i];
+        // skip these ES6 specific properties to reduce noise
+        // in the output - unless there were set to true
+        if (typeof(val) == 'boolean' && val == false) {
+            switch (i) {
+                case "computed":
+                case "static":
+                case "restParameter":
+                case "this":
+                case "super":
+                case "star":
+                case "default":
+                case "starDefaultStar":
+                case "arrow":
+                case "generator":
+                case "let":
+                case "const":
+                    continue;
+             }
+        }
+
         if (val instanceof Parser.Tree) {
             result[i] = this.convert(val);
         } else if (val instanceof Parser.List) {
--- a/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/parserapi.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -1,4 +1,4 @@
-[
+[
 {
   "endPosition": "1113",
   "kind": "COMPILATION_UNIT",
@@ -6,8 +6,13 @@
     {
       "endPosition": "1123",
       "kind": "VARIABLE",
-      "name": "x",
-      "startPosition": "1117",
+      "binding": {
+        "endPosition": "1118",
+        "kind": "IDENTIFIER",
+        "name": "x",
+        "startPosition": "1117"
+      },
+      "startPosition": "1113",
       "initializer": {
         "endPosition": "1123",
         "kind": "ARRAY_LITERAL",
@@ -18,8 +23,13 @@
     {
       "endPosition": "1147",
       "kind": "VARIABLE",
-      "name": "y",
-      "startPosition": "1129",
+      "binding": {
+        "endPosition": "1130",
+        "kind": "IDENTIFIER",
+        "name": "y",
+        "startPosition": "1129"
+      },
+      "startPosition": "1125",
       "initializer": {
         "endPosition": "1147",
         "kind": "ARRAY_LITERAL",
@@ -55,8 +65,13 @@
     {
       "endPosition": "1165",
       "kind": "VARIABLE",
-      "name": "z",
-      "startPosition": "1153",
+      "binding": {
+        "endPosition": "1154",
+        "kind": "IDENTIFIER",
+        "name": "z",
+        "startPosition": "1153"
+      },
+      "startPosition": "1149",
       "initializer": {
         "endPosition": "1165",
         "kind": "ARRAY_LITERAL",
@@ -82,8 +97,13 @@
     {
       "endPosition": "1200",
       "kind": "VARIABLE",
-      "name": "k",
-      "startPosition": "1171",
+      "binding": {
+        "endPosition": "1172",
+        "kind": "IDENTIFIER",
+        "name": "k",
+        "startPosition": "1171"
+      },
+      "startPosition": "1167",
       "initializer": {
         "endPosition": "1200",
         "kind": "ARRAY_LITERAL",
@@ -132,8 +152,8 @@
   "sourceName": "parsertests/array_literal.js",
   "strict": "false",
   "startPosition": "1113"
-}
-,
+}
+,
 {
   "endPosition": "1126",
   "kind": "COMPILATION_UNIT",
@@ -406,8 +426,8 @@
   "sourceName": "parsertests/assignmentExpr.js",
   "strict": "false",
   "startPosition": "1126"
-}
-,
+}
+,
 {
   "endPosition": "1116",
   "kind": "COMPILATION_UNIT",
@@ -912,8 +932,8 @@
   "sourceName": "parsertests/binaryExpr.js",
   "strict": "false",
   "startPosition": "1116"
-}
-,
+}
+,
 {
   "endPosition": "1117",
   "kind": "COMPILATION_UNIT",
@@ -959,8 +979,8 @@
   "sourceName": "parsertests/block.js",
   "strict": "false",
   "startPosition": "1117"
-}
-,
+}
+,
 {
   "endPosition": "1117",
   "kind": "COMPILATION_UNIT",
@@ -1060,8 +1080,8 @@
   "sourceName": "parsertests/breakStat.js",
   "strict": "false",
   "startPosition": "1117"
-}
-,
+}
+,
 {
   "endPosition": "1117",
   "kind": "COMPILATION_UNIT",
@@ -1098,8 +1118,8 @@
   "sourceName": "parsertests/condExpr.js",
   "strict": "false",
   "startPosition": "1117"
-}
-,
+}
+,
 {
   "endPosition": "1120",
   "kind": "COMPILATION_UNIT",
@@ -1199,8 +1219,8 @@
   "sourceName": "parsertests/continueStat.js",
   "strict": "false",
   "startPosition": "1120"
-}
-,
+}
+,
 {
   "endPosition": "1118",
   "kind": "COMPILATION_UNIT",
@@ -1214,8 +1234,8 @@
   "sourceName": "parsertests/debuggerStat.js",
   "strict": "false",
   "startPosition": "1118"
-}
-,
+}
+,
 {
   "endPosition": "1137",
   "kind": "COMPILATION_UNIT",
@@ -1223,7 +1243,12 @@
     {
       "endPosition": "1172",
       "kind": "FUNCTION",
-      "name": "hello",
+      "name": {
+        "endPosition": "1151",
+        "kind": "IDENTIFIER",
+        "name": "hello",
+        "startPosition": "1146"
+      },
       "body": {
         "endPosition": "1170",
         "kind": "BLOCK",
@@ -1262,7 +1287,12 @@
     {
       "endPosition": "1203",
       "kind": "FUNCTION",
-      "name": "hello",
+      "name": {
+        "endPosition": "1187",
+        "kind": "IDENTIFIER",
+        "name": "hello",
+        "startPosition": "1182"
+      },
       "body": {
         "endPosition": "1201",
         "kind": "BLOCK",
@@ -1308,7 +1338,12 @@
     {
       "endPosition": "1240",
       "kind": "FUNCTION",
-      "name": "hello",
+      "name": {
+        "endPosition": "1218",
+        "kind": "IDENTIFIER",
+        "name": "hello",
+        "startPosition": "1213"
+      },
       "body": {
         "endPosition": "1238",
         "kind": "BLOCK",
@@ -1366,8 +1401,13 @@
     {
       "endPosition": "1282",
       "kind": "VARIABLE",
-      "name": "hello",
-      "startPosition": "1245",
+      "binding": {
+        "endPosition": "1250",
+        "kind": "IDENTIFIER",
+        "name": "hello",
+        "startPosition": "1245"
+      },
+      "startPosition": "1241",
       "initializer": {
         "endPosition": "1264",
         "kind": "FUNCTION_EXPRESSION",
@@ -1410,12 +1450,22 @@
     {
       "endPosition": "1331",
       "kind": "VARIABLE",
-      "name": "hello",
-      "startPosition": "1288",
+      "binding": {
+        "endPosition": "1293",
+        "kind": "IDENTIFIER",
+        "name": "hello",
+        "startPosition": "1288"
+      },
+      "startPosition": "1284",
       "initializer": {
         "endPosition": "1313",
         "kind": "FUNCTION_EXPRESSION",
-        "name": "hello",
+        "name": {
+          "endPosition": "1310",
+          "kind": "IDENTIFIER",
+          "name": "hello",
+          "startPosition": "1305"
+        },
         "body": {
           "endPosition": "1329",
           "kind": "BLOCK",
@@ -1473,7 +1523,12 @@
     {
       "endPosition": "1380",
       "kind": "FUNCTION",
-      "name": "test",
+      "name": {
+        "endPosition": "1361",
+        "kind": "IDENTIFIER",
+        "name": "test",
+        "startPosition": "1357"
+      },
       "body": {
         "endPosition": "1377",
         "kind": "BLOCK",
@@ -1500,8 +1555,8 @@
   "sourceName": "parsertests/functions.js",
   "strict": "false",
   "startPosition": "1137"
-}
-,
+}
+,
 {
   "endPosition": "1114",
   "kind": "COMPILATION_UNIT",
@@ -1604,8 +1659,8 @@
   "sourceName": "parsertests/ifStat.js",
   "strict": "false",
   "startPosition": "1114"
-}
-,
+}
+,
 {
   "endPosition": "1113",
   "kind": "COMPILATION_UNIT",
@@ -1668,8 +1723,8 @@
   "sourceName": "parsertests/labelledStat.js",
   "strict": "false",
   "startPosition": "1113"
-}
-,
+}
+,
 {
   "endPosition": "1125",
   "kind": "COMPILATION_UNIT",
@@ -2066,8 +2121,8 @@
   "sourceName": "parsertests/lhsExpr.js",
   "strict": "false",
   "startPosition": "1125"
-}
-,
+}
+,
 {
   "endPosition": "1110",
   "kind": "COMPILATION_UNIT",
@@ -2350,8 +2405,8 @@
   "sourceName": "parsertests/loopStat.js",
   "strict": "false",
   "startPosition": "1110"
-}
-,
+}
+,
 {
   "endPosition": "1125",
   "kind": "COMPILATION_UNIT",
@@ -2608,6 +2663,7 @@
                         "expression": {
                           "endPosition": "1272",
                           "kind": "IDENTIFIER",
+                          "this": "true",
                           "name": "this",
                           "startPosition": "1268"
                         },
@@ -2650,6 +2706,7 @@
                           "expression": {
                             "endPosition": "1300",
                             "kind": "IDENTIFIER",
+                            "this": "true",
                             "name": "this",
                             "startPosition": "1296"
                           },
@@ -2705,8 +2762,8 @@
   "sourceName": "parsertests/objectLitExpr.js",
   "strict": "false",
   "startPosition": "1125"
-}
-,
+}
+,
 {
   "endPosition": "1118",
   "kind": "COMPILATION_UNIT",
@@ -2781,8 +2838,8 @@
   "sourceName": "parsertests/parenExpr.js",
   "strict": "false",
   "startPosition": "1118"
-}
-,
+}
+,
 {
   "endPosition": "1119",
   "kind": "COMPILATION_UNIT",
@@ -2791,6 +2848,7 @@
       "expression": {
         "endPosition": "1123",
         "kind": "IDENTIFIER",
+        "this": "true",
         "name": "this",
         "startPosition": "1119"
       },
@@ -2995,8 +3053,8 @@
   "sourceName": "parsertests/primaryExpr.js",
   "strict": "false",
   "startPosition": "1119"
-}
-,
+}
+,
 {
   "endPosition": "1114",
   "kind": "COMPILATION_UNIT",
@@ -3004,8 +3062,13 @@
     {
       "endPosition": "1127",
       "kind": "VARIABLE",
-      "name": "x",
-      "startPosition": "1118",
+      "binding": {
+        "endPosition": "1119",
+        "kind": "IDENTIFIER",
+        "name": "x",
+        "startPosition": "1118"
+      },
+      "startPosition": "1114",
       "initializer": {
         "endPosition": "1127",
         "kind": "REGEXP_LITERAL",
@@ -3017,8 +3080,13 @@
     {
       "endPosition": "1143",
       "kind": "VARIABLE",
-      "name": "y",
-      "startPosition": "1133",
+      "binding": {
+        "endPosition": "1134",
+        "kind": "IDENTIFIER",
+        "name": "y",
+        "startPosition": "1133"
+      },
+      "startPosition": "1129",
       "initializer": {
         "endPosition": "1143",
         "kind": "REGEXP_LITERAL",
@@ -3030,8 +3098,13 @@
     {
       "endPosition": "1168",
       "kind": "VARIABLE",
-      "name": "z",
-      "startPosition": "1149",
+      "binding": {
+        "endPosition": "1150",
+        "kind": "IDENTIFIER",
+        "name": "z",
+        "startPosition": "1149"
+      },
+      "startPosition": "1145",
       "initializer": {
         "endPosition": "1168",
         "kind": "REGEXP_LITERAL",
@@ -3044,8 +3117,8 @@
   "sourceName": "parsertests/regexp_literal.js",
   "strict": "false",
   "startPosition": "1114"
-}
-,
+}
+,
 {
   "endPosition": "1118",
   "kind": "COMPILATION_UNIT",
@@ -3144,8 +3217,8 @@
   "sourceName": "parsertests/returnStat.js",
   "strict": "false",
   "startPosition": "1118"
-}
-,
+}
+,
 {
   "endPosition": "1111",
   "kind": "COMPILATION_UNIT",
@@ -3309,8 +3382,8 @@
   "sourceName": "parsertests/switchStat.js",
   "strict": "false",
   "startPosition": "1111"
-}
-,
+}
+,
 {
   "endPosition": "1110",
   "kind": "COMPILATION_UNIT",
@@ -3421,8 +3494,8 @@
   "sourceName": "parsertests/throwStat.js",
   "strict": "false",
   "startPosition": "1110"
-}
-,
+}
+,
 {
   "endPosition": "1121",
   "kind": "COMPILATION_UNIT",
@@ -3783,8 +3856,8 @@
   "sourceName": "parsertests/tryCatchStat.js",
   "strict": "false",
   "startPosition": "1121"
-}
-,
+}
+,
 {
   "endPosition": "1115",
   "kind": "COMPILATION_UNIT",
@@ -3969,8 +4042,8 @@
   "sourceName": "parsertests/unaryExpr.js",
   "strict": "false",
   "startPosition": "1115"
-}
-,
+}
+,
 {
   "endPosition": "1122",
   "kind": "COMPILATION_UNIT",
@@ -3989,7 +4062,12 @@
     {
       "endPosition": "1165",
       "kind": "FUNCTION",
-      "name": "f",
+      "name": {
+        "endPosition": "1146",
+        "kind": "IDENTIFIER",
+        "name": "f",
+        "startPosition": "1145"
+      },
       "body": {
         "endPosition": "1162",
         "kind": "BLOCK",
@@ -4016,8 +4094,8 @@
   "sourceName": "parsertests/useStrict.js",
   "strict": "true",
   "startPosition": "1122"
-}
-,
+}
+,
 {
   "endPosition": "1143",
   "kind": "COMPILATION_UNIT",
@@ -4025,26 +4103,46 @@
     {
       "endPosition": "1148",
       "kind": "VARIABLE",
-      "name": "a",
-      "startPosition": "1147"
+      "binding": {
+        "endPosition": "1148",
+        "kind": "IDENTIFIER",
+        "name": "a",
+        "startPosition": "1147"
+      },
+      "startPosition": "1143"
     },
     {
       "endPosition": "1155",
       "kind": "VARIABLE",
-      "name": "a",
-      "startPosition": "1154"
+      "binding": {
+        "endPosition": "1155",
+        "kind": "IDENTIFIER",
+        "name": "a",
+        "startPosition": "1154"
+      },
+      "startPosition": "1150"
     },
     {
       "endPosition": "1158",
       "kind": "VARIABLE",
-      "name": "b",
-      "startPosition": "1157"
+      "binding": {
+        "endPosition": "1158",
+        "kind": "IDENTIFIER",
+        "name": "b",
+        "startPosition": "1157"
+      },
+      "startPosition": "1150"
     },
     {
       "endPosition": "1200",
       "kind": "VARIABLE",
-      "name": "a",
-      "startPosition": "1190",
+      "binding": {
+        "endPosition": "1191",
+        "kind": "IDENTIFIER",
+        "name": "a",
+        "startPosition": "1190"
+      },
+      "startPosition": "1186",
       "initializer": {
         "endPosition": "1200",
         "kind": "STRING_LITERAL",
@@ -4055,8 +4153,13 @@
     {
       "endPosition": "1212",
       "kind": "VARIABLE",
-      "name": "a",
-      "startPosition": "1207",
+      "binding": {
+        "endPosition": "1208",
+        "kind": "IDENTIFIER",
+        "name": "a",
+        "startPosition": "1207"
+      },
+      "startPosition": "1203",
       "initializer": {
         "endPosition": "1212",
         "kind": "NUMBER_LITERAL",
@@ -4067,8 +4170,13 @@
     {
       "endPosition": "1219",
       "kind": "VARIABLE",
-      "name": "b",
-      "startPosition": "1214",
+      "binding": {
+        "endPosition": "1215",
+        "kind": "IDENTIFIER",
+        "name": "b",
+        "startPosition": "1214"
+      },
+      "startPosition": "1203",
       "initializer": {
         "endPosition": "1219",
         "kind": "NUMBER_LITERAL",
@@ -4079,8 +4187,13 @@
     {
       "endPosition": "1226",
       "kind": "VARIABLE",
-      "name": "c",
-      "startPosition": "1221",
+      "binding": {
+        "endPosition": "1222",
+        "kind": "IDENTIFIER",
+        "name": "c",
+        "startPosition": "1221"
+      },
+      "startPosition": "1203",
       "initializer": {
         "endPosition": "1226",
         "kind": "NUMBER_LITERAL",
@@ -4092,8 +4205,8 @@
   "sourceName": "parsertests/varDecl.js",
   "strict": "false",
   "startPosition": "1143"
-}
-,
+}
+,
 {
   "endPosition": "1111",
   "kind": "COMPILATION_UNIT",
@@ -4142,8 +4255,8 @@
   "sourceName": "parsertests/withStat.js",
   "strict": "false",
   "startPosition": "1111"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/caseoutofswitch.js",
   "code": "case (1090, 4)",
@@ -4152,8 +4265,8 @@
   "position": "1090",
   "message": "parsernegativetests/caseoutofswitch.js:29:0 Expected an operand but found case\ncase 23:\n^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/caseoutofswitch.js",
   "code": "default (1112, 7)",
@@ -4162,8 +4275,8 @@
   "position": "1112",
   "message": "parsernegativetests/caseoutofswitch.js:31:0 Expected an operand but found default\ndefault:\n^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4240,8 +4353,8 @@
   "sourceName": "parsernegativetests/caseoutofswitch.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegalbreak.js",
   "code": "break (1090, 5)",
@@ -4250,8 +4363,8 @@
   "position": "1090",
   "message": "parsernegativetests/illegalbreak.js:29:0 Illegal break statement\nbreak;\n^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegalbreak.js",
   "code": "ident (1103, 3)",
@@ -4260,8 +4373,8 @@
   "position": "1103",
   "message": "parsernegativetests/illegalbreak.js:30:6 Undefined Label \"foo\"\nbreak foo;\n      ^",
   "lineNumber": "30"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4290,8 +4403,8 @@
   "sourceName": "parsernegativetests/illegalbreak.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegalcontinue.js",
   "code": "continue (1090, 8)",
@@ -4300,8 +4413,8 @@
   "position": "1090",
   "message": "parsernegativetests/illegalcontinue.js:29:0 Illegal continue statement\ncontinue;\n^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegalcontinue.js",
   "code": "ident (1109, 3)",
@@ -4310,8 +4423,8 @@
   "position": "1109",
   "message": "parsernegativetests/illegalcontinue.js:30:9 Undefined Label \"foo\"\ncontinue foo;\n         ^",
   "lineNumber": "30"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4340,8 +4453,8 @@
   "sourceName": "parsernegativetests/illegalcontinue.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegallvalue.js",
   "code": "decimal (1090, 2)",
@@ -4350,8 +4463,8 @@
   "position": "1090",
   "message": "parsernegativetests/illegallvalue.js:29:0 Invalid left hand side for assignment\n44 = 54;\n^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegallvalue.js",
   "code": "decimal (1099, 3)",
@@ -4360,8 +4473,8 @@
   "position": "1099",
   "message": "parsernegativetests/illegallvalue.js:30:0 Invalid left hand side for assignment\n233 += 33;\n^",
   "lineNumber": "30"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegallvalue.js",
   "code": "decimal (1110, 4)",
@@ -4370,8 +4483,8 @@
   "position": "1110",
   "message": "parsernegativetests/illegallvalue.js:31:0 Invalid left hand side for assignment\n3423 -= 234;\n^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4410,8 +4523,8 @@
   "sourceName": "parsernegativetests/illegallvalue.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/illegaloperator.js",
   "code": "* (1093, 1)",
@@ -4420,8 +4533,8 @@
   "position": "1093",
   "message": "parsernegativetests/illegaloperator.js:29:3 Expected an operand but found *\nx ** y\n   ^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4440,8 +4553,8 @@
   "sourceName": "parsernegativetests/illegaloperator.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/keywordident.js",
   "code": "var (1094, 3)",
@@ -4450,8 +4563,8 @@
   "position": "1094",
   "message": "parsernegativetests/keywordident.js:29:4 Expected ident but found var\nvar var = 23;\n    ^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4469,8 +4582,13 @@
     {
       "endPosition": "1115",
       "kind": "VARIABLE",
-      "name": "x",
-      "startPosition": "1108",
+      "binding": {
+        "endPosition": "1109",
+        "kind": "IDENTIFIER",
+        "name": "x",
+        "startPosition": "1108"
+      },
+      "startPosition": "1104",
       "initializer": {
         "endPosition": "1115",
         "kind": "NUMBER_LITERAL",
@@ -4482,8 +4600,8 @@
   "sourceName": "parsernegativetests/keywordident.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/parenmissing.js",
   "code": "; (1096, 1)",
@@ -4492,8 +4610,8 @@
   "position": "1096",
   "message": "parsernegativetests/parenmissing.js:29:6 Expected ) but found ;\n(1 + 2;\n      ^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/parenmissing.js",
   "code": ") (1103, 1)",
@@ -4502,8 +4620,8 @@
   "position": "1103",
   "message": "parsernegativetests/parenmissing.js:30:5 Expected ; but found )\nx * y);\n     ^",
   "lineNumber": "30"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4554,8 +4672,8 @@
   "sourceName": "parsernegativetests/parenmissing.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/repeatedproperty.js",
   "code": "ident (1111, 3)",
@@ -4564,8 +4682,8 @@
   "position": "1111",
   "message": "parsernegativetests/repeatedproperty.js:29:21 Property \"foo\" already defined\nvar obj = { foo: 34, get foo() { return 'hello' } };\n                     ^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/repeatedproperty.js",
   "code": "ident (1165, 3)",
@@ -4574,8 +4692,8 @@
   "position": "1165",
   "message": "parsernegativetests/repeatedproperty.js:30:22 Property \"foo\" already defined\nvar obj1 = { foo: 34, set foo(x) { } };\n                      ^",
   "lineNumber": "30"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/repeatedproperty.js",
   "code": "ident (1205, 3)",
@@ -4584,8 +4702,8 @@
   "position": "1205",
   "message": "parsernegativetests/repeatedproperty.js:31:22 Property \"foo\" already defined\nvar obj2 = { foo: 34, set foo(x) { } };\n                      ^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/repeatedproperty.js",
   "code": "ident (1251, 3)",
@@ -4594,8 +4712,8 @@
   "position": "1251",
   "message": "parsernegativetests/repeatedproperty.js:32:28 Property \"bar\" already defined\nvar obj3 = { get bar() { }, get bar() {} };\n                            ^",
   "lineNumber": "32"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/repeatedproperty.js",
   "code": "ident (1296, 3)",
@@ -4604,8 +4722,8 @@
   "position": "1296",
   "message": "parsernegativetests/repeatedproperty.js:33:29 Property \"bar\" already defined\nvar obj4 = { set bar(x) { }, set bar(x) {} };\n                             ^",
   "lineNumber": "33"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4664,8 +4782,8 @@
   "sourceName": "parsernegativetests/repeatedproperty.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/strict_repeatedproperty.js",
   "code": "ident (1126, 3)",
@@ -4674,8 +4792,8 @@
   "position": "1126",
   "message": "parsernegativetests/strict_repeatedproperty.js:31:21 Property \"foo\" already defined\nvar obj = { foo: 34, foo: 'hello' };\n                     ^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4705,8 +4823,8 @@
   "sourceName": "parsernegativetests/strict_repeatedproperty.js",
   "strict": "true",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/strict_repeatparam.js",
   "code": "ident (1122, 1)",
@@ -4715,8 +4833,8 @@
   "position": "1122",
   "message": "parsernegativetests/strict_repeatparam.js:31:17 strict mode function cannot have duplicate parameter name \"x\"\nfunction func(x, x) {}\n                 ^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4746,8 +4864,8 @@
   "sourceName": "parsernegativetests/strict_repeatparam.js",
   "strict": "true",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/strict_with.js",
   "code": "with (1105, 4)",
@@ -4756,8 +4874,8 @@
   "position": "1105",
   "message": "parsernegativetests/strict_with.js:31:0 \"with\" statement cannot be used in strict mode\nwith({}) {}\n^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/strict_with.js",
   "code": ") (1112, 1)",
@@ -4766,8 +4884,8 @@
   "position": "1112",
   "message": "parsernegativetests/strict_with.js:31:7 Expected ; but found )\nwith({}) {}\n       ^",
   "lineNumber": "31"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4807,8 +4925,8 @@
   "sourceName": "parsernegativetests/strict_with.js",
   "strict": "true",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/toplevelreturn.js",
   "code": "return (1090, 6)",
@@ -4817,8 +4935,8 @@
   "position": "1090",
   "message": "parsernegativetests/toplevelreturn.js:29:0 Invalid return statement\nreturn;\n^",
   "lineNumber": "29"
-}
-,
+}
+,
 {
   "fileName": "parsernegativetests/toplevelreturn.js",
   "code": "return (1098, 6)",
@@ -4827,8 +4945,8 @@
   "position": "1098",
   "message": "parsernegativetests/toplevelreturn.js:30:0 Invalid return statement\nreturn 23;\n^",
   "lineNumber": "30"
-}
-,
+}
+,
 {
   "endPosition": "1090",
   "kind": "COMPILATION_UNIT",
@@ -4857,8 +4975,8 @@
   "sourceName": "parsernegativetests/toplevelreturn.js",
   "strict": "false",
   "startPosition": "1090"
-}
-,
+}
+,
 {
   "endPosition": "1136",
   "kind": "COMPILATION_UNIT",
@@ -4866,7 +4984,12 @@
     {
       "endPosition": "1222",
       "kind": "FUNCTION",
-      "name": "Parser",
+      "name": {
+        "endPosition": "1151",
+        "kind": "IDENTIFIER",
+        "name": "Parser",
+        "startPosition": "1145"
+      },
       "body": {
         "endPosition": "1220",
         "kind": "BLOCK",
@@ -4898,6 +5021,7 @@
                 "expression": {
                   "endPosition": "1193",
                   "kind": "IDENTIFIER",
+                  "this": "true",
                   "name": "this",
                   "startPosition": "1189"
                 },
@@ -5165,8 +5289,13 @@
               {
                 "endPosition": "1718",
                 "kind": "VARIABLE",
-                "name": "tree",
-                "startPosition": "1669",
+                "binding": {
+                  "endPosition": "1673",
+                  "kind": "IDENTIFIER",
+                  "name": "tree",
+                  "startPosition": "1669"
+                },
+                "startPosition": "1665",
                 "initializer": {
                   "endPosition": "1718",
                   "kind": "FUNCTION_INVOCATION",
@@ -5177,6 +5306,7 @@
                       "expression": {
                         "endPosition": "1680",
                         "kind": "IDENTIFIER",
+                        "this": "true",
                         "name": "this",
                         "startPosition": "1676"
                       },
@@ -5272,6 +5402,7 @@
                     "expression": {
                       "endPosition": "1790",
                       "kind": "IDENTIFIER",
+                      "this": "true",
                       "name": "this",
                       "startPosition": "1786"
                     },
@@ -5429,7 +5560,7 @@
           "endPosition": "2016",
           "kind": "FUNCTION_EXPRESSION",
           "body": {
-            "endPosition": "2994",
+            "endPosition": "3634",
             "kind": "BLOCK",
             "statements": [
               {
@@ -5554,8 +5685,13 @@
               {
                 "endPosition": "2169",
                 "kind": "VARIABLE",
-                "name": "obj",
-                "startPosition": "2132",
+                "binding": {
+                  "endPosition": "2135",
+                  "kind": "IDENTIFIER",
+                  "name": "obj",
+                  "startPosition": "2132"
+                },
+                "startPosition": "2128",
                 "initializer": {
                   "endPosition": "2169",
                   "kind": "FUNCTION_INVOCATION",
@@ -5591,8 +5727,13 @@
               {
                 "endPosition": "2190",
                 "kind": "VARIABLE",
-                "name": "result",
-                "startPosition": "2179",
+                "binding": {
+                  "endPosition": "2185",
+                  "kind": "IDENTIFIER",
+                  "name": "result",
+                  "startPosition": "2179"
+                },
+                "startPosition": "2175",
                 "initializer": {
                   "endPosition": "2190",
                   "kind": "OBJECT_LITERAL",
@@ -5603,8 +5744,13 @@
               {
                 "endPosition": "2206",
                 "kind": "VARIABLE",
-                "name": "i",
-                "startPosition": "2205"
+                "binding": {
+                  "endPosition": "2206",
+                  "kind": "IDENTIFIER",
+                  "name": "i",
+                  "startPosition": "2205"
+                },
+                "startPosition": "2201"
               },
               {
                 "expression": {
@@ -5613,7 +5759,7 @@
                   "name": "obj",
                   "startPosition": "2210"
                 },
-                "endPosition": "2975",
+                "endPosition": "3615",
                 "kind": "FOR_IN_LOOP",
                 "forEach": "false",
                 "variable": {
@@ -5623,14 +5769,19 @@
                   "startPosition": "2205"
                 },
                 "statement": {
-                  "endPosition": "2975",
+                  "endPosition": "3615",
                   "kind": "BLOCK",
                   "statements": [
                     {
                       "endPosition": "2241",
                       "kind": "VARIABLE",
-                      "name": "val",
-                      "startPosition": "2229",
+                      "binding": {
+                        "endPosition": "2232",
+                        "kind": "IDENTIFIER",
+                        "name": "val",
+                        "startPosition": "2229"
+                      },
+                      "startPosition": "2225",
                       "initializer": {
                         "expression": {
                           "endPosition": "2238",
@@ -5652,605 +5803,836 @@
                     {
                       "condition": {
                         "leftOperand": {
-                          "endPosition": "2258",
+                          "leftOperand": {
+                            "expression": {
+                              "endPosition": "2384",
+                              "kind": "IDENTIFIER",
+                              "name": "val",
+                              "startPosition": "2381"
+                            },
+                            "endPosition": "2384",
+                            "kind": "TYPEOF",
+                            "startPosition": "2374"
+                          },
+                          "endPosition": "2397",
+                          "kind": "EQUAL_TO",
+                          "rightOperand": {
+                            "endPosition": "2397",
+                            "kind": "STRING_LITERAL",
+                            "value": "boolean",
+                            "startPosition": "2390"
+                          },
+                          "startPosition": "2374"
+                        },
+                        "endPosition": "2414",
+                        "kind": "CONDITIONAL_AND",
+                        "rightOperand": {
+                          "leftOperand": {
+                            "endPosition": "2405",
+                            "kind": "IDENTIFIER",
+                            "name": "val",
+                            "startPosition": "2402"
+                          },
+                          "endPosition": "2414",
+                          "kind": "EQUAL_TO",
+                          "rightOperand": {
+                            "endPosition": "2414",
+                            "kind": "BOOLEAN_LITERAL",
+                            "value": "false",
+                            "startPosition": "2409"
+                          },
+                          "startPosition": "2402"
+                        },
+                        "startPosition": "2374"
+                      },
+                      "endPosition": "2881",
+                      "kind": "IF",
+                      "startPosition": "2370",
+                      "thenStatement": {
+                        "endPosition": "2881",
+                        "kind": "BLOCK",
+                        "statements": [
+                          {
+                            "cases": [
+                              {
+                                "expression": {
+                                  "endPosition": "2473",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "computed",
+                                  "startPosition": "2465"
+                                },
+                                "endPosition": "2475",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2459"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2504",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "static",
+                                  "startPosition": "2498"
+                                },
+                                "endPosition": "2506",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2492"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2542",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "restParameter",
+                                  "startPosition": "2529"
+                                },
+                                "endPosition": "2544",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2523"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2571",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "this",
+                                  "startPosition": "2567"
+                                },
+                                "endPosition": "2573",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2561"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2601",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "super",
+                                  "startPosition": "2596"
+                                },
+                                "endPosition": "2603",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2590"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2630",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "star",
+                                  "startPosition": "2626"
+                                },
+                                "endPosition": "2632",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2620"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2662",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "default",
+                                  "startPosition": "2655"
+                                },
+                                "endPosition": "2664",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2649"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2702",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "starDefaultStar",
+                                  "startPosition": "2687"
+                                },
+                                "endPosition": "2704",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2681"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2732",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "arrow",
+                                  "startPosition": "2727"
+                                },
+                                "endPosition": "2734",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2721"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2766",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "generator",
+                                  "startPosition": "2757"
+                                },
+                                "endPosition": "2768",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2751"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2794",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "let",
+                                  "startPosition": "2791"
+                                },
+                                "endPosition": "2796",
+                                "kind": "CASE",
+                                "statements": [],
+                                "startPosition": "2785"
+                              },
+                              {
+                                "expression": {
+                                  "endPosition": "2824",
+                                  "kind": "STRING_LITERAL",
+                                  "value": "const",
+                                  "startPosition": "2819"
+                                },
+                                "endPosition": "2856",
+                                "kind": "CASE",
+                                "statements": [
+                                  {
+                                    "endPosition": "2856",
+                                    "kind": "CONTINUE",
+                                    "startPosition": "2847"
+                                  }
+                                ],
+                                "startPosition": "2813"
+                              }
+                            ],
+                            "expression": {
+                              "endPosition": "2439",
+                              "kind": "IDENTIFIER",
+                              "name": "i",
+                              "startPosition": "2438"
+                            },
+                            "endPosition": "2871",
+                            "kind": "SWITCH",
+                            "startPosition": "2430"
+                          }
+                        ],
+                        "startPosition": "2416"
+                      }
+                    },
+                    {
+                      "condition": {
+                        "leftOperand": {
+                          "endPosition": "2898",
                           "kind": "IDENTIFIER",
                           "name": "val",
-                          "startPosition": "2255"
+                          "startPosition": "2895"
                         },
                         "expression": {
-                          "endPosition": "2258",
+                          "endPosition": "2898",
                           "kind": "IDENTIFIER",
                           "name": "val",
-                          "startPosition": "2255"
+                          "startPosition": "2895"
                         },
-                        "endPosition": "2281",
+                        "endPosition": "2921",
                         "kind": "INSTANCE_OF",
                         "rightOperand": {
                           "identifier": "Tree",
                           "expression": {
-                            "endPosition": "2276",
+                            "endPosition": "2916",
                             "kind": "IDENTIFIER",
                             "name": "Parser",
-                            "startPosition": "2270"
+                            "startPosition": "2910"
                           },
-                          "endPosition": "2281",
+                          "endPosition": "2921",
                           "kind": "MEMBER_SELECT",
-                          "startPosition": "2270"
+                          "startPosition": "2910"
                         },
                         "type": {
                           "identifier": "Tree",
                           "expression": {
-                            "endPosition": "2276",
+                            "endPosition": "2916",
                             "kind": "IDENTIFIER",
                             "name": "Parser",
-                            "startPosition": "2270"
+                            "startPosition": "2910"
                           },
-                          "endPosition": "2281",
+                          "endPosition": "2921",
                           "kind": "MEMBER_SELECT",
-                          "startPosition": "2270"
+                          "startPosition": "2910"
                         },
-                        "startPosition": "2255"
+                        "startPosition": "2895"
                       },
                       "elseStatement": {
                         "condition": {
                           "leftOperand": {
-                            "endPosition": "2350",
+                            "endPosition": "2990",
                             "kind": "IDENTIFIER",
                             "name": "val",
-                            "startPosition": "2347"
+                            "startPosition": "2987"
                           },
                           "expression": {
-                            "endPosition": "2350",
+                            "endPosition": "2990",
                             "kind": "IDENTIFIER",
                             "name": "val",
-                            "startPosition": "2347"
+                            "startPosition": "2987"
                           },
-                          "endPosition": "2373",
+                          "endPosition": "3013",
                           "kind": "INSTANCE_OF",
                           "rightOperand": {
                             "identifier": "List",
                             "expression": {
-                              "endPosition": "2368",
+                              "endPosition": "3008",
                               "kind": "IDENTIFIER",
                               "name": "Parser",
-                              "startPosition": "2362"
+                              "startPosition": "3002"
                             },
-                            "endPosition": "2373",
+                            "endPosition": "3013",
                             "kind": "MEMBER_SELECT",
-                            "startPosition": "2362"
+                            "startPosition": "3002"
                           },
                           "type": {
                             "identifier": "List",
                             "expression": {
-                              "endPosition": "2368",
+                              "endPosition": "3008",
                               "kind": "IDENTIFIER",
                               "name": "Parser",
-                              "startPosition": "2362"
+                              "startPosition": "3002"
                             },
-                            "endPosition": "2373",
+                            "endPosition": "3013",
                             "kind": "MEMBER_SELECT",
-                            "startPosition": "2362"
+                            "startPosition": "3002"
                           },
-                          "startPosition": "2347"
+                          "startPosition": "2987"
                         },
                         "elseStatement": {
-                          "endPosition": "2969",
+                          "endPosition": "3609",
                           "kind": "BLOCK",
                           "statements": [
                             {
                               "cases": [
                                 {
                                   "expression": {
-                                    "endPosition": "2625",
+                                    "endPosition": "3265",
                                     "kind": "STRING_LITERAL",
                                     "value": "number",
-                                    "startPosition": "2619"
+                                    "startPosition": "3259"
                                   },
-                                  "endPosition": "2627",
+                                  "endPosition": "3267",
                                   "kind": "CASE",
                                   "statements": [],
-                                  "startPosition": "2613"
+                                  "startPosition": "3253"
                                 },
                                 {
                                   "expression": {
-                                    "endPosition": "2656",
+                                    "endPosition": "3296",
                                     "kind": "STRING_LITERAL",
                                     "value": "string",
-                                    "startPosition": "2650"
+                                    "startPosition": "3290"
                                   },
-                                  "endPosition": "2658",
+                                  "endPosition": "3298",
                                   "kind": "CASE",
                                   "statements": [],
-                                  "startPosition": "2644"
+                                  "startPosition": "3284"
                                 },
                                 {
                                   "expression": {
-                                    "endPosition": "2688",
+                                    "endPosition": "3328",
                                     "kind": "STRING_LITERAL",
                                     "value": "boolean",
-                                    "startPosition": "2681"
+                                    "startPosition": "3321"
                                   },
-                                  "endPosition": "2762",
+                                  "endPosition": "3402",
                                   "kind": "CASE",
                                   "statements": [
                                     {
                                       "expression": {
                                         "expression": {
-                                          "endPosition": "2734",
+                                          "endPosition": "3374",
                                           "kind": "FUNCTION_INVOCATION",
                                           "functionSelect": {
-                                            "endPosition": "2729",
+                                            "endPosition": "3369",
                                             "kind": "IDENTIFIER",
                                             "name": "String",
-                                            "startPosition": "2723"
+                                            "startPosition": "3363"
                                           },
                                           "arguments": [
                                             {
-                                              "endPosition": "2733",
+                                              "endPosition": "3373",
                                               "kind": "IDENTIFIER",
                                               "name": "val",
-                                              "startPosition": "2730"
+                                              "startPosition": "3370"
                                             }
                                           ],
-                                          "startPosition": "2723"
+                                          "startPosition": "3363"
                                         },
-                                        "endPosition": "2734",
+                                        "endPosition": "3374",
                                         "kind": "ASSIGNMENT",
                                         "variable": {
                                           "expression": {
-                                            "endPosition": "2717",
+                                            "endPosition": "3357",
                                             "kind": "IDENTIFIER",
                                             "name": "result",
-                                            "startPosition": "2711"
+                                            "startPosition": "3351"
                                           },
-                                          "endPosition": "2720",
+                                          "endPosition": "3360",
                                           "kind": "ARRAY_ACCESS",
                                           "index": {
-                                            "endPosition": "2719",
+                                            "endPosition": "3359",
                                             "kind": "IDENTIFIER",
                                             "name": "i",
-                                            "startPosition": "2718"
+                                            "startPosition": "3358"
                                           },
-                                          "startPosition": "2711"
+                                          "startPosition": "3351"
                                         },
-                                        "startPosition": "2711"
+                                        "startPosition": "3351"
                                       },
-                                      "endPosition": "2734",
+                                      "endPosition": "3374",
                                       "kind": "EXPRESSION_STATEMENT",
-                                      "startPosition": "2711"
+                                      "startPosition": "3351"
                                     },
                                     {
-                                      "endPosition": "2762",
+                                      "endPosition": "3402",
                                       "kind": "BREAK",
-                                      "startPosition": "2756"
+                                      "startPosition": "3396"
                                     }
                                   ],
-                                  "startPosition": "2675"
+                                  "startPosition": "3315"
                                 },
                                 {
-                                  "endPosition": "2945",
+                                  "endPosition": "3585",
                                   "kind": "CASE",
                                   "statements": [
                                     {
                                       "condition": {
                                         "leftOperand": {
                                           "leftOperand": {
-                                            "endPosition": "2815",
+                                            "endPosition": "3455",
                                             "kind": "IDENTIFIER",
                                             "name": "val",
-                                            "startPosition": "2812"
+                                            "startPosition": "3452"
                                           },
                                           "expression": {
-                                            "endPosition": "2815",
+                                            "endPosition": "3455",
                                             "kind": "IDENTIFIER",
                                             "name": "val",
-                                            "startPosition": "2812"
+                                            "startPosition": "3452"
                                           },
-                                          "endPosition": "2841",
+                                          "endPosition": "3481",
                                           "kind": "INSTANCE_OF",
                                           "rightOperand": {
                                             "identifier": "Long",
                                             "expression": {
                                               "identifier": "lang",
                                               "expression": {
-                                                "endPosition": "2831",
+                                                "endPosition": "3471",
                                                 "kind": "IDENTIFIER",
                                                 "name": "java",
-                                                "startPosition": "2827"
+                                                "startPosition": "3467"
                                               },
-                                              "endPosition": "2836",
+                                              "endPosition": "3476",
                                               "kind": "MEMBER_SELECT",
-                                              "startPosition": "2827"
+                                              "startPosition": "3467"
                                             },
-                                            "endPosition": "2841",
+                                            "endPosition": "3481",
                                             "kind": "MEMBER_SELECT",
-                                            "startPosition": "2827"
+                                            "startPosition": "3467"
                                           },
                                           "type": {
                                             "identifier": "Long",
                                             "expression": {
                                               "identifier": "lang",
                                               "expression": {
-                                                "endPosition": "2831",
+                                                "endPosition": "3471",
                                                 "kind": "IDENTIFIER",
                                                 "name": "java",
-                                                "startPosition": "2827"
+                                                "startPosition": "3467"
                                               },
-                                              "endPosition": "2836",
+                                              "endPosition": "3476",
                                               "kind": "MEMBER_SELECT",
-                                              "startPosition": "2827"
+                                              "startPosition": "3467"
                                             },
-                                            "endPosition": "2841",
+                                            "endPosition": "3481",
                                             "kind": "MEMBER_SELECT",
-                                            "startPosition": "2827"
+                                            "startPosition": "3467"
                                           },
-                                          "startPosition": "2812"
+                                          "startPosition": "3452"
                                         },
-                                        "endPosition": "2871",
+                                        "endPosition": "3511",
                                         "kind": "CONDITIONAL_OR",
                                         "rightOperand": {
                                           "leftOperand": {
-                                            "endPosition": "2848",
+                                            "endPosition": "3488",
                                             "kind": "IDENTIFIER",
                                             "name": "val",
-                                            "startPosition": "2845"
+                                            "startPosition": "3485"
                                           },
                                           "expression": {
-                                            "endPosition": "2848",
+                                            "endPosition": "3488",
                                             "kind": "IDENTIFIER",
                                             "name": "val",
-                                            "startPosition": "2845"
+                                            "startPosition": "3485"
                                           },
-                                          "endPosition": "2871",
+                                          "endPosition": "3511",
                                           "kind": "INSTANCE_OF",
                                           "rightOperand": {
                                             "identifier": "Enum",
                                             "expression": {
-                                              "endPosition": "2866",
+                                              "endPosition": "3506",
                                               "kind": "IDENTIFIER",
                                               "name": "Parser",
-                                              "startPosition": "2860"
+                                              "startPosition": "3500"
                                             },
-                                            "endPosition": "2871",
+                                            "endPosition": "3511",
                                             "kind": "MEMBER_SELECT",
-                                            "startPosition": "2860"
+                                            "startPosition": "3500"
                                           },
                                           "type": {
                                             "identifier": "Enum",
                                             "expression": {
-                                              "endPosition": "2866",
+                                              "endPosition": "3506",
                                               "kind": "IDENTIFIER",
                                               "name": "Parser",
-                                              "startPosition": "2860"
+                                              "startPosition": "3500"
                                             },
-                                            "endPosition": "2871",
+                                            "endPosition": "3511",
                                             "kind": "MEMBER_SELECT",
-                                            "startPosition": "2860"
+                                            "startPosition": "3500"
                                           },
-                                          "startPosition": "2845"
+                                          "startPosition": "3485"
                                         },
-                                        "startPosition": "2812"
+                                        "startPosition": "3452"
                                       },
-                                      "endPosition": "2945",
+                                      "endPosition": "3585",
                                       "kind": "IF",
-                                      "startPosition": "2808",
+                                      "startPosition": "3448",
                                       "thenStatement": {
-                                        "endPosition": "2945",
+                                        "endPosition": "3585",
                                         "kind": "BLOCK",
                                         "statements": [
                                           {
                                             "expression": {
                                               "expression": {
-                                                "endPosition": "2922",
+                                                "endPosition": "3562",
                                                 "kind": "FUNCTION_INVOCATION",
                                                 "functionSelect": {
-                                                  "endPosition": "2917",
+                                                  "endPosition": "3557",
                                                   "kind": "IDENTIFIER",
                                                   "name": "String",
-                                                  "startPosition": "2911"
+                                                  "startPosition": "3551"
                                                 },
                                                 "arguments": [
                                                   {
-                                                    "endPosition": "2921",
+                                                    "endPosition": "3561",
                                                     "kind": "IDENTIFIER",
                                                     "name": "val",
-                                                    "startPosition": "2918"
+                                                    "startPosition": "3558"
                                                   }
                                                 ],
-                                                "startPosition": "2911"
+                                                "startPosition": "3551"
                                               },
-                                              "endPosition": "2922",
+                                              "endPosition": "3562",
                                               "kind": "ASSIGNMENT",
                                               "variable": {
                                                 "expression": {
-                                                  "endPosition": "2905",
+                                                  "endPosition": "3545",
                                                   "kind": "IDENTIFIER",
                                                   "name": "result",
-                                                  "startPosition": "2899"
+                                                  "startPosition": "3539"
                                                 },
-                                                "endPosition": "2908",
+                                                "endPosition": "3548",
                                                 "kind": "ARRAY_ACCESS",
                                                 "index": {
-                                                  "endPosition": "2907",
+                                                  "endPosition": "3547",
                                                   "kind": "IDENTIFIER",
                                                   "name": "i",
-                                                  "startPosition": "2906"
+                                                  "startPosition": "3546"
                                                 },
-                                                "startPosition": "2899"
+                                                "startPosition": "3539"
                                               },
-                                              "startPosition": "2899"
+                                              "startPosition": "3539"
                                             },
-                                            "endPosition": "2922",
+                                            "endPosition": "3562",
                                             "kind": "EXPRESSION_STATEMENT",
-                                            "startPosition": "2899"
+                                            "startPosition": "3539"
                                           }
                                         ],
-                                        "startPosition": "2873"
+                                        "startPosition": "3513"
                                       }
                                     }
                                   ],
-                                  "startPosition": "2779"
+                                  "startPosition": "3419"
                                 }
                               ],
                               "expression": {
                                 "expression": {
-                                  "endPosition": "2593",
+                                  "endPosition": "3233",
                                   "kind": "IDENTIFIER",
                                   "name": "val",
-                                  "startPosition": "2590"
+                                  "startPosition": "3230"
                                 },
-                                "endPosition": "2593",
+                                "endPosition": "3233",
                                 "kind": "TYPEOF",
-                                "startPosition": "2583"
+                                "startPosition": "3223"
                               },
-                              "endPosition": "2959",
+                              "endPosition": "3599",
                               "kind": "SWITCH",
-                              "startPosition": "2575"
+                              "startPosition": "3215"
                             }
                           ],
-                          "startPosition": "2561"
+                          "startPosition": "3201"
                         },
-                        "endPosition": "2969",
+                        "endPosition": "3609",
                         "kind": "IF",
-                        "startPosition": "2343",
+                        "startPosition": "2983",
                         "thenStatement": {
-                          "endPosition": "2555",
+                          "endPosition": "3195",
                           "kind": "BLOCK",
                           "statements": [
                             {
-                              "endPosition": "2420",
+                              "endPosition": "3060",
                               "kind": "VARIABLE",
-                              "name": "arr",
-                              "startPosition": "2393",
+                              "binding": {
+                                "endPosition": "3036",
+                                "kind": "IDENTIFIER",
+                                "name": "arr",
+                                "startPosition": "3033"
+                              },
+                              "startPosition": "3029",
                               "initializer": {
                                 "constructorExpression": {
-                                  "endPosition": "2420",
+                                  "endPosition": "3060",
                                   "kind": "FUNCTION_INVOCATION",
                                   "functionSelect": {
-                                    "endPosition": "2408",
+                                    "endPosition": "3048",
                                     "kind": "IDENTIFIER",
                                     "name": "Array",
-                                    "startPosition": "2403"
+                                    "startPosition": "3043"
                                   },
                                   "arguments": [
                                     {
-                                      "endPosition": "2419",
+                                      "endPosition": "3059",
                                       "kind": "FUNCTION_INVOCATION",
                                       "functionSelect": {
                                         "identifier": "size",
                                         "expression": {
-                                          "endPosition": "2412",
+                                          "endPosition": "3052",
                                           "kind": "IDENTIFIER",
                                           "name": "val",
-                                          "startPosition": "2409"
+                                          "startPosition": "3049"
                                         },
-                                        "endPosition": "2417",
+                                        "endPosition": "3057",
                                         "kind": "MEMBER_SELECT",
-                                        "startPosition": "2409"
+                                        "startPosition": "3049"
                                       },
                                       "arguments": [],
-                                      "startPosition": "2409"
+                                      "startPosition": "3049"
                                     }
                                   ],
-                                  "startPosition": "2403"
+                                  "startPosition": "3043"
                                 },
-                                "endPosition": "2420",
+                                "endPosition": "3060",
                                 "kind": "NEW",
-                                "startPosition": "2399"
+                                "startPosition": "3039"
                               }
                             },
                             {
-                              "endPosition": "2444",
+                              "endPosition": "3084",
                               "kind": "VARIABLE",
-                              "name": "j",
-                              "startPosition": "2443"
+                              "binding": {
+                                "endPosition": "3084",
+                                "kind": "IDENTIFIER",
+                                "name": "j",
+                                "startPosition": "3083"
+                              },
+                              "startPosition": "3079"
                             },
                             {
                               "expression": {
-                                "endPosition": "2451",
+                                "endPosition": "3091",
                                 "kind": "IDENTIFIER",
                                 "name": "val",
-                                "startPosition": "2448"
+                                "startPosition": "3088"
                               },
-                              "endPosition": "2515",
+                              "endPosition": "3155",
                               "kind": "FOR_IN_LOOP",
                               "forEach": "false",
                               "variable": {
-                                "endPosition": "2444",
+                                "endPosition": "3084",
                                 "kind": "IDENTIFIER",
                                 "name": "j",
-                                "startPosition": "2443"
+                                "startPosition": "3083"
                               },
                               "statement": {
-                                "endPosition": "2515",
+                                "endPosition": "3155",
                                 "kind": "BLOCK",
                                 "statements": [
                                   {
                                     "expression": {
                                       "expression": {
-                                        "endPosition": "2500",
+                                        "endPosition": "3140",
                                         "kind": "FUNCTION_INVOCATION",
                                         "functionSelect": {
                                           "identifier": "convert",
                                           "expression": {
-                                            "endPosition": "2484",
+                                            "endPosition": "3124",
                                             "kind": "IDENTIFIER",
+                                            "this": "true",
                                             "name": "this",
-                                            "startPosition": "2480"
+                                            "startPosition": "3120"
                                           },
-                                          "endPosition": "2492",
+                                          "endPosition": "3132",
                                           "kind": "MEMBER_SELECT",
-                                          "startPosition": "2480"
+                                          "startPosition": "3120"
                                         },
                                         "arguments": [
                                           {
                                             "expression": {
-                                              "endPosition": "2496",
+                                              "endPosition": "3136",
                                               "kind": "IDENTIFIER",
                                               "name": "val",
-                                              "startPosition": "2493"
+                                              "startPosition": "3133"
                                             },
-                                            "endPosition": "2499",
+                                            "endPosition": "3139",
                                             "kind": "ARRAY_ACCESS",
                                             "index": {
-                                              "endPosition": "2498",
+                                              "endPosition": "3138",
                                               "kind": "IDENTIFIER",
                                               "name": "j",
-                                              "startPosition": "2497"
+                                              "startPosition": "3137"
                                             },
-                                            "startPosition": "2493"
+                                            "startPosition": "3133"
                                           }
                                         ],
-                                        "startPosition": "2480"
+                                        "startPosition": "3120"
                                       },
-                                      "endPosition": "2500",
+                                      "endPosition": "3140",
                                       "kind": "ASSIGNMENT",
                                       "variable": {
                                         "expression": {
-                                          "endPosition": "2474",
+                                          "endPosition": "3114",
                                           "kind": "IDENTIFIER",
                                           "name": "arr",
-                                          "startPosition": "2471"
+                                          "startPosition": "3111"
                                         },
-                                        "endPosition": "2477",
+                                        "endPosition": "3117",
                                         "kind": "ARRAY_ACCESS",
                                         "index": {
-                                          "endPosition": "2476",
+                                          "endPosition": "3116",
                                           "kind": "IDENTIFIER",
                                           "name": "j",
-                                          "startPosition": "2475"
+                                          "startPosition": "3115"
                                         },
-                                        "startPosition": "2471"
+                                        "startPosition": "3111"
                                       },
-                                      "startPosition": "2471"
+                                      "startPosition": "3111"
                                     },
-                                    "endPosition": "2500",
+                                    "endPosition": "3140",
                                     "kind": "EXPRESSION_STATEMENT",
-                                    "startPosition": "2471"
+                                    "startPosition": "3111"
                                   }
                                 ],
-                                "startPosition": "2453"
+                                "startPosition": "3093"
                               },
-                              "startPosition": "2434"
+                              "startPosition": "3074"
                             },
                             {
                               "expression": {
                                 "expression": {
-                                  "endPosition": "2544",
+                                  "endPosition": "3184",
                                   "kind": "IDENTIFIER",
                                   "name": "arr",
-                                  "startPosition": "2541"
+                                  "startPosition": "3181"
                                 },
-                                "endPosition": "2544",
+                                "endPosition": "3184",
                                 "kind": "ASSIGNMENT",
                                 "variable": {
                                   "expression": {
-                                    "endPosition": "2535",
+                                    "endPosition": "3175",
                                     "kind": "IDENTIFIER",
                                     "name": "result",
-                                    "startPosition": "2529"
+                                    "startPosition": "3169"
                                   },
-                                  "endPosition": "2538",
+                                  "endPosition": "3178",
                                   "kind": "ARRAY_ACCESS",
                                   "index": {
-                                    "endPosition": "2537",
+                                    "endPosition": "3177",
                                     "kind": "IDENTIFIER",
                                     "name": "i",
-                                    "startPosition": "2536"
+                                    "startPosition": "3176"
                                   },
-                                  "startPosition": "2529"
+                                  "startPosition": "3169"
                                 },
-                                "startPosition": "2529"
+                                "startPosition": "3169"
                               },
-                              "endPosition": "2544",
+                              "endPosition": "3184",
                               "kind": "EXPRESSION_STATEMENT",
-                              "startPosition": "2529"
+                              "startPosition": "3169"
                             }
                           ],
-                          "startPosition": "2375"
+                          "startPosition": "3015"
                         }
                       },
-                      "endPosition": "2969",
+                      "endPosition": "3609",
                       "kind": "IF",
-                      "startPosition": "2251",
+                      "startPosition": "2891",
                       "thenStatement": {
-                        "endPosition": "2337",
+                        "endPosition": "2977",
                         "kind": "BLOCK",
                         "statements": [
                           {
                             "expression": {
                               "expression": {
-                                "endPosition": "2326",
+                                "endPosition": "2966",
                                 "kind": "FUNCTION_INVOCATION",
                                 "functionSelect": {
                                   "identifier": "convert",
                                   "expression": {
-                                    "endPosition": "2313",
+                                    "endPosition": "2953",
                                     "kind": "IDENTIFIER",
+                                    "this": "true",
                                     "name": "this",
-                                    "startPosition": "2309"
+                                    "startPosition": "2949"
                                   },
-                                  "endPosition": "2321",
+                                  "endPosition": "2961",
                                   "kind": "MEMBER_SELECT",
-                                  "startPosition": "2309"
+                                  "startPosition": "2949"
                                 },
                                 "arguments": [
                                   {
-                                    "endPosition": "2325",
+                                    "endPosition": "2965",
                                     "kind": "IDENTIFIER",
                                     "name": "val",
-                                    "startPosition": "2322"
+                                    "startPosition": "2962"
                                   }
                                 ],
-                                "startPosition": "2309"
+                                "startPosition": "2949"
                               },
-                              "endPosition": "2326",
+                              "endPosition": "2966",
                               "kind": "ASSIGNMENT",
                               "variable": {
                                 "expression": {
-                                  "endPosition": "2303",
+                                  "endPosition": "2943",
                                   "kind": "IDENTIFIER",
                                   "name": "result",
-                                  "startPosition": "2297"
+                                  "startPosition": "2937"
                                 },
-                                "endPosition": "2306",
+                                "endPosition": "2946",
                                 "kind": "ARRAY_ACCESS",
                                 "index": {
-                                  "endPosition": "2305",
+                                  "endPosition": "2945",
                                   "kind": "IDENTIFIER",
                                   "name": "i",
-                                  "startPosition": "2304"
+                                  "startPosition": "2944"
                                 },
-                                "startPosition": "2297"
+                                "startPosition": "2937"
                               },
-                              "startPosition": "2297"
+                              "startPosition": "2937"
                             },
-                            "endPosition": "2326",
+                            "endPosition": "2966",
                             "kind": "EXPRESSION_STATEMENT",
-                            "startPosition": "2297"
+                            "startPosition": "2937"
                           }
                         ],
-                        "startPosition": "2283"
+                        "startPosition": "2923"
                       }
                     }
                   ],
@@ -6260,14 +6642,14 @@
               },
               {
                 "expression": {
-                  "endPosition": "2993",
+                  "endPosition": "3633",
                   "kind": "IDENTIFIER",
                   "name": "result",
-                  "startPosition": "2987"
+                  "startPosition": "3627"
                 },
-                "endPosition": "2994",
+                "endPosition": "3634",
                 "kind": "RETURN",
-                "startPosition": "2980"
+                "startPosition": "3620"
               }
             ],
             "startPosition": "2016"
@@ -6305,105 +6687,120 @@
         },
         "startPosition": "1974"
       },
-      "endPosition": "2996",
+      "endPosition": "3636",
       "kind": "EXPRESSION_STATEMENT",
       "startPosition": "1974"
     },
     {
-      "endPosition": "3726",
+      "endPosition": "4366",
       "kind": "FUNCTION",
-      "name": "processFiles",
+      "name": {
+        "endPosition": "3659",
+        "kind": "IDENTIFIER",
+        "name": "processFiles",
+        "startPosition": "3647"
+      },
       "body": {
-        "endPosition": "3724",
+        "endPosition": "4364",
         "kind": "BLOCK",
         "statements": [
           {
-            "endPosition": "3070",
+            "endPosition": "3710",
             "kind": "VARIABLE",
-            "name": "File",
-            "startPosition": "3038",
+            "binding": {
+              "endPosition": "3682",
+              "kind": "IDENTIFIER",
+              "name": "File",
+              "startPosition": "3678"
+            },
+            "startPosition": "3674",
             "initializer": {
-              "endPosition": "3070",
+              "endPosition": "3710",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
                 "identifier": "type",
                 "expression": {
-                  "endPosition": "3049",
+                  "endPosition": "3689",
                   "kind": "IDENTIFIER",
                   "name": "Java",
-                  "startPosition": "3045"
+                  "startPosition": "3685"
                 },
-                "endPosition": "3054",
+                "endPosition": "3694",
                 "kind": "MEMBER_SELECT",
-                "startPosition": "3045"
+                "startPosition": "3685"
               },
               "arguments": [
                 {
-                  "endPosition": "3068",
+                  "endPosition": "3708",
                   "kind": "STRING_LITERAL",
                   "value": "java.io.File",
-                  "startPosition": "3056"
+                  "startPosition": "3696"
                 }
               ],
-              "startPosition": "3045"
+              "startPosition": "3685"
             }
           },
           {
-            "endPosition": "3126",
+            "endPosition": "3766",
             "kind": "VARIABLE",
-            "name": "files",
-            "startPosition": "3080",
+            "binding": {
+              "endPosition": "3725",
+              "kind": "IDENTIFIER",
+              "name": "files",
+              "startPosition": "3720"
+            },
+            "startPosition": "3716",
             "initializer": {
-              "endPosition": "3126",
+              "endPosition": "3766",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
                 "identifier": "listFiles",
                 "expression": {
                   "constructorExpression": {
-                    "endPosition": "3114",
+                    "endPosition": "3754",
                     "kind": "FUNCTION_INVOCATION",
                     "functionSelect": {
-                      "endPosition": "3096",
+                      "endPosition": "3736",
                       "kind": "IDENTIFIER",
                       "name": "File",
-                      "startPosition": "3092"
+                      "startPosition": "3732"
                     },
                     "arguments": [
                       {
                         "leftOperand": {
-                          "endPosition": "3104",
+                          "endPosition": "3744",
                           "kind": "IDENTIFIER",
                           "name": "__DIR__",
-                          "startPosition": "3097"
+                          "startPosition": "3737"
                         },
-                        "endPosition": "3113",
+                        "endPosition": "3753",
                         "kind": "PLUS",
                         "rightOperand": {
-                          "endPosition": "3113",
+                          "endPosition": "3753",
                           "kind": "IDENTIFIER",
                           "name": "subdir",
-                          "startPosition": "3107"
+                          "startPosition": "3747"
                         },
-                        "startPosition": "3097"
+                        "startPosition": "3737"
                       }
                     ],
-                    "startPosition": "3092"
+                    "startPosition": "3732"
                   },
-                  "endPosition": "3114",
+                  "endPosition": "3754",
                   "kind": "NEW",
-                  "startPosition": "3088"
+                  "startPosition": "3728"
                 },
-                "endPosition": "3124",
+                "endPosition": "3764",
                 "kind": "MEMBER_SELECT",
-                "startPosition": "3088"
+                "startPosition": "3728"
               },
               "arguments": [],
-              "startPosition": "3088"
+              "startPosition": "3728"
             }
           },
           {
             "expression": {
-              "endPosition": "3160",
+              "endPosition": "3800",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
                 "identifier": "sort",
@@ -6412,751 +6809,786 @@
                   "expression": {
                     "identifier": "util",
                     "expression": {
-                      "endPosition": "3136",
+                      "endPosition": "3776",
                       "kind": "IDENTIFIER",
                       "name": "java",
-                      "startPosition": "3132"
+                      "startPosition": "3772"
                     },
-                    "endPosition": "3141",
+                    "endPosition": "3781",
                     "kind": "MEMBER_SELECT",
-                    "startPosition": "3132"
+                    "startPosition": "3772"
                   },
-                  "endPosition": "3148",
+                  "endPosition": "3788",
                   "kind": "MEMBER_SELECT",
-                  "startPosition": "3132"
+                  "startPosition": "3772"
                 },
-                "endPosition": "3153",
+                "endPosition": "3793",
                 "kind": "MEMBER_SELECT",
-                "startPosition": "3132"
+                "startPosition": "3772"
               },
               "arguments": [
                 {
-                  "endPosition": "3159",
+                  "endPosition": "3799",
                   "kind": "IDENTIFIER",
                   "name": "files",
-                  "startPosition": "3154"
+                  "startPosition": "3794"
                 }
               ],
-              "startPosition": "3132"
+              "startPosition": "3772"
             },
-            "endPosition": "3160",
+            "endPosition": "3800",
             "kind": "EXPRESSION_STATEMENT",
-            "startPosition": "3132"
+            "startPosition": "3772"
           },
           {
-            "endPosition": "3184",
+            "endPosition": "3824",
             "kind": "VARIABLE",
-            "name": "file",
-            "startPosition": "3180"
+            "binding": {
+              "endPosition": "3824",
+              "kind": "IDENTIFIER",
+              "name": "file",
+              "startPosition": "3820"
+            },
+            "startPosition": "3816"
           },
           {
             "expression": {
-              "endPosition": "3193",
+              "endPosition": "3833",
               "kind": "IDENTIFIER",
               "name": "files",
-              "startPosition": "3188"
+              "startPosition": "3828"
             },
-            "endPosition": "3724",
+            "endPosition": "4364",
             "kind": "FOR_IN_LOOP",
             "forEach": "true",
             "variable": {
-              "endPosition": "3184",
+              "endPosition": "3824",
               "kind": "IDENTIFIER",
               "name": "file",
-              "startPosition": "3180"
+              "startPosition": "3820"
             },
             "statement": {
-              "endPosition": "3724",
+              "endPosition": "4364",
               "kind": "BLOCK",
               "statements": [
                 {
                   "condition": {
-                    "endPosition": "3234",
+                    "endPosition": "3874",
                     "kind": "FUNCTION_INVOCATION",
                     "functionSelect": {
                       "identifier": "endsWith",
                       "expression": {
                         "identifier": "name",
                         "expression": {
-                          "endPosition": "3213",
+                          "endPosition": "3853",
                           "kind": "IDENTIFIER",
                           "name": "file",
-                          "startPosition": "3209"
+                          "startPosition": "3849"
                         },
-                        "endPosition": "3218",
+                        "endPosition": "3858",
                         "kind": "MEMBER_SELECT",
-                        "startPosition": "3209"
+                        "startPosition": "3849"
                       },
-                      "endPosition": "3227",
+                      "endPosition": "3867",
                       "kind": "MEMBER_SELECT",
-                      "startPosition": "3209"
+                      "startPosition": "3849"
                     },
                     "arguments": [
                       {
-                        "endPosition": "3232",
+                        "endPosition": "3872",
                         "kind": "STRING_LITERAL",
                         "value": ".js",
-                        "startPosition": "3229"
+                        "startPosition": "3869"
                       }
                     ],
-                    "startPosition": "3209"
+                    "startPosition": "3849"
                   },
-                  "endPosition": "3718",
+                  "endPosition": "4358",
                   "kind": "IF",
-                  "startPosition": "3205",
+                  "startPosition": "3845",
                   "thenStatement": {
-                    "endPosition": "3718",
+                    "endPosition": "4358",
                     "kind": "BLOCK",
                     "statements": [
                       {
-                        "endPosition": "3278",
+                        "endPosition": "3918",
                         "kind": "VARIABLE",
-                        "name": "script",
-                        "startPosition": "3254",
+                        "binding": {
+                          "endPosition": "3900",
+                          "kind": "IDENTIFIER",
+                          "name": "script",
+                          "startPosition": "3894"
+                        },
+                        "startPosition": "3890",
                         "initializer": {
-                          "endPosition": "3278",
+                          "endPosition": "3918",
                           "kind": "FUNCTION_INVOCATION",
                           "functionSelect": {
-                            "endPosition": "3272",
+                            "endPosition": "3912",
                             "kind": "IDENTIFIER",
                             "name": "readFully",
-                            "startPosition": "3263"
+                            "startPosition": "3903"
                           },
                           "arguments": [
                             {
-                              "endPosition": "3277",
+                              "endPosition": "3917",
                               "kind": "IDENTIFIER",
                               "name": "file",
-                              "startPosition": "3273"
+                              "startPosition": "3913"
                             }
                           ],
-                          "startPosition": "3263"
+                          "startPosition": "3903"
                         }
                       },
                       {
-                        "endPosition": "3317",
+                        "endPosition": "3957",
                         "kind": "VARIABLE",
-                        "name": "parser",
-                        "startPosition": "3296",
+                        "binding": {
+                          "endPosition": "3942",
+                          "kind": "IDENTIFIER",
+                          "name": "parser",
+                          "startPosition": "3936"
+                        },
+                        "startPosition": "3932",
                         "initializer": {
                           "constructorExpression": {
-                            "endPosition": "3317",
+                            "endPosition": "3957",
                             "kind": "FUNCTION_INVOCATION",
                             "functionSelect": {
-                              "endPosition": "3315",
+                              "endPosition": "3955",
                               "kind": "IDENTIFIER",
                               "name": "Parser",
-                              "startPosition": "3309"
+                              "startPosition": "3949"
                             },
                             "arguments": [],
-                            "startPosition": "3309"
+                            "startPosition": "3949"
                           },
-                          "endPosition": "3317",
+                          "endPosition": "3957",
                           "kind": "NEW",
-                          "startPosition": "3305"
+                          "startPosition": "3945"
                         }
                       },
                       {
-                        "endPosition": "3578",
+                        "endPosition": "4218",
                         "kind": "VARIABLE",
-                        "name": "tree",
-                        "startPosition": "3335",
+                        "binding": {
+                          "endPosition": "3979",
+                          "kind": "IDENTIFIER",
+                          "name": "tree",
+                          "startPosition": "3975"
+                        },
+                        "startPosition": "3971",
                         "initializer": {
-                          "endPosition": "3578",
+                          "endPosition": "4218",
                           "kind": "FUNCTION_INVOCATION",
                           "functionSelect": {
                             "identifier": "parse",
                             "expression": {
-                              "endPosition": "3348",
+                              "endPosition": "3988",
                               "kind": "IDENTIFIER",
                               "name": "parser",
-                              "startPosition": "3342"
+                              "startPosition": "3982"
                             },
-                            "endPosition": "3354",
+                            "endPosition": "3994",
                             "kind": "MEMBER_SELECT",
-                            "startPosition": "3342"
+                            "startPosition": "3982"
                           },
                           "arguments": [
                             {
                               "leftOperand": {
                                 "leftOperand": {
-                                  "endPosition": "3361",
+                                  "endPosition": "4001",
                                   "kind": "IDENTIFIER",
                                   "name": "subdir",
-                                  "startPosition": "3355"
+                                  "startPosition": "3995"
                                 },
-                                "endPosition": "3366",
+                                "endPosition": "4006",
                                 "kind": "PLUS",
                                 "rightOperand": {
-                                  "endPosition": "3366",
+                                  "endPosition": "4006",
                                   "kind": "STRING_LITERAL",
                                   "value": "/",
-                                  "startPosition": "3365"
+                                  "startPosition": "4005"
                                 },
-                                "startPosition": "3355"
+                                "startPosition": "3995"
                               },
-                              "endPosition": "3379",
+                              "endPosition": "4019",
                               "kind": "PLUS",
                               "rightOperand": {
                                 "identifier": "name",
                                 "expression": {
-                                  "endPosition": "3374",
+                                  "endPosition": "4014",
                                   "kind": "IDENTIFIER",
                                   "name": "file",
-                                  "startPosition": "3370"
+                                  "startPosition": "4010"
                                 },
-                                "endPosition": "3379",
+                                "endPosition": "4019",
                                 "kind": "MEMBER_SELECT",
-                                "startPosition": "3370"
+                                "startPosition": "4010"
                               },
-                              "startPosition": "3355"
+                              "startPosition": "3995"
                             },
                             {
-                              "endPosition": "3387",
+                              "endPosition": "4027",
                               "kind": "IDENTIFIER",
                               "name": "script",
-                              "startPosition": "3381"
+                              "startPosition": "4021"
                             },
                             {
-                              "endPosition": "3426",
+                              "endPosition": "4066",
                               "kind": "FUNCTION_EXPRESSION",
                               "body": {
-                                "endPosition": "3559",
+                                "endPosition": "4199",
                                 "kind": "BLOCK",
                                 "statements": [
                                   {
                                     "expression": {
-                                      "endPosition": "3526",
+                                      "endPosition": "4166",
                                       "kind": "FUNCTION_INVOCATION",
                                       "functionSelect": {
-                                        "endPosition": "3453",
+                                        "endPosition": "4093",
                                         "kind": "IDENTIFIER",
                                         "name": "print",
-                                        "startPosition": "3448"
+                                        "startPosition": "4088"
                                       },
                                       "arguments": [
                                         {
-                                          "endPosition": "3525",
+                                          "endPosition": "4165",
                                           "kind": "FUNCTION_INVOCATION",
                                           "functionSelect": {
                                             "identifier": "replace",
                                             "expression": {
-                                              "endPosition": "3505",
+                                              "endPosition": "4145",
                                               "kind": "FUNCTION_INVOCATION",
                                               "functionSelect": {
                                                 "identifier": "stringify",
                                                 "expression": {
-                                                  "endPosition": "3458",
+                                                  "endPosition": "4098",
                                                   "kind": "IDENTIFIER",
                                                   "name": "JSON",
-                                                  "startPosition": "3454"
+                                                  "startPosition": "4094"
                                                 },
-                                                "endPosition": "3468",
+                                                "endPosition": "4108",
                                                 "kind": "MEMBER_SELECT",
-                                                "startPosition": "3454"
+                                                "startPosition": "4094"
                                               },
                                               "arguments": [
                                                 {
-                                                  "endPosition": "3495",
+                                                  "endPosition": "4135",
                                                   "kind": "FUNCTION_INVOCATION",
                                                   "functionSelect": {
                                                     "identifier": "convert",
                                                     "expression": {
-                                                      "endPosition": "3475",
+                                                      "endPosition": "4115",
                                                       "kind": "IDENTIFIER",
                                                       "name": "parser",
-                                                      "startPosition": "3469"
+                                                      "startPosition": "4109"
                                                     },
-                                                    "endPosition": "3483",
+                                                    "endPosition": "4123",
                                                     "kind": "MEMBER_SELECT",
-                                                    "startPosition": "3469"
+                                                    "startPosition": "4109"
                                                   },
                                                   "arguments": [
                                                     {
-                                                      "endPosition": "3494",
+                                                      "endPosition": "4134",
                                                       "kind": "IDENTIFIER",
                                                       "name": "diagnostic",
-                                                      "startPosition": "3484"
+                                                      "startPosition": "4124"
                                                     }
                                                   ],
-                                                  "startPosition": "3469"
+                                                  "startPosition": "4109"
                                                 },
                                                 {
-                                                  "endPosition": "3501",
+                                                  "endPosition": "4141",
                                                   "kind": "NULL_LITERAL",
-                                                  "startPosition": "3497"
+                                                  "startPosition": "4137"
                                                 },
                                                 {
-                                                  "endPosition": "3504",
+                                                  "endPosition": "4144",
                                                   "kind": "NUMBER_LITERAL",
                                                   "value": "2",
-                                                  "startPosition": "3503"
+                                                  "startPosition": "4143"
                                                 }
                                               ],
-                                              "startPosition": "3454"
+                                              "startPosition": "4094"
                                             },
-                                            "endPosition": "3513",
+                                            "endPosition": "4153",
                                             "kind": "MEMBER_SELECT",
-                                            "startPosition": "3454"
+                                            "startPosition": "4094"
                                           },
                                           "arguments": [
                                             {
-                                              "endPosition": "3520",
+                                              "endPosition": "4160",
                                               "kind": "REGEXP_LITERAL",
                                               "options": "g",
                                               "pattern": "\\\\r",
-                                              "startPosition": "3514"
+                                              "startPosition": "4154"
                                             },
                                             {
-                                              "endPosition": "3523",
+                                              "endPosition": "4163",
                                               "kind": "STRING_LITERAL",
                                               "value": "",
-                                              "startPosition": "3523"
+                                              "startPosition": "4163"
                                             }
                                           ],
-                                          "startPosition": "3513"
+                                          "startPosition": "4153"
                                         }
                                       ],
-                                      "startPosition": "3448"
+                                      "startPosition": "4088"
                                     },
-                                    "endPosition": "3526",
+                                    "endPosition": "4166",
                                     "kind": "EXPRESSION_STATEMENT",
-                                    "startPosition": "3448"
+                                    "startPosition": "4088"
                                   },
                                   {
                                     "expression": {
-                                      "endPosition": "3558",
+                                      "endPosition": "4198",
                                       "kind": "FUNCTION_INVOCATION",
                                       "functionSelect": {
-                                        "endPosition": "3553",
+                                        "endPosition": "4193",
                                         "kind": "IDENTIFIER",
                                         "name": "print",
-                                        "startPosition": "3548"
+                                        "startPosition": "4188"
                                       },
                                       "arguments": [
                                         {
-                                          "endPosition": "3556",
+                                          "endPosition": "4196",
                                           "kind": "STRING_LITERAL",
                                           "value": ",",
-                                          "startPosition": "3555"
+                                          "startPosition": "4195"
                                         }
                                       ],
-                                      "startPosition": "3548"
+                                      "startPosition": "4188"
                                     },
-                                    "endPosition": "3558",
+                                    "endPosition": "4198",
                                     "kind": "EXPRESSION_STATEMENT",
-                                    "startPosition": "3548"
+                                    "startPosition": "4188"
                                   }
                                 ],
-                                "startPosition": "3426"
+                                "startPosition": "4066"
                               },
                               "strict": "false",
-                              "startPosition": "3426",
+                              "startPosition": "4066",
                               "parameters": [
                                 {
-                                  "endPosition": "3424",
+                                  "endPosition": "4064",
                                   "kind": "IDENTIFIER",
                                   "name": "diagnostic",
-                                  "startPosition": "3414"
+                                  "startPosition": "4054"
                                 }
                               ]
                             }
                           ],
-                          "startPosition": "3342"
+                          "startPosition": "3982"
                         }
                       },
                       {
                         "condition": {
                           "leftOperand": {
-                            "endPosition": "3601",
+                            "endPosition": "4241",
                             "kind": "IDENTIFIER",
                             "name": "tree",
-                            "startPosition": "3597"
+                            "startPosition": "4237"
                           },
-                          "endPosition": "3609",
+                          "endPosition": "4249",
                           "kind": "NOT_EQUAL_TO",
                           "rightOperand": {
-                            "endPosition": "3609",
+                            "endPosition": "4249",
                             "kind": "NULL_LITERAL",
-                            "startPosition": "3605"
+                            "startPosition": "4245"
                           },
-                          "startPosition": "3597"
+                          "startPosition": "4237"
                         },
-                        "endPosition": "3708",
+                        "endPosition": "4348",
                         "kind": "IF",
-                        "startPosition": "3593",
+                        "startPosition": "4233",
                         "thenStatement": {
-                          "endPosition": "3708",
+                          "endPosition": "4348",
                           "kind": "BLOCK",
                           "statements": [
                             {
                               "expression": {
-                                "endPosition": "3665",
+                                "endPosition": "4305",
                                 "kind": "FUNCTION_INVOCATION",
                                 "functionSelect": {
-                                  "endPosition": "3634",
+                                  "endPosition": "4274",
                                   "kind": "IDENTIFIER",
                                   "name": "print",
-                                  "startPosition": "3629"
+                                  "startPosition": "4269"
                                 },
                                 "arguments": [
                                   {
-                                    "endPosition": "3664",
+                                    "endPosition": "4304",
                                     "kind": "FUNCTION_INVOCATION",
                                     "functionSelect": {
                                       "identifier": "stringify",
                                       "expression": {
-                                        "endPosition": "3639",
+                                        "endPosition": "4279",
                                         "kind": "IDENTIFIER",
                                         "name": "JSON",
-                                        "startPosition": "3635"
+                                        "startPosition": "4275"
                                       },
-                                      "endPosition": "3649",
+                                      "endPosition": "4289",
                                       "kind": "MEMBER_SELECT",
-                                      "startPosition": "3635"
+                                      "startPosition": "4275"
                                     },
                                     "arguments": [
                                       {
-                                        "endPosition": "3654",
+                                        "endPosition": "4294",
                                         "kind": "IDENTIFIER",
                                         "name": "tree",
-                                        "startPosition": "3650"
+                                        "startPosition": "4290"
                                       },
                                       {
-                                        "endPosition": "3660",
+                                        "endPosition": "4300",
                                         "kind": "NULL_LITERAL",
-                                        "startPosition": "3656"
+                                        "startPosition": "4296"
                                       },
                                       {
-                                        "endPosition": "3663",
+                                        "endPosition": "4303",
                                         "kind": "NUMBER_LITERAL",
                                         "value": "2",
-                                        "startPosition": "3662"
+                                        "startPosition": "4302"
                                       }
                                     ],
-                                    "startPosition": "3635"
+                                    "startPosition": "4275"
                                   }
                                 ],
-                                "startPosition": "3629"
+                                "startPosition": "4269"
                               },
-                              "endPosition": "3665",
+                              "endPosition": "4305",
                               "kind": "EXPRESSION_STATEMENT",
-                              "startPosition": "3629"
+                              "startPosition": "4269"
                             },
                             {
                               "expression": {
-                                "endPosition": "3693",
+                                "endPosition": "4333",
                                 "kind": "FUNCTION_INVOCATION",
                                 "functionSelect": {
-                                  "endPosition": "3688",
+                                  "endPosition": "4328",
                                   "kind": "IDENTIFIER",
                                   "name": "print",
-                                  "startPosition": "3683"
+                                  "startPosition": "4323"
                                 },
                                 "arguments": [
                                   {
-                                    "endPosition": "3691",
+                                    "endPosition": "4331",
                                     "kind": "STRING_LITERAL",
                                     "value": ",",
-                                    "startPosition": "3690"
+                                    "startPosition": "4330"
                                   }
                                 ],
-                                "startPosition": "3683"
+                                "startPosition": "4323"
                               },
-                              "endPosition": "3693",
+                              "endPosition": "4333",
                               "kind": "EXPRESSION_STATEMENT",
-                              "startPosition": "3683"
+                              "startPosition": "4323"
                             }
                           ],
-                          "startPosition": "3611"
+                          "startPosition": "4251"
                         }
                       }
                     ],
-                    "startPosition": "3236"
+                    "startPosition": "3876"
                   }
                 }
               ],
-              "startPosition": "3195"
+              "startPosition": "3835"
             },
-            "startPosition": "3166"
+            "startPosition": "3806"
           }
         ],
-        "startPosition": "3028"
+        "startPosition": "3668"
       },
       "strict": "false",
-      "startPosition": "2998",
+      "startPosition": "3638",
       "parameters": [
         {
-          "endPosition": "3026",
+          "endPosition": "3666",
           "kind": "IDENTIFIER",
           "name": "subdir",
-          "startPosition": "3020"
+          "startPosition": "3660"
         }
       ]
     },
     {
-      "endPosition": "4070",
+      "endPosition": "4710",
       "kind": "FUNCTION",
-      "name": "main",
+      "name": {
+        "endPosition": "4421",
+        "kind": "IDENTIFIER",
+        "name": "main",
+        "startPosition": "4417"
+      },
       "body": {
-        "endPosition": "4068",
+        "endPosition": "4708",
         "kind": "BLOCK",
         "statements": [
           {
             "expression": {
-              "endPosition": "3800",
+              "endPosition": "4440",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
-                "endPosition": "3795",
+                "endPosition": "4435",
                 "kind": "IDENTIFIER",
                 "name": "print",
-                "startPosition": "3790"
+                "startPosition": "4430"
               },
               "arguments": [
                 {
-                  "endPosition": "3798",
+                  "endPosition": "4438",
                   "kind": "STRING_LITERAL",
                   "value": "[",
-                  "startPosition": "3797"
+                  "startPosition": "4437"
                 }
               ],
-              "startPosition": "3790"
+              "startPosition": "4430"
             },
-            "endPosition": "3800",
+            "endPosition": "4440",
             "kind": "EXPRESSION_STATEMENT",
-            "startPosition": "3790"
+            "startPosition": "4430"
           },
           {
             "expression": {
-              "endPosition": "3834",
+              "endPosition": "4474",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
-                "endPosition": "3819",
+                "endPosition": "4459",
                 "kind": "IDENTIFIER",
                 "name": "processFiles",
-                "startPosition": "3807"
+                "startPosition": "4447"
               },
               "arguments": [
                 {
-                  "endPosition": "3832",
+                  "endPosition": "4472",
                   "kind": "STRING_LITERAL",
                   "value": "parsertests",
-                  "startPosition": "3821"
+                  "startPosition": "4461"
                 }
               ],
-              "startPosition": "3807"
+              "startPosition": "4447"
             },
-            "endPosition": "3834",
+            "endPosition": "4474",
             "kind": "EXPRESSION_STATEMENT",
-            "startPosition": "3807"
+            "startPosition": "4447"
           },
           {
             "expression": {
-              "endPosition": "3875",
+              "endPosition": "4515",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
-                "endPosition": "3852",
+                "endPosition": "4492",
                 "kind": "IDENTIFIER",
                 "name": "processFiles",
-                "startPosition": "3840"
+                "startPosition": "4480"
               },
               "arguments": [
                 {
-                  "endPosition": "3873",
+                  "endPosition": "4513",
                   "kind": "STRING_LITERAL",
                   "value": "parsernegativetests",
-                  "startPosition": "3854"
+                  "startPosition": "4494"
                 }
               ],
-              "startPosition": "3840"
+              "startPosition": "4480"
             },
-            "endPosition": "3875",
+            "endPosition": "4515",
             "kind": "EXPRESSION_STATEMENT",
-            "startPosition": "3840"
+            "startPosition": "4480"
           },
           {
-            "endPosition": "3944",
+            "endPosition": "4584",
             "kind": "VARIABLE",
-            "name": "script",
-            "startPosition": "3916",
+            "binding": {
+              "endPosition": "4562",
+              "kind": "IDENTIFIER",
+              "name": "script",
+              "startPosition": "4556"
+            },
+            "startPosition": "4552",
             "initializer": {
-              "endPosition": "3944",
+              "endPosition": "4584",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
-                "endPosition": "3934",
+                "endPosition": "4574",
                 "kind": "IDENTIFIER",
                 "name": "readFully",
-                "startPosition": "3925"
+                "startPosition": "4565"
               },
               "arguments": [
                 {
-                  "endPosition": "3943",
+                  "endPosition": "4583",
                   "kind": "IDENTIFIER",
                   "name": "__FILE__",
-                  "startPosition": "3935"
+                  "startPosition": "4575"
                 }
               ],
-              "startPosition": "3925"
+              "startPosition": "4565"
             }
           },
           {
-            "endPosition": "4009",
+            "endPosition": "4649",
             "kind": "VARIABLE",
-            "name": "tree",
-            "startPosition": "3954",
+            "binding": {
+              "endPosition": "4598",
+              "kind": "IDENTIFIER",
+              "name": "tree",
+              "startPosition": "4594"
+            },
+            "startPosition": "4590",
             "initializer": {
-              "endPosition": "4009",
+              "endPosition": "4649",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
                 "identifier": "parse",
                 "expression": {
                   "constructorExpression": {
-                    "endPosition": "3973",
+                    "endPosition": "4613",
                     "kind": "FUNCTION_INVOCATION",
                     "functionSelect": {
-                      "endPosition": "3971",
+                      "endPosition": "4611",
                       "kind": "IDENTIFIER",
                       "name": "Parser",
-                      "startPosition": "3965"
+                      "startPosition": "4605"
                     },
                     "arguments": [],
-                    "startPosition": "3965"
+                    "startPosition": "4605"
                   },
-                  "endPosition": "3973",
+                  "endPosition": "4613",
                   "kind": "NEW",
-                  "startPosition": "3961"
+                  "startPosition": "4601"
                 },
-                "endPosition": "3979",
+                "endPosition": "4619",
                 "kind": "MEMBER_SELECT",
-                "startPosition": "3961"
+                "startPosition": "4601"
               },
               "arguments": [
                 {
-                  "endPosition": "3993",
+                  "endPosition": "4633",
                   "kind": "STRING_LITERAL",
                   "value": "parserapi.js",
-                  "startPosition": "3981"
+                  "startPosition": "4621"
                 },
                 {
-                  "endPosition": "4002",
+                  "endPosition": "4642",
                   "kind": "IDENTIFIER",
                   "name": "script",
-                  "startPosition": "3996"
+                  "startPosition": "4636"
                 },
                 {
-                  "endPosition": "4008",
+                  "endPosition": "4648",
                   "kind": "NULL_LITERAL",
-                  "startPosition": "4004"
+                  "startPosition": "4644"
                 }
               ],
-              "startPosition": "3961"
+              "startPosition": "4601"
             }
           },
           {
             "expression": {
-              "endPosition": "4051",
+              "endPosition": "4691",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
-                "endPosition": "4020",
+                "endPosition": "4660",
                 "kind": "IDENTIFIER",
                 "name": "print",
-                "startPosition": "4015"
+                "startPosition": "4655"
               },
               "arguments": [
                 {
-                  "endPosition": "4050",
+                  "endPosition": "4690",
                   "kind": "FUNCTION_INVOCATION",
                   "functionSelect": {
                     "identifier": "stringify",
                     "expression": {
-                      "endPosition": "4025",
+                      "endPosition": "4665",
                       "kind": "IDENTIFIER",
                       "name": "JSON",
-                      "startPosition": "4021"
+                      "startPosition": "4661"
                     },
-                    "endPosition": "4035",
+                    "endPosition": "4675",
                     "kind": "MEMBER_SELECT",
-                    "startPosition": "4021"
+                    "startPosition": "4661"
                   },
                   "arguments": [
                     {
-                      "endPosition": "4040",
+                      "endPosition": "4680",
                       "kind": "IDENTIFIER",
                       "name": "tree",
-                      "startPosition": "4036"
+                      "startPosition": "4676"
                     },
                     {
-                      "endPosition": "4046",
+                      "endPosition": "4686",
                       "kind": "NULL_LITERAL",
-                      "startPosition": "4042"
+                      "startPosition": "4682"
                     },
                     {
-                      "endPosition": "4049",
+                      "endPosition": "4689",
                       "kind": "NUMBER_LITERAL",
                       "value": "2",
-                      "startPosition": "4048"
+                      "startPosition": "4688"
                     }
                   ],
-                  "startPosition": "4021"
+                  "startPosition": "4661"
                 }
               ],
-              "startPosition": "4015"
+              "startPosition": "4655"
             },
-            "endPosition": "4051",
+            "endPosition": "4691",
             "kind": "EXPRESSION_STATEMENT",
-            "startPosition": "4015"
+            "startPosition": "4655"
           },
           {
             "expression": {
-              "endPosition": "4067",
+              "endPosition": "4707",
               "kind": "FUNCTION_INVOCATION",
               "functionSelect": {
-                "endPosition": "4062",
+                "endPosition": "4702",
                 "kind": "IDENTIFIER",
                 "name": "print",
-                "startPosition": "4057"
+                "startPosition": "4697"
               },
               "arguments": [
                 {
-                  "endPosition": "4065",
+                  "endPosition": "4705",
                   "kind": "STRING_LITERAL",
                   "value": "]",
-                  "startPosition": "4064"
+                  "startPosition": "4704"
                 }
               ],
-              "startPosition": "4057"
+              "startPosition": "4697"
             },
-            "endPosition": "4067",
+            "endPosition": "4707",
             "kind": "EXPRESSION_STATEMENT",
-            "startPosition": "4057"
+            "startPosition": "4697"
           }
         ],
-        "startPosition": "3784"
+        "startPosition": "4424"
       },
       "strict": "false",
-      "startPosition": "3768",
+      "startPosition": "4408",
       "parameters": []
     },
     {
       "expression": {
-        "endPosition": "4078",
+        "endPosition": "4718",
         "kind": "FUNCTION_INVOCATION",
         "functionSelect": {
-          "endPosition": "4076",
+          "endPosition": "4716",
           "kind": "IDENTIFIER",
           "name": "main",
-          "startPosition": "4072"
+          "startPosition": "4712"
         },
         "arguments": [],
-        "startPosition": "4072"
-      },
-      "endPosition": "4078",
+        "startPosition": "4712"
+      },
+      "endPosition": "4718",
       "kind": "EXPRESSION_STATEMENT",
-      "startPosition": "4072"
+      "startPosition": "4712"
     }
   ],
   "sourceName": "parserapi.js",
   "strict": "false",
   "startPosition": "1136"
-}
-]
+}
+]
--- a/nashorn/test/script/nosecurity/parservisitor.js	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/parservisitor.js	Mon Jul 18 09:38:08 2016 -0700
@@ -202,7 +202,7 @@
 parse("funcdecl.js", "function func() {}", 
     new (Java.extend(SimpleTreeVisitor))() {
         visitFunctionDeclaration: function(fd) {
-            print("in visitFunctionDeclaration " + fd.name);
+            print("in visitFunctionDeclaration " + fd.name.name);
         }
     });
 
@@ -361,7 +361,7 @@
 parse("var.js", "var x = 34;", 
     new (Java.extend(SimpleTreeVisitor))() {
         visitVariable: function(vn) {
-            print("in visitVariable " + vn.name + " = " + vn.initializer.value);
+            print("in visitVariable " + vn.binding.name + " = " + vn.initializer.value);
         }
     });
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/arrow.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 arrows.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+var f = x=>x*2;
+[].map(v => v + 1);
+
+EOF
+
+parse("arrow.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitExpressionStatement : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/arrow.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,103 @@
+[
+  {
+    "endPosition": "15",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "6",
+      "kind": "IDENTIFIER",
+      "name": "f",
+      "startPosition": "5"
+    },
+    "startPosition": "1",
+    "initializer": {
+      "endPosition": "12",
+      "arrow": "true",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "leftOperand": {
+          "endPosition": "13",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "12"
+        },
+        "endPosition": "15",
+        "kind": "MULTIPLY",
+        "rightOperand": {
+          "endPosition": "15",
+          "kind": "NUMBER_LITERAL",
+          "value": "2",
+          "startPosition": "14"
+        },
+        "startPosition": "12"
+      },
+      "strict": "false",
+      "startPosition": "12",
+      "parameters": [
+        {
+          "endPosition": "10",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "9"
+        }
+      ]
+    }
+  },
+  {
+    "expression": {
+      "endPosition": "35",
+      "kind": "FUNCTION_INVOCATION",
+      "functionSelect": {
+        "identifier": "map",
+        "expression": {
+          "endPosition": "19",
+          "kind": "ARRAY_LITERAL",
+          "elements": [],
+          "startPosition": "17"
+        },
+        "endPosition": "23",
+        "kind": "MEMBER_SELECT",
+        "startPosition": "17"
+      },
+      "arguments": [
+        {
+          "endPosition": "29",
+          "arrow": "true",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "leftOperand": {
+              "endPosition": "30",
+              "kind": "IDENTIFIER",
+              "name": "v",
+              "startPosition": "29"
+            },
+            "endPosition": "34",
+            "kind": "PLUS",
+            "rightOperand": {
+              "endPosition": "34",
+              "kind": "NUMBER_LITERAL",
+              "value": "1",
+              "startPosition": "33"
+            },
+            "startPosition": "29"
+          },
+          "strict": "false",
+          "startPosition": "29",
+          "parameters": [
+            {
+              "endPosition": "25",
+              "kind": "IDENTIFIER",
+              "name": "v",
+              "startPosition": "24"
+            }
+          ]
+        }
+      ],
+      "startPosition": "17"
+    },
+    "endPosition": "35",
+    "kind": "EXPRESSION_STATEMENT",
+    "startPosition": "17"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/arrow_params.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 arrow params.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+var f1 = (x=2)=>x*3;
+var f2 = ({x, y})=>x*y;
+var f3 = ([x, y])=>x+y;
+var f4 = ({x, y}={y: 4, x: 5})=>x*y;
+var f5 = ([x, y]=[3, 6])=>x+y;
+
+EOF
+
+parse("arrow_params.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/arrow_params.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,411 @@
+[
+  {
+    "endPosition": "20",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "7",
+      "kind": "IDENTIFIER",
+      "name": "f1",
+      "startPosition": "5"
+    },
+    "startPosition": "1",
+    "initializer": {
+      "endPosition": "17",
+      "arrow": "true",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "leftOperand": {
+          "endPosition": "18",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "17"
+        },
+        "endPosition": "20",
+        "kind": "MULTIPLY",
+        "rightOperand": {
+          "endPosition": "20",
+          "kind": "NUMBER_LITERAL",
+          "value": "3",
+          "startPosition": "19"
+        },
+        "startPosition": "17"
+      },
+      "strict": "false",
+      "startPosition": "17",
+      "parameters": [
+        {
+          "expression": {
+            "endPosition": "14",
+            "kind": "NUMBER_LITERAL",
+            "value": "2",
+            "startPosition": "13"
+          },
+          "endPosition": "14",
+          "kind": "ASSIGNMENT",
+          "variable": {
+            "endPosition": "12",
+            "kind": "IDENTIFIER",
+            "name": "x",
+            "startPosition": "11"
+          },
+          "startPosition": "11"
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "44",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "28",
+      "kind": "IDENTIFIER",
+      "name": "f2",
+      "startPosition": "26"
+    },
+    "startPosition": "22",
+    "initializer": {
+      "endPosition": "41",
+      "arrow": "true",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "leftOperand": {
+          "endPosition": "42",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "41"
+        },
+        "endPosition": "44",
+        "kind": "MULTIPLY",
+        "rightOperand": {
+          "endPosition": "44",
+          "kind": "IDENTIFIER",
+          "name": "y",
+          "startPosition": "43"
+        },
+        "startPosition": "41"
+      },
+      "strict": "false",
+      "startPosition": "41",
+      "parameters": [
+        {
+          "endPosition": "38",
+          "kind": "OBJECT_LITERAL",
+          "startPosition": "32",
+          "properties": [
+            {
+              "getter": "null",
+              "endPosition": "34",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "34",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "33"
+              },
+              "startPosition": "33",
+              "key": {
+                "endPosition": "34",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "33"
+              }
+            },
+            {
+              "getter": "null",
+              "endPosition": "37",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "37",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "36"
+              },
+              "startPosition": "36",
+              "key": {
+                "endPosition": "37",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "36"
+              }
+            }
+          ]
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "68",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "52",
+      "kind": "IDENTIFIER",
+      "name": "f3",
+      "startPosition": "50"
+    },
+    "startPosition": "46",
+    "initializer": {
+      "endPosition": "65",
+      "arrow": "true",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "leftOperand": {
+          "endPosition": "66",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "65"
+        },
+        "endPosition": "68",
+        "kind": "PLUS",
+        "rightOperand": {
+          "endPosition": "68",
+          "kind": "IDENTIFIER",
+          "name": "y",
+          "startPosition": "67"
+        },
+        "startPosition": "65"
+      },
+      "strict": "false",
+      "startPosition": "65",
+      "parameters": [
+        {
+          "endPosition": "62",
+          "kind": "ARRAY_LITERAL",
+          "elements": [
+            {
+              "endPosition": "58",
+              "kind": "IDENTIFIER",
+              "name": "x",
+              "startPosition": "57"
+            },
+            {
+              "endPosition": "61",
+              "kind": "IDENTIFIER",
+              "name": "y",
+              "startPosition": "60"
+            }
+          ],
+          "startPosition": "56"
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "105",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "76",
+      "kind": "IDENTIFIER",
+      "name": "f4",
+      "startPosition": "74"
+    },
+    "startPosition": "70",
+    "initializer": {
+      "endPosition": "102",
+      "arrow": "true",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "leftOperand": {
+          "endPosition": "103",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "102"
+        },
+        "endPosition": "105",
+        "kind": "MULTIPLY",
+        "rightOperand": {
+          "endPosition": "105",
+          "kind": "IDENTIFIER",
+          "name": "y",
+          "startPosition": "104"
+        },
+        "startPosition": "102"
+      },
+      "strict": "false",
+      "startPosition": "102",
+      "parameters": [
+        {
+          "expression": {
+            "endPosition": "99",
+            "kind": "OBJECT_LITERAL",
+            "startPosition": "87",
+            "properties": [
+              {
+                "getter": "null",
+                "endPosition": "92",
+                "kind": "PROPERTY",
+                "setter": "null",
+                "value": {
+                  "endPosition": "92",
+                  "kind": "NUMBER_LITERAL",
+                  "value": "4",
+                  "startPosition": "91"
+                },
+                "startPosition": "88",
+                "key": {
+                  "endPosition": "89",
+                  "kind": "IDENTIFIER",
+                  "name": "y",
+                  "startPosition": "88"
+                }
+              },
+              {
+                "getter": "null",
+                "endPosition": "98",
+                "kind": "PROPERTY",
+                "setter": "null",
+                "value": {
+                  "endPosition": "98",
+                  "kind": "NUMBER_LITERAL",
+                  "value": "5",
+                  "startPosition": "97"
+                },
+                "startPosition": "94",
+                "key": {
+                  "endPosition": "95",
+                  "kind": "IDENTIFIER",
+                  "name": "x",
+                  "startPosition": "94"
+                }
+              }
+            ]
+          },
+          "endPosition": "99",
+          "kind": "ASSIGNMENT",
+          "variable": {
+            "endPosition": "86",
+            "kind": "OBJECT_LITERAL",
+            "startPosition": "80",
+            "properties": [
+              {
+                "getter": "null",
+                "endPosition": "82",
+                "kind": "PROPERTY",
+                "setter": "null",
+                "value": {
+                  "endPosition": "82",
+                  "kind": "IDENTIFIER",
+                  "name": "x",
+                  "startPosition": "81"
+                },
+                "startPosition": "81",
+                "key": {
+                  "endPosition": "82",
+                  "kind": "IDENTIFIER",
+                  "name": "x",
+                  "startPosition": "81"
+                }
+              },
+              {
+                "getter": "null",
+                "endPosition": "85",
+                "kind": "PROPERTY",
+                "setter": "null",
+                "value": {
+                  "endPosition": "85",
+                  "kind": "IDENTIFIER",
+                  "name": "y",
+                  "startPosition": "84"
+                },
+                "startPosition": "84",
+                "key": {
+                  "endPosition": "85",
+                  "kind": "IDENTIFIER",
+                  "name": "y",
+                  "startPosition": "84"
+                }
+              }
+            ]
+          },
+          "startPosition": "80"
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "136",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "113",
+      "kind": "IDENTIFIER",
+      "name": "f5",
+      "startPosition": "111"
+    },
+    "startPosition": "107",
+    "initializer": {
+      "endPosition": "133",
+      "arrow": "true",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "leftOperand": {
+          "endPosition": "134",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "133"
+        },
+        "endPosition": "136",
+        "kind": "PLUS",
+        "rightOperand": {
+          "endPosition": "136",
+          "kind": "IDENTIFIER",
+          "name": "y",
+          "startPosition": "135"
+        },
+        "startPosition": "133"
+      },
+      "strict": "false",
+      "startPosition": "133",
+      "parameters": [
+        {
+          "expression": {
+            "endPosition": "130",
+            "kind": "ARRAY_LITERAL",
+            "elements": [
+              {
+                "endPosition": "126",
+                "kind": "NUMBER_LITERAL",
+                "value": "3",
+                "startPosition": "125"
+              },
+              {
+                "endPosition": "129",
+                "kind": "NUMBER_LITERAL",
+                "value": "6",
+                "startPosition": "128"
+              }
+            ],
+            "startPosition": "124"
+          },
+          "endPosition": "130",
+          "kind": "ASSIGNMENT",
+          "variable": {
+            "endPosition": "123",
+            "kind": "ARRAY_LITERAL",
+            "elements": [
+              {
+                "endPosition": "119",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "118"
+              },
+              {
+                "endPosition": "122",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "121"
+              }
+            ],
+            "startPosition": "117"
+          },
+          "startPosition": "117"
+        }
+      ]
+    }
+  }
+]
--- a/nashorn/test/script/nosecurity/treeapi/assignment.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/assignment.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -146,4 +146,4 @@
     },
     "startPosition": "61"
   }
-]
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/class.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 class.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+class Shape {
+    constructor() {
+        Shape.numShapes++;
+    }
+
+    static get numShapes() {
+        return !this.count_ ? 0 : this.count_
+    }
+
+    static set numShapes(val) {
+         this.count_ = val
+    }
+}
+
+class Circle extends Shape {
+    constructor(radius) {
+        super();
+        this.radius_ = radius
+        Circle.numCircles++
+    }
+
+    static draw(circle, canvas) {
+        // drawing code
+    }
+
+    static get numCircles() {
+        return !this.count_ ? 0 : this.count_
+    }
+
+    static set numCircles(val) {
+         this.count_ = val
+    }
+
+    area() {
+        return Math.pow(this.radius, 2) * Math.PI
+    }
+
+    get radius() {
+        return this.radius_
+    }
+
+    set radius(radius) {
+        if (!Number.isInteger(radius))
+            throw new TypeError("Circle radius is not an int");
+        this.radius_ = radius
+    }
+}
+
+EOF
+
+parse("class.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitClassDeclaration : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/class.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,751 @@
+[
+  {
+    "classElements": [
+      {
+        "getter": {
+          "endPosition": "96",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "endPosition": "143",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "expression": {
+                  "condition": {
+                    "expression": {
+                      "identifier": "count_",
+                      "expression": {
+                        "endPosition": "118",
+                        "kind": "IDENTIFIER",
+                        "this": "true",
+                        "name": "this",
+                        "startPosition": "114"
+                      },
+                      "endPosition": "125",
+                      "kind": "MEMBER_SELECT",
+                      "startPosition": "114"
+                    },
+                    "endPosition": "125",
+                    "kind": "LOGICAL_COMPLEMENT",
+                    "startPosition": "113"
+                  },
+                  "endPosition": "143",
+                  "kind": "CONDITIONAL_EXPRESSION",
+                  "trueExpression": {
+                    "endPosition": "129",
+                    "kind": "NUMBER_LITERAL",
+                    "value": "0",
+                    "startPosition": "128"
+                  },
+                  "falseExpression": {
+                    "identifier": "count_",
+                    "expression": {
+                      "endPosition": "136",
+                      "kind": "IDENTIFIER",
+                      "this": "true",
+                      "name": "this",
+                      "startPosition": "132"
+                    },
+                    "endPosition": "143",
+                    "kind": "MEMBER_SELECT",
+                    "startPosition": "132"
+                  },
+                  "startPosition": "126"
+                },
+                "endPosition": "143",
+                "kind": "RETURN",
+                "startPosition": "106"
+              }
+            ],
+            "startPosition": "96"
+          },
+          "strict": "true",
+          "startPosition": "96",
+          "parameters": []
+        },
+        "static": "true",
+        "endPosition": "149",
+        "kind": "PROPERTY",
+        "setter": {
+          "endPosition": "181",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "endPosition": "209",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "expression": {
+                  "expression": {
+                    "endPosition": "209",
+                    "kind": "IDENTIFIER",
+                    "name": "val",
+                    "startPosition": "206"
+                  },
+                  "endPosition": "209",
+                  "kind": "ASSIGNMENT",
+                  "variable": {
+                    "identifier": "count_",
+                    "expression": {
+                      "endPosition": "196",
+                      "kind": "IDENTIFIER",
+                      "this": "true",
+                      "name": "this",
+                      "startPosition": "192"
+                    },
+                    "endPosition": "203",
+                    "kind": "MEMBER_SELECT",
+                    "startPosition": "192"
+                  },
+                  "startPosition": "192"
+                },
+                "endPosition": "209",
+                "kind": "EXPRESSION_STATEMENT",
+                "startPosition": "192"
+              }
+            ],
+            "startPosition": "181"
+          },
+          "strict": "true",
+          "startPosition": "181",
+          "parameters": [
+            {
+              "endPosition": "179",
+              "kind": "IDENTIFIER",
+              "name": "val",
+              "startPosition": "176"
+            }
+          ]
+        },
+        "value": "null",
+        "startPosition": "80",
+        "key": {
+          "endPosition": "93",
+          "kind": "IDENTIFIER",
+          "name": "numShapes",
+          "startPosition": "84"
+        }
+      }
+    ],
+    "endPosition": "12",
+    "kind": "CLASS",
+    "classHeritage": "null",
+    "name": {
+      "endPosition": "12",
+      "kind": "IDENTIFIER",
+      "name": "Shape",
+      "startPosition": "7"
+    },
+    "constructor": {
+      "getter": "null",
+      "endPosition": "67",
+      "kind": "PROPERTY",
+      "setter": "null",
+      "value": {
+        "endPosition": "33",
+        "kind": "FUNCTION_EXPRESSION",
+        "name": {
+          "endPosition": "30",
+          "kind": "IDENTIFIER",
+          "name": "constructor",
+          "startPosition": "19"
+        },
+        "body": {
+          "endPosition": "61",
+          "kind": "BLOCK",
+          "statements": [
+            {
+              "expression": {
+                "expression": {
+                  "identifier": "numShapes",
+                  "expression": {
+                    "endPosition": "48",
+                    "kind": "IDENTIFIER",
+                    "name": "Shape",
+                    "startPosition": "43"
+                  },
+                  "endPosition": "58",
+                  "kind": "MEMBER_SELECT",
+                  "startPosition": "43"
+                },
+                "endPosition": "60",
+                "kind": "POSTFIX_INCREMENT",
+                "startPosition": "43"
+              },
+              "endPosition": "60",
+              "kind": "EXPRESSION_STATEMENT",
+              "startPosition": "43"
+            }
+          ],
+          "startPosition": "33"
+        },
+        "strict": "true",
+        "startPosition": "33",
+        "parameters": []
+      },
+      "startPosition": "19",
+      "key": {
+        "endPosition": "30",
+        "kind": "IDENTIFIER",
+        "name": "constructor",
+        "startPosition": "19"
+      }
+    },
+    "startPosition": "1"
+  },
+  {
+    "classElements": [
+      {
+        "getter": "null",
+        "static": "true",
+        "endPosition": "419",
+        "kind": "PROPERTY",
+        "setter": "null",
+        "value": {
+          "endPosition": "388",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": {
+            "endPosition": "371",
+            "kind": "IDENTIFIER",
+            "name": "draw",
+            "startPosition": "367"
+          },
+          "body": {
+            "endPosition": "389",
+            "kind": "BLOCK",
+            "statements": [],
+            "startPosition": "388"
+          },
+          "strict": "true",
+          "startPosition": "388",
+          "parameters": [
+            {
+              "endPosition": "378",
+              "kind": "IDENTIFIER",
+              "name": "circle",
+              "startPosition": "372"
+            },
+            {
+              "endPosition": "386",
+              "kind": "IDENTIFIER",
+              "name": "canvas",
+              "startPosition": "380"
+            }
+          ]
+        },
+        "startPosition": "367",
+        "key": {
+          "endPosition": "371",
+          "kind": "IDENTIFIER",
+          "name": "draw",
+          "startPosition": "367"
+        }
+      },
+      {
+        "getter": {
+          "endPosition": "449",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "endPosition": "496",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "expression": {
+                  "condition": {
+                    "expression": {
+                      "identifier": "count_",
+                      "expression": {
+                        "endPosition": "471",
+                        "kind": "IDENTIFIER",
+                        "this": "true",
+                        "name": "this",
+                        "startPosition": "467"
+                      },
+                      "endPosition": "478",
+                      "kind": "MEMBER_SELECT",
+                      "startPosition": "467"
+                    },
+                    "endPosition": "478",
+                    "kind": "LOGICAL_COMPLEMENT",
+                    "startPosition": "466"
+                  },
+                  "endPosition": "496",
+                  "kind": "CONDITIONAL_EXPRESSION",
+                  "trueExpression": {
+                    "endPosition": "482",
+                    "kind": "NUMBER_LITERAL",
+                    "value": "0",
+                    "startPosition": "481"
+                  },
+                  "falseExpression": {
+                    "identifier": "count_",
+                    "expression": {
+                      "endPosition": "489",
+                      "kind": "IDENTIFIER",
+                      "this": "true",
+                      "name": "this",
+                      "startPosition": "485"
+                    },
+                    "endPosition": "496",
+                    "kind": "MEMBER_SELECT",
+                    "startPosition": "485"
+                  },
+                  "startPosition": "479"
+                },
+                "endPosition": "496",
+                "kind": "RETURN",
+                "startPosition": "459"
+              }
+            ],
+            "startPosition": "449"
+          },
+          "strict": "true",
+          "startPosition": "449",
+          "parameters": []
+        },
+        "static": "true",
+        "endPosition": "502",
+        "kind": "PROPERTY",
+        "setter": {
+          "endPosition": "535",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "endPosition": "563",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "expression": {
+                  "expression": {
+                    "endPosition": "563",
+                    "kind": "IDENTIFIER",
+                    "name": "val",
+                    "startPosition": "560"
+                  },
+                  "endPosition": "563",
+                  "kind": "ASSIGNMENT",
+                  "variable": {
+                    "identifier": "count_",
+                    "expression": {
+                      "endPosition": "550",
+                      "kind": "IDENTIFIER",
+                      "this": "true",
+                      "name": "this",
+                      "startPosition": "546"
+                    },
+                    "endPosition": "557",
+                    "kind": "MEMBER_SELECT",
+                    "startPosition": "546"
+                  },
+                  "startPosition": "546"
+                },
+                "endPosition": "563",
+                "kind": "EXPRESSION_STATEMENT",
+                "startPosition": "546"
+              }
+            ],
+            "startPosition": "535"
+          },
+          "strict": "true",
+          "startPosition": "535",
+          "parameters": [
+            {
+              "endPosition": "533",
+              "kind": "IDENTIFIER",
+              "name": "val",
+              "startPosition": "530"
+            }
+          ]
+        },
+        "value": "null",
+        "startPosition": "432",
+        "key": {
+          "endPosition": "446",
+          "kind": "IDENTIFIER",
+          "name": "numCircles",
+          "startPosition": "436"
+        }
+      },
+      {
+        "getter": "null",
+        "endPosition": "639",
+        "kind": "PROPERTY",
+        "setter": "null",
+        "value": {
+          "endPosition": "582",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": {
+            "endPosition": "579",
+            "kind": "IDENTIFIER",
+            "name": "area",
+            "startPosition": "575"
+          },
+          "body": {
+            "endPosition": "633",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "expression": {
+                  "leftOperand": {
+                    "endPosition": "623",
+                    "kind": "FUNCTION_INVOCATION",
+                    "functionSelect": {
+                      "identifier": "pow",
+                      "expression": {
+                        "endPosition": "603",
+                        "kind": "IDENTIFIER",
+                        "name": "Math",
+                        "startPosition": "599"
+                      },
+                      "endPosition": "607",
+                      "kind": "MEMBER_SELECT",
+                      "startPosition": "599"
+                    },
+                    "arguments": [
+                      {
+                        "identifier": "radius",
+                        "expression": {
+                          "endPosition": "612",
+                          "kind": "IDENTIFIER",
+                          "this": "true",
+                          "name": "this",
+                          "startPosition": "608"
+                        },
+                        "endPosition": "619",
+                        "kind": "MEMBER_SELECT",
+                        "startPosition": "608"
+                      },
+                      {
+                        "endPosition": "622",
+                        "kind": "NUMBER_LITERAL",
+                        "value": "2",
+                        "startPosition": "621"
+                      }
+                    ],
+                    "startPosition": "599"
+                  },
+                  "endPosition": "633",
+                  "kind": "MULTIPLY",
+                  "rightOperand": {
+                    "identifier": "PI",
+                    "expression": {
+                      "endPosition": "630",
+                      "kind": "IDENTIFIER",
+                      "name": "Math",
+                      "startPosition": "626"
+                    },
+                    "endPosition": "633",
+                    "kind": "MEMBER_SELECT",
+                    "startPosition": "626"
+                  },
+                  "startPosition": "599"
+                },
+                "endPosition": "633",
+                "kind": "RETURN",
+                "startPosition": "592"
+              }
+            ],
+            "startPosition": "582"
+          },
+          "strict": "true",
+          "startPosition": "582",
+          "parameters": []
+        },
+        "startPosition": "575",
+        "key": {
+          "endPosition": "579",
+          "kind": "IDENTIFIER",
+          "name": "area",
+          "startPosition": "575"
+        }
+      },
+      {
+        "getter": {
+          "endPosition": "658",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "endPosition": "687",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "expression": {
+                  "identifier": "radius_",
+                  "expression": {
+                    "endPosition": "679",
+                    "kind": "IDENTIFIER",
+                    "this": "true",
+                    "name": "this",
+                    "startPosition": "675"
+                  },
+                  "endPosition": "687",
+                  "kind": "MEMBER_SELECT",
+                  "startPosition": "675"
+                },
+                "endPosition": "687",
+                "kind": "RETURN",
+                "startPosition": "668"
+              }
+            ],
+            "startPosition": "658"
+          },
+          "strict": "true",
+          "startPosition": "658",
+          "parameters": []
+        },
+        "endPosition": "693",
+        "kind": "PROPERTY",
+        "setter": {
+          "endPosition": "718",
+          "kind": "FUNCTION_EXPRESSION",
+          "name": "null",
+          "body": {
+            "endPosition": "852",
+            "kind": "BLOCK",
+            "statements": [
+              {
+                "condition": {
+                  "expression": {
+                    "endPosition": "757",
+                    "kind": "FUNCTION_INVOCATION",
+                    "functionSelect": {
+                      "identifier": "isInteger",
+                      "expression": {
+                        "endPosition": "739",
+                        "kind": "IDENTIFIER",
+                        "name": "Number",
+                        "startPosition": "733"
+                      },
+                      "endPosition": "749",
+                      "kind": "MEMBER_SELECT",
+                      "startPosition": "733"
+                    },
+                    "arguments": [
+                      {
+                        "endPosition": "756",
+                        "kind": "IDENTIFIER",
+                        "name": "radius",
+                        "startPosition": "750"
+                      }
+                    ],
+                    "startPosition": "733"
+                  },
+                  "endPosition": "757",
+                  "kind": "LOGICAL_COMPLEMENT",
+                  "startPosition": "732"
+                },
+                "elseStatement": "null",
+                "endPosition": "822",
+                "kind": "IF",
+                "startPosition": "728",
+                "thenStatement": {
+                  "expression": {
+                    "constructorExpression": {
+                      "endPosition": "821",
+                      "kind": "FUNCTION_INVOCATION",
+                      "functionSelect": {
+                        "endPosition": "790",
+                        "kind": "IDENTIFIER",
+                        "name": "TypeError",
+                        "startPosition": "781"
+                      },
+                      "arguments": [
+                        {
+                          "endPosition": "819",
+                          "kind": "STRING_LITERAL",
+                          "value": "Circle radius is not an int",
+                          "startPosition": "792"
+                        }
+                      ],
+                      "startPosition": "781"
+                    },
+                    "endPosition": "821",
+                    "kind": "NEW",
+                    "startPosition": "777"
+                  },
+                  "endPosition": "822",
+                  "kind": "THROW",
+                  "startPosition": "771"
+                }
+              },
+              {
+                "expression": {
+                  "expression": {
+                    "endPosition": "852",
+                    "kind": "IDENTIFIER",
+                    "name": "radius",
+                    "startPosition": "846"
+                  },
+                  "endPosition": "852",
+                  "kind": "ASSIGNMENT",
+                  "variable": {
+                    "identifier": "radius_",
+                    "expression": {
+                      "endPosition": "835",
+                      "kind": "IDENTIFIER",
+                      "this": "true",
+                      "name": "this",
+                      "startPosition": "831"
+                    },
+                    "endPosition": "843",
+                    "kind": "MEMBER_SELECT",
+                    "startPosition": "831"
+                  },
+                  "startPosition": "831"
+                },
+                "endPosition": "852",
+                "kind": "EXPRESSION_STATEMENT",
+                "startPosition": "831"
+              }
+            ],
+            "startPosition": "718"
+          },
+          "strict": "true",
+          "startPosition": "718",
+          "parameters": [
+            {
+              "endPosition": "716",
+              "kind": "IDENTIFIER",
+              "name": "radius",
+              "startPosition": "710"
+            }
+          ]
+        },
+        "value": "null",
+        "startPosition": "645",
+        "key": {
+          "endPosition": "655",
+          "kind": "IDENTIFIER",
+          "name": "radius",
+          "startPosition": "649"
+        }
+      }
+    ],
+    "endPosition": "231",
+    "kind": "CLASS",
+    "classHeritage": {
+      "endPosition": "245",
+      "kind": "IDENTIFIER",
+      "name": "Shape",
+      "startPosition": "240"
+    },
+    "name": {
+      "endPosition": "231",
+      "kind": "IDENTIFIER",
+      "name": "Circle",
+      "startPosition": "225"
+    },
+    "constructor": {
+      "getter": "null",
+      "endPosition": "354",
+      "kind": "PROPERTY",
+      "setter": "null",
+      "value": {
+        "endPosition": "272",
+        "kind": "FUNCTION_EXPRESSION",
+        "name": {
+          "endPosition": "263",
+          "kind": "IDENTIFIER",
+          "name": "constructor",
+          "startPosition": "252"
+        },
+        "body": {
+          "endPosition": "348",
+          "kind": "BLOCK",
+          "statements": [
+            {
+              "expression": {
+                "endPosition": "289",
+                "kind": "FUNCTION_INVOCATION",
+                "functionSelect": {
+                  "super": "true",
+                  "endPosition": "287",
+                  "kind": "IDENTIFIER",
+                  "name": "super",
+                  "startPosition": "282"
+                },
+                "arguments": [],
+                "startPosition": "282"
+              },
+              "endPosition": "289",
+              "kind": "EXPRESSION_STATEMENT",
+              "startPosition": "282"
+            },
+            {
+              "expression": {
+                "expression": {
+                  "endPosition": "320",
+                  "kind": "IDENTIFIER",
+                  "name": "radius",
+                  "startPosition": "314"
+                },
+                "endPosition": "320",
+                "kind": "ASSIGNMENT",
+                "variable": {
+                  "identifier": "radius_",
+                  "expression": {
+                    "endPosition": "303",
+                    "kind": "IDENTIFIER",
+                    "this": "true",
+                    "name": "this",
+                    "startPosition": "299"
+                  },
+                  "endPosition": "311",
+                  "kind": "MEMBER_SELECT",
+                  "startPosition": "299"
+                },
+                "startPosition": "299"
+              },
+              "endPosition": "320",
+              "kind": "EXPRESSION_STATEMENT",
+              "startPosition": "299"
+            },
+            {
+              "expression": {
+                "expression": {
+                  "identifier": "numCircles",
+                  "expression": {
+                    "endPosition": "335",
+                    "kind": "IDENTIFIER",
+                    "name": "Circle",
+                    "startPosition": "329"
+                  },
+                  "endPosition": "346",
+                  "kind": "MEMBER_SELECT",
+                  "startPosition": "329"
+                },
+                "endPosition": "348",
+                "kind": "POSTFIX_INCREMENT",
+                "startPosition": "329"
+              },
+              "endPosition": "348",
+              "kind": "EXPRESSION_STATEMENT",
+              "startPosition": "329"
+            }
+          ],
+          "startPosition": "272"
+        },
+        "strict": "true",
+        "startPosition": "272",
+        "parameters": [
+          {
+            "endPosition": "270",
+            "kind": "IDENTIFIER",
+            "name": "radius",
+            "startPosition": "264"
+          }
+        ]
+      },
+      "startPosition": "252",
+      "key": {
+        "endPosition": "263",
+        "kind": "IDENTIFIER",
+        "name": "constructor",
+        "startPosition": "252"
+      }
+    },
+    "startPosition": "219"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/const.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 consts.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+const PI = 3.14;
+
+EOF
+
+parse("generator.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/const.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,20 @@
+[
+  {
+    "const": "true",
+    "endPosition": "16",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "9",
+      "kind": "IDENTIFIER",
+      "name": "PI",
+      "startPosition": "7"
+    },
+    "startPosition": "1",
+    "initializer": {
+      "endPosition": "16",
+      "kind": "NUMBER_LITERAL",
+      "value": "3.14",
+      "startPosition": "12"
+    }
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/defaultparams.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 default parameters.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+function func(x = 3, y) {
+    return x + y;
+}
+
+var f = function (x = 4, y = 5) { return x * y }
+
+EOF
+
+parse("defaultparams.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitFunctionDeclaration : function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/defaultparams.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,151 @@
+[
+  {
+    "endPosition": "46",
+    "kind": "FUNCTION",
+    "name": {
+      "endPosition": "14",
+      "kind": "IDENTIFIER",
+      "name": "func",
+      "startPosition": "10"
+    },
+    "body": {
+      "endPosition": "44",
+      "kind": "BLOCK",
+      "statements": [
+        {
+          "expression": {
+            "leftOperand": {
+              "endPosition": "39",
+              "kind": "IDENTIFIER",
+              "name": "x",
+              "startPosition": "38"
+            },
+            "endPosition": "43",
+            "kind": "PLUS",
+            "rightOperand": {
+              "endPosition": "43",
+              "kind": "IDENTIFIER",
+              "name": "y",
+              "startPosition": "42"
+            },
+            "startPosition": "38"
+          },
+          "endPosition": "44",
+          "kind": "RETURN",
+          "startPosition": "31"
+        }
+      ],
+      "startPosition": "25"
+    },
+    "strict": "false",
+    "startPosition": "1",
+    "parameters": [
+      {
+        "expression": {
+          "endPosition": "20",
+          "kind": "NUMBER_LITERAL",
+          "value": "3",
+          "startPosition": "19"
+        },
+        "endPosition": "20",
+        "kind": "ASSIGNMENT",
+        "variable": {
+          "endPosition": "16",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "15"
+        },
+        "startPosition": "15"
+      },
+      {
+        "endPosition": "23",
+        "kind": "IDENTIFIER",
+        "name": "y",
+        "startPosition": "22"
+      }
+    ]
+  },
+  {
+    "endPosition": "96",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "53",
+      "kind": "IDENTIFIER",
+      "name": "f",
+      "startPosition": "52"
+    },
+    "startPosition": "48",
+    "initializer": {
+      "endPosition": "80",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "endPosition": "94",
+        "kind": "BLOCK",
+        "statements": [
+          {
+            "expression": {
+              "leftOperand": {
+                "endPosition": "90",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "89"
+              },
+              "endPosition": "94",
+              "kind": "MULTIPLY",
+              "rightOperand": {
+                "endPosition": "94",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "93"
+              },
+              "startPosition": "89"
+            },
+            "endPosition": "94",
+            "kind": "RETURN",
+            "startPosition": "82"
+          }
+        ],
+        "startPosition": "80"
+      },
+      "strict": "false",
+      "startPosition": "80",
+      "parameters": [
+        {
+          "expression": {
+            "endPosition": "71",
+            "kind": "NUMBER_LITERAL",
+            "value": "4",
+            "startPosition": "70"
+          },
+          "endPosition": "71",
+          "kind": "ASSIGNMENT",
+          "variable": {
+            "endPosition": "67",
+            "kind": "IDENTIFIER",
+            "name": "x",
+            "startPosition": "66"
+          },
+          "startPosition": "66"
+        },
+        {
+          "expression": {
+            "endPosition": "78",
+            "kind": "NUMBER_LITERAL",
+            "value": "5",
+            "startPosition": "77"
+          },
+          "endPosition": "78",
+          "kind": "ASSIGNMENT",
+          "variable": {
+            "endPosition": "74",
+            "kind": "IDENTIFIER",
+            "name": "y",
+            "startPosition": "73"
+          },
+          "startPosition": "73"
+        }
+      ]
+    }
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/destructuring_assign.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 destructuring assignments.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+var a, b;
+[a, b] = [1, 2];
+({a, b} = {a:11, b:12});
+
+EOF
+
+parse("destructuring_assign.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitAssignment : function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/destructuring_assign.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,164 @@
+[
+  {
+    "endPosition": "6",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "6",
+      "kind": "IDENTIFIER",
+      "name": "a",
+      "startPosition": "5"
+    },
+    "startPosition": "1",
+    "initializer": "null"
+  },
+  {
+    "endPosition": "9",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "9",
+      "kind": "IDENTIFIER",
+      "name": "b",
+      "startPosition": "8"
+    },
+    "startPosition": "1",
+    "initializer": "null"
+  },
+  {
+    "expression": {
+      "endPosition": "26",
+      "kind": "ARRAY_LITERAL",
+      "elements": [
+        {
+          "endPosition": "22",
+          "kind": "NUMBER_LITERAL",
+          "value": "1",
+          "startPosition": "21"
+        },
+        {
+          "endPosition": "25",
+          "kind": "NUMBER_LITERAL",
+          "value": "2",
+          "startPosition": "24"
+        }
+      ],
+      "startPosition": "20"
+    },
+    "endPosition": "26",
+    "kind": "ASSIGNMENT",
+    "variable": {
+      "endPosition": "17",
+      "kind": "ARRAY_LITERAL",
+      "elements": [
+        {
+          "endPosition": "13",
+          "kind": "IDENTIFIER",
+          "name": "a",
+          "startPosition": "12"
+        },
+        {
+          "endPosition": "16",
+          "kind": "IDENTIFIER",
+          "name": "b",
+          "startPosition": "15"
+        }
+      ],
+      "startPosition": "11"
+    },
+    "startPosition": "11"
+  },
+  {
+    "expression": {
+      "endPosition": "50",
+      "kind": "OBJECT_LITERAL",
+      "startPosition": "38",
+      "properties": [
+        {
+          "getter": "null",
+          "endPosition": "43",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "43",
+            "kind": "NUMBER_LITERAL",
+            "value": "11",
+            "startPosition": "41"
+          },
+          "startPosition": "39",
+          "key": {
+            "endPosition": "40",
+            "kind": "IDENTIFIER",
+            "name": "a",
+            "startPosition": "39"
+          }
+        },
+        {
+          "getter": "null",
+          "endPosition": "49",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "49",
+            "kind": "NUMBER_LITERAL",
+            "value": "12",
+            "startPosition": "47"
+          },
+          "startPosition": "45",
+          "key": {
+            "endPosition": "46",
+            "kind": "IDENTIFIER",
+            "name": "b",
+            "startPosition": "45"
+          }
+        }
+      ]
+    },
+    "endPosition": "50",
+    "kind": "ASSIGNMENT",
+    "variable": {
+      "endPosition": "35",
+      "kind": "OBJECT_LITERAL",
+      "startPosition": "29",
+      "properties": [
+        {
+          "getter": "null",
+          "endPosition": "31",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "31",
+            "kind": "IDENTIFIER",
+            "name": "a",
+            "startPosition": "30"
+          },
+          "startPosition": "30",
+          "key": {
+            "endPosition": "31",
+            "kind": "IDENTIFIER",
+            "name": "a",
+            "startPosition": "30"
+          }
+        },
+        {
+          "getter": "null",
+          "endPosition": "34",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "34",
+            "kind": "IDENTIFIER",
+            "name": "b",
+            "startPosition": "33"
+          },
+          "startPosition": "33",
+          "key": {
+            "endPosition": "34",
+            "kind": "IDENTIFIER",
+            "name": "b",
+            "startPosition": "33"
+          }
+        }
+      ]
+    },
+    "startPosition": "29"
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/destructuring_decl.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 destructuring initializatons, assignemts.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+var [a, b] = [1, 2];
+
+var { x, y } = obj;
+EOF
+
+parse("destructuring_assign.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitAssignment : function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/destructuring_decl.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,101 @@
+[
+  {
+    "endPosition": "20",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "11",
+      "kind": "ARRAY_LITERAL",
+      "elements": [
+        {
+          "endPosition": "7",
+          "kind": "IDENTIFIER",
+          "name": "a",
+          "startPosition": "6"
+        },
+        {
+          "endPosition": "10",
+          "kind": "IDENTIFIER",
+          "name": "b",
+          "startPosition": "9"
+        }
+      ],
+      "startPosition": "5"
+    },
+    "startPosition": "1",
+    "initializer": {
+      "endPosition": "20",
+      "kind": "ARRAY_LITERAL",
+      "elements": [
+        {
+          "endPosition": "16",
+          "kind": "NUMBER_LITERAL",
+          "value": "1",
+          "startPosition": "15"
+        },
+        {
+          "endPosition": "19",
+          "kind": "NUMBER_LITERAL",
+          "value": "2",
+          "startPosition": "18"
+        }
+      ],
+      "startPosition": "14"
+    }
+  },
+  {
+    "endPosition": "41",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "35",
+      "kind": "OBJECT_LITERAL",
+      "startPosition": "27",
+      "properties": [
+        {
+          "getter": "null",
+          "endPosition": "30",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "30",
+            "kind": "IDENTIFIER",
+            "name": "x",
+            "startPosition": "29"
+          },
+          "startPosition": "29",
+          "key": {
+            "endPosition": "30",
+            "kind": "IDENTIFIER",
+            "name": "x",
+            "startPosition": "29"
+          }
+        },
+        {
+          "getter": "null",
+          "endPosition": "33",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "33",
+            "kind": "IDENTIFIER",
+            "name": "y",
+            "startPosition": "32"
+          },
+          "startPosition": "32",
+          "key": {
+            "endPosition": "33",
+            "kind": "IDENTIFIER",
+            "name": "y",
+            "startPosition": "32"
+          }
+        }
+      ]
+    },
+    "startPosition": "23",
+    "initializer": {
+      "endPosition": "41",
+      "kind": "IDENTIFIER",
+      "name": "obj",
+      "startPosition": "38"
+    }
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/destructuring_params.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 default parameters.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+function func({x, y}) {
+}
+
+var f = function({a, b}) { }
+
+function x({x, y} = { x: 44, y: 45 }) {}
+
+EOF
+
+parse("destructuring_params.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitFunctionDeclaration : function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/destructuring_params.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,253 @@
+[
+  {
+    "endPosition": "26",
+    "kind": "FUNCTION",
+    "name": {
+      "endPosition": "14",
+      "kind": "IDENTIFIER",
+      "name": "func",
+      "startPosition": "10"
+    },
+    "body": {
+      "endPosition": "24",
+      "kind": "BLOCK",
+      "statements": [],
+      "startPosition": "23"
+    },
+    "strict": "false",
+    "startPosition": "1",
+    "parameters": [
+      {
+        "endPosition": "21",
+        "kind": "OBJECT_LITERAL",
+        "startPosition": "15",
+        "properties": [
+          {
+            "getter": "null",
+            "endPosition": "17",
+            "kind": "PROPERTY",
+            "setter": "null",
+            "value": {
+              "endPosition": "17",
+              "kind": "IDENTIFIER",
+              "name": "x",
+              "startPosition": "16"
+            },
+            "startPosition": "16",
+            "key": {
+              "endPosition": "17",
+              "kind": "IDENTIFIER",
+              "name": "x",
+              "startPosition": "16"
+            }
+          },
+          {
+            "getter": "null",
+            "endPosition": "20",
+            "kind": "PROPERTY",
+            "setter": "null",
+            "value": {
+              "endPosition": "20",
+              "kind": "IDENTIFIER",
+              "name": "y",
+              "startPosition": "19"
+            },
+            "startPosition": "19",
+            "key": {
+              "endPosition": "20",
+              "kind": "IDENTIFIER",
+              "name": "y",
+              "startPosition": "19"
+            }
+          }
+        ]
+      }
+    ]
+  },
+  {
+    "endPosition": "56",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "33",
+      "kind": "IDENTIFIER",
+      "name": "f",
+      "startPosition": "32"
+    },
+    "startPosition": "28",
+    "initializer": {
+      "endPosition": "53",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "endPosition": "54",
+        "kind": "BLOCK",
+        "statements": [],
+        "startPosition": "53"
+      },
+      "strict": "false",
+      "startPosition": "53",
+      "parameters": [
+        {
+          "endPosition": "51",
+          "kind": "OBJECT_LITERAL",
+          "startPosition": "45",
+          "properties": [
+            {
+              "getter": "null",
+              "endPosition": "47",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "47",
+                "kind": "IDENTIFIER",
+                "name": "a",
+                "startPosition": "46"
+              },
+              "startPosition": "46",
+              "key": {
+                "endPosition": "47",
+                "kind": "IDENTIFIER",
+                "name": "a",
+                "startPosition": "46"
+              }
+            },
+            {
+              "getter": "null",
+              "endPosition": "50",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "50",
+                "kind": "IDENTIFIER",
+                "name": "b",
+                "startPosition": "49"
+              },
+              "startPosition": "49",
+              "key": {
+                "endPosition": "50",
+                "kind": "IDENTIFIER",
+                "name": "b",
+                "startPosition": "49"
+              }
+            }
+          ]
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "98",
+    "kind": "FUNCTION",
+    "name": {
+      "endPosition": "68",
+      "kind": "IDENTIFIER",
+      "name": "x",
+      "startPosition": "67"
+    },
+    "body": {
+      "endPosition": "97",
+      "kind": "BLOCK",
+      "statements": [],
+      "startPosition": "96"
+    },
+    "strict": "false",
+    "startPosition": "58",
+    "parameters": [
+      {
+        "expression": {
+          "endPosition": "94",
+          "kind": "OBJECT_LITERAL",
+          "startPosition": "78",
+          "properties": [
+            {
+              "getter": "null",
+              "endPosition": "85",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "85",
+                "kind": "NUMBER_LITERAL",
+                "value": "44",
+                "startPosition": "83"
+              },
+              "startPosition": "80",
+              "key": {
+                "endPosition": "81",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "80"
+              }
+            },
+            {
+              "getter": "null",
+              "endPosition": "92",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "92",
+                "kind": "NUMBER_LITERAL",
+                "value": "45",
+                "startPosition": "90"
+              },
+              "startPosition": "87",
+              "key": {
+                "endPosition": "88",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "87"
+              }
+            }
+          ]
+        },
+        "endPosition": "94",
+        "kind": "ASSIGNMENT",
+        "variable": {
+          "endPosition": "75",
+          "kind": "OBJECT_LITERAL",
+          "startPosition": "69",
+          "properties": [
+            {
+              "getter": "null",
+              "endPosition": "71",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "71",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "70"
+              },
+              "startPosition": "70",
+              "key": {
+                "endPosition": "71",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "70"
+              }
+            },
+            {
+              "getter": "null",
+              "endPosition": "74",
+              "kind": "PROPERTY",
+              "setter": "null",
+              "value": {
+                "endPosition": "74",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "73"
+              },
+              "startPosition": "73",
+              "key": {
+                "endPosition": "74",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "73"
+              }
+            }
+          ]
+        },
+        "startPosition": "69"
+      }
+    ]
+  }
+]
--- a/nashorn/test/script/nosecurity/treeapi/functionCall.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/functionCall.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -252,4 +252,4 @@
     ],
     "startPosition": "139"
   }
-]
+]
--- a/nashorn/test/script/nosecurity/treeapi/functionDeclaration.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/functionDeclaration.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -2,7 +2,12 @@
   {
     "endPosition": "17",
     "kind": "FUNCTION",
-    "name": "a",
+    "name": {
+      "endPosition": "11",
+      "kind": "IDENTIFIER",
+      "name": "a",
+      "startPosition": "10"
+    },
     "body": {
       "endPosition": "16",
       "kind": "BLOCK",
@@ -16,7 +21,12 @@
   {
     "endPosition": "62",
     "kind": "FUNCTION",
-    "name": "d",
+    "name": {
+      "endPosition": "28",
+      "kind": "IDENTIFIER",
+      "name": "d",
+      "startPosition": "27"
+    },
     "body": {
       "endPosition": "60",
       "kind": "BLOCK",
@@ -24,7 +34,12 @@
         {
           "endPosition": "60",
           "kind": "FUNCTION",
-          "name": "e",
+          "name": {
+            "endPosition": "46",
+            "kind": "IDENTIFIER",
+            "name": "e",
+            "startPosition": "45"
+          },
           "body": {
             "endPosition": "59",
             "kind": "BLOCK",
@@ -70,7 +85,12 @@
   {
     "endPosition": "89",
     "kind": "FUNCTION",
-    "name": "f",
+    "name": {
+      "endPosition": "73",
+      "kind": "IDENTIFIER",
+      "name": "f",
+      "startPosition": "72"
+    },
     "body": {
       "endPosition": "88",
       "kind": "BLOCK",
@@ -122,7 +142,12 @@
   {
     "endPosition": "121",
     "kind": "FUNCTION",
-    "name": "j",
+    "name": {
+      "endPosition": "100",
+      "kind": "IDENTIFIER",
+      "name": "j",
+      "startPosition": "99"
+    },
     "body": {
       "endPosition": "120",
       "kind": "BLOCK",
@@ -158,4 +183,4 @@
       }
     ]
   }
-]
+]
--- a/nashorn/test/script/nosecurity/treeapi/functionExpr.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/functionExpr.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -125,4 +125,4 @@
     "startPosition": "110",
     "parameters": []
   }
-]
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/generator.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 generators.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+function* id(){
+  var idx = 0;
+  while(idx < 3)
+    yield idx++;
+}
+
+var obj = {
+    *q (x, y) {
+       yield 1;
+    }
+};
+
+var f = {
+    [Symbol.iterator]: function*() {
+        var cur = 1;
+        for (;;) {
+            yield cur;
+        }
+    }
+};
+
+EOF
+
+parse("generator.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitFunctionDeclaration : function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/generator.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,266 @@
+[
+  {
+    "endPosition": "67",
+    "kind": "FUNCTION",
+    "name": {
+      "endPosition": "13",
+      "kind": "IDENTIFIER",
+      "name": "id",
+      "startPosition": "11"
+    },
+    "generator": "true",
+    "body": {
+      "endPosition": "65",
+      "kind": "BLOCK",
+      "statements": [
+        {
+          "endPosition": "30",
+          "kind": "VARIABLE",
+          "binding": {
+            "endPosition": "26",
+            "kind": "IDENTIFIER",
+            "name": "idx",
+            "startPosition": "23"
+          },
+          "startPosition": "19",
+          "initializer": {
+            "endPosition": "30",
+            "kind": "NUMBER_LITERAL",
+            "value": "0",
+            "startPosition": "29"
+          }
+        },
+        {
+          "condition": {
+            "leftOperand": {
+              "endPosition": "43",
+              "kind": "IDENTIFIER",
+              "name": "idx",
+              "startPosition": "40"
+            },
+            "endPosition": "47",
+            "kind": "LESS_THAN",
+            "rightOperand": {
+              "endPosition": "47",
+              "kind": "NUMBER_LITERAL",
+              "value": "3",
+              "startPosition": "46"
+            },
+            "startPosition": "40"
+          },
+          "endPosition": "65",
+          "kind": "WHILE_LOOP",
+          "statement": {
+            "expression": {
+              "expression": {
+                "expression": {
+                  "endPosition": "62",
+                  "kind": "IDENTIFIER",
+                  "name": "idx",
+                  "startPosition": "59"
+                },
+                "endPosition": "64",
+                "kind": "POSTFIX_INCREMENT",
+                "startPosition": "59"
+              },
+              "endPosition": "64",
+              "kind": "YIELD",
+              "startPosition": "53"
+            },
+            "endPosition": "64",
+            "kind": "EXPRESSION_STATEMENT",
+            "startPosition": "53"
+          },
+          "startPosition": "34"
+        }
+      ],
+      "startPosition": "15"
+    },
+    "strict": "false",
+    "startPosition": "1",
+    "parameters": []
+  },
+  {
+    "endPosition": "120",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "76",
+      "kind": "IDENTIFIER",
+      "name": "obj",
+      "startPosition": "73"
+    },
+    "startPosition": "69",
+    "initializer": {
+      "endPosition": "120",
+      "kind": "OBJECT_LITERAL",
+      "startPosition": "79",
+      "properties": [
+        {
+          "getter": "null",
+          "endPosition": "118",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "95",
+            "kind": "FUNCTION_EXPRESSION",
+            "name": {
+              "endPosition": "87",
+              "kind": "IDENTIFIER",
+              "name": "q",
+              "startPosition": "85"
+            },
+            "generator": "true",
+            "body": {
+              "endPosition": "112",
+              "kind": "BLOCK",
+              "statements": [
+                {
+                  "expression": {
+                    "expression": {
+                      "endPosition": "111",
+                      "kind": "NUMBER_LITERAL",
+                      "value": "1",
+                      "startPosition": "110"
+                    },
+                    "endPosition": "111",
+                    "kind": "YIELD",
+                    "startPosition": "104"
+                  },
+                  "endPosition": "111",
+                  "kind": "EXPRESSION_STATEMENT",
+                  "startPosition": "104"
+                }
+              ],
+              "startPosition": "95"
+            },
+            "strict": "false",
+            "startPosition": "95",
+            "parameters": [
+              {
+                "endPosition": "90",
+                "kind": "IDENTIFIER",
+                "name": "x",
+                "startPosition": "89"
+              },
+              {
+                "endPosition": "93",
+                "kind": "IDENTIFIER",
+                "name": "y",
+                "startPosition": "92"
+              }
+            ]
+          },
+          "startPosition": "85",
+          "key": {
+            "endPosition": "87",
+            "kind": "IDENTIFIER",
+            "name": "q",
+            "startPosition": "85"
+          }
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "250",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "128",
+      "kind": "IDENTIFIER",
+      "name": "f",
+      "startPosition": "127"
+    },
+    "startPosition": "123",
+    "initializer": {
+      "endPosition": "250",
+      "kind": "OBJECT_LITERAL",
+      "startPosition": "131",
+      "properties": [
+        {
+          "getter": "null",
+          "computed": "true",
+          "endPosition": "248",
+          "kind": "PROPERTY",
+          "setter": "null",
+          "value": {
+            "endPosition": "168",
+            "kind": "FUNCTION_EXPRESSION",
+            "name": "null",
+            "generator": "true",
+            "body": {
+              "endPosition": "242",
+              "kind": "BLOCK",
+              "statements": [
+                {
+                  "endPosition": "189",
+                  "kind": "VARIABLE",
+                  "binding": {
+                    "endPosition": "185",
+                    "kind": "IDENTIFIER",
+                    "name": "cur",
+                    "startPosition": "182"
+                  },
+                  "startPosition": "178",
+                  "initializer": {
+                    "endPosition": "189",
+                    "kind": "NUMBER_LITERAL",
+                    "value": "1",
+                    "startPosition": "188"
+                  }
+                },
+                {
+                  "condition": "null",
+                  "endPosition": "242",
+                  "kind": "FOR_LOOP",
+                  "statement": {
+                    "endPosition": "242",
+                    "kind": "BLOCK",
+                    "statements": [
+                      {
+                        "expression": {
+                          "expression": {
+                            "endPosition": "231",
+                            "kind": "IDENTIFIER",
+                            "name": "cur",
+                            "startPosition": "228"
+                          },
+                          "endPosition": "231",
+                          "kind": "YIELD",
+                          "startPosition": "222"
+                        },
+                        "endPosition": "231",
+                        "kind": "EXPRESSION_STATEMENT",
+                        "startPosition": "222"
+                      }
+                    ],
+                    "startPosition": "208"
+                  },
+                  "update": "null",
+                  "startPosition": "199",
+                  "initializer": "null"
+                }
+              ],
+              "startPosition": "168"
+            },
+            "strict": "false",
+            "startPosition": "168",
+            "parameters": []
+          },
+          "startPosition": "137",
+          "key": {
+            "identifier": "iterator",
+            "expression": {
+              "endPosition": "144",
+              "kind": "IDENTIFIER",
+              "name": "Symbol",
+              "startPosition": "138"
+            },
+            "endPosition": "153",
+            "kind": "MEMBER_SELECT",
+            "startPosition": "138"
+          }
+        }
+      ]
+    }
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/let.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 lets.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+let x = 3;
+
+EOF
+
+parse("let.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitVariable : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/let.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,20 @@
+[
+  {
+    "endPosition": "10",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "6",
+      "kind": "IDENTIFIER",
+      "name": "x",
+      "startPosition": "5"
+    },
+    "let": "true",
+    "startPosition": "1",
+    "initializer": {
+      "endPosition": "10",
+      "kind": "NUMBER_LITERAL",
+      "value": "3",
+      "startPosition": "9"
+    }
+  }
+]
--- a/nashorn/test/script/nosecurity/treeapi/memberSelect.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/memberSelect.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -28,6 +28,7 @@
     "expression": {
       "endPosition": "34",
       "kind": "IDENTIFIER",
+      "this": "true",
       "name": "this",
       "startPosition": "30"
     },
@@ -47,4 +48,4 @@
     "kind": "MEMBER_SELECT",
     "startPosition": "40"
   }
-]
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/modules.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 modules.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+import myDef, * as myMod from "my-mod";
+
+export function func() {}
+
+EOF
+
+var mod = parseModule("foo", code);
+print(JSON.stringify(convert(mod), null, 2))
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/modules.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,82 @@
+{
+  "endPosition": "0",
+  "kind": "COMPILATION_UNIT",
+  "module": {
+    "indirectExportEntries": [],
+    "endPosition": "0",
+    "kind": "MODULE",
+    "localExportEntries": [
+      {
+        "localName": {
+          "endPosition": "62",
+          "kind": "IDENTIFIER",
+          "name": "func",
+          "startPosition": "58"
+        },
+        "endPosition": "67",
+        "kind": "EXPORT_ENTRY",
+        "moduleRequest": "null",
+        "exportName": {
+          "endPosition": "62",
+          "kind": "IDENTIFIER",
+          "name": "func",
+          "startPosition": "58"
+        },
+        "importName": "null",
+        "startPosition": "49"
+      }
+    ],
+    "starExportEntries": [],
+    "startPosition": "0",
+    "importEntries": [
+      {
+        "localName": {
+          "endPosition": "25",
+          "kind": "IDENTIFIER",
+          "name": "myMod",
+          "startPosition": "20"
+        },
+        "endPosition": "38",
+        "kind": "IMPORT_ENTRY",
+        "moduleRequest": {
+          "endPosition": "30",
+          "kind": "IDENTIFIER",
+          "name": "my-mod",
+          "startPosition": "32"
+        },
+        "importName": {
+          "star": "true",
+          "endPosition": "14",
+          "kind": "IDENTIFIER",
+          "name": "*",
+          "startPosition": "15"
+        },
+        "startPosition": "1"
+      }
+    ]
+  },
+  "sourceElements": [
+    {
+      "endPosition": "67",
+      "kind": "FUNCTION",
+      "name": {
+        "endPosition": "62",
+        "kind": "IDENTIFIER",
+        "name": "func",
+        "startPosition": "58"
+      },
+      "body": {
+        "endPosition": "66",
+        "kind": "BLOCK",
+        "statements": [],
+        "startPosition": "65"
+      },
+      "strict": "true",
+      "startPosition": "49",
+      "parameters": []
+    }
+  ],
+  "sourceName": "foo",
+  "strict": "true",
+  "startPosition": "0"
+}
--- a/nashorn/test/script/nosecurity/treeapi/new.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/new.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -117,4 +117,4 @@
     "kind": "NEW",
     "startPosition": "59"
   }
-]
+]
--- a/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/objectLiteral.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -226,6 +226,7 @@
                   "expression": {
                     "endPosition": "163",
                     "kind": "IDENTIFIER",
+                    "this": "true",
                     "name": "this",
                     "startPosition": "159"
                   },
@@ -269,6 +270,7 @@
                     "expression": {
                       "endPosition": "191",
                       "kind": "IDENTIFIER",
+                      "this": "true",
                       "name": "this",
                       "startPosition": "187"
                     },
@@ -307,4 +309,4 @@
       }
     ]
   }
-]
+]
--- a/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/property.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -89,4 +89,4 @@
       "startPosition": "64"
     }
   }
-]
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/rest.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 rest arguments.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+function func(a, ...all) {}
+
+function bar(...allargs) {}
+
+var f = function(x, ...extra) {}
+var f2 = function(...rest) {}
+
+EOF
+
+parse("rest.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitFunctionDeclaration: function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable: function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/rest.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,134 @@
+[
+  {
+    "endPosition": "28",
+    "kind": "FUNCTION",
+    "name": {
+      "endPosition": "14",
+      "kind": "IDENTIFIER",
+      "name": "func",
+      "startPosition": "10"
+    },
+    "body": {
+      "endPosition": "27",
+      "kind": "BLOCK",
+      "statements": [],
+      "startPosition": "26"
+    },
+    "strict": "false",
+    "startPosition": "1",
+    "parameters": [
+      {
+        "endPosition": "16",
+        "kind": "IDENTIFIER",
+        "name": "a",
+        "startPosition": "15"
+      },
+      {
+        "endPosition": "24",
+        "restParameter": "true",
+        "kind": "IDENTIFIER",
+        "name": "all",
+        "startPosition": "21"
+      }
+    ]
+  },
+  {
+    "endPosition": "57",
+    "kind": "FUNCTION",
+    "name": {
+      "endPosition": "42",
+      "kind": "IDENTIFIER",
+      "name": "bar",
+      "startPosition": "39"
+    },
+    "body": {
+      "endPosition": "56",
+      "kind": "BLOCK",
+      "statements": [],
+      "startPosition": "55"
+    },
+    "strict": "false",
+    "startPosition": "30",
+    "parameters": [
+      {
+        "endPosition": "53",
+        "restParameter": "true",
+        "kind": "IDENTIFIER",
+        "name": "allargs",
+        "startPosition": "46"
+      }
+    ]
+  },
+  {
+    "endPosition": "91",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "64",
+      "kind": "IDENTIFIER",
+      "name": "f",
+      "startPosition": "63"
+    },
+    "startPosition": "59",
+    "initializer": {
+      "endPosition": "89",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "endPosition": "90",
+        "kind": "BLOCK",
+        "statements": [],
+        "startPosition": "89"
+      },
+      "strict": "false",
+      "startPosition": "89",
+      "parameters": [
+        {
+          "endPosition": "77",
+          "kind": "IDENTIFIER",
+          "name": "x",
+          "startPosition": "76"
+        },
+        {
+          "endPosition": "87",
+          "restParameter": "true",
+          "kind": "IDENTIFIER",
+          "name": "extra",
+          "startPosition": "82"
+        }
+      ]
+    }
+  },
+  {
+    "endPosition": "121",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "98",
+      "kind": "IDENTIFIER",
+      "name": "f2",
+      "startPosition": "96"
+    },
+    "startPosition": "92",
+    "initializer": {
+      "endPosition": "119",
+      "kind": "FUNCTION_EXPRESSION",
+      "name": "null",
+      "body": {
+        "endPosition": "120",
+        "kind": "BLOCK",
+        "statements": [],
+        "startPosition": "119"
+      },
+      "strict": "false",
+      "startPosition": "119",
+      "parameters": [
+        {
+          "endPosition": "117",
+          "restParameter": "true",
+          "kind": "IDENTIFIER",
+          "name": "rest",
+          "startPosition": "113"
+        }
+      ]
+    }
+  }
+]
--- a/nashorn/test/script/nosecurity/treeapi/return.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/return.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -59,4 +59,4 @@
     "kind": "RETURN",
     "startPosition": "207"
   }
-]
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/spread.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 spread arguments.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = <<EOF
+
+foo(a, ...b);
+
+bar(3, ...[3, 5, 546]);
+
+var arr = [3, ...a, 5];
+var arr2 = [4, ...[5, 6], 78];
+
+EOF
+
+parse("spread.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitFunctionCall: function (node, obj) {
+        obj.push(convert(node))
+    },
+    visitVariable: function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/spread.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,176 @@
+[
+  {
+    "endPosition": "13",
+    "kind": "FUNCTION_INVOCATION",
+    "functionSelect": {
+      "endPosition": "4",
+      "kind": "IDENTIFIER",
+      "name": "foo",
+      "startPosition": "1"
+    },
+    "arguments": [
+      {
+        "endPosition": "6",
+        "kind": "IDENTIFIER",
+        "name": "a",
+        "startPosition": "5"
+      },
+      {
+        "expression": {
+          "endPosition": "12",
+          "kind": "IDENTIFIER",
+          "name": "b",
+          "startPosition": "11"
+        },
+        "endPosition": "12",
+        "kind": "SPREAD",
+        "startPosition": "8"
+      }
+    ],
+    "startPosition": "1"
+  },
+  {
+    "endPosition": "38",
+    "kind": "FUNCTION_INVOCATION",
+    "functionSelect": {
+      "endPosition": "19",
+      "kind": "IDENTIFIER",
+      "name": "bar",
+      "startPosition": "16"
+    },
+    "arguments": [
+      {
+        "endPosition": "21",
+        "kind": "NUMBER_LITERAL",
+        "value": "3",
+        "startPosition": "20"
+      },
+      {
+        "expression": {
+          "endPosition": "37",
+          "kind": "ARRAY_LITERAL",
+          "elements": [
+            {
+              "endPosition": "28",
+              "kind": "NUMBER_LITERAL",
+              "value": "3",
+              "startPosition": "27"
+            },
+            {
+              "endPosition": "31",
+              "kind": "NUMBER_LITERAL",
+              "value": "5",
+              "startPosition": "30"
+            },
+            {
+              "endPosition": "36",
+              "kind": "NUMBER_LITERAL",
+              "value": "546",
+              "startPosition": "33"
+            }
+          ],
+          "startPosition": "26"
+        },
+        "endPosition": "37",
+        "kind": "SPREAD",
+        "startPosition": "23"
+      }
+    ],
+    "startPosition": "16"
+  },
+  {
+    "endPosition": "63",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "48",
+      "kind": "IDENTIFIER",
+      "name": "arr",
+      "startPosition": "45"
+    },
+    "startPosition": "41",
+    "initializer": {
+      "endPosition": "63",
+      "kind": "ARRAY_LITERAL",
+      "elements": [
+        {
+          "endPosition": "53",
+          "kind": "NUMBER_LITERAL",
+          "value": "3",
+          "startPosition": "52"
+        },
+        {
+          "expression": {
+            "endPosition": "59",
+            "kind": "IDENTIFIER",
+            "name": "a",
+            "startPosition": "58"
+          },
+          "endPosition": "59",
+          "kind": "SPREAD",
+          "startPosition": "55"
+        },
+        {
+          "endPosition": "62",
+          "kind": "NUMBER_LITERAL",
+          "value": "5",
+          "startPosition": "61"
+        }
+      ],
+      "startPosition": "51"
+    }
+  },
+  {
+    "endPosition": "94",
+    "kind": "VARIABLE",
+    "binding": {
+      "endPosition": "73",
+      "kind": "IDENTIFIER",
+      "name": "arr2",
+      "startPosition": "69"
+    },
+    "startPosition": "65",
+    "initializer": {
+      "endPosition": "94",
+      "kind": "ARRAY_LITERAL",
+      "elements": [
+        {
+          "endPosition": "78",
+          "kind": "NUMBER_LITERAL",
+          "value": "4",
+          "startPosition": "77"
+        },
+        {
+          "expression": {
+            "endPosition": "89",
+            "kind": "ARRAY_LITERAL",
+            "elements": [
+              {
+                "endPosition": "85",
+                "kind": "NUMBER_LITERAL",
+                "value": "5",
+                "startPosition": "84"
+              },
+              {
+                "endPosition": "88",
+                "kind": "NUMBER_LITERAL",
+                "value": "6",
+                "startPosition": "87"
+              }
+            ],
+            "startPosition": "83"
+          },
+          "endPosition": "89",
+          "kind": "SPREAD",
+          "startPosition": "80"
+        },
+        {
+          "endPosition": "93",
+          "kind": "NUMBER_LITERAL",
+          "value": "78",
+          "startPosition": "91"
+        }
+      ],
+      "startPosition": "76"
+    }
+  }
+]
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/template_literal.js	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * Tests to check representation of ES6 template literal.
+ *
+ * @test
+ * @run
+ */
+
+load(__DIR__ + "utils.js")
+
+var code = "`your name is ${name} and you work for ${company}`"
+
+parse("template_literal.js", code, "--language=es6", new (Java.extend(visitor_es6, {
+    visitTemplateLiteral : function (node, obj) {
+        obj.push(convert(node))
+    }
+})))
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nashorn/test/script/nosecurity/treeapi/template_literal.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -0,0 +1,39 @@
+[
+  {
+    "endPosition": "49",
+    "kind": "TEMPLATE_LITERAL",
+    "expressions": [
+      {
+        "endPosition": "14",
+        "kind": "STRING_LITERAL",
+        "value": "your name is ",
+        "startPosition": "1"
+      },
+      {
+        "endPosition": "20",
+        "kind": "IDENTIFIER",
+        "name": "name",
+        "startPosition": "16"
+      },
+      {
+        "endPosition": "39",
+        "kind": "STRING_LITERAL",
+        "value": " and you work for ",
+        "startPosition": "21"
+      },
+      {
+        "endPosition": "48",
+        "kind": "IDENTIFIER",
+        "name": "company",
+        "startPosition": "41"
+      },
+      {
+        "endPosition": "49",
+        "kind": "STRING_LITERAL",
+        "value": "",
+        "startPosition": "49"
+      }
+    ],
+    "startPosition": "1"
+  }
+]
--- a/nashorn/test/script/nosecurity/treeapi/utils.js	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/utils.js	Mon Jul 18 09:38:08 2016 -0700
@@ -30,17 +30,42 @@
 var tree = Java.type('jdk.nashorn.api.tree.Tree');
 var list = Java.type('java.util.List');
 var visitor = Java.type('jdk.nashorn.api.tree.SimpleTreeVisitorES5_1');
+var visitor_es6 = Java.type('jdk.nashorn.api.tree.SimpleTreeVisitorES6');
 var file = Java.type('java.io.File')
 var cls = Java.type('java.lang.Class')
 
 function convert (value) {
-    if (!value) {
+    if (!value || typeof(value) != 'object') {
         return value;
     }
     var  obj = Object.bindProperties({}, value)
     var result = {}
     for (var i in obj) {
+        if (i == "lineMap") {
+            continue;
+        }
+
         var val = obj[i]
+        // skip these ES6 specific properties to reduce noise
+        // in the output - unless there were set to true
+        if (typeof(val) == 'boolean' && val == false) {
+            switch (i) {
+                case "computed":
+                case "static":
+                case "restParameter":
+                case "this":
+                case "super":
+                case "star":
+                case "default":
+                case "starDefaultStar":
+                case "arrow":
+                case "generator":
+                case "let":
+                case "const":
+                    continue;
+             }
+        }
+
         if (typeof(val) == 'object') {
             if (val instanceof cls) {
                 continue;
@@ -72,6 +97,9 @@
     print(JSON.stringify(results, null, 2))
 }
 
+function parseModule(name, code) {
+    return parser.create("--es6-module").parse(name, code, null);
+}
 
 function parseDiagnostic (code, args) {
     var messages = new Array()
@@ -79,4 +107,4 @@
         messages.push(convert(message))
     })
     print(JSON.stringify(messages, null, 2).replace(/\\r/g, ''))
-}
\ No newline at end of file
+}
--- a/nashorn/test/script/nosecurity/treeapi/variable.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/variable.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -2,15 +2,25 @@
   {
     "endPosition": "6",
     "kind": "VARIABLE",
-    "name": "a",
-    "startPosition": "5",
+    "binding": {
+      "endPosition": "6",
+      "kind": "IDENTIFIER",
+      "name": "a",
+      "startPosition": "5"
+    },
+    "startPosition": "1",
     "initializer": "null"
   },
   {
     "endPosition": "16",
     "kind": "VARIABLE",
-    "name": "x",
-    "startPosition": "11",
+    "binding": {
+      "endPosition": "12",
+      "kind": "IDENTIFIER",
+      "name": "x",
+      "startPosition": "11"
+    },
+    "startPosition": "7",
     "initializer": {
       "endPosition": "16",
       "kind": "NUMBER_LITERAL",
@@ -21,15 +31,25 @@
   {
     "endPosition": "24",
     "kind": "VARIABLE",
-    "name": "x23",
-    "startPosition": "21",
+    "binding": {
+      "endPosition": "24",
+      "kind": "IDENTIFIER",
+      "name": "x23",
+      "startPosition": "21"
+    },
+    "startPosition": "17",
     "initializer": "null"
   },
   {
     "endPosition": "32",
     "kind": "VARIABLE",
-    "name": "$y",
-    "startPosition": "26",
+    "binding": {
+      "endPosition": "28",
+      "kind": "IDENTIFIER",
+      "name": "$y",
+      "startPosition": "26"
+    },
+    "startPosition": "17",
     "initializer": {
       "endPosition": "32",
       "kind": "NUMBER_LITERAL",
@@ -40,8 +60,13 @@
   {
     "endPosition": "36",
     "kind": "VARIABLE",
-    "name": "_z",
-    "startPosition": "34",
+    "binding": {
+      "endPosition": "36",
+      "kind": "IDENTIFIER",
+      "name": "_z",
+      "startPosition": "34"
+    },
+    "startPosition": "17",
     "initializer": "null"
   }
-]
+]
--- a/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED	Fri Jul 15 09:05:36 2016 -0700
+++ b/nashorn/test/script/nosecurity/treeapi/with.js.EXPECTED	Mon Jul 18 09:38:08 2016 -0700
@@ -114,6 +114,7 @@
               "expression": {
                 "endPosition": "76",
                 "kind": "IDENTIFIER",
+                "this": "true",
                 "name": "this",
                 "startPosition": "72"
               },
@@ -140,4 +141,4 @@
     },
     "startPosition": "52"
   }
-]
+]