Merge
authorjwilhelm
Tue, 17 Apr 2018 15:25:13 +0200
changeset 49762 b07d069b189a
parent 49707 f7fd051519ac (current diff)
parent 49761 46dc568d6804 (diff)
child 49763 1ccf5fae9664
Merge
src/hotspot/share/gc/cms/vmStructs_parNew.hpp
src/hotspot/share/gc/g1/g1_globals.cpp
src/hotspot/share/memory/binaryTreeDictionary.cpp
src/hotspot/share/memory/freeList.cpp
src/hotspot/share/runtime/commandLineFlagConstraintsGC.cpp
src/hotspot/share/runtime/commandLineFlagConstraintsGC.hpp
test/hotspot/jtreg/runtime/6626217/Test6626217.sh
test/hotspot/jtreg/runtime/6626217/many_loader1.java.foo
test/hotspot/jtreg/runtime/6626217/many_loader2.java.foo
test/jdk/ProblemList.txt
--- a/make/autoconf/flags-cflags.m4	Tue Apr 17 15:39:20 2018 +0200
+++ b/make/autoconf/flags-cflags.m4	Tue Apr 17 15:25:13 2018 +0200
@@ -453,7 +453,7 @@
   elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     ALWAYS_DEFINES_JDK="-DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_DEPRECATE \
         -D_CRT_NONSTDC_NO_DEPRECATE -DWIN32 -DIAL"
-    ALWAYS_DEFINES_JVM="-DNOMINMAX"
+    ALWAYS_DEFINES_JVM="-DNOMINMAX -DWIN32_LEAN_AND_MEAN"
   fi
 
   ###############################################################################
--- a/make/hotspot/lib/JvmOverrideFiles.gmk	Tue Apr 17 15:39:20 2018 +0200
+++ b/make/hotspot/lib/JvmOverrideFiles.gmk	Tue Apr 17 15:25:13 2018 +0200
@@ -34,6 +34,7 @@
   BUILD_LIBJVM_jvmciCompilerToVM.cpp_CXXFLAGS := -fno-var-tracking-assignments
   BUILD_LIBJVM_jvmciCompilerToVMInit.cpp_CXXFLAGS := -fno-var-tracking-assignments
   BUILD_LIBJVM_assembler_x86.cpp_CXXFLAGS := -Wno-maybe-uninitialized
+  BUILD_LIBJVM_cardTableBarrierSetAssembler_x86.cpp_CXXFLAGS := -Wno-maybe-uninitialized
   BUILD_LIBJVM_interp_masm_x86.cpp_CXXFLAGS := -Wno-uninitialized
 endif
 
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Tue Apr 17 15:25:13 2018 +0200
@@ -5847,8 +5847,8 @@
 operand immByteMapBase()
 %{
   // Get base of card map
-  predicate(Universe::heap()->barrier_set()->is_a(BarrierSet::CardTableBarrierSet) &&
-            (jbyte*)n->get_ptr() == ((CardTableBarrierSet*)(Universe::heap()->barrier_set()))->card_table()->byte_map_base());
+  predicate(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet) &&
+            (jbyte*)n->get_ptr() == ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base());
   match(ConP);
 
   op_cost(0);
@@ -16167,9 +16167,8 @@
   format %{ "String Equals $str1,$str2,$cnt -> $result" %}
   ins_encode %{
     // Count is in 8-bit bytes; non-Compact chars are 16 bits.
-    __ arrays_equals($str1$$Register, $str2$$Register,
-                     $result$$Register, $cnt$$Register,
-                     1, /*is_string*/true);
+    __ string_equals($str1$$Register, $str2$$Register,
+                     $result$$Register, $cnt$$Register, 1);
   %}
   ins_pipe(pipe_class_memory);
 %}
@@ -16184,42 +16183,42 @@
   format %{ "String Equals $str1,$str2,$cnt -> $result" %}
   ins_encode %{
     // Count is in 8-bit bytes; non-Compact chars are 16 bits.
-    __ asrw($cnt$$Register, $cnt$$Register, 1);
-    __ arrays_equals($str1$$Register, $str2$$Register,
-                     $result$$Register, $cnt$$Register,
-                     2, /*is_string*/true);
+    __ string_equals($str1$$Register, $str2$$Register,
+                     $result$$Register, $cnt$$Register, 2);
   %}
   ins_pipe(pipe_class_memory);
 %}
 
 instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
-                      iRegP_R10 tmp, rFlagsReg cr)
+                       iRegP_R3 tmp1, iRegP_R4 tmp2, iRegP_R5 tmp3,
+                       iRegP_R10 tmp, rFlagsReg cr)
 %{
   predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
   match(Set result (AryEq ary1 ary2));
-  effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr);
+  effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
 
   format %{ "Array Equals $ary1,ary2 -> $result    // KILL $tmp" %}
   ins_encode %{
     __ arrays_equals($ary1$$Register, $ary2$$Register,
-                     $result$$Register, $tmp$$Register,
-                     1, /*is_string*/false);
+                     $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
+                     $result$$Register, $tmp$$Register, 1);
     %}
   ins_pipe(pipe_class_memory);
 %}
 
 instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
-                      iRegP_R10 tmp, rFlagsReg cr)
+                       iRegP_R3 tmp1, iRegP_R4 tmp2, iRegP_R5 tmp3,
+                       iRegP_R10 tmp, rFlagsReg cr)
 %{
   predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
   match(Set result (AryEq ary1 ary2));
-  effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr);
+  effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
 
   format %{ "Array Equals $ary1,ary2 -> $result    // KILL $tmp" %}
   ins_encode %{
     __ arrays_equals($ary1$$Register, $ary2$$Register,
-                     $result$$Register, $tmp$$Register,
-                     2, /*is_string*/false);
+                     $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
+                     $result$$Register, $tmp$$Register, 2);
   %}
   ins_pipe(pipe_class_memory);
 %}
--- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -819,7 +819,7 @@
   void NAME(Register Rd, Register Rn, unsigned immr, unsigned imms) {   \
     starti;                                                             \
     f(opcode, 31, 22), f(immr, 21, 16), f(imms, 15, 10);                \
-    rf(Rn, 5), rf(Rd, 0);                                               \
+    zrf(Rn, 5), rf(Rd, 0);                                              \
   }
 
   INSN(sbfmw, 0b0001001100);
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -46,6 +46,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 
@@ -1106,7 +1107,7 @@
         StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);
         // arg0 : previous value of memory
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ mov(r0, (int)id);
           __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), r0);
@@ -1118,13 +1119,9 @@
         const Register thread = rthread;
         const Register tmp = rscratch1;
 
-        Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                             SATBMarkQueue::byte_offset_of_active()));
-
-        Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                             SATBMarkQueue::byte_offset_of_index()));
-        Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                        SATBMarkQueue::byte_offset_of_buf()));
+        Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
+        Address queue_index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
+        Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
 
         Label done;
         Label runtime;
@@ -1162,7 +1159,7 @@
       {
         StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ mov(r0, (int)id);
           __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), r0);
@@ -1181,10 +1178,8 @@
 
         const Register thread = rthread;
 
-        Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                             DirtyCardQueue::byte_offset_of_index()));
-        Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                        DirtyCardQueue::byte_offset_of_buf()));
+        Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
+        Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
 
         const Register card_offset = rscratch2;
         // LR is free here, so we can use it to hold the byte_map_base.
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,12 +25,12 @@
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
 #include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "runtime/thread.hpp"
 #include "interpreter/interp_masm.hpp"
+#include "runtime/sharedRuntime.hpp"
 
 #define __ masm->
 
@@ -75,3 +75,233 @@
   __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSet::write_ref_array_post_entry), 2);
   __ pop(saved_regs, sp);
 }
+
+void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
+                                                 Register obj,
+                                                 Register pre_val,
+                                                 Register thread,
+                                                 Register tmp,
+                                                 bool tosca_live,
+                                                 bool expand_call) {
+  // If expand_call is true then we expand the call_VM_leaf macro
+  // directly to skip generating the check by
+  // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
+
+  assert(thread == rthread, "must be");
+
+  Label done;
+  Label runtime;
+
+  assert_different_registers(obj, pre_val, tmp, rscratch1);
+  assert(pre_val != noreg &&  tmp != noreg, "expecting a register");
+
+  Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
+  Address index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
+  Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
+
+  // Is marking active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ ldrw(tmp, in_progress);
+  } else {
+    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ ldrb(tmp, in_progress);
+  }
+  __ cbzw(tmp, done);
+
+  // Do we need to load the previous value?
+  if (obj != noreg) {
+    __ load_heap_oop(pre_val, Address(obj, 0));
+  }
+
+  // Is the previous value null?
+  __ cbz(pre_val, done);
+
+  // Can we store original value in the thread's buffer?
+  // Is index == 0?
+  // (The index field is typed as size_t.)
+
+  __ ldr(tmp, index);                      // tmp := *index_adr
+  __ cbz(tmp, runtime);                    // tmp == 0?
+                                        // If yes, goto runtime
+
+  __ sub(tmp, tmp, wordSize);              // tmp := tmp - wordSize
+  __ str(tmp, index);                      // *index_adr := tmp
+  __ ldr(rscratch1, buffer);
+  __ add(tmp, tmp, rscratch1);             // tmp := tmp + *buffer_adr
+
+  // Record the previous value
+  __ str(pre_val, Address(tmp, 0));
+  __ b(done);
+
+  __ bind(runtime);
+  // save the live input values
+  RegSet saved = RegSet::of(pre_val);
+  if (tosca_live) saved += RegSet::of(r0);
+  if (obj != noreg) saved += RegSet::of(obj);
+
+  __ push(saved, sp);
+
+  // Calling the runtime using the regular call_VM_leaf mechanism generates
+  // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
+  // that checks that the *(rfp+frame::interpreter_frame_last_sp) == NULL.
+  //
+  // If we care generating the pre-barrier without a frame (e.g. in the
+  // intrinsified Reference.get() routine) then ebp might be pointing to
+  // the caller frame and so this check will most likely fail at runtime.
+  //
+  // Expanding the call directly bypasses the generation of the check.
+  // So when we do not have have a full interpreter frame on the stack
+  // expand_call should be passed true.
+
+  if (expand_call) {
+    assert(pre_val != c_rarg1, "smashed arg");
+    __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
+  } else {
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
+  }
+
+  __ pop(saved, sp);
+
+  __ bind(done);
+
+}
+
+void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
+                                                  Register store_addr,
+                                                  Register new_val,
+                                                  Register thread,
+                                                  Register tmp,
+                                                  Register tmp2) {
+  assert(thread == rthread, "must be");
+  assert_different_registers(store_addr, new_val, thread, tmp, tmp2,
+                             rscratch1);
+  assert(store_addr != noreg && new_val != noreg && tmp != noreg
+         && tmp2 != noreg, "expecting a register");
+
+  Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
+  Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
+
+  BarrierSet* bs = BarrierSet::barrier_set();
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
+  CardTable* ct = ctbs->card_table();
+  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  Label done;
+  Label runtime;
+
+  // Does store cross heap regions?
+
+  __ eor(tmp, store_addr, new_val);
+  __ lsr(tmp, tmp, HeapRegion::LogOfHRGrainBytes);
+  __ cbz(tmp, done);
+
+  // crosses regions, storing NULL?
+
+  __ cbz(new_val, done);
+
+  // storing region crossing non-NULL, is card already dirty?
+
+  ExternalAddress cardtable((address) ct->byte_map_base());
+  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+  const Register card_addr = tmp;
+
+  __ lsr(card_addr, store_addr, CardTable::card_shift);
+
+  // get the address of the card
+  __ load_byte_map_base(tmp2);
+  __ add(card_addr, card_addr, tmp2);
+  __ ldrb(tmp2, Address(card_addr));
+  __ cmpw(tmp2, (int)G1CardTable::g1_young_card_val());
+  __ br(Assembler::EQ, done);
+
+  assert((int)CardTable::dirty_card_val() == 0, "must be 0");
+
+  __ membar(Assembler::StoreLoad);
+
+  __ ldrb(tmp2, Address(card_addr));
+  __ cbzw(tmp2, done);
+
+  // storing a region crossing, non-NULL oop, card is clean.
+  // dirty card and log.
+
+  __ strb(zr, Address(card_addr));
+
+  __ ldr(rscratch1, queue_index);
+  __ cbz(rscratch1, runtime);
+  __ sub(rscratch1, rscratch1, wordSize);
+  __ str(rscratch1, queue_index);
+
+  __ ldr(tmp2, buffer);
+  __ str(card_addr, Address(tmp2, rscratch1));
+  __ b(done);
+
+  __ bind(runtime);
+  // save the live input values
+  RegSet saved = RegSet::of(store_addr, new_val);
+  __ push(saved, sp);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
+  __ pop(saved, sp);
+
+  __ bind(done);
+}
+
+void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                    Register dst, Address src, Register tmp1, Register tmp_thread) {
+  bool on_oop = type == T_OBJECT || type == T_ARRAY;
+  bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
+  bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+  bool on_reference = on_weak || on_phantom;
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
+  if (on_oop && on_reference) {
+    // Generate the G1 pre-barrier code to log the value of
+    // the referent field in an SATB buffer.
+    g1_write_barrier_pre(masm /* masm */,
+                         noreg /* obj */,
+                         dst /* pre_val */,
+                         rthread /* thread */,
+                         tmp1 /* tmp */,
+                         true /* tosca_live */,
+                         true /* expand_call */);
+  }
+}
+
+void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Address dst, Register val, Register tmp1, Register tmp2) {
+  // flatten object address if needed
+  if (dst.index() == noreg && dst.offset() == 0) {
+    if (dst.base() != r3) {
+      __ mov(r3, dst.base());
+    }
+  } else {
+    __ lea(r3, dst);
+  }
+
+  g1_write_barrier_pre(masm,
+                       r3 /* obj */,
+                       tmp2 /* pre_val */,
+                       rthread /* thread */,
+                       tmp1  /* tmp */,
+                       val != noreg /* tosca_live */,
+                       false /* expand_call */);
+
+  if (val == noreg) {
+    __ store_heap_oop_null(Address(r3, 0));
+  } else {
+    // G1 barrier needs uncompressed oop for region cross check.
+    Register new_val = val;
+    if (UseCompressedOops) {
+      new_val = rscratch2;
+      __ mov(new_val, val);
+    }
+    __ store_heap_oop(Address(r3, 0), val);
+    g1_write_barrier_post(masm,
+                          r3 /* store_adr */,
+                          new_val /* new_val */,
+                          rthread /* thread */,
+                          tmp1 /* tmp */,
+                          tmp2 /* tmp2 */);
+  }
+
+}
+
+#undef __
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -34,6 +34,28 @@
                                        Register addr, Register count, RegSet saved_regs);
   void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                         Register start, Register end, Register tmp, RegSet saved_regs);
+
+  void g1_write_barrier_pre(MacroAssembler* masm,
+                            Register obj,
+                            Register pre_val,
+                            Register thread,
+                            Register tmp,
+                            bool tosca_live,
+                            bool expand_call);
+
+  void g1_write_barrier_post(MacroAssembler* masm,
+                             Register store_addr,
+                             Register new_val,
+                             Register thread,
+                             Register tmp,
+                             Register tmp2);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Address dst, Register val, Register tmp1, Register tmp2);
+
+public:
+  void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+               Register dst, Address src, Register tmp1, Register tmp_thread);
 };
 
 #endif // CPU_AARCH64_GC_G1_G1BARRIERSETASSEMBLER_AARCH64_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+
+#define __ masm->
+
+void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                  Register dst, Address src, Register tmp1, Register tmp_thread) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  switch (type) {
+  case T_OBJECT:
+  case T_ARRAY: {
+    if (on_heap) {
+      __ load_heap_oop(dst, src);
+    } else {
+      assert(on_root, "why else?");
+      __ ldr(dst, src);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                   Address dst, Register val, Register tmp1, Register tmp2) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  switch (type) {
+  case T_OBJECT:
+  case T_ARRAY: {
+    if (on_heap) {
+      __ store_heap_oop(dst, val);
+    } else {
+      assert(on_root, "why else?");
+      __ str(val, dst);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
--- a/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/barrierSetAssembler_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -35,6 +35,12 @@
                                   Register addr, Register count, RegSet saved_regs) {}
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register start, Register end, Register tmp, RegSet saved_regs) {}
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Register dst, Address src, Register tmp1, Register tmp_thread);
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Address dst, Register val, Register tmp1, Register tmp2);
+
+  virtual void barrier_stubs_init() {}
 };
 
 #endif // CPU_AARCH64_GC_SHARED_BARRIERSETASSEMBLER_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,15 +28,44 @@
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 
 #define __ masm->
 
+
+void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst) {
+
+  BarrierSet* bs = BarrierSet::barrier_set();
+  assert(bs->kind() == BarrierSet::CardTableBarrierSet, "Wrong barrier set kind");
+
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
+  CardTable* ct = ctbs->card_table();
+  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  __ lsr(obj, obj, CardTable::card_shift);
+
+  assert(CardTable::dirty_card_val() == 0, "must be");
+
+  __ load_byte_map_base(rscratch1);
+
+  if (UseCondCardMark) {
+    Label L_already_dirty;
+    __ membar(Assembler::StoreLoad);
+    __ ldrb(rscratch2,  Address(obj, rscratch1));
+    __ cbz(rscratch2, L_already_dirty);
+    __ strb(zr, Address(obj, rscratch1));
+    __ bind(L_already_dirty);
+  } else {
+    if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
+      __ membar(Assembler::StoreStore);
+    }
+    __ strb(zr, Address(obj, rscratch1));
+  }
+}
+
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                                     Register start, Register end, Register scratch, RegSet saved_regs) {
-
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
@@ -58,3 +87,22 @@
   __ subs(count, count, 1);
   __ br(Assembler::GE, L_loop);
 }
+
+void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                                Address dst, Register val, Register tmp1, Register tmp2) {
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+  if (val == noreg) {
+    __ store_heap_oop_null(dst);
+  } else {
+    __ store_heap_oop(dst, val);
+    // flatten object address if needed
+    if (!precise || (dst.index() == noreg && dst.offset() == 0)) {
+      store_check(masm, dst.base(), dst);
+    } else {
+      __ lea(r3, dst);
+      store_check(masm, r3, dst);
+    }
+  }
+}
--- a/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/cardTableBarrierSetAssembler_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,8 +30,13 @@
 
 class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
+  void store_check(MacroAssembler* masm, Register obj, Address dst);
+
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                 Register start, Register end, Register tmp, RegSet saved_regs);
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Address dst, Register val, Register tmp1, Register tmp2);
+
 };
 
 #endif // #ifndef CPU_AARCH64_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -43,3 +43,18 @@
     gen_write_ref_array_post_barrier(masm, decorators, start, end, tmp, saved_regs);
   }
 }
+
+
+void ModRefBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                             Address dst, Register val, Register tmp1, Register tmp2) {
+  BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2);
+}
+
+void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Address dst, Register val, Register tmp1, Register tmp2) {
+  if (type == T_OBJECT || type == T_ARRAY) {
+    oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2);
+  } else {
+    BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2);
+  }
+}
--- a/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/shared/modRefBarrierSetAssembler_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,6 +28,10 @@
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 
+// The ModRefBarrierSetAssembler filters away accesses on BasicTypes other
+// than T_OBJECT/T_ARRAY (oops). The oop accesses call one of the protected
+// accesses, which are overridden in the concrete BarrierSetAssembler.
+
 class ModRefBarrierSetAssembler: public BarrierSetAssembler {
 protected:
   virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
@@ -35,11 +39,16 @@
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                 Register start, Register end, Register tmp, RegSet saved_regs) {}
 
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Address dst, Register val, Register tmp1, Register tmp2);
+
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register addr, Register count, RegSet saved_regs);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register start, Register end, Register tmp, RegSet saved_regs);
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Address dst, Register val, Register tmp1, Register tmp2);
 };
 
 #endif // CPU_AARCH64_GC_SHARED_MODREFBARRIERSETASSEMBLER_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -147,6 +147,10 @@
           "Use CRC32 instructions for CRC32 computation")               \
   product(bool, UseSIMDForMemoryOps, false,                             \
           "Use SIMD instructions in generated memory move code")        \
+  product(bool, UseSIMDForArrayEquals, true,                            \
+          "Use SIMD instructions in generated array equals code")       \
+  product(bool, UseSimpleArrayEquals, false,                            \
+          "Use simpliest and shortest implementation for array equals") \
   product(bool, AvoidUnalignedAccesses, false,                          \
           "Avoid generating unaligned memory accesses")                 \
   product(bool, UseLSE, false,                                          \
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -24,6 +24,8 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interp_masm_aarch64.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
@@ -277,9 +279,8 @@
   resolve_oop_handle(result);
   // Add in the index
   add(result, result, tmp);
-  load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
-  // The resulting oop is null if the reference is not yet resolved.
-  // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(this, IN_HEAP, T_OBJECT, result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), /*tmp1*/ noreg, /*tmp_thread*/ noreg);
 }
 
 void InterpreterMacroAssembler::load_resolved_klass_at_offset(
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,7 +29,9 @@
 #include "jvm.h"
 #include "asm/assembler.hpp"
 #include "asm/assembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "gc/shared/cardTable.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "interpreter/interpreter.hpp"
 #include "compiler/disassembler.hpp"
@@ -50,7 +52,6 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif
 
@@ -2091,6 +2092,28 @@
 }
 #endif
 
+void MacroAssembler::resolve_jobject(Register value, Register thread, Register tmp) {
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  Label done, not_weak;
+  cbz(value, done);           // Use NULL as-is.
+
+  STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
+  tbz(r0, 0, not_weak);    // Test for jweak tag.
+
+  // Resolve jweak.
+  bs->load_at(this, IN_ROOT | ON_PHANTOM_OOP_REF, T_OBJECT,
+                    value, Address(value, -JNIHandles::weak_tag_value), tmp, thread);
+  verify_oop(value);
+  b(done);
+
+  bind(not_weak);
+  // Resolve (untagged) jobject.
+  bs->load_at(this, IN_ROOT | ON_STRONG_OOP_REF, T_OBJECT,
+                    value, Address(value, 0), tmp, thread);
+  verify_oop(value);
+  bind(done);
+}
+
 void MacroAssembler::stop(const char* msg) {
   address ip = pc();
   pusha();
@@ -3609,43 +3632,6 @@
   cmp(src1, rscratch1);
 }
 
-void MacroAssembler::store_check(Register obj, Address dst) {
-  store_check(obj);
-}
-
-void MacroAssembler::store_check(Register obj) {
-  // Does a store check for the oop in register obj. The content of
-  // register obj is destroyed afterwards.
-
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  assert(bs->kind() == BarrierSet::CardTableBarrierSet,
-         "Wrong barrier set kind");
-
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
-  CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
-  lsr(obj, obj, CardTable::card_shift);
-
-  assert(CardTable::dirty_card_val() == 0, "must be");
-
-  load_byte_map_base(rscratch1);
-
-  if (UseCondCardMark) {
-    Label L_already_dirty;
-    membar(StoreLoad);
-    ldrb(rscratch2,  Address(obj, rscratch1));
-    cbz(rscratch2, L_already_dirty);
-    strb(zr, Address(obj, rscratch1));
-    bind(L_already_dirty);
-  } else {
-    if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
-      membar(StoreStore);
-    }
-    strb(zr, Address(obj, rscratch1));
-  }
-}
-
 void MacroAssembler::load_klass(Register dst, Register src) {
   if (UseCompressedClassPointers) {
     ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
@@ -4009,190 +3995,6 @@
     str(zr, dst);
 }
 
-#if INCLUDE_ALL_GCS
-/*
- * g1_write_barrier_pre -- G1GC pre-write barrier for store of new_val at
- * store_addr.
- *
- * Allocates rscratch1
- */
-void MacroAssembler::g1_write_barrier_pre(Register obj,
-                                          Register pre_val,
-                                          Register thread,
-                                          Register tmp,
-                                          bool tosca_live,
-                                          bool expand_call) {
-  // If expand_call is true then we expand the call_VM_leaf macro
-  // directly to skip generating the check by
-  // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
-
-  assert(thread == rthread, "must be");
-
-  Label done;
-  Label runtime;
-
-  assert_different_registers(obj, pre_val, tmp, rscratch1);
-  assert(pre_val != noreg &&  tmp != noreg, "expecting a register");
-
-  Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_active()));
-  Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_index()));
-  Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_buf()));
-
-
-  // Is marking active?
-  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    ldrw(tmp, in_progress);
-  } else {
-    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-    ldrb(tmp, in_progress);
-  }
-  cbzw(tmp, done);
-
-  // Do we need to load the previous value?
-  if (obj != noreg) {
-    load_heap_oop(pre_val, Address(obj, 0));
-  }
-
-  // Is the previous value null?
-  cbz(pre_val, done);
-
-  // Can we store original value in the thread's buffer?
-  // Is index == 0?
-  // (The index field is typed as size_t.)
-
-  ldr(tmp, index);                      // tmp := *index_adr
-  cbz(tmp, runtime);                    // tmp == 0?
-                                        // If yes, goto runtime
-
-  sub(tmp, tmp, wordSize);              // tmp := tmp - wordSize
-  str(tmp, index);                      // *index_adr := tmp
-  ldr(rscratch1, buffer);
-  add(tmp, tmp, rscratch1);             // tmp := tmp + *buffer_adr
-
-  // Record the previous value
-  str(pre_val, Address(tmp, 0));
-  b(done);
-
-  bind(runtime);
-  // save the live input values
-  push(r0->bit(tosca_live) | obj->bit(obj != noreg) | pre_val->bit(true), sp);
-
-  // Calling the runtime using the regular call_VM_leaf mechanism generates
-  // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
-  // that checks that the *(rfp+frame::interpreter_frame_last_sp) == NULL.
-  //
-  // If we care generating the pre-barrier without a frame (e.g. in the
-  // intrinsified Reference.get() routine) then ebp might be pointing to
-  // the caller frame and so this check will most likely fail at runtime.
-  //
-  // Expanding the call directly bypasses the generation of the check.
-  // So when we do not have have a full interpreter frame on the stack
-  // expand_call should be passed true.
-
-  if (expand_call) {
-    assert(pre_val != c_rarg1, "smashed arg");
-    pass_arg1(this, thread);
-    pass_arg0(this, pre_val);
-    MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2);
-  } else {
-    call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
-  }
-
-  pop(r0->bit(tosca_live) | obj->bit(obj != noreg) | pre_val->bit(true), sp);
-
-  bind(done);
-}
-
-/*
- * g1_write_barrier_post -- G1GC post-write barrier for store of new_val at
- * store_addr
- *
- * Allocates rscratch1
- */
-void MacroAssembler::g1_write_barrier_post(Register store_addr,
-                                           Register new_val,
-                                           Register thread,
-                                           Register tmp,
-                                           Register tmp2) {
-  assert(thread == rthread, "must be");
-  assert_different_registers(store_addr, new_val, thread, tmp, tmp2,
-                             rscratch1);
-  assert(store_addr != noreg && new_val != noreg && tmp != noreg
-         && tmp2 != noreg, "expecting a register");
-
-  Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                       DirtyCardQueue::byte_offset_of_index()));
-  Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                       DirtyCardQueue::byte_offset_of_buf()));
-
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
-  CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
-  Label done;
-  Label runtime;
-
-  // Does store cross heap regions?
-
-  eor(tmp, store_addr, new_val);
-  lsr(tmp, tmp, HeapRegion::LogOfHRGrainBytes);
-  cbz(tmp, done);
-
-  // crosses regions, storing NULL?
-
-  cbz(new_val, done);
-
-  // storing region crossing non-NULL, is card already dirty?
-
-  ExternalAddress cardtable((address) ct->byte_map_base());
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-  const Register card_addr = tmp;
-
-  lsr(card_addr, store_addr, CardTable::card_shift);
-
-  // get the address of the card
-  load_byte_map_base(tmp2);
-  add(card_addr, card_addr, tmp2);
-  ldrb(tmp2, Address(card_addr));
-  cmpw(tmp2, (int)G1CardTable::g1_young_card_val());
-  br(Assembler::EQ, done);
-
-  assert((int)CardTable::dirty_card_val() == 0, "must be 0");
-
-  membar(Assembler::StoreLoad);
-
-  ldrb(tmp2, Address(card_addr));
-  cbzw(tmp2, done);
-
-  // storing a region crossing, non-NULL oop, card is clean.
-  // dirty card and log.
-
-  strb(zr, Address(card_addr));
-
-  ldr(rscratch1, queue_index);
-  cbz(rscratch1, runtime);
-  sub(rscratch1, rscratch1, wordSize);
-  str(rscratch1, queue_index);
-
-  ldr(tmp2, buffer);
-  str(card_addr, Address(tmp2, rscratch1));
-  b(done);
-
-  bind(runtime);
-  // save the live input values
-  push(store_addr->bit(true) | new_val->bit(true), sp);
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
-  pop(store_addr->bit(true) | new_val->bit(true), sp);
-
-  bind(done);
-}
-
-#endif // INCLUDE_ALL_GCS
-
 Address MacroAssembler::allocate_metadata_address(Metadata* obj) {
   assert(oop_recorder() != NULL, "this assembler needs a Recorder");
   int index = oop_recorder()->allocate_metadata_index(obj);
@@ -4515,7 +4317,7 @@
 
 void MacroAssembler::load_byte_map_base(Register reg) {
   jbyte *byte_map_base =
-    ((CardTableBarrierSet*)(Universe::heap()->barrier_set()))->card_table()->byte_map_base();
+    ((CardTableBarrierSet*)(BarrierSet::barrier_set()))->card_table()->byte_map_base();
 
   if (is_valid_AArch64_address((address)byte_map_base)) {
     // Strictly speaking the byte_map_base isn't an address at all,
@@ -5182,28 +4984,11 @@
   BIND(DONE);
 }
 
-// Compare Strings or char/byte arrays.
-
-// is_string is true iff this is a string comparison.
-
-// For Strings we're passed the address of the first characters in a1
-// and a2 and the length in cnt1.
-
-// For byte and char arrays we're passed the arrays themselves and we
-// have to extract length fields and do null checks here.
-
-// elem_size is the element size in bytes: either 1 or 2.
-
-// There are two implementations.  For arrays >= 8 bytes, all
-// comparisons (including the final one, which may overlap) are
-// performed 8 bytes at a time.  For arrays < 8 bytes, we compare a
-// halfword, then a short, and then a byte.
-
-void MacroAssembler::arrays_equals(Register a1, Register a2,
-                                   Register result, Register cnt1,
-                                   int elem_size, bool is_string)
+void MacroAssembler::arrays_equals(Register a1, Register a2, Register tmp3,
+                                   Register tmp4, Register tmp5, Register result,
+                                   Register cnt1, int elem_size)
 {
-  Label SAME, DONE, SHORT, NEXT_WORD, ONE;
+  Label DONE;
   Register tmp1 = rscratch1;
   Register tmp2 = rscratch2;
   Register cnt2 = tmp2;  // cnt2 only used in array length compare
@@ -5212,6 +4997,7 @@
   int length_offset = arrayOopDesc::length_offset_in_bytes();
   int base_offset
     = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE);
+  int stubBytesThreshold = 3 * 64 + (UseSIMDForArrayEquals ? 0 : 16);
 
   assert(elem_size == 1 || elem_size == 2, "must be char or byte");
   assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
@@ -5220,43 +5006,229 @@
   {
     const char kind = (elem_size == 2) ? 'U' : 'L';
     char comment[64];
-    snprintf(comment, sizeof comment, "%s%c%s {",
-             is_string ? "string_equals" : "array_equals",
-             kind, "{");
+    snprintf(comment, sizeof comment, "array_equals%c{", kind);
+    BLOCK_COMMENT(comment);
+  }
+#endif
+  if (UseSimpleArrayEquals) {
+    Label NEXT_WORD, SHORT, SAME, TAIL03, TAIL01, A_MIGHT_BE_NULL, A_IS_NOT_NULL;
+    // if (a1==a2)
+    //     return true;
+    // if (a==null || a2==null)
+    //     return false;
+    // a1 & a2 == 0 means (some-pointer is null) or
+    // (very-rare-or-even-probably-impossible-pointer-values)
+    // so, we can save one branch in most cases
+    eor(rscratch1, a1, a2);
+    tst(a1, a2);
+    mov(result, false);
+    cbz(rscratch1, SAME);
+    br(EQ, A_MIGHT_BE_NULL);
+    // if (a1.length != a2.length)
+    //      return false;
+    bind(A_IS_NOT_NULL);
+    ldrw(cnt1, Address(a1, length_offset));
+    ldrw(cnt2, Address(a2, length_offset));
+    eorw(tmp5, cnt1, cnt2);
+    cbnzw(tmp5, DONE);
+    lea(a1, Address(a1, base_offset));
+    lea(a2, Address(a2, base_offset));
+    // Check for short strings, i.e. smaller than wordSize.
+    subs(cnt1, cnt1, elem_per_word);
+    br(Assembler::LT, SHORT);
+    // Main 8 byte comparison loop.
+    bind(NEXT_WORD); {
+      ldr(tmp1, Address(post(a1, wordSize)));
+      ldr(tmp2, Address(post(a2, wordSize)));
+      subs(cnt1, cnt1, elem_per_word);
+      eor(tmp5, tmp1, tmp2);
+      cbnz(tmp5, DONE);
+    } br(GT, NEXT_WORD);
+    // Last longword.  In the case where length == 4 we compare the
+    // same longword twice, but that's still faster than another
+    // conditional branch.
+    // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when
+    // length == 4.
+    if (log_elem_size > 0)
+      lsl(cnt1, cnt1, log_elem_size);
+    ldr(tmp3, Address(a1, cnt1));
+    ldr(tmp4, Address(a2, cnt1));
+    eor(tmp5, tmp3, tmp4);
+    cbnz(tmp5, DONE);
+    b(SAME);
+    bind(A_MIGHT_BE_NULL);
+    // in case both a1 and a2 are not-null, proceed with loads
+    cbz(a1, DONE);
+    cbz(a2, DONE);
+    b(A_IS_NOT_NULL);
+    bind(SHORT);
+
+    tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left.
+    {
+      ldrw(tmp1, Address(post(a1, 4)));
+      ldrw(tmp2, Address(post(a2, 4)));
+      eorw(tmp5, tmp1, tmp2);
+      cbnzw(tmp5, DONE);
+    }
+    bind(TAIL03);
+    tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left.
+    {
+      ldrh(tmp3, Address(post(a1, 2)));
+      ldrh(tmp4, Address(post(a2, 2)));
+      eorw(tmp5, tmp3, tmp4);
+      cbnzw(tmp5, DONE);
+    }
+    bind(TAIL01);
+    if (elem_size == 1) { // Only needed when comparing byte arrays.
+      tbz(cnt1, 0, SAME); // 0-1 bytes left.
+      {
+        ldrb(tmp1, a1);
+        ldrb(tmp2, a2);
+        eorw(tmp5, tmp1, tmp2);
+        cbnzw(tmp5, DONE);
+      }
+    }
+    bind(SAME);
+    mov(result, true);
+  } else {
+    Label NEXT_DWORD, A_IS_NULL, SHORT, TAIL, TAIL2, STUB, EARLY_OUT,
+        CSET_EQ, LAST_CHECK, LEN_IS_ZERO, SAME;
+    cbz(a1, A_IS_NULL);
+    ldrw(cnt1, Address(a1, length_offset));
+    cbz(a2, A_IS_NULL);
+    ldrw(cnt2, Address(a2, length_offset));
+    mov(result, false);
+    // on most CPUs a2 is still "locked"(surprisingly) in ldrw and it's
+    // faster to perform another branch before comparing a1 and a2
+    cmp(cnt1, elem_per_word);
+    br(LE, SHORT); // short or same
+    cmp(a1, a2);
+    br(EQ, SAME);
+    ldr(tmp3, Address(pre(a1, base_offset)));
+    cmp(cnt1, stubBytesThreshold);
+    br(GE, STUB);
+    ldr(tmp4, Address(pre(a2, base_offset)));
+    sub(tmp5, zr, cnt1, LSL, 3 + log_elem_size);
+    cmp(cnt2, cnt1);
+    br(NE, DONE);
+
+    // Main 16 byte comparison loop with 2 exits
+    bind(NEXT_DWORD); {
+      ldr(tmp1, Address(pre(a1, wordSize)));
+      ldr(tmp2, Address(pre(a2, wordSize)));
+      subs(cnt1, cnt1, 2 * elem_per_word);
+      br(LE, TAIL);
+      eor(tmp4, tmp3, tmp4);
+      cbnz(tmp4, DONE);
+      ldr(tmp3, Address(pre(a1, wordSize)));
+      ldr(tmp4, Address(pre(a2, wordSize)));
+      cmp(cnt1, elem_per_word);
+      br(LE, TAIL2);
+      cmp(tmp1, tmp2);
+    } br(EQ, NEXT_DWORD);
+    b(DONE);
+
+    bind(TAIL);
+    eor(tmp4, tmp3, tmp4);
+    eor(tmp2, tmp1, tmp2);
+    lslv(tmp2, tmp2, tmp5);
+    orr(tmp5, tmp4, tmp2);
+    cmp(tmp5, zr);
+    b(CSET_EQ);
+
+    bind(TAIL2);
+    eor(tmp2, tmp1, tmp2);
+    cbnz(tmp2, DONE);
+    b(LAST_CHECK);
+
+    bind(STUB);
+    ldr(tmp4, Address(pre(a2, base_offset)));
+    cmp(cnt2, cnt1);
+    br(NE, DONE);
+    if (elem_size == 2) { // convert to byte counter
+      lsl(cnt1, cnt1, 1);
+    }
+    eor(tmp5, tmp3, tmp4);
+    cbnz(tmp5, DONE);
+    RuntimeAddress stub = RuntimeAddress(StubRoutines::aarch64::large_array_equals());
+    assert(stub.target() != NULL, "array_equals_long stub has not been generated");
+    trampoline_call(stub);
+    b(DONE);
+
+    bind(SAME);
+    mov(result, true);
+    b(DONE);
+    bind(A_IS_NULL);
+    // a1 or a2 is null. if a2 == a2 then return true. else return false
+    cmp(a1, a2);
+    b(CSET_EQ);
+    bind(EARLY_OUT);
+    // (a1 != null && a2 == null) || (a1 != null && a2 != null && a1 == a2)
+    // so, if a2 == null => return false(0), else return true, so we can return a2
+    mov(result, a2);
+    b(DONE);
+    bind(LEN_IS_ZERO);
+    cmp(cnt2, zr);
+    b(CSET_EQ);
+    bind(SHORT);
+    cbz(cnt1, LEN_IS_ZERO);
+    sub(tmp5, zr, cnt1, LSL, 3 + log_elem_size);
+    ldr(tmp3, Address(a1, base_offset));
+    ldr(tmp4, Address(a2, base_offset));
+    bind(LAST_CHECK);
+    eor(tmp4, tmp3, tmp4);
+    lslv(tmp5, tmp4, tmp5);
+    cmp(tmp5, zr);
+    bind(CSET_EQ);
+    cset(result, EQ);
+  }
+
+  // That's it.
+  bind(DONE);
+
+  BLOCK_COMMENT("} array_equals");
+}
+
+// Compare Strings
+
+// For Strings we're passed the address of the first characters in a1
+// and a2 and the length in cnt1.
+// elem_size is the element size in bytes: either 1 or 2.
+// There are two implementations.  For arrays >= 8 bytes, all
+// comparisons (including the final one, which may overlap) are
+// performed 8 bytes at a time.  For strings < 8 bytes, we compare a
+// halfword, then a short, and then a byte.
+
+void MacroAssembler::string_equals(Register a1, Register a2,
+                                   Register result, Register cnt1, int elem_size)
+{
+  Label SAME, DONE, SHORT, NEXT_WORD;
+  Register tmp1 = rscratch1;
+  Register tmp2 = rscratch2;
+  Register cnt2 = tmp2;  // cnt2 only used in array length compare
+
+  assert(elem_size == 1 || elem_size == 2, "must be 2 or 1 byte");
+  assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2);
+
+#ifndef PRODUCT
+  {
+    const char kind = (elem_size == 2) ? 'U' : 'L';
+    char comment[64];
+    snprintf(comment, sizeof comment, "{string_equals%c", kind);
     BLOCK_COMMENT(comment);
   }
 #endif
 
   mov(result, false);
 
-  if (!is_string) {
-    // if (a==a2)
-    //     return true;
-    eor(rscratch1, a1, a2);
-    cbz(rscratch1, SAME);
-    // if (a==null || a2==null)
-    //     return false;
-    cbz(a1, DONE);
-    cbz(a2, DONE);
-    // if (a1.length != a2.length)
-    //      return false;
-    ldrw(cnt1, Address(a1, length_offset));
-    ldrw(cnt2, Address(a2, length_offset));
-    eorw(tmp1, cnt1, cnt2);
-    cbnzw(tmp1, DONE);
-
-    lea(a1, Address(a1, base_offset));
-    lea(a2, Address(a2, base_offset));
-  }
-
   // Check for short strings, i.e. smaller than wordSize.
-  subs(cnt1, cnt1, elem_per_word);
+  subs(cnt1, cnt1, wordSize);
   br(Assembler::LT, SHORT);
   // Main 8 byte comparison loop.
   bind(NEXT_WORD); {
     ldr(tmp1, Address(post(a1, wordSize)));
     ldr(tmp2, Address(post(a2, wordSize)));
-    subs(cnt1, cnt1, elem_per_word);
+    subs(cnt1, cnt1, wordSize);
     eor(tmp1, tmp1, tmp2);
     cbnz(tmp1, DONE);
   } br(GT, NEXT_WORD);
@@ -5265,18 +5237,16 @@
   // conditional branch.
   // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when
   // length == 4.
-  if (log_elem_size > 0)
-    lsl(cnt1, cnt1, log_elem_size);
   ldr(tmp1, Address(a1, cnt1));
   ldr(tmp2, Address(a2, cnt1));
-  eor(tmp1, tmp1, tmp2);
-  cbnz(tmp1, DONE);
+  eor(tmp2, tmp1, tmp2);
+  cbnz(tmp2, DONE);
   b(SAME);
 
   bind(SHORT);
   Label TAIL03, TAIL01;
 
-  tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left.
+  tbz(cnt1, 2, TAIL03); // 0-7 bytes left.
   {
     ldrw(tmp1, Address(post(a1, 4)));
     ldrw(tmp2, Address(post(a2, 4)));
@@ -5284,7 +5254,7 @@
     cbnzw(tmp1, DONE);
   }
   bind(TAIL03);
-  tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left.
+  tbz(cnt1, 1, TAIL01); // 0-3 bytes left.
   {
     ldrh(tmp1, Address(post(a1, 2)));
     ldrh(tmp2, Address(post(a2, 2)));
@@ -5292,7 +5262,7 @@
     cbnzw(tmp1, DONE);
   }
   bind(TAIL01);
-  if (elem_size == 1) { // Only needed when comparing byte arrays.
+  if (elem_size == 1) { // Only needed when comparing 1-byte elements
     tbz(cnt1, 0, SAME); // 0-1 bytes left.
     {
       ldrb(tmp1, a1);
@@ -5307,7 +5277,7 @@
 
   // That's it.
   bind(DONE);
-  BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals");
+  BLOCK_COMMENT("} string_equals");
 }
 
 
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -779,6 +779,8 @@
   void store_check(Register obj);                // store check for obj - register is destroyed afterwards
   void store_check(Register obj, Address dst);   // same as above, dst is exact store location (reg. is destroyed)
 
+  void resolve_jobject(Register value, Register thread, Register tmp);
+
 #if INCLUDE_ALL_GCS
 
   void g1_write_barrier_pre(Register obj,
@@ -1225,9 +1227,11 @@
 
   void has_negatives(Register ary1, Register len, Register result);
 
-  void arrays_equals(Register a1, Register a2,
-                     Register result, Register cnt1,
-                     int elem_size, bool is_string);
+  void arrays_equals(Register a1, Register a2, Register result, Register cnt1,
+                     Register tmp1, Register tmp2, Register tmp3, int elem_size);
+
+  void string_equals(Register a1, Register a2, Register result, Register cnt1,
+                     int elem_size);
 
   void fill_words(Register base, Register cnt, Register value);
   void zero_words(Register base, u_int64_t cnt);
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -2050,29 +2050,7 @@
 
   // Unbox oop result, e.g. JNIHandles::resolve result.
   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
-    Label done, not_weak;
-    __ cbz(r0, done);           // Use NULL as-is.
-    STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
-    __ tbz(r0, 0, not_weak);    // Test for jweak tag.
-    // Resolve jweak.
-    __ ldr(r0, Address(r0, -JNIHandles::weak_tag_value));
-    __ verify_oop(r0);
-#if INCLUDE_ALL_GCS
-    if (UseG1GC) {
-      __ g1_write_barrier_pre(noreg /* obj */,
-                              r0 /* pre_val */,
-                              rthread /* thread */,
-                              rscratch2 /* tmp */,
-                              true /* tosca_live */,
-                              true /* expand_call */);
-    }
-#endif // INCLUDE_ALL_GCS
-    __ b(done);
-    __ bind(not_weak);
-    // Resolve (untagged) jobject.
-    __ ldr(r0, Address(r0, 0));
-    __ verify_oop(r0);
-    __ bind(done);
+    __ resolve_jobject(r0, rthread, rscratch2);
   }
 
   if (CheckJNICalls) {
--- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1359,7 +1359,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, is_oop, d, count, saved_reg);
 
     if (is_oop) {
@@ -1433,7 +1433,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, is_oop, d, count, saved_regs);
 
     if (is_oop) {
@@ -1795,7 +1795,7 @@
       decorators |= AS_DEST_NOT_INITIALIZED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, is_oop, to, count, wb_pre_saved_regs);
 
     // save the original count
@@ -3813,6 +3813,182 @@
     __ ret(lr);
     return entry;
   }
+
+  void generate_large_array_equals_loop_nonsimd(int loopThreshold,
+        bool usePrefetch, Label &NOT_EQUAL) {
+    Register a1 = r1, a2 = r2, result = r0, cnt1 = r10, tmp1 = rscratch1,
+        tmp2 = rscratch2, tmp3 = r3, tmp4 = r4, tmp5 = r5, tmp6 = r11,
+        tmp7 = r12, tmp8 = r13;
+    Label LOOP;
+
+    __ ldp(tmp1, tmp3, Address(__ post(a1, 2 * wordSize)));
+    __ ldp(tmp2, tmp4, Address(__ post(a2, 2 * wordSize)));
+    __ bind(LOOP);
+    if (usePrefetch) {
+      __ prfm(Address(a1, SoftwarePrefetchHintDistance));
+      __ prfm(Address(a2, SoftwarePrefetchHintDistance));
+    }
+    __ ldp(tmp5, tmp7, Address(__ post(a1, 2 * wordSize)));
+    __ eor(tmp1, tmp1, tmp2);
+    __ eor(tmp3, tmp3, tmp4);
+    __ ldp(tmp6, tmp8, Address(__ post(a2, 2 * wordSize)));
+    __ orr(tmp1, tmp1, tmp3);
+    __ cbnz(tmp1, NOT_EQUAL);
+    __ ldp(tmp1, tmp3, Address(__ post(a1, 2 * wordSize)));
+    __ eor(tmp5, tmp5, tmp6);
+    __ eor(tmp7, tmp7, tmp8);
+    __ ldp(tmp2, tmp4, Address(__ post(a2, 2 * wordSize)));
+    __ orr(tmp5, tmp5, tmp7);
+    __ cbnz(tmp5, NOT_EQUAL);
+    __ ldp(tmp5, tmp7, Address(__ post(a1, 2 * wordSize)));
+    __ eor(tmp1, tmp1, tmp2);
+    __ eor(tmp3, tmp3, tmp4);
+    __ ldp(tmp6, tmp8, Address(__ post(a2, 2 * wordSize)));
+    __ orr(tmp1, tmp1, tmp3);
+    __ cbnz(tmp1, NOT_EQUAL);
+    __ ldp(tmp1, tmp3, Address(__ post(a1, 2 * wordSize)));
+    __ eor(tmp5, tmp5, tmp6);
+    __ sub(cnt1, cnt1, 8 * wordSize);
+    __ eor(tmp7, tmp7, tmp8);
+    __ ldp(tmp2, tmp4, Address(__ post(a2, 2 * wordSize)));
+    __ cmp(cnt1, loopThreshold);
+    __ orr(tmp5, tmp5, tmp7);
+    __ cbnz(tmp5, NOT_EQUAL);
+    __ br(__ GE, LOOP);
+    // post-loop
+    __ eor(tmp1, tmp1, tmp2);
+    __ eor(tmp3, tmp3, tmp4);
+    __ orr(tmp1, tmp1, tmp3);
+    __ sub(cnt1, cnt1, 2 * wordSize);
+    __ cbnz(tmp1, NOT_EQUAL);
+  }
+
+  void generate_large_array_equals_loop_simd(int loopThreshold,
+        bool usePrefetch, Label &NOT_EQUAL) {
+    Register a1 = r1, a2 = r2, result = r0, cnt1 = r10, tmp1 = rscratch1,
+        tmp2 = rscratch2;
+    Label LOOP;
+
+    __ bind(LOOP);
+    if (usePrefetch) {
+      __ prfm(Address(a1, SoftwarePrefetchHintDistance));
+      __ prfm(Address(a2, SoftwarePrefetchHintDistance));
+    }
+    __ ld1(v0, v1, v2, v3, __ T2D, Address(__ post(a1, 4 * 2 * wordSize)));
+    __ sub(cnt1, cnt1, 8 * wordSize);
+    __ ld1(v4, v5, v6, v7, __ T2D, Address(__ post(a2, 4 * 2 * wordSize)));
+    __ cmp(cnt1, loopThreshold);
+    __ eor(v0, __ T16B, v0, v4);
+    __ eor(v1, __ T16B, v1, v5);
+    __ eor(v2, __ T16B, v2, v6);
+    __ eor(v3, __ T16B, v3, v7);
+    __ orr(v0, __ T16B, v0, v1);
+    __ orr(v1, __ T16B, v2, v3);
+    __ orr(v0, __ T16B, v0, v1);
+    __ umov(tmp1, v0, __ D, 0);
+    __ umov(tmp2, v0, __ D, 1);
+    __ orr(tmp1, tmp1, tmp2);
+    __ cbnz(tmp1, NOT_EQUAL);
+    __ br(__ GE, LOOP);
+  }
+
+  // a1 = r1 - array1 address
+  // a2 = r2 - array2 address
+  // result = r0 - return value. Already contains "false"
+  // cnt1 = r10 - amount of elements left to check, reduced by wordSize
+  // r3-r5 are reserved temporary registers
+  address generate_large_array_equals() {
+    StubCodeMark mark(this, "StubRoutines", "large_array_equals");
+    Register a1 = r1, a2 = r2, result = r0, cnt1 = r10, tmp1 = rscratch1,
+        tmp2 = rscratch2, tmp3 = r3, tmp4 = r4, tmp5 = r5, tmp6 = r11,
+        tmp7 = r12, tmp8 = r13;
+    Label TAIL, NOT_EQUAL, EQUAL, NOT_EQUAL_NO_POP, NO_PREFETCH_LARGE_LOOP,
+        SMALL_LOOP, POST_LOOP;
+    const int PRE_LOOP_SIZE = UseSIMDForArrayEquals ? 0 : 16;
+    // calculate if at least 32 prefetched bytes are used
+    int prefetchLoopThreshold = SoftwarePrefetchHintDistance + 32;
+    int nonPrefetchLoopThreshold = (64 + PRE_LOOP_SIZE);
+    RegSet spilled_regs = RegSet::range(tmp6, tmp8);
+    assert_different_registers(a1, a2, result, cnt1, tmp1, tmp2, tmp3, tmp4,
+        tmp5, tmp6, tmp7, tmp8);
+
+    __ align(CodeEntryAlignment);
+    address entry = __ pc();
+    __ enter();
+    __ sub(cnt1, cnt1, wordSize);  // first 8 bytes were loaded outside of stub
+    // also advance pointers to use post-increment instead of pre-increment
+    __ add(a1, a1, wordSize);
+    __ add(a2, a2, wordSize);
+    if (AvoidUnalignedAccesses) {
+      // both implementations (SIMD/nonSIMD) are using relatively large load
+      // instructions (ld1/ldp), which has huge penalty (up to x2 exec time)
+      // on some CPUs in case of address is not at least 16-byte aligned.
+      // Arrays are 8-byte aligned currently, so, we can make additional 8-byte
+      // load if needed at least for 1st address and make if 16-byte aligned.
+      Label ALIGNED16;
+      __ tbz(a1, 3, ALIGNED16);
+      __ ldr(tmp1, Address(__ post(a1, wordSize)));
+      __ ldr(tmp2, Address(__ post(a2, wordSize)));
+      __ sub(cnt1, cnt1, wordSize);
+      __ eor(tmp1, tmp1, tmp2);
+      __ cbnz(tmp1, NOT_EQUAL_NO_POP);
+      __ bind(ALIGNED16);
+    }
+    if (UseSIMDForArrayEquals) {
+      if (SoftwarePrefetchHintDistance >= 0) {
+        __ cmp(cnt1, prefetchLoopThreshold);
+        __ br(__ LE, NO_PREFETCH_LARGE_LOOP);
+        generate_large_array_equals_loop_simd(prefetchLoopThreshold,
+            /* prfm = */ true, NOT_EQUAL);
+        __ cmp(cnt1, nonPrefetchLoopThreshold);
+        __ br(__ LT, TAIL);
+      }
+      __ bind(NO_PREFETCH_LARGE_LOOP);
+      generate_large_array_equals_loop_simd(nonPrefetchLoopThreshold,
+          /* prfm = */ false, NOT_EQUAL);
+    } else {
+      __ push(spilled_regs, sp);
+      if (SoftwarePrefetchHintDistance >= 0) {
+        __ cmp(cnt1, prefetchLoopThreshold);
+        __ br(__ LE, NO_PREFETCH_LARGE_LOOP);
+        generate_large_array_equals_loop_nonsimd(prefetchLoopThreshold,
+            /* prfm = */ true, NOT_EQUAL);
+        __ cmp(cnt1, nonPrefetchLoopThreshold);
+        __ br(__ LT, TAIL);
+      }
+      __ bind(NO_PREFETCH_LARGE_LOOP);
+      generate_large_array_equals_loop_nonsimd(nonPrefetchLoopThreshold,
+          /* prfm = */ false, NOT_EQUAL);
+    }
+    __ bind(TAIL);
+      __ cbz(cnt1, EQUAL);
+      __ subs(cnt1, cnt1, wordSize);
+      __ br(__ LE, POST_LOOP);
+    __ bind(SMALL_LOOP);
+      __ ldr(tmp1, Address(__ post(a1, wordSize)));
+      __ ldr(tmp2, Address(__ post(a2, wordSize)));
+      __ subs(cnt1, cnt1, wordSize);
+      __ eor(tmp1, tmp1, tmp2);
+      __ cbnz(tmp1, NOT_EQUAL);
+      __ br(__ GT, SMALL_LOOP);
+    __ bind(POST_LOOP);
+      __ ldr(tmp1, Address(a1, cnt1));
+      __ ldr(tmp2, Address(a2, cnt1));
+      __ eor(tmp1, tmp1, tmp2);
+      __ cbnz(tmp1, NOT_EQUAL);
+    __ bind(EQUAL);
+      __ mov(result, true);
+    __ bind(NOT_EQUAL);
+      if (!UseSIMDForArrayEquals) {
+        __ pop(spilled_regs, sp);
+      }
+    __ bind(NOT_EQUAL_NO_POP);
+    __ leave();
+    __ ret(lr);
+    return entry;
+  }
+
+
   /**
    *  Arguments:
    *
@@ -4895,6 +5071,11 @@
     // has negatives stub for large arrays.
     StubRoutines::aarch64::_has_negatives = generate_has_negatives(StubRoutines::aarch64::_has_negatives_long);
 
+    // array equals stub for large arrays.
+    if (!UseSimpleArrayEquals) {
+      StubRoutines::aarch64::_large_array_equals = generate_large_array_equals();
+    }
+
     if (UseMultiplyToLenIntrinsic) {
       StubRoutines::_multiplyToLen = generate_multiplyToLen();
     }
--- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -46,6 +46,7 @@
 address StubRoutines::aarch64::_zero_blocks = NULL;
 address StubRoutines::aarch64::_has_negatives = NULL;
 address StubRoutines::aarch64::_has_negatives_long = NULL;
+address StubRoutines::aarch64::_large_array_equals = NULL;
 bool StubRoutines::aarch64::_completed = false;
 
 /**
--- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -65,6 +65,7 @@
 
   static address _has_negatives;
   static address _has_negatives_long;
+  static address _large_array_equals;
   static bool _completed;
 
  public:
@@ -131,6 +132,10 @@
       return _has_negatives_long;
   }
 
+  static address large_array_equals() {
+      return _large_array_equals;
+  }
+
   static bool complete() {
     return _completed;
   }
--- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * Copyright (c) 2014, Red Hat Inc. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
@@ -889,7 +890,6 @@
 
 // Method entry for java.lang.ref.Reference.get.
 address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
-#if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1
   //
@@ -923,43 +923,29 @@
   const int referent_offset = java_lang_ref_Reference::referent_offset;
   guarantee(referent_offset > 0, "referent offset not initialized");
 
-  if (UseG1GC) {
-    Label slow_path;
-    const Register local_0 = c_rarg0;
-    // Check if local 0 != NULL
-    // If the receiver is null then it is OK to jump to the slow path.
-    __ ldr(local_0, Address(esp, 0));
-    __ cbz(local_0, slow_path);
+  Label slow_path;
+  const Register local_0 = c_rarg0;
+  // Check if local 0 != NULL
+  // If the receiver is null then it is OK to jump to the slow path.
+  __ ldr(local_0, Address(esp, 0));
+  __ cbz(local_0, slow_path);
 
-    // Load the value of the referent field.
-    const Address field_address(local_0, referent_offset);
-    __ load_heap_oop(local_0, field_address);
+  __ mov(r19, r13);   // Move senderSP to a callee-saved register
 
-    __ mov(r19, r13);   // Move senderSP to a callee-saved register
-    // Generate the G1 pre-barrier code to log the value of
-    // the referent field in an SATB buffer.
-    __ enter(); // g1_write may call runtime
-    __ g1_write_barrier_pre(noreg /* obj */,
-                            local_0 /* pre_val */,
-                            rthread /* thread */,
-                            rscratch2 /* tmp */,
-                            true /* tosca_live */,
-                            true /* expand_call */);
-    __ leave();
-    // areturn
-    __ andr(sp, r19, -16);  // done with stack
-    __ ret(lr);
+  // Load the value of the referent field.
+  const Address field_address(local_0, referent_offset);
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT, local_0, field_address, /*tmp1*/ rscratch2, /*tmp2*/ rscratch1);
 
-    // generate a vanilla interpreter entry as the slow path
-    __ bind(slow_path);
-    __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
-    return entry;
-  }
-#endif // INCLUDE_ALL_GCS
+  // areturn
+  __ andr(sp, r19, -16);  // done with stack
+  __ ret(lr);
 
-  // If G1 is not enabled then attempt to go through the accessor entry point
-  // Reference.get is an accessor
-  return NULL;
+  // generate a vanilla interpreter entry as the slow path
+  __ bind(slow_path);
+  __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
+  return entry;
+
 }
 
 /**
@@ -1434,28 +1420,7 @@
     __ br(Assembler::NE, no_oop);
     // Unbox oop result, e.g. JNIHandles::resolve result.
     __ pop(ltos);
-    __ cbz(r0, store_result);   // Use NULL as-is.
-    STATIC_ASSERT(JNIHandles::weak_tag_mask == 1u);
-    __ tbz(r0, 0, not_weak);    // Test for jweak tag.
-    // Resolve jweak.
-    __ ldr(r0, Address(r0, -JNIHandles::weak_tag_value));
-#if INCLUDE_ALL_GCS
-    if (UseG1GC) {
-      __ enter();                   // Barrier may call runtime.
-      __ g1_write_barrier_pre(noreg /* obj */,
-                              r0 /* pre_val */,
-                              rthread /* thread */,
-                              t /* tmp */,
-                              true /* tosca_live */,
-                              true /* expand_call */);
-      __ leave();
-    }
-#endif // INCLUDE_ALL_GCS
-    __ b(store_result);
-    __ bind(not_weak);
-    // Resolve (untagged) jobject.
-    __ ldr(r0, Address(r0, 0));
-    __ bind(store_result);
+    __ resolve_jobject(r0, rthread, t);
     __ str(r0, Address(rfp, frame::interpreter_frame_oop_temp_offset*wordSize));
     // keep stack depth as expected by pushing oop which will eventually be discarded
     __ push(ltos);
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/interp_masm.hpp"
@@ -142,76 +143,20 @@
 // Store an oop (or NULL) at the Address described by obj.
 // If val == noreg this means store a NULL
 static void do_oop_store(InterpreterMacroAssembler* _masm,
-                         Address obj,
+                         Address dst,
                          Register val,
-                         BarrierSet::Name barrier,
-                         bool precise) {
+                         DecoratorSet decorators) {
   assert(val == noreg || val == r0, "parameter is just for looks");
-  switch (barrier) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      {
-        // flatten object address if needed
-        if (obj.index() == noreg && obj.offset() == 0) {
-          if (obj.base() != r3) {
-            __ mov(r3, obj.base());
-          }
-        } else {
-          __ lea(r3, obj);
-        }
-        __ g1_write_barrier_pre(r3 /* obj */,
-                                r1 /* pre_val */,
-                                rthread /* thread */,
-                                r10  /* tmp */,
-                                val != noreg /* tosca_live */,
-                                false /* expand_call */);
-        if (val == noreg) {
-          __ store_heap_oop_null(Address(r3, 0));
-        } else {
-          // G1 barrier needs uncompressed oop for region cross check.
-          Register new_val = val;
-          if (UseCompressedOops) {
-            new_val = rscratch2;
-            __ mov(new_val, val);
-          }
-          __ store_heap_oop(Address(r3, 0), val);
-          __ g1_write_barrier_post(r3 /* store_adr */,
-                                   new_val /* new_val */,
-                                   rthread /* thread */,
-                                   r10 /* tmp */,
-                                   r1 /* tmp2 */);
-        }
-
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-      {
-        if (val == noreg) {
-          __ store_heap_oop_null(obj);
-        } else {
-          __ store_heap_oop(obj, val);
-          // flatten object address if needed
-          if (!precise || (obj.index() == noreg && obj.offset() == 0)) {
-            __ store_check(obj.base());
-          } else {
-            __ lea(r3, obj);
-            __ store_check(r3);
-          }
-        }
-      }
-      break;
-    case BarrierSet::ModRef:
-      if (val == noreg) {
-        __ store_heap_oop_null(obj);
-      } else {
-        __ store_heap_oop(obj, val);
-      }
-      break;
-    default      :
-      ShouldNotReachHere();
-
-  }
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->store_at(_masm, decorators, T_OBJECT, dst, val, /*tmp1*/ r10, /*tmp2*/ r1);
+}
+
+static void do_oop_load(InterpreterMacroAssembler* _masm,
+                        Address src,
+                        Register dst,
+                        DecoratorSet decorators) {
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(_masm, decorators, T_OBJECT, dst, src, /*tmp1*/ r10, /*tmp_thread*/ r1);
 }
 
 Address TemplateTable::at_bcp(int offset) {
@@ -865,7 +810,10 @@
   index_check(r0, r1); // leaves index in r1, kills rscratch1
   int s = (UseCompressedOops ? 2 : 3);
   __ lea(r1, Address(r0, r1, Address::uxtw(s)));
-  __ load_heap_oop(r0, Address(r1, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  do_oop_load(_masm,
+              Address(r1, arrayOopDesc::base_offset_in_bytes(T_OBJECT)),
+              r0,
+              IN_HEAP | IN_HEAP_ARRAY);
 }
 
 void TemplateTable::baload()
@@ -1193,7 +1141,7 @@
   // Get the value we will store
   __ ldr(r0, at_tos());
   // Now store using the appropriate barrier
-  do_oop_store(_masm, element_address, r0, _bs->kind(), true);
+  do_oop_store(_masm, element_address, r0, IN_HEAP | IN_HEAP_ARRAY);
   __ b(done);
 
   // Have a NULL in r0, r3=array, r2=index.  Store NULL at ary[idx]
@@ -1201,7 +1149,7 @@
   __ profile_null_seen(r2);
 
   // Store a NULL
-  do_oop_store(_masm, element_address, noreg, _bs->kind(), true);
+  do_oop_store(_masm, element_address, noreg, IN_HEAP | IN_HEAP_ARRAY);
 
   // Pop stack arguments
   __ bind(done);
@@ -2591,7 +2539,7 @@
   __ cmp(flags, atos);
   __ br(Assembler::NE, notObj);
   // atos
-  __ load_heap_oop(r0, field);
+  do_oop_load(_masm, field, r0, IN_HEAP);
   __ push(atos);
   if (rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_agetfield, bc, r1);
@@ -2834,7 +2782,7 @@
     __ pop(atos);
     if (!is_static) pop_and_check_object(obj);
     // Store into the field
-    do_oop_store(_masm, field, r0, _bs->kind(), false);
+    do_oop_store(_masm, field, r0, IN_HEAP);
     if (rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_aputfield, bc, r1, true, byte_no);
     }
@@ -3054,7 +3002,7 @@
   // access field
   switch (bytecode()) {
   case Bytecodes::_fast_aputfield:
-    do_oop_store(_masm, field, r0, _bs->kind(), false);
+    do_oop_store(_masm, field, r0, IN_HEAP);
     break;
   case Bytecodes::_fast_lputfield:
     __ str(r0, field);
@@ -3146,7 +3094,7 @@
   // access field
   switch (bytecode()) {
   case Bytecodes::_fast_agetfield:
-    __ load_heap_oop(r0, field);
+    do_oop_load(_masm, field, r0, IN_HEAP);
     __ verify_oop(r0);
     break;
   case Bytecodes::_fast_lgetfield:
@@ -3216,7 +3164,7 @@
     __ ldrw(r0, Address(r0, r1, Address::lsl(0)));
     break;
   case atos:
-    __ load_heap_oop(r0, Address(r0, r1, Address::lsl(0)));
+    do_oop_load(_masm, Address(r0, r1, Address::lsl(0)), r0, IN_HEAP);
     __ verify_oop(r0);
     break;
   case ftos:
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -203,7 +203,11 @@
     if (FLAG_IS_DEFAULT(UseSIMDForMemoryOps)) {
       FLAG_SET_DEFAULT(UseSIMDForMemoryOps, (_variant > 0));
     }
+    if (FLAG_IS_DEFAULT(UseSIMDForArrayEquals)) {
+      FLAG_SET_DEFAULT(UseSIMDForArrayEquals, false);
+    }
   }
+
   // ThunderX2
   if ((_cpu == CPU_CAVIUM && (_model == 0xAF)) ||
       (_cpu == CPU_BROADCOM && (_model == 0x516))) {
@@ -218,7 +222,25 @@
     }
   }
 
-  if (_cpu == CPU_ARM && (_model == 0xd03 || _model2 == 0xd03)) _features |= CPU_A53MAC;
+  // Cortex A53
+  if (_cpu == CPU_ARM && (_model == 0xd03 || _model2 == 0xd03)) {
+    _features |= CPU_A53MAC;
+    if (FLAG_IS_DEFAULT(UseSIMDForArrayEquals)) {
+      FLAG_SET_DEFAULT(UseSIMDForArrayEquals, false);
+    }
+  }
+
+  // Cortex A73
+  if (_cpu == CPU_ARM && (_model == 0xd09 || _model2 == 0xd09)) {
+    if (FLAG_IS_DEFAULT(SoftwarePrefetchHintDistance)) {
+      FLAG_SET_DEFAULT(SoftwarePrefetchHintDistance, -1);
+    }
+    // A73 is faster with short-and-easy-for-speculative-execution-loop
+    if (FLAG_IS_DEFAULT(UseSimpleArrayEquals)) {
+      FLAG_SET_DEFAULT(UseSimpleArrayEquals, true);
+    }
+  }
+
   if (_cpu == CPU_ARM && (_model == 0xd07 || _model2 == 0xd07)) _features |= CPU_STXR_PREFETCH;
   // If an olde style /proc/cpuinfo (cpu_lines == 1) then if _model is an A57 (0xd07)
   // we assume the worst and assume we could be on a big little system and have
--- a/src/hotspot/cpu/arm/assembler_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/assembler_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,7 +44,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
--- a/src/hotspot/cpu/arm/assembler_arm_32.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/assembler_arm_32.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,7 +44,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
--- a/src/hotspot/cpu/arm/assembler_arm_64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/assembler_arm_64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,7 +44,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
--- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -533,9 +533,11 @@
     set_card(tmp, card_addr);
     __ branch_destination(L_already_dirty->label());
   } else {
+#if INCLUDE_ALL_GCS
     if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
       __ membar_storestore();
     }
+#endif
     set_card(tmp, card_addr);
   }
 }
--- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -45,6 +45,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 // Note: Rtemp usage is this file should not impact C2 and should be
@@ -540,7 +541,7 @@
 
         __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ mov(R0, (int)id);
           __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), R0);
@@ -564,12 +565,9 @@
         const Register r_index_1    = R1;
         const Register r_buffer_2   = R2;
 
-        Address queue_active(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                               SATBMarkQueue::byte_offset_of_active()));
-        Address queue_index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                              SATBMarkQueue::byte_offset_of_index()));
-        Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                         SATBMarkQueue::byte_offset_of_buf()));
+        Address queue_active(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
+        Address queue_index(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
+        Address buffer(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
 
         Label done;
         Label runtime;
@@ -620,7 +618,7 @@
 
         __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ mov(R0, (int)id);
           __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), R0);
@@ -632,10 +630,8 @@
         Label recheck;
         Label runtime;
 
-        Address queue_index(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                              DirtyCardQueue::byte_offset_of_index()));
-        Address buffer(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                         DirtyCardQueue::byte_offset_of_buf()));
+        Address queue_index(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
+        Address buffer(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
 
         AddressLiteral cardtable(ci_card_table_address_as<address>(), relocInfo::none);
 
--- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,7 +28,6 @@
 #include "gc/g1/g1BarrierSetAssembler.hpp"
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/thread.hpp"
--- a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -35,6 +35,8 @@
                                   Register addr, Register count, int callee_saved_regs) {}
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, bool is_oop,
                                   Register addr, Register count, Register tmp) {}
+
+  virtual void barrier_stubs_init() {}
 };
 
 #endif // CPU_ARM_GC_SHARED_BARRIERSETASSEMBLER_ARM_HPP
--- a/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/gc/shared/cardTableBarrierSetAssembler_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,7 +44,7 @@
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                                     Register addr, Register count, Register tmp) {
   BLOCK_COMMENT("CardTablePostBarrier");
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
--- a/src/hotspot/cpu/arm/interp_masm_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/interp_masm_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -45,7 +45,6 @@
 
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
@@ -411,7 +410,7 @@
 // Sets card_table_base register.
 void InterpreterMacroAssembler::store_check_part1(Register card_table_base) {
   // Check barrier set type (should be card table) and element size
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   assert(bs->kind() == BarrierSet::CardTableBarrierSet,
          "Wrong barrier set kind");
 
@@ -451,9 +450,11 @@
 #endif
 
   if (UseCondCardMark) {
+#if INCLUDE_ALL_GCS
     if (UseConcMarkSweepGC) {
       membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), noreg);
     }
+#endif
     Label already_dirty;
 
     ldrb(tmp, card_table_addr);
@@ -463,9 +464,11 @@
     bind(already_dirty);
 
   } else {
+#if INCLUDE_ALL_GCS
     if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
       membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreStore), noreg);
     }
+#endif
     set_card(card_table_base, card_table_addr, tmp);
   }
 }
@@ -474,7 +477,7 @@
 #ifdef AARCH64
   strb(ZR, card_table_addr);
 #else
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
   if ((((uintptr_t)ct->byte_map_base() & 0xff) == 0)) {
     // Card table is aligned so the lowest byte of the table address base is zero.
--- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,6 +29,7 @@
 #include "ci/ciEnv.hpp"
 #include "code/nativeInst.hpp"
 #include "compiler/disassembler.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
@@ -46,7 +47,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif
 
@@ -2175,12 +2176,9 @@
     assert_different_registers(pre_val, tmp1, tmp2, noreg);
   }
 
-  Address in_progress(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                        SATBMarkQueue::byte_offset_of_active()));
-  Address index(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                  SATBMarkQueue::byte_offset_of_index()));
-  Address buffer(Rthread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                   SATBMarkQueue::byte_offset_of_buf()));
+  Address in_progress(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
+  Address index(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
+  Address buffer(Rthread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
 
   // Is marking active?
   assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "adjust this code");
@@ -2261,12 +2259,10 @@
                                            Register tmp2,
                                            Register tmp3) {
 
-  Address queue_index(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                        DirtyCardQueue::byte_offset_of_index()));
-  Address buffer(Rthread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                   DirtyCardQueue::byte_offset_of_buf()));
-
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  Address queue_index(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
+  Address buffer(Rthread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
+
+  BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
   Label done;
--- a/src/hotspot/cpu/ppc/assembler_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/assembler_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -39,7 +39,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
--- a/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/assembler_ppc.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -620,7 +620,7 @@
 inline void Assembler::stqcx_(Register s, Register a, Register b)                             { emit_int32( STQCX_OPCODE | rs(s) | ra0mem(a) | rb(b) | rc(1)); }
 
 // Instructions for adjusting thread priority
-// for simultaneous multithreading (SMT) on POWER5.
+// for simultaneous multithreading (SMT) on >= POWER5.
 inline void Assembler::smt_prio_very_low()    { Assembler::or_unchecked(R31, R31, R31); }
 inline void Assembler::smt_prio_low()         { Assembler::or_unchecked(R1,  R1,  R1); }
 inline void Assembler::smt_prio_medium_low()  { Assembler::or_unchecked(R6,  R6,  R6); }
@@ -628,11 +628,11 @@
 inline void Assembler::smt_prio_medium_high() { Assembler::or_unchecked(R5,  R5,  R5); }
 inline void Assembler::smt_prio_high()        { Assembler::or_unchecked(R3,  R3,  R3); }
 // >= Power7
-inline void Assembler::smt_yield()            { Assembler::or_unchecked(R27, R27, R27); }
-inline void Assembler::smt_mdoio()            { Assembler::or_unchecked(R29, R29, R29); }
-inline void Assembler::smt_mdoom()            { Assembler::or_unchecked(R30, R30, R30); }
-// >= Power8
-inline void Assembler::smt_miso()             { Assembler::or_unchecked(R26, R26, R26); }
+inline void Assembler::smt_yield()            { Assembler::or_unchecked(R27, R27, R27); } // never actually implemented
+inline void Assembler::smt_mdoio()            { Assembler::or_unchecked(R29, R29, R29); } // never actually implemetned
+inline void Assembler::smt_mdoom()            { Assembler::or_unchecked(R30, R30, R30); } // never actually implemented
+// Power8
+inline void Assembler::smt_miso()             { Assembler::or_unchecked(R26, R26, R26); } // never actually implemented
 
 inline void Assembler::twi_0(Register a)      { twi_unchecked(0, a, 0);}
 
--- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -45,6 +45,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 // Implementation of StubAssembler
@@ -710,7 +711,7 @@
 #if INCLUDE_ALL_GCS
     case g1_pre_barrier_slow_id:
       {
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           goto unimplemented_entry;
         }
@@ -724,15 +725,9 @@
         Register tmp2 = R15;
 
         Label refill, restart, marking_not_active;
-        int satb_q_active_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_active());
-        int satb_q_index_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_index());
-        int satb_q_buf_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_buf());
+        int satb_q_active_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
+        int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
+        int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
 
         // Spill
         __ std(tmp, -16, R1_SP);
@@ -787,7 +782,7 @@
 
   case g1_post_barrier_slow_id:
     {
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           goto unimplemented_entry;
         }
@@ -829,12 +824,8 @@
         __ li(tmp, G1CardTable::dirty_card_val());
         __ stb(tmp, 0, addr);
 
-        int dirty_card_q_index_byte_offset =
-          in_bytes(JavaThread::dirty_card_queue_offset() +
-                   DirtyCardQueue::byte_offset_of_index());
-        int dirty_card_q_buf_byte_offset =
-          in_bytes(JavaThread::dirty_card_queue_offset() +
-                   DirtyCardQueue::byte_offset_of_buf());
+        int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
+        int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 
         __ bind(restart);
 
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,10 +28,10 @@
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "runtime/thread.hpp"
 #include "interpreter/interp_masm.hpp"
+#include "runtime/sharedRuntime.hpp"
 
 #define __ masm->
 
@@ -49,10 +49,10 @@
 
     // Is marking active?
     if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-      __ lwz(R0, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
+      __ lwz(R0, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread);
     } else {
       guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-      __ lbz(R0, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
+      __ lbz(R0, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread);
     }
     __ cmpdi(CCR0, R0, 0);
     __ beq(CCR0, filtered);
@@ -98,3 +98,245 @@
   __ addi(R1_SP, R1_SP, frame_size); // pop_frame();
   __ restore_LR_CR(R0);
 }
+
+void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, DecoratorSet decorators, Register obj, RegisterOrConstant ind_or_offs, Register pre_val,
+                                                 Register tmp1, Register tmp2, bool needs_frame) {
+  bool not_null  = (decorators & OOP_NOT_NULL) != 0,
+       preloaded = obj == noreg;
+  Register nv_save = noreg;
+
+  if (preloaded) {
+    // We are not loading the previous value so make
+    // sure that we don't trash the value in pre_val
+    // with the code below.
+    assert_different_registers(pre_val, tmp1, tmp2);
+    if (pre_val->is_volatile()) {
+      nv_save = !tmp1->is_volatile() ? tmp1 : tmp2;
+      assert(!nv_save->is_volatile(), "need one nv temp register if pre_val lives in volatile register");
+    }
+  }
+
+  Label runtime, filtered;
+
+  // Is marking active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ lwz(tmp1, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread);
+  } else {
+    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ lbz(tmp1, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread);
+  }
+  __ cmpdi(CCR0, tmp1, 0);
+  __ beq(CCR0, filtered);
+
+  // Do we need to load the previous value?
+  if (!preloaded) {
+    // Load the previous value...
+    if (UseCompressedOops) {
+      __ lwz(pre_val, ind_or_offs, obj);
+    } else {
+      __ ld(pre_val, ind_or_offs, obj);
+    }
+    // Previous value has been loaded into Rpre_val.
+  }
+  assert(pre_val != noreg, "must have a real register");
+
+  // Is the previous value null?
+  if (preloaded && not_null) {
+#ifdef ASSERT
+    __ cmpdi(CCR0, pre_val, 0);
+    __ asm_assert_ne("null oop not allowed (G1 pre)", 0x321); // Checked by caller.
+#endif
+  } else {
+    __ cmpdi(CCR0, pre_val, 0);
+    __ beq(CCR0, filtered);
+  }
+
+  if (!preloaded && UseCompressedOops) {
+    __ decode_heap_oop_not_null(pre_val);
+  }
+
+  // OK, it's not filtered, so we'll need to call enqueue. In the normal
+  // case, pre_val will be a scratch G-reg, but there are some cases in
+  // which it's an O-reg. In the first case, do a normal call. In the
+  // latter, do a save here and call the frameless version.
+
+  // Can we store original value in the thread's buffer?
+  // Is index == 0?
+  // (The index field is typed as size_t.)
+  const Register Rbuffer = tmp1, Rindex = tmp2;
+
+  __ ld(Rindex, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()), R16_thread);
+  __ cmpdi(CCR0, Rindex, 0);
+  __ beq(CCR0, runtime); // If index == 0, goto runtime.
+  __ ld(Rbuffer, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()), R16_thread);
+
+  __ addi(Rindex, Rindex, -wordSize); // Decrement index.
+  __ std(Rindex, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()), R16_thread);
+
+  // Record the previous value.
+  __ stdx(pre_val, Rbuffer, Rindex);
+  __ b(filtered);
+
+  __ bind(runtime);
+
+  // May need to preserve LR. Also needed if current frame is not compatible with C calling convention.
+  if (needs_frame) {
+    __ save_LR_CR(tmp1);
+    __ push_frame_reg_args(0, tmp2);
+  }
+
+  if (pre_val->is_volatile() && preloaded) { __ mr(nv_save, pre_val); } // Save pre_val across C call if it was preloaded.
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, R16_thread);
+  if (pre_val->is_volatile() && preloaded) { __ mr(pre_val, nv_save); } // restore
+
+  if (needs_frame) {
+    __ pop_frame();
+    __ restore_LR_CR(tmp1);
+  }
+
+  __ bind(filtered);
+}
+
+void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register store_addr, Register new_val,
+                                                  Register tmp1, Register tmp2, Register tmp3) {
+  bool not_null = (decorators & OOP_NOT_NULL) != 0;
+
+  Label runtime, filtered;
+  assert_different_registers(store_addr, new_val, tmp1, tmp2);
+
+  CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
+  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  // Does store cross heap regions?
+  if (G1RSBarrierRegionFilter) {
+    __ xorr(tmp1, store_addr, new_val);
+    __ srdi_(tmp1, tmp1, HeapRegion::LogOfHRGrainBytes);
+    __ beq(CCR0, filtered);
+  }
+
+  // Crosses regions, storing NULL?
+  if (not_null) {
+#ifdef ASSERT
+    __ cmpdi(CCR0, new_val, 0);
+    __ asm_assert_ne("null oop not allowed (G1 post)", 0x322); // Checked by caller.
+#endif
+  } else {
+    __ cmpdi(CCR0, new_val, 0);
+    __ beq(CCR0, filtered);
+  }
+
+  // Storing region crossing non-NULL, is card already dirty?
+  const Register Rcard_addr = tmp1;
+  Register Rbase = tmp2;
+  __ load_const_optimized(Rbase, (address)(ct->card_table()->byte_map_base()), /*temp*/ tmp3);
+
+  __ srdi(Rcard_addr, store_addr, CardTable::card_shift);
+
+  // Get the address of the card.
+  __ lbzx(/*card value*/ tmp3, Rbase, Rcard_addr);
+  __ cmpwi(CCR0, tmp3, (int)G1CardTable::g1_young_card_val());
+  __ beq(CCR0, filtered);
+
+  __ membar(Assembler::StoreLoad);
+  __ lbzx(/*card value*/ tmp3, Rbase, Rcard_addr);  // Reload after membar.
+  __ cmpwi(CCR0, tmp3 /* card value */, (int)G1CardTable::dirty_card_val());
+  __ beq(CCR0, filtered);
+
+  // Storing a region crossing, non-NULL oop, card is clean.
+  // Dirty card and log.
+  __ li(tmp3, (int)G1CardTable::dirty_card_val());
+  //release(); // G1: oops are allowed to get visible after dirty marking.
+  __ stbx(tmp3, Rbase, Rcard_addr);
+
+  __ add(Rcard_addr, Rbase, Rcard_addr); // This is the address which needs to get enqueued.
+  Rbase = noreg; // end of lifetime
+
+  const Register Rqueue_index = tmp2,
+                 Rqueue_buf   = tmp3;
+  __ ld(Rqueue_index, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()), R16_thread);
+  __ cmpdi(CCR0, Rqueue_index, 0);
+  __ beq(CCR0, runtime); // index == 0 then jump to runtime
+  __ ld(Rqueue_buf, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()), R16_thread);
+
+  __ addi(Rqueue_index, Rqueue_index, -wordSize); // decrement index
+  __ std(Rqueue_index, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()), R16_thread);
+
+  __ stdx(Rcard_addr, Rqueue_buf, Rqueue_index); // store card
+  __ b(filtered);
+
+  __ bind(runtime);
+
+  // Save the live input values.
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, R16_thread);
+
+  __ bind(filtered);
+}
+
+void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                       Register base, RegisterOrConstant ind_or_offs, Register val,
+                                       Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+  // Load and record the previous value.
+  g1_write_barrier_pre(masm, decorators, base, ind_or_offs,
+                       tmp1, tmp2, tmp3, needs_frame);
+
+  BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
+
+  // No need for post barrier if storing NULL
+  if (val != noreg) {
+    if (precise) {
+      if (ind_or_offs.is_constant()) {
+        __ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp1);
+      } else {
+        __ add(base, ind_or_offs.as_register(), base);
+      }
+    }
+    g1_write_barrier_post(masm, decorators, base, val, tmp1, tmp2, tmp3);
+  }
+}
+
+void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                    Register base, RegisterOrConstant ind_or_offs, Register dst,
+                                    Register tmp1, Register tmp2, bool needs_frame, Label *is_null) {
+  bool on_oop = type == T_OBJECT || type == T_ARRAY;
+  bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
+  bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+  bool on_reference = on_weak || on_phantom;
+  Label done;
+  if (on_oop && on_reference && is_null == NULL) { is_null = &done; }
+  // Load the value of the referent field.
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, base, ind_or_offs, dst, tmp1, tmp2, needs_frame, is_null);
+  if (on_oop && on_reference) {
+    // Generate the G1 pre-barrier code to log the value of
+    // the referent field in an SATB buffer. Note with
+    // these parameters the pre-barrier does not generate
+    // the load of the previous value
+    // We only reach here if value is not null.
+    g1_write_barrier_pre(masm, decorators | OOP_NOT_NULL, noreg /* obj */, (intptr_t)0, dst /* pre_val */,
+                         tmp1, tmp2, needs_frame);
+  }
+  __ bind(done);
+}
+
+void G1BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2, bool needs_frame) {
+  Label done, not_weak;
+  __ cmpdi(CCR0, value, 0);
+  __ beq(CCR0, done);         // Use NULL as-is.
+
+  __ clrrdi(tmp1, value, JNIHandles::weak_tag_size);
+  __ andi_(tmp2, value, JNIHandles::weak_tag_mask);
+  __ ld(value, 0, tmp1);      // Resolve (untagged) jobject.
+
+  __ beq(CCR0, not_weak);     // Test for jweak tag.
+  __ verify_oop(value);
+  g1_write_barrier_pre(masm, IN_ROOT | ON_PHANTOM_OOP_REF,
+                       noreg, noreg, value,
+                       tmp1, tmp2, needs_frame);
+  __ bind(not_weak);
+  __ verify_oop(value);
+  __ bind(done);
+}
+
+#undef __
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -34,6 +34,22 @@
   virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register from, Register to, Register count,
                                                Register preserve1, Register preserve2);
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register preserve);
+
+  void g1_write_barrier_pre(MacroAssembler* masm, DecoratorSet decorators, Register obj, RegisterOrConstant ind_or_offs, Register pre_val,
+                            Register tmp1, Register tmp2, bool needs_frame);
+  void g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register store_addr, Register new_val,
+                             Register tmp1, Register tmp2, Register tmp3);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Register base, RegisterOrConstant ind_or_offs, Register val,
+                            Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
+
+public:
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Register base, RegisterOrConstant ind_or_offs, Register dst,
+                       Register tmp1, Register tmp2, bool needs_frame, Label *is_null = NULL);
+
+  virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2, bool needs_frame);
 };
 
 #endif // CPU_PPC_GC_G1_G1BARRIERSETASSEMBLER_PPC_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, SAP SE. All rights reserved.
+ * 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 "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                   Register base, RegisterOrConstant ind_or_offs, Register val,
+                                   Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
+  bool on_heap  = (decorators & IN_HEAP) != 0;
+  bool on_root  = (decorators & IN_ROOT) != 0;
+  bool not_null = (decorators & OOP_NOT_NULL) != 0;
+  assert(on_heap || on_root, "where?");
+  assert_different_registers(base, val, tmp1, tmp2, R0);
+
+  switch (type) {
+  case T_ARRAY:
+  case T_OBJECT: {
+    if (UseCompressedOops && on_heap) {
+      Register co = tmp1;
+      if (val == noreg) {
+        __ li(co, 0);
+      } else {
+        co = not_null ? __ encode_heap_oop_not_null(tmp1, val) : __ encode_heap_oop(tmp1, val);
+      }
+      __ stw(co, ind_or_offs, base, tmp2);
+    } else {
+      if (val == noreg) {
+        val = tmp1;
+        __ li(val, 0);
+      }
+      __ std(val, ind_or_offs, base, tmp2);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                  Register base, RegisterOrConstant ind_or_offs, Register dst,
+                                  Register tmp1, Register tmp2, bool needs_frame, Label *is_null) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  assert(on_heap || on_root, "where?");
+  assert_different_registers(ind_or_offs.register_or_noreg(), dst, R0);
+
+  switch (type) {
+  case T_ARRAY:
+  case T_OBJECT: {
+    if (UseCompressedOops && on_heap) {
+      __ lwz(dst, ind_or_offs, base);
+      if (is_null) {
+        __ cmpwi(CCR0, dst, 0);
+        __ beq(CCR0, *is_null);
+        __ decode_heap_oop_not_null(dst);
+      } else {
+        __ decode_heap_oop(dst);
+      }
+    } else {
+      __ ld(dst, ind_or_offs, base);
+      if (is_null) {
+        __ cmpdi(CCR0, dst, 0);
+        __ beq(CCR0, *is_null);
+      }
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value,
+                                          Register tmp1, Register tmp2, bool needs_frame) {
+  Label done;
+  __ cmpdi(CCR0, value, 0);
+  __ beq(CCR0, done);         // Use NULL as-is.
+
+  __ clrrdi(tmp1, value, JNIHandles::weak_tag_size);
+  __ ld(value, 0, tmp1);      // Resolve (untagged) jobject.
+
+  __ verify_oop(value);
+  __ bind(done);
+}
--- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -38,6 +38,18 @@
                                   Register src, Register dst, Register count, Register preserve1, Register preserve2) {}
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register dst, Register count, Register preserve) {}
+
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Register base, RegisterOrConstant ind_or_offs, Register val,
+                        Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
+
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Register base, RegisterOrConstant ind_or_offs, Register dst,
+                       Register tmp1, Register tmp2, bool needs_frame, Label *is_null = NULL);
+
+  virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2, bool needs_frame);
+
+  virtual void barrier_stubs_init() {}
 };
 
 #endif // CPU_PPC_GC_SHARED_BARRIERSETASSEMBLER_PPC_HPP
--- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,7 +29,6 @@
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 
 #define __ masm->
@@ -44,7 +43,7 @@
 
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr,
                                                                     Register count, Register preserve) {
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
   assert_different_registers(addr, count, R0);
@@ -72,3 +71,41 @@
   __ bdnz(Lstore_loop);
   __ bind(Lskip_loop);
 }
+
+void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm,
+                                                    jbyte* byte_map_base,
+                                                    Register tmp, Register obj) {
+  assert_different_registers(obj, tmp, R0);
+  __ load_const_optimized(tmp, (address)byte_map_base, R0);
+  __ srdi(obj, obj, CardTable::card_shift);
+  __ li(R0, CardTable::dirty_card_val());
+  if (UseConcMarkSweepGC) { __ membar(Assembler::StoreStore); }
+  __ stbx(R0, tmp, obj);
+}
+
+void CardTableBarrierSetAssembler::card_write_barrier_post(MacroAssembler* masm, Register store_addr, Register tmp) {
+  CardTableBarrierSet* bs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
+  card_table_write(masm, bs->card_table()->byte_map_base(), tmp, store_addr);
+}
+
+void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                                Register base, RegisterOrConstant ind_or_offs, Register val,
+                                                Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+
+  BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
+
+  // No need for post barrier if storing NULL
+  if (val != noreg) {
+    if (precise) {
+      if (ind_or_offs.is_constant()) {
+        __ add_const_optimized(base, base, ind_or_offs.as_constant(), tmp1);
+      } else {
+        __ add(base, ind_or_offs.as_register(), base);
+      }
+    }
+    card_write_barrier_post(masm, base, tmp1);
+  }
+}
--- a/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/shared/cardTableBarrierSetAssembler_ppc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,8 +31,16 @@
 
 class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr,
-                                                Register count, Register preserve);
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+                                                Register addr, Register count, Register preserve);
+
+  void card_table_write(MacroAssembler* masm, jbyte* byte_map_base, Register tmp, Register obj);
+
+  void card_write_barrier_post(MacroAssembler* masm, Register store_addr, Register tmp);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Register base, RegisterOrConstant ind_or_offs, Register val,
+                            Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
 };
 
 #endif // CPU_PPC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_PPC_HPP
--- a/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -55,3 +55,19 @@
     }
   }
 }
+
+void ModRefBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                             Register base, RegisterOrConstant ind_or_offs, Register val,
+                                             Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
+  BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
+}
+
+void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Register base, RegisterOrConstant ind_or_offs, Register val,
+                                         Register tmp1, Register tmp2, Register tmp3, bool needs_frame) {
+  if (type == T_OBJECT || type == T_ARRAY) {
+    oop_store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
+  } else {
+    BarrierSetAssembler::store_at(masm, decorators, type, base, ind_or_offs, val, tmp1, tmp2, tmp3, needs_frame);
+  }
+}
--- a/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/shared/modRefBarrierSetAssembler_ppc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,17 +29,28 @@
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 
+// The ModRefBarrierSetAssembler filters away accesses on BasicTypes other
+// than T_OBJECT/T_ARRAY (oops). The oop accesses call one of the protected
+// accesses, which are overridden in the concrete BarrierSetAssembler.
+
 class ModRefBarrierSetAssembler: public BarrierSetAssembler {
 protected:
   virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register from, Register to, Register count,
                                                Register preserve1, Register preserve2) {}
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register preserve) {}
 
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Register base, RegisterOrConstant ind_or_offs, Register val,
+                            Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count, Register preserve1, Register preserve2);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register dst, Register count, Register preserve);
+
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Register base, RegisterOrConstant ind_or_offs, Register val,
+                        Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
 };
 
 #endif // CPU_PPC_GC_SHARED_MODREFBARRIERSETASSEMBLER_PPC_HPP
--- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interp_masm_ppc.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "prims/jvmtiThreadState.hpp"
@@ -492,9 +494,8 @@
 #endif
   // Add in the index.
   add(result, tmp, result);
-  load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, is_null);
-  // The resulting oop is null if the reference is not yet resolved.
-  // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(this, IN_HEAP, T_OBJECT, result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, tmp, R0, false, is_null);
 }
 
 // load cpool->resolved_klass_at(index)
@@ -2446,4 +2447,3 @@
 
   // Dtrace support not implemented.
 }
-
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,9 +26,9 @@
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "compiler/disassembler.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/resourceArea.hpp"
 #include "nativeInst_ppc.hpp"
@@ -43,12 +43,6 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/heapRegion.hpp"
-#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER2
 #include "opto/intrinsicnode.hpp"
 #endif
@@ -2579,7 +2573,6 @@
   if (checkRetry) { bind(*checkRetry); }
   addic_(retry_count_Reg, retry_count_Reg, -1);
   blt(CCR0, doneRetry);
-  smt_yield(); // Can't use wait(). No permission (SIGILL).
   b(retryLabel);
   bind(doneRetry);
 }
@@ -2590,7 +2583,7 @@
 // output: retry_count_Reg decremented by 1
 // CTR is killed
 void MacroAssembler::rtm_retry_lock_on_busy(Register retry_count_Reg, Register owner_addr_Reg, Label& retryLabel) {
-  Label SpinLoop, doneRetry;
+  Label SpinLoop, doneRetry, doRetry;
   addic_(retry_count_Reg, retry_count_Reg, -1);
   blt(CCR0, doneRetry);
 
@@ -2599,16 +2592,26 @@
     mtctr(R0);
   }
 
+  // low thread priority
+  smt_prio_low();
   bind(SpinLoop);
-  smt_yield(); // Can't use waitrsv(). No permission (SIGILL).
 
   if (RTMSpinLoopCount > 1) {
-    bdz(retryLabel);
+    bdz(doRetry);
     ld(R0, 0, owner_addr_Reg);
     cmpdi(CCR0, R0, 0);
     bne(CCR0, SpinLoop);
   }
 
+  bind(doRetry);
+
+  // restore thread priority to default in userspace
+#ifdef LINUX
+  smt_prio_medium_low();
+#else
+  smt_prio_medium();
+#endif
+
   b(retryLabel);
 
   bind(doneRetry);
@@ -3031,213 +3034,11 @@
   bne(CCR0, slow_path);
 }
 
-
-// GC barrier helper macros
-
-// Write the card table byte if needed.
-void MacroAssembler::card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp) {
-  CardTableBarrierSet* bs =
-    barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
-  assert(bs->kind() == BarrierSet::CardTableBarrierSet, "wrong barrier");
-  CardTable* ct = bs->card_table();
-#ifdef ASSERT
-  cmpdi(CCR0, Rnew_val, 0);
-  asm_assert_ne("null oop not allowed", 0x321);
-#endif
-  card_table_write(ct->byte_map_base(), Rtmp, Rstore_addr);
-}
-
-// Write the card table byte.
-void MacroAssembler::card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj) {
-  assert_different_registers(Robj, Rtmp, R0);
-  load_const_optimized(Rtmp, (address)byte_map_base, R0);
-  srdi(Robj, Robj, CardTable::card_shift);
-  li(R0, 0); // dirty
-  if (UseConcMarkSweepGC) membar(Assembler::StoreStore);
-  stbx(R0, Rtmp, Robj);
-}
-
-// Kills R31 if value is a volatile register.
 void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2, bool needs_frame) {
-  Label done;
-  cmpdi(CCR0, value, 0);
-  beq(CCR0, done);         // Use NULL as-is.
-
-  clrrdi(tmp1, value, JNIHandles::weak_tag_size);
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) { andi_(tmp2, value, JNIHandles::weak_tag_mask); }
-#endif
-  ld(value, 0, tmp1);      // Resolve (untagged) jobject.
-
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) {
-    Label not_weak;
-    beq(CCR0, not_weak);   // Test for jweak tag.
-    verify_oop(value);
-    g1_write_barrier_pre(noreg, // obj
-                         noreg, // offset
-                         value, // pre_val
-                         tmp1, tmp2, needs_frame);
-    bind(not_weak);
-  }
-#endif // INCLUDE_ALL_GCS
-  verify_oop(value);
-  bind(done);
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->resolve_jobject(this, value, tmp1, tmp2, needs_frame);
 }
 
-#if INCLUDE_ALL_GCS
-// General G1 pre-barrier generator.
-// Goal: record the previous value if it is not null.
-void MacroAssembler::g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
-                                          Register Rtmp1, Register Rtmp2, bool needs_frame) {
-  Label runtime, filtered;
-
-  // Is marking active?
-  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    lwz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
-  } else {
-    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-    lbz(Rtmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
-  }
-  cmpdi(CCR0, Rtmp1, 0);
-  beq(CCR0, filtered);
-
-  // Do we need to load the previous value?
-  if (Robj != noreg) {
-    // Load the previous value...
-    if (UseCompressedOops) {
-      lwz(Rpre_val, offset, Robj);
-    } else {
-      ld(Rpre_val, offset, Robj);
-    }
-    // Previous value has been loaded into Rpre_val.
-  }
-  assert(Rpre_val != noreg, "must have a real register");
-
-  // Is the previous value null?
-  cmpdi(CCR0, Rpre_val, 0);
-  beq(CCR0, filtered);
-
-  if (Robj != noreg && UseCompressedOops) {
-    decode_heap_oop_not_null(Rpre_val);
-  }
-
-  // OK, it's not filtered, so we'll need to call enqueue. In the normal
-  // case, pre_val will be a scratch G-reg, but there are some cases in
-  // which it's an O-reg. In the first case, do a normal call. In the
-  // latter, do a save here and call the frameless version.
-
-  // Can we store original value in the thread's buffer?
-  // Is index == 0?
-  // (The index field is typed as size_t.)
-  const Register Rbuffer = Rtmp1, Rindex = Rtmp2;
-
-  ld(Rindex, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index()), R16_thread);
-  cmpdi(CCR0, Rindex, 0);
-  beq(CCR0, runtime); // If index == 0, goto runtime.
-  ld(Rbuffer, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf()), R16_thread);
-
-  addi(Rindex, Rindex, -wordSize); // Decrement index.
-  std(Rindex, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index()), R16_thread);
-
-  // Record the previous value.
-  stdx(Rpre_val, Rbuffer, Rindex);
-  b(filtered);
-
-  bind(runtime);
-
-  // May need to preserve LR. Also needed if current frame is not compatible with C calling convention.
-  if (needs_frame) {
-    save_LR_CR(Rtmp1);
-    push_frame_reg_args(0, Rtmp2);
-  }
-
-  if (Rpre_val->is_volatile() && Robj == noreg) mr(R31, Rpre_val); // Save pre_val across C call if it was preloaded.
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_val, R16_thread);
-  if (Rpre_val->is_volatile() && Robj == noreg) mr(Rpre_val, R31); // restore
-
-  if (needs_frame) {
-    pop_frame();
-    restore_LR_CR(Rtmp1);
-  }
-
-  bind(filtered);
-}
-
-// General G1 post-barrier generator
-// Store cross-region card.
-void MacroAssembler::g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1, Register Rtmp2, Register Rtmp3, Label *filtered_ext) {
-  Label runtime, filtered_int;
-  Label& filtered = (filtered_ext != NULL) ? *filtered_ext : filtered_int;
-  assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2);
-
-  G1BarrierSet* bs =
-    barrier_set_cast<G1BarrierSet>(Universe::heap()->barrier_set());
-  CardTable* ct = bs->card_table();
-
-  // Does store cross heap regions?
-  if (G1RSBarrierRegionFilter) {
-    xorr(Rtmp1, Rstore_addr, Rnew_val);
-    srdi_(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes);
-    beq(CCR0, filtered);
-  }
-
-  // Crosses regions, storing NULL?
-#ifdef ASSERT
-  cmpdi(CCR0, Rnew_val, 0);
-  asm_assert_ne("null oop not allowed (G1)", 0x322); // Checked by caller on PPC64, so following branch is obsolete:
-  //beq(CCR0, filtered);
-#endif
-
-  // Storing region crossing non-NULL, is card already dirty?
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-  const Register Rcard_addr = Rtmp1;
-  Register Rbase = Rtmp2;
-  load_const_optimized(Rbase, (address)ct->byte_map_base(), /*temp*/ Rtmp3);
-
-  srdi(Rcard_addr, Rstore_addr, CardTable::card_shift);
-
-  // Get the address of the card.
-  lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr);
-  cmpwi(CCR0, Rtmp3, (int)G1CardTable::g1_young_card_val());
-  beq(CCR0, filtered);
-
-  membar(Assembler::StoreLoad);
-  lbzx(/*card value*/ Rtmp3, Rbase, Rcard_addr);  // Reload after membar.
-  cmpwi(CCR0, Rtmp3 /* card value */, CardTable::dirty_card_val());
-  beq(CCR0, filtered);
-
-  // Storing a region crossing, non-NULL oop, card is clean.
-  // Dirty card and log.
-  li(Rtmp3, CardTable::dirty_card_val());
-  //release(); // G1: oops are allowed to get visible after dirty marking.
-  stbx(Rtmp3, Rbase, Rcard_addr);
-
-  add(Rcard_addr, Rbase, Rcard_addr); // This is the address which needs to get enqueued.
-  Rbase = noreg; // end of lifetime
-
-  const Register Rqueue_index = Rtmp2,
-                 Rqueue_buf   = Rtmp3;
-  ld(Rqueue_index, in_bytes(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index()), R16_thread);
-  cmpdi(CCR0, Rqueue_index, 0);
-  beq(CCR0, runtime); // index == 0 then jump to runtime
-  ld(Rqueue_buf, in_bytes(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_buf()), R16_thread);
-
-  addi(Rqueue_index, Rqueue_index, -wordSize); // decrement index
-  std(Rqueue_index, in_bytes(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index()), R16_thread);
-
-  stdx(Rcard_addr, Rqueue_buf, Rqueue_index); // store card
-  b(filtered);
-
-  bind(runtime);
-
-  // Save the live input values.
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, R16_thread);
-
-  bind(filtered_int);
-}
-#endif // INCLUDE_ALL_GCS
-
 // Values for last_Java_pc, and last_Java_sp must comply to the rules
 // in frame_ppc.hpp.
 void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc) {
--- a/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -650,21 +650,8 @@
   // Check if safepoint requested and if so branch
   void safepoint_poll(Label& slow_path, Register temp_reg);
 
-  // GC barrier support.
-  void card_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp);
-  void card_table_write(jbyte* byte_map_base, Register Rtmp, Register Robj);
-
   void resolve_jobject(Register value, Register tmp1, Register tmp2, bool needs_frame);
 
-#if INCLUDE_ALL_GCS
-  // General G1 pre-barrier generator.
-  void g1_write_barrier_pre(Register Robj, RegisterOrConstant offset, Register Rpre_val,
-                            Register Rtmp1, Register Rtmp2, bool needs_frame = false);
-  // General G1 post-barrier generator
-  void g1_write_barrier_post(Register Rstore_addr, Register Rnew_val, Register Rtmp1,
-                             Register Rtmp2, Register Rtmp3, Label *filtered_ext = NULL);
-#endif
-
   // Support for managing the JavaThread pointer (i.e.; the reference to
   // thread-local information).
 
--- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -2495,7 +2495,7 @@
   // --------------------------------------------------------------------------
 
   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
-    __ resolve_jobject(R3_RET, r_temp_1, r_temp_2, /* needs_frame */ false); // kills R31
+    __ resolve_jobject(R3_RET, r_temp_1, r_temp_2, /* needs_frame */ false);
   }
 
   if (CheckJNICalls) {
--- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -2032,7 +2032,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, R3_ARG1, R4_ARG2, R5_ARG3, noreg, noreg);
 
     if (UseCompressedOops) {
@@ -2071,7 +2071,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, R3_ARG1, R4_ARG2, R5_ARG3, noreg, noreg);
 
     if (UseCompressedOops) {
@@ -2164,7 +2164,7 @@
       decorators |= AS_DEST_NOT_INITIALIZED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, R3_from, R4_to, R5_count, /* preserve: */ R6_ckoff, R7_ckval);
 
     //inc_counter_np(SharedRuntime::_checkcast_array_copy_ctr, R12_tmp, R3_RET);
--- a/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/templateInterpreterGenerator_ppc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015, 2017, SAP SE. All rights reserved.
+ * Copyright (c) 2015, 2018, SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
@@ -402,7 +403,7 @@
      break;
   case T_OBJECT:
     // JNIHandles::resolve result.
-    __ resolve_jobject(R3_RET, R11_scratch1, R12_scratch2, /* needs_frame */ true); // kills R31
+    __ resolve_jobject(R3_RET, R11_scratch1, R31, /* needs_frame */ true); // kills R31
     break;
   case T_FLOAT:
      break;
@@ -504,59 +505,50 @@
   //   regular method entry code to generate the NPE.
   //
 
-  if (UseG1GC) {
-    address entry = __ pc();
+  address entry = __ pc();
 
-    const int referent_offset = java_lang_ref_Reference::referent_offset;
-    guarantee(referent_offset > 0, "referent offset not initialized");
+  const int referent_offset = java_lang_ref_Reference::referent_offset;
+  guarantee(referent_offset > 0, "referent offset not initialized");
 
-    Label slow_path;
+  Label slow_path;
 
-    // Debugging not possible, so can't use __ skip_if_jvmti_mode(slow_path, GR31_SCRATCH);
+  // Debugging not possible, so can't use __ skip_if_jvmti_mode(slow_path, GR31_SCRATCH);
 
-    // In the G1 code we don't check if we need to reach a safepoint. We
-    // continue and the thread will safepoint at the next bytecode dispatch.
-
-    // If the receiver is null then it is OK to jump to the slow path.
-    __ ld(R3_RET, Interpreter::stackElementSize, R15_esp); // get receiver
+  // In the G1 code we don't check if we need to reach a safepoint. We
+  // continue and the thread will safepoint at the next bytecode dispatch.
 
-    // Check if receiver == NULL and go the slow path.
-    __ cmpdi(CCR0, R3_RET, 0);
-    __ beq(CCR0, slow_path);
+  // If the receiver is null then it is OK to jump to the slow path.
+  __ ld(R3_RET, Interpreter::stackElementSize, R15_esp); // get receiver
 
-    // Load the value of the referent field.
-    __ load_heap_oop(R3_RET, referent_offset, R3_RET);
+  // Check if receiver == NULL and go the slow path.
+  __ cmpdi(CCR0, R3_RET, 0);
+  __ beq(CCR0, slow_path);
 
-    // Generate the G1 pre-barrier code to log the value of
-    // the referent field in an SATB buffer. Note with
-    // these parameters the pre-barrier does not generate
-    // the load of the previous value.
+  // Load the value of the referent field.
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT,
+                    R3_RET, referent_offset, R3_RET,
+                    /* non-volatile temp */ R31, R11_scratch1, true);
 
-    // Restore caller sp for c2i case.
-#ifdef ASSERT
-      __ ld(R9_ARG7, 0, R1_SP);
-      __ ld(R10_ARG8, 0, R21_sender_SP);
-      __ cmpd(CCR0, R9_ARG7, R10_ARG8);
-      __ asm_assert_eq("backlink", 0x544);
-#endif // ASSERT
-    __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
+  // Generate the G1 pre-barrier code to log the value of
+  // the referent field in an SATB buffer. Note with
+  // these parameters the pre-barrier does not generate
+  // the load of the previous value.
 
-    __ g1_write_barrier_pre(noreg,         // obj
-                            noreg,         // offset
-                            R3_RET,        // pre_val
-                            R11_scratch1,  // tmp
-                            R12_scratch2,  // tmp
-                            true);         // needs_frame
+  // Restore caller sp for c2i case.
+#ifdef ASSERT
+  __ ld(R9_ARG7, 0, R1_SP);
+  __ ld(R10_ARG8, 0, R21_sender_SP);
+  __ cmpd(CCR0, R9_ARG7, R10_ARG8);
+  __ asm_assert_eq("backlink", 0x544);
+#endif // ASSERT
+  __ mr(R1_SP, R21_sender_SP); // Cut the stack back to where the caller started.
 
-    __ blr();
+  __ blr();
 
-    // Generate regular method entry.
-    __ bind(slow_path);
-    __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1);
-    return entry;
-  }
-
-  return NULL;
+  __ bind(slow_path);
+  __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals), R11_scratch1);
+  return entry;
 }
 
 address TemplateInterpreterGenerator::generate_StackOverflowError_handler() {
--- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/interp_masm.hpp"
@@ -53,99 +54,29 @@
 // Kills:
 //   Rbase, Rtmp
 static void do_oop_store(InterpreterMacroAssembler* _masm,
-                         Register           Rbase,
+                         Register           base,
                          RegisterOrConstant offset,
-                         Register           Rval,         // Noreg means always null.
-                         Register           Rtmp1,
-                         Register           Rtmp2,
-                         Register           Rtmp3,
-                         BarrierSet::Name   barrier,
-                         bool               precise,
-                         bool               check_null) {
-  assert_different_registers(Rtmp1, Rtmp2, Rtmp3, Rval, Rbase);
-
-  switch (barrier) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      {
-        // Load and record the previous value.
-        __ g1_write_barrier_pre(Rbase, offset,
-                                Rtmp3, /* holder of pre_val ? */
-                                Rtmp1, Rtmp2, false /* frame */);
-
-        Label Lnull, Ldone;
-        if (Rval != noreg) {
-          if (check_null) {
-            __ cmpdi(CCR0, Rval, 0);
-            __ beq(CCR0, Lnull);
-          }
-          __ store_heap_oop_not_null(Rval, offset, Rbase, /*Rval must stay uncompressed.*/ Rtmp1);
-          // Mark the card.
-          if (!(offset.is_constant() && offset.as_constant() == 0) && precise) {
-            __ add(Rbase, offset, Rbase);
-          }
-          __ g1_write_barrier_post(Rbase, Rval, Rtmp1, Rtmp2, Rtmp3, /*filtered (fast path)*/ &Ldone);
-          if (check_null) { __ b(Ldone); }
-        }
-
-        if (Rval == noreg || check_null) { // Store null oop.
-          Register Rnull = Rval;
-          __ bind(Lnull);
-          if (Rval == noreg) {
-            Rnull = Rtmp1;
-            __ li(Rnull, 0);
-          }
-          if (UseCompressedOops) {
-            __ stw(Rnull, offset, Rbase);
-          } else {
-            __ std(Rnull, offset, Rbase);
-          }
-        }
-        __ bind(Ldone);
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-      {
-        Label Lnull, Ldone;
-        if (Rval != noreg) {
-          if (check_null) {
-            __ cmpdi(CCR0, Rval, 0);
-            __ beq(CCR0, Lnull);
-          }
-          __ store_heap_oop_not_null(Rval, offset, Rbase, /*Rval should better stay uncompressed.*/ Rtmp1);
-          // Mark the card.
-          if (!(offset.is_constant() && offset.as_constant() == 0) && precise) {
-            __ add(Rbase, offset, Rbase);
-          }
-          __ card_write_barrier_post(Rbase, Rval, Rtmp1);
-          if (check_null) {
-            __ b(Ldone);
-          }
-        }
-
-        if (Rval == noreg || check_null) { // Store null oop.
-          Register Rnull = Rval;
-          __ bind(Lnull);
-          if (Rval == noreg) {
-            Rnull = Rtmp1;
-            __ li(Rnull, 0);
-          }
-          if (UseCompressedOops) {
-            __ stw(Rnull, offset, Rbase);
-          } else {
-            __ std(Rnull, offset, Rbase);
-          }
-        }
-        __ bind(Ldone);
-      }
-      break;
-    case BarrierSet::ModRef:
-      ShouldNotReachHere();
-      break;
-    default:
-      ShouldNotReachHere();
-  }
+                         Register           val,         // Noreg means always null.
+                         Register           tmp1,
+                         Register           tmp2,
+                         Register           tmp3,
+                         DecoratorSet       decorators) {
+  assert_different_registers(tmp1, tmp2, tmp3, val, base);
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->store_at(_masm, decorators, T_OBJECT, base, offset, val, tmp1, tmp2, tmp3, false);
+}
+
+static void do_oop_load(InterpreterMacroAssembler* _masm,
+                        Register base,
+                        RegisterOrConstant offset,
+                        Register dst,
+                        Register tmp1,
+                        Register tmp2,
+                        DecoratorSet decorators) {
+  assert_different_registers(base, tmp1, tmp2);
+  assert_different_registers(dst, tmp1, tmp2);
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(_masm, decorators, T_OBJECT, base, offset, dst, tmp1, tmp2, false);
 }
 
 // ============================================================================
@@ -755,9 +686,11 @@
   // result tos: array
   const Register Rload_addr = R3_ARG1,
                  Rarray     = R4_ARG2,
-                 Rtemp      = R5_ARG3;
+                 Rtemp      = R5_ARG3,
+                 Rtemp2     = R31;
   __ index_check(Rarray, R17_tos /* index */, UseCompressedOops ? 2 : LogBytesPerWord, Rtemp, Rload_addr);
-  __ load_heap_oop(R17_tos, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Rload_addr);
+  do_oop_load(_masm, Rload_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos, Rtemp, Rtemp2,
+              IN_HEAP | IN_HEAP_ARRAY);
   __ verify_oop(R17_tos);
   //__ dcbt(R17_tos); // prefetch
 }
@@ -1084,14 +1017,14 @@
 
   __ bind(Lis_null);
   do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), noreg /* 0 */,
-               Rscratch, Rscratch2, Rscratch3, _bs->kind(), true /* precise */, false /* check_null */);
+               Rscratch, Rscratch2, Rscratch3, IN_HEAP | IN_HEAP_ARRAY);
   __ profile_null_seen(Rscratch, Rscratch2);
   __ b(Ldone);
 
   // Store is OK.
   __ bind(Lstore_ok);
   do_oop_store(_masm, Rstore_addr, arrayOopDesc::base_offset_in_bytes(T_OBJECT), R17_tos /* value */,
-               Rscratch, Rscratch2, Rscratch3, _bs->kind(), true /* precise */, false /* check_null */);
+               Rscratch, Rscratch2, Rscratch3, IN_HEAP | IN_HEAP_ARRAY | OOP_NOT_NULL);
 
   __ bind(Ldone);
   // Adjust sp (pops array, index and value).
@@ -2714,7 +2647,7 @@
   __ fence(); // Volatile entry point (one instruction before non-volatile_entry point).
   assert(branch_table[atos] == 0, "can't compute twice");
   branch_table[atos] = __ pc(); // non-volatile_entry point
-  __ load_heap_oop(R17_tos, (RegisterOrConstant)Roffset, Rclass_or_obj);
+  do_oop_load(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, /* nv temp */ Rflags, IN_HEAP);
   __ verify_oop(R17_tos);
   __ push(atos);
   //__ dcbt(R17_tos); // prefetch
@@ -3047,7 +2980,7 @@
   branch_table[atos] = __ pc(); // non-volatile_entry point
   __ pop(atos);
   if (!is_static) { pop_and_check_object(Rclass_or_obj); } // kills R11_scratch1
-  do_oop_store(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, Rscratch2, Rscratch3, _bs->kind(), false /* precise */, true /* check null */);
+  do_oop_store(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, Rscratch2, Rscratch3, IN_HEAP);
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_aputfield, Rbc, Rscratch, true, byte_no);
   }
@@ -3122,7 +3055,7 @@
   switch(bytecode()) {
     case Bytecodes::_fast_aputfield:
       // Store into the field.
-      do_oop_store(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, Rscratch2, Rscratch3, _bs->kind(), false /* precise */, true /* check null */);
+      do_oop_store(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, Rscratch2, Rscratch3, IN_HEAP);
       break;
 
     case Bytecodes::_fast_iputfield:
@@ -3196,13 +3129,13 @@
   switch(bytecode()) {
     case Bytecodes::_fast_agetfield:
     {
-      __ load_heap_oop(R17_tos, (RegisterOrConstant)Roffset, Rclass_or_obj);
+      do_oop_load(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, /* nv temp */ Rflags, IN_HEAP);
       __ verify_oop(R17_tos);
       __ dispatch_epilog(state, Bytecodes::length_for(bytecode()));
 
       __ bind(LisVolatile);
       if (support_IRIW_for_not_multiple_copy_atomic_cpu) { __ fence(); }
-      __ load_heap_oop(R17_tos, (RegisterOrConstant)Roffset, Rclass_or_obj);
+      do_oop_load(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, /* nv temp */ Rflags, IN_HEAP);
       __ verify_oop(R17_tos);
       __ twi_0(R17_tos);
       __ isync();
@@ -3336,13 +3269,13 @@
   switch(state) {
   case atos:
     {
-      __ load_heap_oop(R17_tos, (RegisterOrConstant)Roffset, Rclass_or_obj);
+      do_oop_load(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, /* nv temp */ Rflags, IN_HEAP);
       __ verify_oop(R17_tos);
       __ dispatch_epilog(state, Bytecodes::length_for(bytecode()) - 1); // Undo bcp increment.
 
       __ bind(LisVolatile);
       if (support_IRIW_for_not_multiple_copy_atomic_cpu) { __ fence(); }
-      __ load_heap_oop(R17_tos, (RegisterOrConstant)Roffset, Rclass_or_obj);
+      do_oop_load(_masm, Rclass_or_obj, Roffset, R17_tos, Rscratch, /* nv temp */ Rflags, IN_HEAP);
       __ verify_oop(R17_tos);
       __ twi_0(R17_tos);
       __ isync();
--- a/src/hotspot/cpu/s390/assembler_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/assembler_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -40,7 +40,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif
 
--- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -45,6 +45,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 // Implementation of StubAssembler
@@ -767,7 +768,7 @@
     case g1_pre_barrier_slow_id:
       { // Z_R1_scratch: previous value of memory
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ should_not_reach_here(FILE_AND_LINE);
           break;
@@ -780,15 +781,9 @@
         Register tmp2 = Z_R7;
 
         Label refill, restart, marking_not_active;
-        int satb_q_active_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_active());
-        int satb_q_index_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_index());
-        int satb_q_buf_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_buf());
+        int satb_q_active_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
+        int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
+        int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
 
         // Save tmp registers (see assertion in G1PreBarrierStub::emit_code()).
         __ z_stg(tmp,  0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
@@ -836,7 +831,7 @@
 
     case g1_post_barrier_slow_id:
       { // Z_R1_scratch: oop address, address of updated memory slot
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ should_not_reach_here(FILE_AND_LINE);
           break;
@@ -890,10 +885,8 @@
         // Save registers used below (see assertion in G1PreBarrierStub::emit_code()).
         __ z_stg(r2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
 
-        ByteSize dirty_card_q_index_byte_offset =
-          JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index();
-        ByteSize dirty_card_q_buf_byte_offset =
-          JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_buf();
+        ByteSize dirty_card_q_index_byte_offset = G1ThreadLocalData::dirty_card_queue_index_offset();
+        ByteSize dirty_card_q_buf_byte_offset = G1ThreadLocalData::dirty_card_queue_buffer_offset();
 
         __ bind(restart);
 
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,10 +29,10 @@
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "runtime/thread.hpp"
 #include "interpreter/interp_masm.hpp"
+#include "runtime/sharedRuntime.hpp"
 
 #define __ masm->
 
@@ -49,8 +49,7 @@
     assert_different_registers(addr,  Z_R0_scratch);  // would be destroyed by push_frame()
     assert_different_registers(count, Z_R0_scratch);  // would be destroyed by push_frame()
     Register Rtmp1 = Z_R0_scratch;
-    const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_active());
+    const int active_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
     if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
       __ load_and_test_int(Rtmp1, Address(Z_thread, active_offset));
     } else {
@@ -90,3 +89,321 @@
     __ z_br(Z_R1); // Branch without linking, callee will return to stub caller.
   }
 }
+
+void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                    const Address& src, Register dst, Register tmp1, Register tmp2, Label *is_null) {
+  bool on_oop = type == T_OBJECT || type == T_ARRAY;
+  bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
+  bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+  bool on_reference = on_weak || on_phantom;
+  Label done;
+  if (on_oop && on_reference && is_null == NULL) { is_null = &done; }
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp1, tmp2, is_null);
+  if (on_oop && on_reference) {
+    // Generate the G1 pre-barrier code to log the value of
+    // the referent field in an SATB buffer.
+    g1_write_barrier_pre(masm, decorators | OOP_NOT_NULL,
+                         NULL /* obj */,
+                         dst  /* pre_val */,
+                         noreg/* preserve */ ,
+                         tmp1, tmp2 /* tmp */,
+                         true /* pre_val_needed */);
+  }
+  __ bind(done);
+}
+
+void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm, DecoratorSet decorators,
+                                                 const Address*  obj,
+                                                 Register        Rpre_val,      // Ideally, this is a non-volatile register.
+                                                 Register        Rval,          // Will be preserved.
+                                                 Register        Rtmp1,         // If Rpre_val is volatile, either Rtmp1
+                                                 Register        Rtmp2,         // or Rtmp2 has to be non-volatile.
+                                                 bool            pre_val_needed // Save Rpre_val across runtime call, caller uses it.
+                                                 ) {
+
+  bool not_null  = (decorators & OOP_NOT_NULL) != 0,
+       preloaded = obj == NULL;
+
+  const Register Robj = obj ? obj->base() : noreg,
+                 Roff = obj ? obj->index() : noreg;
+  const int active_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
+  const int buffer_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
+  const int index_offset  = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
+  assert_different_registers(Rtmp1, Rtmp2, Z_R0_scratch); // None of the Rtmp<i> must be Z_R0!!
+  assert_different_registers(Robj, Z_R0_scratch);         // Used for addressing. Furthermore, push_frame destroys Z_R0!!
+  assert_different_registers(Rval, Z_R0_scratch);         // push_frame destroys Z_R0!!
+
+  Label callRuntime, filtered;
+
+  BLOCK_COMMENT("g1_write_barrier_pre {");
+
+  // Is marking active?
+  // Note: value is loaded for test purposes only. No further use here.
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ load_and_test_int(Rtmp1, Address(Z_thread, active_offset));
+  } else {
+    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ load_and_test_byte(Rtmp1, Address(Z_thread, active_offset));
+  }
+  __ z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently.
+
+  assert(Rpre_val != noreg, "must have a real register");
+
+
+  // If an object is given, we need to load the previous value into Rpre_val.
+  if (obj) {
+    // Load the previous value...
+    if (UseCompressedOops) {
+      __ z_llgf(Rpre_val, *obj);
+    } else {
+      __ z_lg(Rpre_val, *obj);
+    }
+  }
+
+  // Is the previous value NULL?
+  // If so, we don't need to record it and we're done.
+  // Note: pre_val is loaded, decompressed and stored (directly or via runtime call).
+  //       Register contents is preserved across runtime call if caller requests to do so.
+  if (preloaded && not_null) {
+#ifdef ASSERT
+    __ z_ltgr(Rpre_val, Rpre_val);
+    __ asm_assert_ne("null oop not allowed (G1 pre)", 0x321); // Checked by caller.
+#endif
+  } else {
+    __ z_ltgr(Rpre_val, Rpre_val);
+    __ z_bre(filtered); // previous value is NULL, so we don't need to record it.
+  }
+
+  // Decode the oop now. We know it's not NULL.
+  if (Robj != noreg && UseCompressedOops) {
+    __ oop_decoder(Rpre_val, Rpre_val, /*maybeNULL=*/false);
+  }
+
+  // OK, it's not filtered, so we'll need to call enqueue.
+
+  // We can store the original value in the thread's buffer
+  // only if index > 0. Otherwise, we need runtime to handle.
+  // (The index field is typed as size_t.)
+  Register Rbuffer = Rtmp1, Rindex = Rtmp2;
+  assert_different_registers(Rbuffer, Rindex, Rpre_val);
+
+  __ z_lg(Rbuffer, buffer_offset, Z_thread);
+
+  __ load_and_test_long(Rindex, Address(Z_thread, index_offset));
+  __ z_bre(callRuntime); // If index == 0, goto runtime.
+
+  __ add2reg(Rindex, -wordSize); // Decrement index.
+  __ z_stg(Rindex, index_offset, Z_thread);
+
+  // Record the previous value.
+  __ z_stg(Rpre_val, 0, Rbuffer, Rindex);
+  __ z_bru(filtered);  // We are done.
+
+  Rbuffer = noreg;  // end of life
+  Rindex  = noreg;  // end of life
+
+  __ bind(callRuntime);
+
+  // Save some registers (inputs and result) over runtime call
+  // by spilling them into the top frame.
+  if (Robj != noreg && Robj->is_volatile()) {
+    __ z_stg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
+  }
+  if (Roff != noreg && Roff->is_volatile()) {
+    __ z_stg(Roff, Roff->encoding()*BytesPerWord, Z_SP);
+  }
+  if (Rval != noreg && Rval->is_volatile()) {
+    __ z_stg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
+  }
+
+  // Save Rpre_val (result) over runtime call.
+  Register Rpre_save = Rpre_val;
+  if ((Rpre_val == Z_R0_scratch) || (pre_val_needed && Rpre_val->is_volatile())) {
+    guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!");
+    Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2;
+  }
+  __ lgr_if_needed(Rpre_save, Rpre_val);
+
+  // Push frame to protect top frame with return pc and spilled register values.
+  __ save_return_pc();
+  __ push_frame_abi160(0); // Will use Z_R0 as tmp.
+
+  // Rpre_val may be destroyed by push_frame().
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_save, Z_thread);
+
+  __ pop_frame();
+  __ restore_return_pc();
+
+  // Restore spilled values.
+  if (Robj != noreg && Robj->is_volatile()) {
+    __ z_lg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
+  }
+  if (Roff != noreg && Roff->is_volatile()) {
+    __ z_lg(Roff, Roff->encoding()*BytesPerWord, Z_SP);
+  }
+  if (Rval != noreg && Rval->is_volatile()) {
+    __ z_lg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
+  }
+  if (pre_val_needed && Rpre_val->is_volatile()) {
+    __ lgr_if_needed(Rpre_val, Rpre_save);
+  }
+
+  __ bind(filtered);
+  BLOCK_COMMENT("} g1_write_barrier_pre");
+}
+
+void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register Rstore_addr, Register Rnew_val,
+                                                  Register Rtmp1, Register Rtmp2, Register Rtmp3) {
+  bool not_null = (decorators & OOP_NOT_NULL) != 0;
+
+  assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2); // Most probably, Rnew_val == Rtmp3.
+
+  Label callRuntime, filtered;
+
+  CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
+  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  BLOCK_COMMENT("g1_write_barrier_post {");
+
+  // Does store cross heap regions?
+  // It does if the two addresses specify different grain addresses.
+  if (G1RSBarrierRegionFilter) {
+    if (VM_Version::has_DistinctOpnds()) {
+      __ z_xgrk(Rtmp1, Rstore_addr, Rnew_val);
+    } else {
+      __ z_lgr(Rtmp1, Rstore_addr);
+      __ z_xgr(Rtmp1, Rnew_val);
+    }
+    __ z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes);
+    __ z_bre(filtered);
+  }
+
+  // Crosses regions, storing NULL?
+  if (not_null) {
+#ifdef ASSERT
+    __ z_ltgr(Rnew_val, Rnew_val);
+    __ asm_assert_ne("null oop not allowed (G1 post)", 0x322); // Checked by caller.
+#endif
+  } else {
+    __ z_ltgr(Rnew_val, Rnew_val);
+    __ z_bre(filtered);
+  }
+
+  Rnew_val = noreg; // end of lifetime
+
+  // Storing region crossing non-NULL, is card already dirty?
+  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
+  assert_different_registers(Rtmp1, Rtmp2, Rtmp3);
+  // Make sure not to use Z_R0 for any of these registers.
+  Register Rcard_addr = (Rtmp1 != Z_R0_scratch) ? Rtmp1 : Rtmp3;
+  Register Rbase      = (Rtmp2 != Z_R0_scratch) ? Rtmp2 : Rtmp3;
+
+  // calculate address of card
+  __ load_const_optimized(Rbase, (address)ct->card_table()->byte_map_base());      // Card table base.
+  __ z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift);         // Index into card table.
+  __ z_algr(Rcard_addr, Rbase);                                      // Explicit calculation needed for cli.
+  Rbase = noreg; // end of lifetime
+
+  // Filter young.
+  assert((unsigned int)G1CardTable::g1_young_card_val() <= 255, "otherwise check this code");
+  __ z_cli(0, Rcard_addr, G1CardTable::g1_young_card_val());
+  __ z_bre(filtered);
+
+  // Check the card value. If dirty, we're done.
+  // This also avoids false sharing of the (already dirty) card.
+  __ z_sync(); // Required to support concurrent cleaning.
+  assert((unsigned int)G1CardTable::dirty_card_val() <= 255, "otherwise check this code");
+  __ z_cli(0, Rcard_addr, G1CardTable::dirty_card_val()); // Reload after membar.
+  __ z_bre(filtered);
+
+  // Storing a region crossing, non-NULL oop, card is clean.
+  // Dirty card and log.
+  __ z_mvi(0, Rcard_addr, G1CardTable::dirty_card_val());
+
+  Register Rcard_addr_x = Rcard_addr;
+  Register Rqueue_index = (Rtmp2 != Z_R0_scratch) ? Rtmp2 : Rtmp1;
+  Register Rqueue_buf   = (Rtmp3 != Z_R0_scratch) ? Rtmp3 : Rtmp1;
+  const int qidx_off    = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
+  const int qbuf_off    = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
+  if ((Rcard_addr == Rqueue_buf) || (Rcard_addr == Rqueue_index)) {
+    Rcard_addr_x = Z_R0_scratch;  // Register shortage. We have to use Z_R0.
+  }
+  __ lgr_if_needed(Rcard_addr_x, Rcard_addr);
+
+  __ load_and_test_long(Rqueue_index, Address(Z_thread, qidx_off));
+  __ z_bre(callRuntime); // Index == 0 then jump to runtime.
+
+  __ z_lg(Rqueue_buf, qbuf_off, Z_thread);
+
+  __ add2reg(Rqueue_index, -wordSize); // Decrement index.
+  __ z_stg(Rqueue_index, qidx_off, Z_thread);
+
+  __ z_stg(Rcard_addr_x, 0, Rqueue_index, Rqueue_buf); // Store card.
+  __ z_bru(filtered);
+
+  __ bind(callRuntime);
+
+  // TODO: do we need a frame? Introduced to be on the safe side.
+  bool needs_frame = true;
+  __ lgr_if_needed(Rcard_addr, Rcard_addr_x); // copy back asap. push_frame will destroy Z_R0_scratch!
+
+  // VM call need frame to access(write) O register.
+  if (needs_frame) {
+    __ save_return_pc();
+    __ push_frame_abi160(0); // Will use Z_R0 as tmp on old CPUs.
+  }
+
+  // Save the live input values.
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, Z_thread);
+
+  if (needs_frame) {
+    __ pop_frame();
+    __ restore_return_pc();
+  }
+
+  __ bind(filtered);
+
+  BLOCK_COMMENT("} g1_write_barrier_post");
+}
+
+void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+  // Load and record the previous value.
+  g1_write_barrier_pre(masm, decorators, &dst, tmp3, val, tmp1, tmp2, false);
+
+  BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
+
+  // No need for post barrier if storing NULL
+  if (val != noreg) {
+    const Register base = dst.base(),
+                   idx  = dst.index();
+    const intptr_t disp = dst.disp();
+    if (precise && (disp != 0 || idx != noreg)) {
+      __ add2reg_with_index(base, disp, idx, base);
+    }
+    g1_write_barrier_post(masm, decorators, base, val, tmp1, tmp2, tmp3);
+  }
+}
+
+void G1BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2) {
+  NearLabel Ldone, Lnot_weak;
+  __ z_ltgr(tmp1, value);
+  __ z_bre(Ldone);          // Use NULL result as-is.
+
+  __ z_nill(value, ~JNIHandles::weak_tag_mask);
+  __ z_lg(value, 0, value); // Resolve (untagged) jobject.
+
+  __ z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag.
+  __ z_braz(Lnot_weak);
+  __ verify_oop(value);
+  DecoratorSet decorators = IN_ROOT | ON_PHANTOM_OOP_REF;
+  g1_write_barrier_pre(masm, decorators, (const Address*)NULL, value, noreg, tmp1, tmp2, true);
+  __ bind(Lnot_weak);
+  __ verify_oop(value);
+  __ bind(Ldone);
+}
+
+#undef __
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,10 +31,29 @@
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
  protected:
-  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                               Register addr, Register count);
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                Register addr, Register count, bool do_return);
+  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count);
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
+                                                bool do_return);
+
+  void g1_write_barrier_pre(MacroAssembler*    masm, DecoratorSet decorators,
+                            const Address*     obj,           // Address of oop or NULL if pre-loaded.
+                            Register           Rpre_val,      // Ideally, this is a non-volatile register.
+                            Register           Rval,          // Will be preserved.
+                            Register           Rtmp1,         // If Rpre_val is volatile, either Rtmp1
+                            Register           Rtmp2,         // or Rtmp2 has to be non-volatile.
+                            bool               pre_val_needed); // Save Rpre_val across runtime call, caller uses it.
+
+  void g1_write_barrier_post(MacroAssembler* masm, DecoratorSet decorators, Register Rstore_addr, Register Rnew_val,
+                             Register Rtmp1, Register Rtmp2, Register Rtmp3);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3);
+
+ public:
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       const Address& src, Register dst, Register tmp1, Register tmp2, Label *is_null = NULL);
+
+  virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2);
 };
 
 #endif // CPU_S390_GC_G1_G1BARRIERSETASSEMBLER_S390_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, SAP SE. All rights reserved.
+ * 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 "gc/shared/barrierSetAssembler.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void BarrierSetAssembler::arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                             Register dst, Register count, bool do_return) {
+  if (do_return) { __ z_br(Z_R14); }
+}
+
+void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                  const Address& addr, Register dst, Register tmp1, Register tmp2, Label *is_null) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  assert(on_heap || on_root, "where?");
+
+  switch (type) {
+  case T_ARRAY:
+  case T_OBJECT: {
+    if (UseCompressedOops && on_heap) {
+      __ z_llgf(dst, addr);
+      if (is_null) {
+        __ compareU32_and_branch(dst, (intptr_t)0, Assembler::bcondEqual, *is_null);
+        __ oop_decoder(dst, dst, false);
+      } else {
+        __ oop_decoder(dst, dst, true);
+      }
+    } else {
+      __ z_lg(dst, addr);
+      if (is_null) {
+        __ compareU64_and_branch(dst, (intptr_t)0, Assembler::bcondEqual, *is_null);
+      }
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                   const Address& addr, Register val, Register tmp1, Register tmp2, Register tmp3) {
+  bool on_heap  = (decorators & IN_HEAP) != 0;
+  bool on_root  = (decorators & IN_ROOT) != 0;
+  bool not_null = (decorators & OOP_NOT_NULL) != 0;
+  assert(on_heap || on_root, "where?");
+  assert_different_registers(val, tmp1, tmp2);
+
+  switch (type) {
+  case T_ARRAY:
+  case T_OBJECT: {
+    if (UseCompressedOops && on_heap) {
+      if (val == noreg) {
+        __ clear_mem(addr, 4);
+      } else if (Universe::narrow_oop_mode() == Universe::UnscaledNarrowOop) {
+        __ z_st(val, addr);
+      } else {
+        Register tmp = (tmp1 != Z_R1) ? tmp1 : tmp2; // Avoid tmp == Z_R1 (see oop_encoder).
+        __ oop_encoder(tmp, val, !not_null);
+        __ z_st(tmp, addr);
+      }
+    } else {
+      if (val == noreg) {
+        __ clear_mem(addr, 8);
+      } else {
+        __ z_stg(val, addr);
+      }
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2) {
+  NearLabel Ldone;
+  __ z_ltgr(tmp1, value);
+  __ z_bre(Ldone);          // Use NULL result as-is.
+
+  __ z_nill(value, ~JNIHandles::weak_tag_mask);
+  __ z_lg(value, 0, value); // Resolve (untagged) jobject.
+
+  __ verify_oop(value);
+  __ bind(Ldone);
+}
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,8 +23,8 @@
  *
  */
 
-#ifndef CPU_S390_GC_G1_BARRIERSETASSEMBLER_S390_HPP
-#define CPU_S390_GC_G1_BARRIERSETASSEMBLER_S390_HPP
+#ifndef CPU_S390_GC_SHARED_BARRIERSETASSEMBLER_S390_HPP
+#define CPU_S390_GC_SHARED_BARRIERSETASSEMBLER_S390_HPP
 
 #include "asm/macroAssembler.hpp"
 #include "memory/allocation.hpp"
@@ -38,6 +38,15 @@
                                   Register src, Register dst, Register count) {}
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register dst, Register count, bool do_return = false);
+
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       const Address& addr, Register dst, Register tmp1, Register tmp2, Label *is_null = NULL);
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        const Address& addr, Register val, Register tmp1, Register tmp2, Register tmp3);
+
+  virtual void resolve_jobject(MacroAssembler* masm, Register value, Register tmp1, Register tmp2);
+
+  virtual void barrier_stubs_init() {}
 };
 
-#endif // CPU_S390_GC_G1_BARRIERSETASSEMBLER_S390_HPP
+#endif // CPU_S390_GC_SHARED_BARRIERSETASSEMBLER_S390_HPP
--- a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,7 +29,6 @@
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 
 #define __ masm->
@@ -46,7 +45,7 @@
 
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
                                                                     bool do_return) {
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
 
@@ -139,3 +138,38 @@
 
   __ bind(done);
 }
+
+void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register store_addr, Register tmp) {
+  // Does a store check for the oop in register obj. The content of
+  // register obj is destroyed afterwards.
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
+  CardTable* ct = ctbs->card_table();
+  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  assert_different_registers(store_addr, tmp);
+
+  __ z_srlg(store_addr, store_addr, CardTable::card_shift);
+  __ load_absolute_address(tmp, (address)ct->byte_map_base());
+  __ z_agr(store_addr, tmp);
+  __ z_mvi(0, store_addr, CardTable::dirty_card_val());
+}
+
+void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                                const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+
+  BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
+
+  // No need for post barrier if storing NULL
+  if (val != noreg) {
+    const Register base = dst.base(),
+                   idx  = dst.index();
+    const intptr_t disp = dst.disp();
+    if (precise && (disp != 0 || idx != noreg)) {
+      __ add2reg_with_index(base, disp, idx, base);
+    }
+    store_check(masm, base, tmp1);
+  }
+}
--- a/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/shared/cardTableBarrierSetAssembler_s390.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,16 +23,21 @@
  *
  */
 
-#ifndef CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
-#define CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
+#ifndef CPU_S390_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_S390_HPP
+#define CPU_S390_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_S390_HPP
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
 
 class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
+  void store_check(MacroAssembler* masm, Register store_addr, Register tmp);
+
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
                                                 bool do_return);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3);
 };
 
-#endif // CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
+#endif // CPU_S390_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_S390_HPP
--- a/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -49,3 +49,17 @@
     if (do_return) { __ z_br(Z_R14); }
   }
 }
+
+void ModRefBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                             const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
+  BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
+}
+
+void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
+  if (type == T_OBJECT || type == T_ARRAY) {
+    oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
+  } else {
+    BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2, tmp3);
+  }
+}
--- a/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/shared/modRefBarrierSetAssembler_s390.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,23 +23,31 @@
  *
  */
 
-#ifndef CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
-#define CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
+#ifndef CPU_S390_GC_SHARED_MODREFBARRIERSETASSEMBLER_S390_HPP
+#define CPU_S390_GC_SHARED_MODREFBARRIERSETASSEMBLER_S390_HPP
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 
+// The ModRefBarrierSetAssembler filters away accesses on BasicTypes other
+// than T_OBJECT/T_ARRAY (oops). The oop accesses call one of the protected
+// accesses, which are overridden in the concrete BarrierSetAssembler.
+
 class ModRefBarrierSetAssembler: public BarrierSetAssembler {
 protected:
   virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count) {}
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count,
                                                 bool do_return);
-
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3);
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register dst, Register count, bool do_return = false);
+
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3);
 };
 
-#endif // CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
+#endif // CPU_S390_GC_SHARED_MODREFBARRIERSETASSEMBLER_S390_HPP
--- a/src/hotspot/cpu/s390/interp_masm_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/interp_masm_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2018 SAP SE. All rights reserved.
  * 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,8 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interp_masm_s390.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
@@ -42,7 +44,7 @@
 #include "runtime/thread.inline.hpp"
 
 // Implementation of InterpreterMacroAssembler.
-// This file specializes the assember with interpreter-specific macros.
+// This file specializes the assembler with interpreter-specific macros.
 
 #ifdef PRODUCT
 #define BLOCK_COMMENT(str)
@@ -389,9 +391,8 @@
   bind(index_ok);
 #endif
   z_agr(result, index);    // Address of indexed array element.
-  load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
-  // The resulting oop is null if the reference is not yet resolved.
-  // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(this, IN_HEAP, T_OBJECT, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), result, tmp, noreg);
 }
 
 // load cpool->resolved_klass_at(index)
@@ -2197,4 +2198,3 @@
     unimplemented("verfiyFPU");
   }
 }
-
--- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2018, SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,8 @@
 #include "asm/codeBuffer.hpp"
 #include "asm/macroAssembler.inline.hpp"
 #include "compiler/disassembler.hpp"
-#include "gc/shared/cardTable.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "interpreter/interpreter.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
@@ -51,12 +52,6 @@
 #include "runtime/stubRoutines.hpp"
 #include "utilities/events.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/heapRegion.hpp"
-#endif
 
 #include <ucontext.h>
 
@@ -3503,315 +3498,10 @@
   // flag == NE indicates failure
 }
 
-// Write to card table for modification at store_addr - register is destroyed afterwards.
-void MacroAssembler::card_write_barrier_post(Register store_addr, Register tmp) {
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
-  CardTable* ct = ctbs->card_table();
-  assert(bs->kind() == BarrierSet::CardTableBarrierSet, "wrong barrier");
-  assert_different_registers(store_addr, tmp);
-  z_srlg(store_addr, store_addr, CardTable::card_shift);
-  load_absolute_address(tmp, (address)ct->byte_map_base());
-  z_agr(store_addr, tmp);
-  z_mvi(0, store_addr, 0); // Store byte 0.
-}
-
 void MacroAssembler::resolve_jobject(Register value, Register tmp1, Register tmp2) {
-  NearLabel Ldone;
-  z_ltgr(tmp1, value);
-  z_bre(Ldone);          // Use NULL result as-is.
-
-  z_nill(value, ~JNIHandles::weak_tag_mask);
-  z_lg(value, 0, value); // Resolve (untagged) jobject.
-
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) {
-    NearLabel Lnot_weak;
-    z_tmll(tmp1, JNIHandles::weak_tag_mask); // Test for jweak tag.
-    z_braz(Lnot_weak);
-    verify_oop(value);
-    g1_write_barrier_pre(noreg /* obj */,
-                         noreg /* offset */,
-                         value /* pre_val */,
-                         noreg /* val */,
-                         tmp1  /* tmp1 */,
-                         tmp2  /* tmp2 */,
-                         true  /* pre_val_needed */);
-    bind(Lnot_weak);
-  }
-#endif // INCLUDE_ALL_GCS
-  verify_oop(value);
-  bind(Ldone);
-}
-
-#if INCLUDE_ALL_GCS
-
-//------------------------------------------------------
-// General G1 pre-barrier generator.
-// Purpose: record the previous value if it is not null.
-// All non-tmps are preserved.
-//------------------------------------------------------
-// Note: Rpre_val needs special attention.
-//   The flag pre_val_needed indicated that the caller of this emitter function
-//   relies on Rpre_val containing the correct value, that is:
-//     either the value it contained on entry to this code segment
-//     or the value that was loaded into the register from (Robj+offset).
-//
-//   Independent from this requirement, the contents of Rpre_val must survive
-//   the push_frame() operation. push_frame() uses Z_R0_scratch by default
-//   to temporarily remember the frame pointer.
-//   If Rpre_val is assigned Z_R0_scratch by the caller, code must be emitted to
-//   save it's value.
-void MacroAssembler::g1_write_barrier_pre(Register           Robj,
-                                          RegisterOrConstant offset,
-                                          Register           Rpre_val,      // Ideally, this is a non-volatile register.
-                                          Register           Rval,          // Will be preserved.
-                                          Register           Rtmp1,         // If Rpre_val is volatile, either Rtmp1
-                                          Register           Rtmp2,         // or Rtmp2 has to be non-volatile..
-                                          bool               pre_val_needed // Save Rpre_val across runtime call, caller uses it.
-                                       ) {
-  Label callRuntime, filtered;
-  const int active_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active());
-  const int buffer_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf());
-  const int index_offset  = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index());
-  assert_different_registers(Rtmp1, Rtmp2, Z_R0_scratch); // None of the Rtmp<i> must be Z_R0!!
-  assert_different_registers(Robj, Z_R0_scratch);         // Used for addressing. Furthermore, push_frame destroys Z_R0!!
-  assert_different_registers(Rval, Z_R0_scratch);         // push_frame destroys Z_R0!!
-
-#ifdef ASSERT
-  // make sure the register is not Z_R0. Used for addressing. Furthermore, would be destroyed by push_frame.
-  if (offset.is_register() && offset.as_register()->encoding() == 0) {
-    tty->print_cr("Roffset(g1_write_barrier_pre)  = %%r%d", offset.as_register()->encoding());
-    assert(false, "bad register for offset");
-  }
-#endif
-
-  BLOCK_COMMENT("g1_write_barrier_pre {");
-
-  // Is marking active?
-  // Note: value is loaded for test purposes only. No further use here.
-  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    load_and_test_int(Rtmp1, Address(Z_thread, active_offset));
-  } else {
-    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-    load_and_test_byte(Rtmp1, Address(Z_thread, active_offset));
-  }
-  z_bre(filtered); // Activity indicator is zero, so there is no marking going on currently.
-
-  assert(Rpre_val != noreg, "must have a real register");
-
-
-  // If an object is given, we need to load the previous value into Rpre_val.
-  if (Robj != noreg) {
-    // Load the previous value...
-    Register ixReg = offset.is_register() ? offset.register_or_noreg() : Z_R0;
-    if (UseCompressedOops) {
-      z_llgf(Rpre_val, offset.constant_or_zero(), ixReg, Robj);
-    } else {
-      z_lg(Rpre_val, offset.constant_or_zero(), ixReg, Robj);
-    }
-  }
-
-  // Is the previous value NULL?
-  // If so, we don't need to record it and we're done.
-  // Note: pre_val is loaded, decompressed and stored (directly or via runtime call).
-  //       Register contents is preserved across runtime call if caller requests to do so.
-  z_ltgr(Rpre_val, Rpre_val);
-  z_bre(filtered); // previous value is NULL, so we don't need to record it.
-
-  // Decode the oop now. We know it's not NULL.
-  if (Robj != noreg && UseCompressedOops) {
-    oop_decoder(Rpre_val, Rpre_val, /*maybeNULL=*/false);
-  }
-
-  // OK, it's not filtered, so we'll need to call enqueue.
-
-  // We can store the original value in the thread's buffer
-  // only if index > 0. Otherwise, we need runtime to handle.
-  // (The index field is typed as size_t.)
-  Register Rbuffer = Rtmp1, Rindex = Rtmp2;
-  assert_different_registers(Rbuffer, Rindex, Rpre_val);
-
-  z_lg(Rbuffer, buffer_offset, Z_thread);
-
-  load_and_test_long(Rindex, Address(Z_thread, index_offset));
-  z_bre(callRuntime); // If index == 0, goto runtime.
-
-  add2reg(Rindex, -wordSize); // Decrement index.
-  z_stg(Rindex, index_offset, Z_thread);
-
-  // Record the previous value.
-  z_stg(Rpre_val, 0, Rbuffer, Rindex);
-  z_bru(filtered);  // We are done.
-
-  Rbuffer = noreg;  // end of life
-  Rindex  = noreg;  // end of life
-
-  bind(callRuntime);
-
-  // Save some registers (inputs and result) over runtime call
-  // by spilling them into the top frame.
-  if (Robj != noreg && Robj->is_volatile()) {
-    z_stg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
-  }
-  if (offset.is_register() && offset.as_register()->is_volatile()) {
-    Register Roff = offset.as_register();
-    z_stg(Roff, Roff->encoding()*BytesPerWord, Z_SP);
-  }
-  if (Rval != noreg && Rval->is_volatile()) {
-    z_stg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
-  }
-
-  // Save Rpre_val (result) over runtime call.
-  Register Rpre_save = Rpre_val;
-  if ((Rpre_val == Z_R0_scratch) || (pre_val_needed && Rpre_val->is_volatile())) {
-    guarantee(!Rtmp1->is_volatile() || !Rtmp2->is_volatile(), "oops!");
-    Rpre_save = !Rtmp1->is_volatile() ? Rtmp1 : Rtmp2;
-  }
-  lgr_if_needed(Rpre_save, Rpre_val);
-
-  // Push frame to protect top frame with return pc and spilled register values.
-  save_return_pc();
-  push_frame_abi160(0); // Will use Z_R0 as tmp.
-
-  // Rpre_val may be destroyed by push_frame().
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), Rpre_save, Z_thread);
-
-  pop_frame();
-  restore_return_pc();
-
-  // Restore spilled values.
-  if (Robj != noreg && Robj->is_volatile()) {
-    z_lg(Robj, Robj->encoding()*BytesPerWord, Z_SP);
-  }
-  if (offset.is_register() && offset.as_register()->is_volatile()) {
-    Register Roff = offset.as_register();
-    z_lg(Roff, Roff->encoding()*BytesPerWord, Z_SP);
-  }
-  if (Rval != noreg && Rval->is_volatile()) {
-    z_lg(Rval, Rval->encoding()*BytesPerWord, Z_SP);
-  }
-  if (pre_val_needed && Rpre_val->is_volatile()) {
-    lgr_if_needed(Rpre_val, Rpre_save);
-  }
-
-  bind(filtered);
-  BLOCK_COMMENT("} g1_write_barrier_pre");
-}
-
-// General G1 post-barrier generator.
-// Purpose: Store cross-region card.
-void MacroAssembler::g1_write_barrier_post(Register Rstore_addr,
-                                           Register Rnew_val,
-                                           Register Rtmp1,
-                                           Register Rtmp2,
-                                           Register Rtmp3) {
-  Label callRuntime, filtered;
-
-  assert_different_registers(Rstore_addr, Rnew_val, Rtmp1, Rtmp2); // Most probably, Rnew_val == Rtmp3.
-
-  G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(Universe::heap()->barrier_set());
-  CardTable* ct = bs->card_table();
-  assert(bs->kind() == BarrierSet::G1BarrierSet, "wrong barrier");
-
-  BLOCK_COMMENT("g1_write_barrier_post {");
-
-  // Does store cross heap regions?
-  // It does if the two addresses specify different grain addresses.
-  if (G1RSBarrierRegionFilter) {
-    if (VM_Version::has_DistinctOpnds()) {
-      z_xgrk(Rtmp1, Rstore_addr, Rnew_val);
-    } else {
-      z_lgr(Rtmp1, Rstore_addr);
-      z_xgr(Rtmp1, Rnew_val);
-    }
-    z_srag(Rtmp1, Rtmp1, HeapRegion::LogOfHRGrainBytes);
-    z_bre(filtered);
-  }
-
-  // Crosses regions, storing NULL?
-#ifdef ASSERT
-  z_ltgr(Rnew_val, Rnew_val);
-  asm_assert_ne("null oop not allowed (G1)", 0x255); // TODO: also on z? Checked by caller on PPC64, so following branch is obsolete:
-  z_bre(filtered);  // Safety net: don't break if we have a NULL oop.
-#endif
-  Rnew_val = noreg; // end of lifetime
-
-  // Storing region crossing non-NULL, is card already dirty?
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-  assert_different_registers(Rtmp1, Rtmp2, Rtmp3);
-  // Make sure not to use Z_R0 for any of these registers.
-  Register Rcard_addr = (Rtmp1 != Z_R0_scratch) ? Rtmp1 : Rtmp3;
-  Register Rbase      = (Rtmp2 != Z_R0_scratch) ? Rtmp2 : Rtmp3;
-
-  // calculate address of card
-  load_const_optimized(Rbase, (address)ct->byte_map_base());      // Card table base.
-  z_srlg(Rcard_addr, Rstore_addr, CardTable::card_shift);         // Index into card table.
-  z_algr(Rcard_addr, Rbase);                                      // Explicit calculation needed for cli.
-  Rbase = noreg; // end of lifetime
-
-  // Filter young.
-  assert((unsigned int)G1CardTable::g1_young_card_val() <= 255, "otherwise check this code");
-  z_cli(0, Rcard_addr, (int)G1CardTable::g1_young_card_val());
-  z_bre(filtered);
-
-  // Check the card value. If dirty, we're done.
-  // This also avoids false sharing of the (already dirty) card.
-  z_sync(); // Required to support concurrent cleaning.
-  assert((unsigned int)CardTable::dirty_card_val() <= 255, "otherwise check this code");
-  z_cli(0, Rcard_addr, CardTable::dirty_card_val()); // Reload after membar.
-  z_bre(filtered);
-
-  // Storing a region crossing, non-NULL oop, card is clean.
-  // Dirty card and log.
-  z_mvi(0, Rcard_addr, CardTable::dirty_card_val());
-
-  Register Rcard_addr_x = Rcard_addr;
-  Register Rqueue_index = (Rtmp2 != Z_R0_scratch) ? Rtmp2 : Rtmp1;
-  Register Rqueue_buf   = (Rtmp3 != Z_R0_scratch) ? Rtmp3 : Rtmp1;
-  const int qidx_off    = in_bytes(JavaThread::dirty_card_queue_offset() + SATBMarkQueue::byte_offset_of_index());
-  const int qbuf_off    = in_bytes(JavaThread::dirty_card_queue_offset() + SATBMarkQueue::byte_offset_of_buf());
-  if ((Rcard_addr == Rqueue_buf) || (Rcard_addr == Rqueue_index)) {
-    Rcard_addr_x = Z_R0_scratch;  // Register shortage. We have to use Z_R0.
-  }
-  lgr_if_needed(Rcard_addr_x, Rcard_addr);
-
-  load_and_test_long(Rqueue_index, Address(Z_thread, qidx_off));
-  z_bre(callRuntime); // Index == 0 then jump to runtime.
-
-  z_lg(Rqueue_buf, qbuf_off, Z_thread);
-
-  add2reg(Rqueue_index, -wordSize); // Decrement index.
-  z_stg(Rqueue_index, qidx_off, Z_thread);
-
-  z_stg(Rcard_addr_x, 0, Rqueue_index, Rqueue_buf); // Store card.
-  z_bru(filtered);
-
-  bind(callRuntime);
-
-  // TODO: do we need a frame? Introduced to be on the safe side.
-  bool needs_frame = true;
-  lgr_if_needed(Rcard_addr, Rcard_addr_x); // copy back asap. push_frame will destroy Z_R0_scratch!
-
-  // VM call need frame to access(write) O register.
-  if (needs_frame) {
-    save_return_pc();
-    push_frame_abi160(0); // Will use Z_R0 as tmp on old CPUs.
-  }
-
-  // Save the live input values.
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), Rcard_addr, Z_thread);
-
-  if (needs_frame) {
-    pop_frame();
-    restore_return_pc();
-  }
-
-  bind(filtered);
-
-  BLOCK_COMMENT("} g1_write_barrier_post");
-}
-#endif // INCLUDE_ALL_GCS
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->resolve_jobject(this, value, tmp1, tmp2);
+}
 
 // Last_Java_sp must comply to the rules in frame_s390.hpp.
 void MacroAssembler::set_last_Java_frame(Register last_Java_sp, Register last_Java_pc, bool allow_relocation) {
--- a/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/macroAssembler_s390.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -744,32 +744,8 @@
   void compiler_fast_lock_object(Register oop, Register box, Register temp1, Register temp2, bool try_bias = UseBiasedLocking);
   void compiler_fast_unlock_object(Register oop, Register box, Register temp1, Register temp2, bool try_bias = UseBiasedLocking);
 
-  // Write to card table for modification at store_addr - register is destroyed afterwards.
-  void card_write_barrier_post(Register store_addr, Register tmp);
-
   void resolve_jobject(Register value, Register tmp1, Register tmp2);
 
-#if INCLUDE_ALL_GCS
-  // General G1 pre-barrier generator.
-  // Purpose: record the previous value if it is not null.
-  // All non-tmps are preserved.
-  void g1_write_barrier_pre(Register           Robj,
-                            RegisterOrConstant offset,
-                            Register           Rpre_val,        // Ideally, this is a non-volatile register.
-                            Register           Rval,            // Will be preserved.
-                            Register           Rtmp1,           // If Rpre_val is volatile, either Rtmp1
-                            Register           Rtmp2,           // or Rtmp2 has to be non-volatile.
-                            bool               pre_val_needed); // Save Rpre_val across runtime call, caller uses it.
-
-  // General G1 post-barrier generator.
-  // Purpose: Store cross-region card.
-  void g1_write_barrier_post(Register Rstore_addr,
-                             Register Rnew_val,
-                             Register Rtmp1,
-                             Register Rtmp2,
-                             Register Rtmp3);
-#endif // INCLUDE_ALL_GCS
-
   // Support for last Java frame (but use call_VM instead where possible).
  private:
   void set_last_Java_frame(Register last_Java_sp, Register last_Java_pc, bool allow_relocation);
--- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1308,7 +1308,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, Z_ARG1, Z_ARG2, Z_ARG3);
 
     generate_disjoint_copy(aligned, size, true, true);
@@ -1400,7 +1400,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, Z_ARG1, Z_ARG2, Z_ARG3);
 
     generate_conjoint_copy(aligned, size, true);  // Must preserve ARG2, ARG3.
--- a/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/templateInterpreterGenerator_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017, SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/abstractInterpreter.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #include "interpreter/interpreter.hpp"
@@ -479,73 +480,55 @@
 }
 
 address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) {
-    // Inputs:
-    //  Z_ARG1 - receiver
-    //
-    // What we do:
-    //  - Load the referent field address.
-    //  - Load the value in the referent field.
-    //  - Pass that value to the pre-barrier.
-    //
-    // In the case of G1 this will record the value of the
-    // referent in an SATB buffer if marking is active.
-    // This will cause concurrent marking to mark the referent
-    // field as live.
-
-    Register  scratch1 = Z_tmp_2;
-    Register  scratch2 = Z_tmp_3;
-    Register  pre_val  = Z_RET;   // return value
-    // Z_esp is callers operand stack pointer, i.e. it points to the parameters.
-    Register  Rargp    = Z_esp;
-
-    Label     slow_path;
-    address   entry = __ pc();
-
-    const int referent_offset = java_lang_ref_Reference::referent_offset;
-    guarantee(referent_offset > 0, "referent offset not initialized");
-
-    BLOCK_COMMENT("Reference_get {");
-
-    //  If the receiver is null then it is OK to jump to the slow path.
-    __ load_and_test_long(pre_val, Address(Rargp, Interpreter::stackElementSize)); // Get receiver.
-    __ z_bre(slow_path);
-
-    //  Load the value of the referent field.
-    __ load_heap_oop(pre_val, referent_offset, pre_val);
-
-    // Restore caller sp for c2i case.
-    __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
-
-    // Generate the G1 pre-barrier code to log the value of
-    // the referent field in an SATB buffer.
-    // Note:
-    //   With these parameters the write_barrier_pre does not
-    //   generate instructions to load the previous value.
-    __ g1_write_barrier_pre(noreg,      // obj
-                            noreg,      // offset
-                            pre_val,    // pre_val
-                            noreg,      // no new val to preserve
-                            scratch1,   // tmp
-                            scratch2,   // tmp
-                            true);      // pre_val_needed
-
-    __ z_br(Z_R14);
-
-    // Branch to previously generated regular method entry.
-    __ bind(slow_path);
-
-    address meth_entry = Interpreter::entry_for_kind(Interpreter::zerolocals);
-    __ jump_to_entry(meth_entry, Z_R1);
-
-    BLOCK_COMMENT("} Reference_get");
-
-    return entry;
-  }
-#endif // INCLUDE_ALL_GCS
-
-  return NULL;
+  // Inputs:
+  //  Z_ARG1 - receiver
+  //
+  // What we do:
+  //  - Load the referent field address.
+  //  - Load the value in the referent field.
+  //  - Pass that value to the pre-barrier.
+  //
+  // In the case of G1 this will record the value of the
+  // referent in an SATB buffer if marking is active.
+  // This will cause concurrent marking to mark the referent
+  // field as live.
+
+  Register  scratch1 = Z_tmp_2;
+  Register  scratch2 = Z_tmp_3;
+  Register  pre_val  = Z_RET;   // return value
+  // Z_esp is callers operand stack pointer, i.e. it points to the parameters.
+  Register  Rargp    = Z_esp;
+
+  Label     slow_path;
+  address   entry = __ pc();
+
+  const int referent_offset = java_lang_ref_Reference::referent_offset;
+  guarantee(referent_offset > 0, "referent offset not initialized");
+
+  BLOCK_COMMENT("Reference_get {");
+
+  //  If the receiver is null then it is OK to jump to the slow path.
+  __ load_and_test_long(pre_val, Address(Rargp, Interpreter::stackElementSize)); // Get receiver.
+  __ z_bre(slow_path);
+
+  //  Load the value of the referent field.
+ BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+ bs->load_at(_masm, IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT,
+                   Address(pre_val, referent_offset), pre_val, scratch1, scratch2);
+
+  // Restore caller sp for c2i case.
+  __ resize_frame_absolute(Z_R10, Z_R0, true); // Cut the stack back to where the caller started.
+  __ z_br(Z_R14);
+
+  // Branch to previously generated regular method entry.
+  __ bind(slow_path);
+
+  address meth_entry = Interpreter::entry_for_kind(Interpreter::zerolocals);
+  __ jump_to_entry(meth_entry, Z_R1);
+
+  BLOCK_COMMENT("} Reference_get");
+
+  return entry;
 }
 
 address TemplateInterpreterGenerator::generate_StackOverflowError_handler() {
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, 2017 SAP SE. All rights reserved.
+ * Copyright (c) 2016, 2018 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/interp_masm.hpp"
@@ -192,97 +193,27 @@
 // Do an oop store like *(base + offset) = val
 // offset can be a register or a constant.
 static void do_oop_store(InterpreterMacroAssembler* _masm,
-                         Register base,
-                         RegisterOrConstant offset,
-                         Register val,
-                         bool val_is_null, // == false does not guarantee that val really is not equal NULL.
-                         Register tmp1,    // If tmp3 is volatile, either tmp1 or tmp2 must be
-                         Register tmp2,    // non-volatile to hold a copy of pre_val across runtime calls.
-                         Register tmp3,    // Ideally, this tmp register is non-volatile, as it is used to
-                                           // hold pre_val (must survive runtime calls).
-                         BarrierSet::Name barrier,
-                         bool precise) {
-  BLOCK_COMMENT("do_oop_store {");
-  assert(val != noreg, "val must always be valid, even if it is zero");
-  assert_different_registers(tmp1, tmp2, tmp3, val, base, offset.register_or_noreg());
-  __ verify_oop(val);
-  switch (barrier) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      {
-#ifdef ASSERT
-        if (val_is_null) { // Check if the flag setting reflects reality.
-          Label OK;
-          __ z_ltgr(val, val);
-          __ z_bre(OK);
-          __ z_illtrap(0x11);
-          __ bind(OK);
-        }
-#endif
-        Register pre_val = tmp3;
-        // Load and record the previous value.
-        __ g1_write_barrier_pre(base, offset, pre_val, val,
-                                tmp1, tmp2,
-                                false);  // Needs to hold pre_val in non_volatile register?
-
-        if (val_is_null) {
-          __ store_heap_oop_null(val, offset, base);
-        } else {
-          Label Done;
-          // val_is_null == false does not guarantee that val really is not equal NULL.
-          // Checking for this case dynamically has some cost, but also some benefit (in GC).
-          // It's hard to say if cost or benefit is greater.
-          { Label OK;
-            __ z_ltgr(val, val);
-            __ z_brne(OK);
-            __ store_heap_oop_null(val, offset, base);
-            __ z_bru(Done);
-            __ bind(OK);
-          }
-          // G1 barrier needs uncompressed oop for region cross check.
-          // Store_heap_oop compresses the oop in the argument register.
-          Register val_work = val;
-          if (UseCompressedOops) {
-            val_work = tmp3;
-            __ z_lgr(val_work, val);
-          }
-          __ store_heap_oop_not_null(val_work, offset, base);
-
-          // We need precise card marks for oop array stores.
-          // Otherwise, cardmarking the object which contains the oop is sufficient.
-          if (precise && !(offset.is_constant() && offset.as_constant() == 0)) {
-            __ add2reg_with_index(base,
-                                  offset.constant_or_zero(),
-                                  offset.register_or_noreg(),
-                                  base);
-          }
-          __ g1_write_barrier_post(base /* store_adr */, val, tmp1, tmp2, tmp3);
-          __ bind(Done);
-        }
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-    {
-      if (val_is_null) {
-        __ store_heap_oop_null(val, offset, base);
-      } else {
-        __ store_heap_oop(val, offset, base);
-        // Flatten object address if needed.
-        if (precise && ((offset.register_or_noreg() != noreg) || (offset.constant_or_zero() != 0))) {
-          __ load_address(base, Address(base, offset.register_or_noreg(), offset.constant_or_zero()));
-        }
-        __ card_write_barrier_post(base, tmp1);
-      }
-    }
-    break;
-  case BarrierSet::ModRef:
-    // fall through
-  default:
-    ShouldNotReachHere();
-
-  }
-  BLOCK_COMMENT("} do_oop_store");
+                         const Address&     addr,
+                         Register           val,         // Noreg means always null.
+                         Register           tmp1,
+                         Register           tmp2,
+                         Register           tmp3,
+                         DecoratorSet       decorators) {
+  assert_different_registers(tmp1, tmp2, tmp3, val, addr.base());
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->store_at(_masm, decorators, T_OBJECT, addr, val, tmp1, tmp2, tmp3);
+}
+
+static void do_oop_load(InterpreterMacroAssembler* _masm,
+                        const Address& addr,
+                        Register dst,
+                        Register tmp1,
+                        Register tmp2,
+                        DecoratorSet decorators) {
+  assert_different_registers(addr.base(), tmp1, tmp2);
+  assert_different_registers(dst, tmp1, tmp2);
+  BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->load_at(_masm, decorators, T_OBJECT, addr, dst, tmp1, tmp2);
 }
 
 Address TemplateTable::at_bcp(int offset) {
@@ -923,8 +854,8 @@
   Register index = Z_tos;
   index_check(Z_tmp_1, index, shift);
   // Now load array element.
-  __ load_heap_oop(Z_tos,
-                   Address(Z_tmp_1, index, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  do_oop_load(_masm, Address(Z_tmp_1, index, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), Z_tos,
+              Z_tmp_2, Z_tmp_3, IN_HEAP | IN_HEAP_ARRAY);
   __ verify_oop(Z_tos);
 }
 
@@ -1260,22 +1191,23 @@
   __ load_absolute_address(tmp1, Interpreter::_throw_ArrayStoreException_entry);
   __ z_br(tmp1);
 
-  // Come here on success.
-  __ bind(ok_is_subtype);
-
-  // Now store using the appropriate barrier.
   Register tmp3 = Rsub_klass;
-  do_oop_store(_masm, Rstore_addr, (intptr_t)0/*offset*/, Rvalue, false/*val==null*/,
-               tmp3, tmp2, tmp1, _bs->kind(), true);
-  __ z_bru(done);
 
   // Have a NULL in Rvalue.
   __ bind(is_null);
   __ profile_null_seen(tmp1);
 
   // Store a NULL.
-  do_oop_store(_masm, Rstore_addr, (intptr_t)0/*offset*/, Rvalue, true/*val==null*/,
-               tmp3, tmp2, tmp1, _bs->kind(), true);
+  do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), noreg,
+               tmp3, tmp2, tmp1, IN_HEAP | IN_HEAP_ARRAY);
+  __ z_bru(done);
+
+  // Come here on success.
+  __ bind(ok_is_subtype);
+
+  // Now store using the appropriate barrier.
+  do_oop_store(_masm, Address(Rstore_addr, (intptr_t)0), Rvalue,
+               tmp3, tmp2, tmp1, IN_HEAP | IN_HEAP_ARRAY | OOP_NOT_NULL);
 
   // Pop stack arguments.
   __ bind(done);
@@ -2831,7 +2763,7 @@
                       // to here is compensated for by the fallthru to "Done".
   {
     unsigned int b_off = __ offset();
-    __ load_heap_oop(Z_tos, field);
+    do_oop_load(_masm, field, Z_tos, Z_tmp_2, Z_tmp_3, IN_HEAP);
     __ verify_oop(Z_tos);
     __ push(atos);
     if (do_rewrite) {
@@ -3160,8 +3092,8 @@
       pop_and_check_object(obj);
     }
     // Store into the field
-    do_oop_store(_masm, obj, off, Z_tos, false,
-                 oopStore_tmp1, oopStore_tmp2, oopStore_tmp3, _bs->kind(), false);
+    do_oop_store(_masm, Address(obj, off), Z_tos,
+                 oopStore_tmp1, oopStore_tmp2, oopStore_tmp3, IN_HEAP);
     if (do_rewrite) {
       patch_bytecode(Bytecodes::_fast_aputfield, bc, Z_ARG5, true, byte_no);
     }
@@ -3322,8 +3254,8 @@
   // access field
   switch (bytecode()) {
     case Bytecodes::_fast_aputfield:
-      do_oop_store(_masm, obj, field_offset, Z_tos, false,
-                   Z_ARG2, Z_ARG3, Z_ARG4, _bs->kind(), false);
+      do_oop_store(_masm, Address(obj, field_offset), Z_tos,
+                   Z_ARG2, Z_ARG3, Z_ARG4, IN_HEAP);
       break;
     case Bytecodes::_fast_lputfield:
       __ reg2mem_opt(Z_tos, field);
@@ -3414,7 +3346,7 @@
   // access field
   switch (bytecode()) {
     case Bytecodes::_fast_agetfield:
-      __ load_heap_oop(Z_tos, field);
+      do_oop_load(_masm, field, Z_tos, Z_tmp_1, Z_tmp_2, IN_HEAP);
       __ verify_oop(Z_tos);
       return;
     case Bytecodes::_fast_lgetfield:
@@ -3470,7 +3402,7 @@
       __ mem2reg_opt(Z_tos, Address(receiver, index), false);
       break;
     case atos:
-      __ load_heap_oop(Z_tos, Address(receiver, index));
+      do_oop_load(_masm, Address(receiver, index), Z_tos, Z_tmp_1, Z_tmp_2, IN_HEAP);
       __ verify_oop(Z_tos);
       break;
     case ftos:
--- a/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -43,6 +43,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 // Implementation of StubAssembler
@@ -761,7 +762,7 @@
 #if INCLUDE_ALL_GCS
     case g1_pre_barrier_slow_id:
       { // G4: previous value of memory
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ save_frame(0);
           __ set((int)id, O1);
@@ -777,15 +778,9 @@
         Register tmp2 = G3_scratch;
 
         Label refill, restart;
-        int satb_q_active_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_active());
-        int satb_q_index_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_index());
-        int satb_q_buf_byte_offset =
-          in_bytes(JavaThread::satb_mark_queue_offset() +
-                   SATBMarkQueue::byte_offset_of_buf());
+        int satb_q_active_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
+        int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
+        int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
 
         // Is marking still active?
         if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
@@ -832,7 +827,7 @@
 
     case g1_post_barrier_slow_id:
       {
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ save_frame(0);
           __ set((int)id, O1);
@@ -886,12 +881,8 @@
         // these registers are now dead
         addr = cardtable = tmp = noreg;
 
-        int dirty_card_q_index_byte_offset =
-          in_bytes(JavaThread::dirty_card_queue_offset() +
-                   DirtyCardQueue::byte_offset_of_index());
-        int dirty_card_q_buf_byte_offset =
-          in_bytes(JavaThread::dirty_card_queue_offset() +
-                   DirtyCardQueue::byte_offset_of_buf());
+        int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
+        int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 
         __ bind(restart);
 
--- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -27,11 +27,10 @@
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "runtime/thread.hpp"
 #include "utilities/macros.hpp"
 
 #define __ masm->
@@ -46,11 +45,10 @@
     Label filtered;
     // Is marking active?
     if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-      __ ld(G2, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), tmp);
+      __ ld(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
     } else {
-      guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
-                "Assumption");
-      __ ldsb(G2, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), tmp);
+      guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+      __ ldsb(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
     }
     // Is marking active?
     __ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
@@ -91,3 +89,408 @@
   __ delayed()->mov(count->after_save(), O1);
   __ restore();
 }
+
+#undef __
+
+static address satb_log_enqueue_with_frame = NULL;
+static u_char* satb_log_enqueue_with_frame_end = NULL;
+
+static address satb_log_enqueue_frameless = NULL;
+static u_char* satb_log_enqueue_frameless_end = NULL;
+
+static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions?
+
+static void generate_satb_log_enqueue(bool with_frame) {
+  BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize);
+  CodeBuffer buf(bb);
+  MacroAssembler masm(&buf);
+
+#define __ masm.
+
+  address start = __ pc();
+  Register pre_val;
+
+  Label refill, restart;
+  if (with_frame) {
+    __ save_frame(0);
+    pre_val = I0;  // Was O0 before the save.
+  } else {
+    pre_val = O0;
+  }
+
+  int satb_q_index_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
+  int satb_q_buf_byte_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
+
+  assert(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t) &&
+         in_bytes(SATBMarkQueue::byte_width_of_buf()) == sizeof(intptr_t),
+         "check sizes in assembly below");
+
+  __ bind(restart);
+
+  // Load the index into the SATB buffer. SATBMarkQueue::_index is a size_t
+  // so ld_ptr is appropriate.
+  __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0);
+
+  // index == 0?
+  __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
+
+  __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1);
+  __ sub(L0, oopSize, L0);
+
+  __ st_ptr(pre_val, L1, L0);  // [_buf + index] := I0
+  if (!with_frame) {
+    // Use return-from-leaf
+    __ retl();
+    __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset);
+  } else {
+    // Not delayed.
+    __ st_ptr(L0, G2_thread, satb_q_index_byte_offset);
+  }
+  if (with_frame) {
+    __ ret();
+    __ delayed()->restore();
+  }
+  __ bind(refill);
+
+  address handle_zero =
+    CAST_FROM_FN_PTR(address,
+                     &SATBMarkQueueSet::handle_zero_index_for_thread);
+  // This should be rare enough that we can afford to save all the
+  // scratch registers that the calling context might be using.
+  __ mov(G1_scratch, L0);
+  __ mov(G3_scratch, L1);
+  __ mov(G4, L2);
+  // We need the value of O0 above (for the write into the buffer), so we
+  // save and restore it.
+  __ mov(O0, L3);
+  // Since the call will overwrite O7, we save and restore that, as well.
+  __ mov(O7, L4);
+  __ call_VM_leaf(L5, handle_zero, G2_thread);
+  __ mov(L0, G1_scratch);
+  __ mov(L1, G3_scratch);
+  __ mov(L2, G4);
+  __ mov(L3, O0);
+  __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
+  __ delayed()->mov(L4, O7);
+
+  if (with_frame) {
+    satb_log_enqueue_with_frame = start;
+    satb_log_enqueue_with_frame_end = __ pc();
+  } else {
+    satb_log_enqueue_frameless = start;
+    satb_log_enqueue_frameless_end = __ pc();
+  }
+
+#undef __
+}
+
+#define __ masm->
+
+void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
+                                                 Register obj,
+                                                 Register index,
+                                                 int offset,
+                                                 Register pre_val,
+                                                 Register tmp,
+                                                 bool preserve_o_regs) {
+  Label filtered;
+
+  if (obj == noreg) {
+    // We are not loading the previous value so make
+    // sure that we don't trash the value in pre_val
+    // with the code below.
+    assert_different_registers(pre_val, tmp);
+  } else {
+    // We will be loading the previous value
+    // in this code so...
+    assert(offset == 0 || index == noreg, "choose one");
+    assert(pre_val == noreg, "check this code");
+  }
+
+  // Is marking active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ ld(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
+  } else {
+    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ ldsb(G2, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), tmp);
+  }
+
+  // Is marking active?
+  __ cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
+
+  // Do we need to load the previous value?
+  if (obj != noreg) {
+    // Load the previous value...
+    if (index == noreg) {
+      if (Assembler::is_simm13(offset)) {
+        __ load_heap_oop(obj, offset, tmp);
+      } else {
+        __ set(offset, tmp);
+        __ load_heap_oop(obj, tmp, tmp);
+      }
+    } else {
+      __ load_heap_oop(obj, index, tmp);
+    }
+    // Previous value has been loaded into tmp
+    pre_val = tmp;
+  }
+
+  assert(pre_val != noreg, "must have a real register");
+
+  // Is the previous value null?
+  __ cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered);
+
+  // OK, it's not filtered, so we'll need to call enqueue.  In the normal
+  // case, pre_val will be a scratch G-reg, but there are some cases in
+  // which it's an O-reg.  In the first case, do a normal call.  In the
+  // latter, do a save here and call the frameless version.
+
+  guarantee(pre_val->is_global() || pre_val->is_out(),
+            "Or we need to think harder.");
+
+  if (pre_val->is_global() && !preserve_o_regs) {
+    __ call(satb_log_enqueue_with_frame);
+    __ delayed()->mov(pre_val, O0);
+  } else {
+    __ save_frame(0);
+    __ call(satb_log_enqueue_frameless);
+    __ delayed()->mov(pre_val->after_save(), O0);
+    __ restore();
+  }
+
+  __ bind(filtered);
+}
+
+#undef __
+
+static address dirty_card_log_enqueue = 0;
+static u_char* dirty_card_log_enqueue_end = 0;
+
+// This gets to assume that o0 contains the object address.
+static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
+  BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2);
+  CodeBuffer buf(bb);
+  MacroAssembler masm(&buf);
+#define __ masm.
+  address start = __ pc();
+
+  Label not_already_dirty, restart, refill, young_card;
+
+  __ srlx(O0, CardTable::card_shift, O0);
+  AddressLiteral addrlit(byte_map_base);
+  __ set(addrlit, O1); // O1 := <card table base>
+  __ ldub(O0, O1, O2); // O2 := [O0 + O1]
+
+  __ cmp_and_br_short(O2, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
+
+  __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+  __ ldub(O0, O1, O2); // O2 := [O0 + O1]
+
+  assert(G1CardTable::dirty_card_val() == 0, "otherwise check this code");
+  __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
+
+  __ bind(young_card);
+  // We didn't take the branch, so we're already dirty: return.
+  // Use return-from-leaf
+  __ retl();
+  __ delayed()->nop();
+
+  // Not dirty.
+  __ bind(not_already_dirty);
+
+  // Get O0 + O1 into a reg by itself
+  __ add(O0, O1, O3);
+
+  // First, dirty it.
+  __ stb(G0, O3, G0);  // [cardPtr] := 0  (i.e., dirty).
+
+  int dirty_card_q_index_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
+  int dirty_card_q_buf_byte_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
+  __ bind(restart);
+
+  // Load the index into the update buffer. DirtyCardQueue::_index is
+  // a size_t so ld_ptr is appropriate here.
+  __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0);
+
+  // index == 0?
+  __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
+
+  __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1);
+  __ sub(L0, oopSize, L0);
+
+  __ st_ptr(O3, L1, L0);  // [_buf + index] := I0
+  // Use return-from-leaf
+  __ retl();
+  __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset);
+
+  __ bind(refill);
+  address handle_zero =
+    CAST_FROM_FN_PTR(address,
+                     &DirtyCardQueueSet::handle_zero_index_for_thread);
+  // This should be rare enough that we can afford to save all the
+  // scratch registers that the calling context might be using.
+  __ mov(G1_scratch, L3);
+  __ mov(G3_scratch, L5);
+  // We need the value of O3 above (for the write into the buffer), so we
+  // save and restore it.
+  __ mov(O3, L6);
+  // Since the call will overwrite O7, we save and restore that, as well.
+  __ mov(O7, L4);
+
+  __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread);
+  __ mov(L3, G1_scratch);
+  __ mov(L5, G3_scratch);
+  __ mov(L6, O3);
+  __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
+  __ delayed()->mov(L4, O7);
+
+  dirty_card_log_enqueue = start;
+  dirty_card_log_enqueue_end = __ pc();
+  // XXX Should have a guarantee here about not going off the end!
+  // Does it already do so?  Do an experiment...
+
+#undef __
+
+}
+
+#define __ masm->
+
+void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp) {
+  Label filtered;
+  MacroAssembler* post_filter_masm = masm;
+
+  if (new_val == G0) return;
+
+  G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+
+  if (G1RSBarrierRegionFilter) {
+    __ xor3(store_addr, new_val, tmp);
+    __ srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp);
+
+    __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
+  }
+
+  // If the "store_addr" register is an "in" or "local" register, move it to
+  // a scratch reg so we can pass it as an argument.
+  bool use_scr = !(store_addr->is_global() || store_addr->is_out());
+  // Pick a scratch register different from "tmp".
+  Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch);
+  // Make sure we use up the delay slot!
+  if (use_scr) {
+    post_filter_masm->mov(store_addr, scr);
+  } else {
+    post_filter_masm->nop();
+  }
+  __ save_frame(0);
+  __ call(dirty_card_log_enqueue);
+  if (use_scr) {
+    __ delayed()->mov(scr, O0);
+  } else {
+    __ delayed()->mov(store_addr->after_save(), O0);
+  }
+  __ restore();
+
+  __ bind(filtered);
+}
+
+void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Register val, Address dst, Register tmp) {
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0;
+
+  bool needs_pre_barrier = in_heap || in_concurrent_root;
+  // No need for post barrier if storing NULL
+  bool needs_post_barrier = val != G0 && in_heap;
+
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+
+  Register index = dst.has_index() ? dst.index() : noreg;
+  int disp = dst.has_disp() ? dst.disp() : 0;
+
+  if (needs_pre_barrier) {
+    // Load and record the previous value.
+    g1_write_barrier_pre(masm, dst.base(), index, disp,
+                         noreg /* pre_val */,
+                         tmp, true /*preserve_o_regs*/);
+  }
+
+  Register new_val = val;
+  if (needs_post_barrier) {
+    // G1 barrier needs uncompressed oop for region cross check.
+    if (UseCompressedOops && val != G0) {
+      new_val = tmp;
+      __ mov(val, new_val);
+    }
+  }
+
+  BarrierSetAssembler::store_at(masm, decorators, type, val, dst, tmp);
+
+  if (needs_post_barrier) {
+    Register base = dst.base();
+    if (precise) {
+      if (!dst.has_index()) {
+        __ add(base, disp, base);
+      } else {
+        assert(!dst.has_disp(), "not supported yet");
+        __ add(base, index, base);
+      }
+    }
+    g1_write_barrier_post(masm, base, new_val, tmp);
+  }
+}
+
+void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                    Address src, Register dst, Register tmp) {
+  bool on_oop = type == T_OBJECT || type == T_ARRAY;
+  bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
+  bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+  bool on_reference = on_weak || on_phantom;
+  // Load the value of the referent field.
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, src, dst, tmp);
+  if (on_oop && on_reference) {
+    // Generate the G1 pre-barrier code to log the value of
+    // the referent field in an SATB buffer. Note with
+    // these parameters the pre-barrier does not generate
+    // the load of the previous value
+
+    Register pre_val = dst;
+    bool saved = false;
+    if (pre_val->is_in()) {
+      // The g1_write_barrier_pre method assumes that the pre_val
+      // is not in an input register.
+      __ save_frame_and_mov(0, pre_val, O0);
+      pre_val = O0;
+      saved = true;
+    }
+
+    g1_write_barrier_pre(masm, noreg /* obj */, noreg /* index */, 0 /* offset */,
+                         pre_val /* pre_val */,
+                         tmp /* tmp */,
+                         true /* preserve_o_regs */);
+
+    if (saved) {
+      __ restore();
+    }
+  }
+}
+
+#undef __
+
+void G1BarrierSetAssembler::barrier_stubs_init() {
+  if (dirty_card_log_enqueue == 0) {
+    G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+    CardTable *ct = bs->card_table();
+    generate_dirty_card_log_enqueue(ct->byte_map_base());
+    assert(dirty_card_log_enqueue != 0, "postcondition.");
+  }
+  if (satb_log_enqueue_with_frame == 0) {
+    generate_satb_log_enqueue(true);
+    assert(satb_log_enqueue_with_frame != 0, "postcondition.");
+  }
+  if (satb_log_enqueue_frameless == 0) {
+    generate_satb_log_enqueue(false);
+    assert(satb_log_enqueue_frameless != 0, "postcondition.");
+  }
+}
--- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,10 +30,19 @@
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
-  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                               Register addr, Register count);
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                Register addr, Register count, Register tmp);
+  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count);
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp);
+
+  void g1_write_barrier_pre(MacroAssembler* masm, Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs);
+  void g1_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Register val, Address dst, Register tmp);
+
+public:
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Address src, Register dst, Register tmp);
+  virtual void barrier_stubs_init();
 };
 
 #endif // CPU_SPARC_GC_G1_G1BARRIERSETASSEMBLER_SPARC_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                   Register val, Address dst, Register tmp) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+
+  switch (type) {
+  case T_ARRAY:
+  case T_OBJECT: {
+    if (on_heap) {
+      if (dst.has_disp() && !Assembler::is_simm13(dst.disp())) {
+        assert(!dst.has_index(), "not supported yet");
+        __ set(dst.disp(), tmp);
+        dst = Address(dst.base(), tmp);
+      }
+      if (UseCompressedOops) {
+        assert(dst.base() != val, "not enough registers");
+        if (oop_not_null) {
+          __ encode_heap_oop_not_null(val);
+        } else {
+          __ encode_heap_oop(val);
+        }
+        __ st(val, dst);
+      } else {
+        __ st_ptr(val, dst);
+      }
+    } else {
+      assert(on_root, "why else?");
+      __ st_ptr(val, dst);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                  Address src, Register dst, Register tmp) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+
+  switch (type) {
+  case T_ARRAY:
+  case T_OBJECT: {
+    if (on_heap) {
+      if (src.has_disp() && !Assembler::is_simm13(src.disp())) {
+        assert(!src.has_index(), "not supported yet");
+        __ set(src.disp(), tmp);
+        src = Address(src.base(), tmp);
+      }
+      if (UseCompressedOops) {
+        __ lduw(src, dst);
+        if (oop_not_null) {
+          __ decode_heap_oop_not_null(dst);
+        } else {
+          __ decode_heap_oop(dst);
+        }
+      } else {
+        __ ld_ptr(src, dst);
+      }
+    } else {
+      assert(on_root, "why else?");
+      __ ld_ptr(src, dst);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
--- a/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/barrierSetAssembler_sparc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -37,6 +37,14 @@
                                   Register src, Register dst, Register count) {}
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count) {}
+
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Register src, Address dst, Register tmp);
+
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Address src, Register dst, Register tmp);
+
+  virtual void barrier_stubs_init() {}
 };
 
 #endif // CPU_SPARC_GC_SHARED_BARRIERSETASSEMBLER_SPARC_HPP
--- a/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,7 +29,6 @@
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 
 #define __ masm->
@@ -44,7 +43,7 @@
 
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                                     Register addr, Register count, Register tmp) {
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
   assert_different_registers(addr, count, tmp);
@@ -70,3 +69,45 @@
 
   __ BIND(L_done);
 }
+
+void CardTableBarrierSetAssembler::card_table_write(MacroAssembler* masm,
+                                                    jbyte* byte_map_base,
+                                                    Register tmp, Register obj) {
+  __ srlx(obj, CardTable::card_shift, obj);
+  assert(tmp != obj, "need separate temp reg");
+  __ set((address) byte_map_base, tmp);
+  __ stb(G0, tmp, obj);
+}
+
+void CardTableBarrierSetAssembler::card_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp) {
+  // If we're writing constant NULL, we can skip the write barrier.
+  if (new_val == G0) return;
+  CardTableBarrierSet* bs = barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
+  card_table_write(masm, bs->card_table()->byte_map_base(), tmp, store_addr);
+}
+
+void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                                Register val, Address dst, Register tmp) {
+  bool in_heap = (decorators & IN_HEAP) != 0;
+
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+
+  // No need for post barrier if storing NULL
+  bool needs_post_barrier = val != G0 && in_heap;
+
+  BarrierSetAssembler::store_at(masm, decorators, type, val, dst, tmp);
+  if (needs_post_barrier) {
+    Register base = dst.base();
+    if (precise) {
+      if (!dst.has_index()) {
+        __ add(base, dst.disp(), base);
+      } else {
+        assert(!dst.has_disp(), "not supported yet");
+        __ add(base, dst.index(), base);
+      }
+    }
+    card_write_barrier_post(masm, base, val, tmp);
+  }
+}
--- a/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/cardTableBarrierSetAssembler_sparc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -32,6 +32,13 @@
 protected:
   virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                 Register addr, Register count, Register tmp);
+
+  void card_table_write(MacroAssembler* masm, jbyte* byte_map_base, Register tmp, Register obj);
+
+  void card_write_barrier_post(MacroAssembler* masm, Register store_addr, Register new_val, Register tmp);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Register val, Address dst, Register tmp);
 };
 
 #endif // CPU_SPARC_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_SPARC_HPP
--- a/src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -55,3 +55,12 @@
     }
   }
 }
+
+void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Register val, Address dst, Register tmp) {
+  if (type == T_OBJECT || type == T_ARRAY) {
+    oop_store_at(masm, decorators, type, val, dst, tmp);
+  } else {
+    BarrierSetAssembler::store_at(masm, decorators, type, val, dst, tmp);
+  }
+}
--- a/src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/shared/modRefBarrierSetAssembler_sparc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,16 +28,27 @@
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 
+// The ModRefBarrierSetAssembler filters away accesses on BasicTypes other
+// than T_OBJECT/T_ARRAY (oops). The oop accesses call one of the protected
+// accesses, which are overridden in the concrete BarrierSetAssembler.
+
 class ModRefBarrierSetAssembler: public BarrierSetAssembler {
 protected:
-  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count) {}
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) {}
+  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+                                               Register addr, Register count) {}
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+                                                Register addr, Register count, Register tmp) {}
 
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Register val, Address dst, Register tmp) = 0;
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count);
+
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Register val, Address dst, Register tmp);
 };
 
 #endif // CPU_SPARC_GC_SHARED_MODREFBARRIERSETASSEMBLER_SPARC_HPP
--- a/src/hotspot/cpu/sparc/interp_masm_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/interp_masm_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -753,7 +753,7 @@
   resolve_oop_handle(result);
   // Add in the index
   add(result, tmp, result);
-  load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result);
+  load_heap_oop(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT), result, tmp);
 }
 
 
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,9 +26,9 @@
 #include "jvm.h"
 #include "asm/macroAssembler.inline.hpp"
 #include "compiler/disassembler.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
@@ -45,12 +45,6 @@
 #include "runtime/stubRoutines.hpp"
 #include "utilities/align.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/heapRegion.hpp"
-#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER2
 #include "opto/intrinsicnode.hpp"
 #endif
@@ -174,6 +168,24 @@
   return r;
 }
 
+void MacroAssembler::resolve_jobject(Register value, Register tmp) {
+  Label done, not_weak;
+  br_null(value, false, Assembler::pn, done); // Use NULL as-is.
+  delayed()->andcc(value, JNIHandles::weak_tag_mask, G0); // Test for jweak
+  brx(Assembler::zero, true, Assembler::pt, not_weak);
+  delayed()->nop();
+  access_load_at(T_OBJECT, IN_ROOT | ON_PHANTOM_OOP_REF,
+                 Address(value, -JNIHandles::weak_tag_value), value, tmp);
+  verify_oop(value);
+  br (Assembler::always, true, Assembler::pt, done);
+  delayed()->nop();
+  bind(not_weak);
+  access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT,
+                 Address(value, 0), value, tmp);
+  verify_oop(value);
+  bind(done);
+}
+
 void MacroAssembler::null_check(Register reg, int offset) {
   if (needs_explicit_null_check((intptr_t)offset)) {
     // provoke OS NULL exception if reg = NULL by
@@ -659,14 +671,6 @@
   }
 }
 
-void MacroAssembler::card_table_write(jbyte* byte_map_base,
-                                      Register tmp, Register obj) {
-  srlx(obj, CardTable::card_shift, obj);
-  assert(tmp != obj, "need separate temp reg");
-  set((address) byte_map_base, tmp);
-  stb(G0, tmp, obj);
-}
-
 
 void MacroAssembler::internal_sethi(const AddressLiteral& addrlit, Register d, bool ForceRelocatable) {
   address save_pc;
@@ -3387,361 +3391,6 @@
 
   bind(no_reserved_zone_enabling);
 }
-
-///////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-static address satb_log_enqueue_with_frame = NULL;
-static u_char* satb_log_enqueue_with_frame_end = NULL;
-
-static address satb_log_enqueue_frameless = NULL;
-static u_char* satb_log_enqueue_frameless_end = NULL;
-
-static int EnqueueCodeSize = 128 DEBUG_ONLY( + 256); // Instructions?
-
-static void generate_satb_log_enqueue(bool with_frame) {
-  BufferBlob* bb = BufferBlob::create("enqueue_with_frame", EnqueueCodeSize);
-  CodeBuffer buf(bb);
-  MacroAssembler masm(&buf);
-
-#define __ masm.
-
-  address start = __ pc();
-  Register pre_val;
-
-  Label refill, restart;
-  if (with_frame) {
-    __ save_frame(0);
-    pre_val = I0;  // Was O0 before the save.
-  } else {
-    pre_val = O0;
-  }
-
-  int satb_q_index_byte_offset =
-    in_bytes(JavaThread::satb_mark_queue_offset() +
-             SATBMarkQueue::byte_offset_of_index());
-
-  int satb_q_buf_byte_offset =
-    in_bytes(JavaThread::satb_mark_queue_offset() +
-             SATBMarkQueue::byte_offset_of_buf());
-
-  assert(in_bytes(SATBMarkQueue::byte_width_of_index()) == sizeof(intptr_t) &&
-         in_bytes(SATBMarkQueue::byte_width_of_buf()) == sizeof(intptr_t),
-         "check sizes in assembly below");
-
-  __ bind(restart);
-
-  // Load the index into the SATB buffer. SATBMarkQueue::_index is a size_t
-  // so ld_ptr is appropriate.
-  __ ld_ptr(G2_thread, satb_q_index_byte_offset, L0);
-
-  // index == 0?
-  __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
-
-  __ ld_ptr(G2_thread, satb_q_buf_byte_offset, L1);
-  __ sub(L0, oopSize, L0);
-
-  __ st_ptr(pre_val, L1, L0);  // [_buf + index] := I0
-  if (!with_frame) {
-    // Use return-from-leaf
-    __ retl();
-    __ delayed()->st_ptr(L0, G2_thread, satb_q_index_byte_offset);
-  } else {
-    // Not delayed.
-    __ st_ptr(L0, G2_thread, satb_q_index_byte_offset);
-  }
-  if (with_frame) {
-    __ ret();
-    __ delayed()->restore();
-  }
-  __ bind(refill);
-
-  address handle_zero =
-    CAST_FROM_FN_PTR(address,
-                     &SATBMarkQueueSet::handle_zero_index_for_thread);
-  // This should be rare enough that we can afford to save all the
-  // scratch registers that the calling context might be using.
-  __ mov(G1_scratch, L0);
-  __ mov(G3_scratch, L1);
-  __ mov(G4, L2);
-  // We need the value of O0 above (for the write into the buffer), so we
-  // save and restore it.
-  __ mov(O0, L3);
-  // Since the call will overwrite O7, we save and restore that, as well.
-  __ mov(O7, L4);
-  __ call_VM_leaf(L5, handle_zero, G2_thread);
-  __ mov(L0, G1_scratch);
-  __ mov(L1, G3_scratch);
-  __ mov(L2, G4);
-  __ mov(L3, O0);
-  __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
-  __ delayed()->mov(L4, O7);
-
-  if (with_frame) {
-    satb_log_enqueue_with_frame = start;
-    satb_log_enqueue_with_frame_end = __ pc();
-  } else {
-    satb_log_enqueue_frameless = start;
-    satb_log_enqueue_frameless_end = __ pc();
-  }
-
-#undef __
-}
-
-void MacroAssembler::g1_write_barrier_pre(Register obj,
-                                          Register index,
-                                          int offset,
-                                          Register pre_val,
-                                          Register tmp,
-                                          bool preserve_o_regs) {
-  Label filtered;
-
-  if (obj == noreg) {
-    // We are not loading the previous value so make
-    // sure that we don't trash the value in pre_val
-    // with the code below.
-    assert_different_registers(pre_val, tmp);
-  } else {
-    // We will be loading the previous value
-    // in this code so...
-    assert(offset == 0 || index == noreg, "choose one");
-    assert(pre_val == noreg, "check this code");
-  }
-
-  // Is marking active?
-  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    ld(G2,
-       in_bytes(JavaThread::satb_mark_queue_offset() +
-                SATBMarkQueue::byte_offset_of_active()),
-       tmp);
-  } else {
-    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
-              "Assumption");
-    ldsb(G2,
-         in_bytes(JavaThread::satb_mark_queue_offset() +
-                  SATBMarkQueue::byte_offset_of_active()),
-         tmp);
-  }
-
-  // Is marking active?
-  cmp_and_br_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
-
-  // Do we need to load the previous value?
-  if (obj != noreg) {
-    // Load the previous value...
-    if (index == noreg) {
-      if (Assembler::is_simm13(offset)) {
-        load_heap_oop(obj, offset, tmp);
-      } else {
-        set(offset, tmp);
-        load_heap_oop(obj, tmp, tmp);
-      }
-    } else {
-      load_heap_oop(obj, index, tmp);
-    }
-    // Previous value has been loaded into tmp
-    pre_val = tmp;
-  }
-
-  assert(pre_val != noreg, "must have a real register");
-
-  // Is the previous value null?
-  cmp_and_brx_short(pre_val, G0, Assembler::equal, Assembler::pt, filtered);
-
-  // OK, it's not filtered, so we'll need to call enqueue.  In the normal
-  // case, pre_val will be a scratch G-reg, but there are some cases in
-  // which it's an O-reg.  In the first case, do a normal call.  In the
-  // latter, do a save here and call the frameless version.
-
-  guarantee(pre_val->is_global() || pre_val->is_out(),
-            "Or we need to think harder.");
-
-  if (pre_val->is_global() && !preserve_o_regs) {
-    call(satb_log_enqueue_with_frame);
-    delayed()->mov(pre_val, O0);
-  } else {
-    save_frame(0);
-    call(satb_log_enqueue_frameless);
-    delayed()->mov(pre_val->after_save(), O0);
-    restore();
-  }
-
-  bind(filtered);
-}
-
-static address dirty_card_log_enqueue = 0;
-static u_char* dirty_card_log_enqueue_end = 0;
-
-// This gets to assume that o0 contains the object address.
-static void generate_dirty_card_log_enqueue(jbyte* byte_map_base) {
-  BufferBlob* bb = BufferBlob::create("dirty_card_enqueue", EnqueueCodeSize*2);
-  CodeBuffer buf(bb);
-  MacroAssembler masm(&buf);
-#define __ masm.
-  address start = __ pc();
-
-  Label not_already_dirty, restart, refill, young_card;
-
-  __ srlx(O0, CardTable::card_shift, O0);
-  AddressLiteral addrlit(byte_map_base);
-  __ set(addrlit, O1); // O1 := <card table base>
-  __ ldub(O0, O1, O2); // O2 := [O0 + O1]
-
-  __ cmp_and_br_short(O2, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
-
-  __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
-  __ ldub(O0, O1, O2); // O2 := [O0 + O1]
-
-  assert(CardTable::dirty_card_val() == 0, "otherwise check this code");
-  __ cmp_and_br_short(O2, G0, Assembler::notEqual, Assembler::pt, not_already_dirty);
-
-  __ bind(young_card);
-  // We didn't take the branch, so we're already dirty: return.
-  // Use return-from-leaf
-  __ retl();
-  __ delayed()->nop();
-
-  // Not dirty.
-  __ bind(not_already_dirty);
-
-  // Get O0 + O1 into a reg by itself
-  __ add(O0, O1, O3);
-
-  // First, dirty it.
-  __ stb(G0, O3, G0);  // [cardPtr] := 0  (i.e., dirty).
-
-  int dirty_card_q_index_byte_offset =
-    in_bytes(JavaThread::dirty_card_queue_offset() +
-             DirtyCardQueue::byte_offset_of_index());
-  int dirty_card_q_buf_byte_offset =
-    in_bytes(JavaThread::dirty_card_queue_offset() +
-             DirtyCardQueue::byte_offset_of_buf());
-  __ bind(restart);
-
-  // Load the index into the update buffer. DirtyCardQueue::_index is
-  // a size_t so ld_ptr is appropriate here.
-  __ ld_ptr(G2_thread, dirty_card_q_index_byte_offset, L0);
-
-  // index == 0?
-  __ cmp_and_brx_short(L0, G0, Assembler::equal, Assembler::pn, refill);
-
-  __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, L1);
-  __ sub(L0, oopSize, L0);
-
-  __ st_ptr(O3, L1, L0);  // [_buf + index] := I0
-  // Use return-from-leaf
-  __ retl();
-  __ delayed()->st_ptr(L0, G2_thread, dirty_card_q_index_byte_offset);
-
-  __ bind(refill);
-  address handle_zero =
-    CAST_FROM_FN_PTR(address,
-                     &DirtyCardQueueSet::handle_zero_index_for_thread);
-  // This should be rare enough that we can afford to save all the
-  // scratch registers that the calling context might be using.
-  __ mov(G1_scratch, L3);
-  __ mov(G3_scratch, L5);
-  // We need the value of O3 above (for the write into the buffer), so we
-  // save and restore it.
-  __ mov(O3, L6);
-  // Since the call will overwrite O7, we save and restore that, as well.
-  __ mov(O7, L4);
-
-  __ call_VM_leaf(L7_thread_cache, handle_zero, G2_thread);
-  __ mov(L3, G1_scratch);
-  __ mov(L5, G3_scratch);
-  __ mov(L6, O3);
-  __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
-  __ delayed()->mov(L4, O7);
-
-  dirty_card_log_enqueue = start;
-  dirty_card_log_enqueue_end = __ pc();
-  // XXX Should have a guarantee here about not going off the end!
-  // Does it already do so?  Do an experiment...
-
-#undef __
-
-}
-
-void MacroAssembler::g1_write_barrier_post(Register store_addr, Register new_val, Register tmp) {
-
-  Label filtered;
-  MacroAssembler* post_filter_masm = this;
-
-  if (new_val == G0) return;
-
-  G1BarrierSet* bs =
-    barrier_set_cast<G1BarrierSet>(Universe::heap()->barrier_set());
-  CardTable* ct = bs->card_table();
-
-  if (G1RSBarrierRegionFilter) {
-    xor3(store_addr, new_val, tmp);
-    srlx(tmp, HeapRegion::LogOfHRGrainBytes, tmp);
-
-    // XXX Should I predict this taken or not?  Does it matter?
-    cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pt, filtered);
-  }
-
-  // If the "store_addr" register is an "in" or "local" register, move it to
-  // a scratch reg so we can pass it as an argument.
-  bool use_scr = !(store_addr->is_global() || store_addr->is_out());
-  // Pick a scratch register different from "tmp".
-  Register scr = (tmp == G1_scratch ? G3_scratch : G1_scratch);
-  // Make sure we use up the delay slot!
-  if (use_scr) {
-    post_filter_masm->mov(store_addr, scr);
-  } else {
-    post_filter_masm->nop();
-  }
-  save_frame(0);
-  call(dirty_card_log_enqueue);
-  if (use_scr) {
-    delayed()->mov(scr, O0);
-  } else {
-    delayed()->mov(store_addr->after_save(), O0);
-  }
-  restore();
-
-  bind(filtered);
-}
-
-// Called from init_globals() after universe_init() and before interpreter_init()
-void g1_barrier_stubs_init() {
-  CollectedHeap* heap = Universe::heap();
-  if (heap->kind() == CollectedHeap::G1) {
-    // Only needed for G1
-    if (dirty_card_log_enqueue == 0) {
-      G1BarrierSet* bs =
-        barrier_set_cast<G1BarrierSet>(heap->barrier_set());
-      CardTable *ct = bs->card_table();
-      generate_dirty_card_log_enqueue(ct->byte_map_base());
-      assert(dirty_card_log_enqueue != 0, "postcondition.");
-    }
-    if (satb_log_enqueue_with_frame == 0) {
-      generate_satb_log_enqueue(true);
-      assert(satb_log_enqueue_with_frame != 0, "postcondition.");
-    }
-    if (satb_log_enqueue_frameless == 0) {
-      generate_satb_log_enqueue(false);
-      assert(satb_log_enqueue_frameless != 0, "postcondition.");
-    }
-  }
-}
-
-#endif // INCLUDE_ALL_GCS
-///////////////////////////////////////////////////////////////////////////////////
-
-void MacroAssembler::card_write_barrier_post(Register store_addr, Register new_val, Register tmp) {
-  // If we're writing constant NULL, we can skip the write barrier.
-  if (new_val == G0) return;
-  CardTableBarrierSet* bs =
-    barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
-  CardTable* ct = bs->card_table();
-
-  assert(bs->kind() == BarrierSet::CardTableBarrierSet, "wrong barrier");
-  card_table_write(ct->byte_map_base(), tmp, store_addr);
-}
-
 // ((OopHandle)result).resolve();
 void MacroAssembler::resolve_oop_handle(Register result) {
   // OopHandle::resolve is an indirection.
@@ -3786,65 +3435,63 @@
   }
 }
 
-void MacroAssembler::load_heap_oop(const Address& s, Register d) {
-  if (UseCompressedOops) {
-    lduw(s, d);
-    decode_heap_oop(d);
+void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators,
+                                     Register src, Address dst, Register tmp) {
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::store_at(this, decorators, type, src, dst, tmp);
   } else {
-    ld_ptr(s, d);
+    bs->store_at(this, decorators, type, src, dst, tmp);
   }
 }
 
-void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d) {
-   if (UseCompressedOops) {
-    lduw(s1, s2, d);
-    decode_heap_oop(d, d);
+void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators,
+                                    Address src, Register dst, Register tmp) {
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::load_at(this, decorators, type, src, dst, tmp);
   } else {
-    ld_ptr(s1, s2, d);
-  }
-}
-
-void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d) {
-   if (UseCompressedOops) {
-    lduw(s1, simm13a, d);
-    decode_heap_oop(d, d);
-  } else {
-    ld_ptr(s1, simm13a, d);
+    bs->load_at(this, decorators, type, src, dst, tmp);
   }
 }
 
-void MacroAssembler::load_heap_oop(Register s1, RegisterOrConstant s2, Register d) {
-  if (s2.is_constant())  load_heap_oop(s1, s2.as_constant(), d);
-  else                   load_heap_oop(s1, s2.as_register(), d);
+void MacroAssembler::load_heap_oop(const Address& s, Register d, Register tmp, DecoratorSet decorators) {
+  access_load_at(T_OBJECT, IN_HEAP | decorators, s, d, tmp);
+}
+
+void MacroAssembler::load_heap_oop(Register s1, Register s2, Register d, Register tmp, DecoratorSet decorators) {
+  access_load_at(T_OBJECT, IN_HEAP | decorators, Address(s1, s2), d, tmp);
 }
 
-void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2) {
-  if (UseCompressedOops) {
-    assert(s1 != d && s2 != d, "not enough registers");
-    encode_heap_oop(d);
-    st(d, s1, s2);
+void MacroAssembler::load_heap_oop(Register s1, int simm13a, Register d, Register tmp, DecoratorSet decorators) {
+  access_load_at(T_OBJECT, IN_HEAP | decorators, Address(s1, simm13a), d, tmp);
+}
+
+void MacroAssembler::load_heap_oop(Register s1, RegisterOrConstant s2, Register d, Register tmp, DecoratorSet decorators) {
+  if (s2.is_constant()) {
+    access_load_at(T_OBJECT, IN_HEAP | decorators, Address(s1, s2.as_constant()), d, tmp);
   } else {
-    st_ptr(d, s1, s2);
+    access_load_at(T_OBJECT, IN_HEAP | decorators, Address(s1, s2.as_register()), d, tmp);
   }
 }
 
-void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a) {
-  if (UseCompressedOops) {
-    assert(s1 != d, "not enough registers");
-    encode_heap_oop(d);
-    st(d, s1, simm13a);
-  } else {
-    st_ptr(d, s1, simm13a);
-  }
+void MacroAssembler::store_heap_oop(Register d, Register s1, Register s2, Register tmp, DecoratorSet decorators) {
+  access_store_at(T_OBJECT, IN_HEAP | decorators, d, Address(s1, s2), tmp);
+}
+
+void MacroAssembler::store_heap_oop(Register d, Register s1, int simm13a, Register tmp, DecoratorSet decorators) {
+  access_store_at(T_OBJECT, IN_HEAP | decorators, d, Address(s1, simm13a), tmp);
 }
 
-void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset) {
-  if (UseCompressedOops) {
-    assert(a.base() != d, "not enough registers");
-    encode_heap_oop(d);
-    st(d, a, offset);
+void MacroAssembler::store_heap_oop(Register d, const Address& a, int offset, Register tmp, DecoratorSet decorators) {
+  if (a.has_index()) {
+    assert(!a.has_disp(), "not supported yet");
+    assert(offset == 0, "not supported yet");
+    access_store_at(T_OBJECT, IN_HEAP | decorators, d, Address(a.base(), a.index()), tmp);
   } else {
-    st_ptr(d, a, offset);
+    access_store_at(T_OBJECT, IN_HEAP | decorators, d, Address(a.base(), a.disp() + offset), tmp);
   }
 }
 
--- a/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/macroAssembler_sparc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -703,6 +703,9 @@
   // cas_ptr will perform cas for 32 bit VM's and casx for 64 bit VM's
   inline void cas_ptr(  Register s1, Register s2, Register d);
 
+  // Resolve a jobject or jweak
+  void resolve_jobject(Register value, Register tmp);
+
   // Functions for isolating 64 bit shifts for LP64
   inline void sll_ptr( Register s1, Register s2, Register d );
   inline void sll_ptr( Register s1, int imm6a,   Register d );
@@ -974,13 +977,25 @@
   void store_klass_gap(Register s, Register dst_oop);
 
    // oop manipulations
-  void load_heap_oop(const Address& s, Register d);
-  void load_heap_oop(Register s1, Register s2, Register d);
-  void load_heap_oop(Register s1, int simm13a, Register d);
-  void load_heap_oop(Register s1, RegisterOrConstant s2, Register d);
-  void store_heap_oop(Register d, Register s1, Register s2);
-  void store_heap_oop(Register d, Register s1, int simm13a);
-  void store_heap_oop(Register d, const Address& a, int offset = 0);
+  void access_store_at(BasicType type, DecoratorSet decorators,
+                       Register src, Address dst, Register tmp);
+  void access_load_at(BasicType type, DecoratorSet decorators,
+                      Address src, Register dst, Register tmp);
+
+  void load_heap_oop(const Address& s, Register d,
+                     Register tmp = noreg, DecoratorSet decorators = 0);
+  void load_heap_oop(Register s1, Register s2, Register d,
+                     Register tmp = noreg, DecoratorSet decorators = 0);
+  void load_heap_oop(Register s1, int simm13a, Register d,
+                     Register tmp = noreg, DecoratorSet decorators = 0);
+  void load_heap_oop(Register s1, RegisterOrConstant s2, Register d,
+                     Register tmp = noreg, DecoratorSet decorators = 0);
+  void store_heap_oop(Register d, Register s1, Register s2,
+                      Register tmp = noreg, DecoratorSet decorators = 0);
+  void store_heap_oop(Register d, Register s1, int simm13a,
+                      Register tmp = noreg, DecoratorSet decorators = 0);
+  void store_heap_oop(Register d, const Address& a, int offset = 0,
+                      Register tmp = noreg, DecoratorSet decorators = 0);
 
   void encode_heap_oop(Register src, Register dst);
   void encode_heap_oop(Register r) {
@@ -1043,19 +1058,6 @@
   // check_and_forward_exception to handle exceptions when it is safe
   void check_and_forward_exception(Register scratch_reg);
 
-  // Write to card table for - register is destroyed afterwards.
-  void card_table_write(jbyte* byte_map_base, Register tmp, Register obj);
-
-  void card_write_barrier_post(Register store_addr, Register new_val, Register tmp);
-
-#if INCLUDE_ALL_GCS
-  // General G1 pre-barrier generator.
-  void g1_write_barrier_pre(Register obj, Register index, int offset, Register pre_val, Register tmp, bool preserve_o_regs);
-
-  // General G1 post-barrier generator
-  void g1_write_barrier_post(Register store_addr, Register new_val, Register tmp);
-#endif // INCLUDE_ALL_GCS
-
   // pushes double TOS element of FPU stack on CPU stack; pops from FPU stack
   void push_fTOS();
 
--- a/src/hotspot/cpu/sparc/memset_with_concurrent_readers_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/memset_with_concurrent_readers_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,8 +31,6 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
 
-#if INCLUDE_ALL_GCS
-
 // An implementation of memset, for use when there may be concurrent
 // readers of the region being stored into.
 //
@@ -156,5 +154,3 @@
   // Fill any partial word suffix.  Also the prefix if size < BytesPerWord.
   fill_subword(to, end, value);
 }
-
-#endif // INCLUDE_ALL_GCS
--- a/src/hotspot/cpu/sparc/methodHandles_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/methodHandles_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -180,13 +180,13 @@
 
   // Load the invoker, as MH -> MH.form -> LF.vmentry
   __ verify_oop(recv);
-  __ load_heap_oop(Address(recv,        NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())),   method_temp);
+  __ load_heap_oop(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes()), method_temp, temp2);
   __ verify_oop(method_temp);
-  __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())),  method_temp);
+  __ load_heap_oop(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes()), method_temp, temp2);
   __ verify_oop(method_temp);
-  __ load_heap_oop(Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), method_temp);
+  __ load_heap_oop(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes()), method_temp, temp2);
   __ verify_oop(method_temp);
-  __ ld_ptr(       Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())),   method_temp);
+  __ ld_ptr(Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())), method_temp);
 
   if (VerifyMethodHandles && !for_compiler_entry) {
     // make sure recv is already on stack
@@ -362,7 +362,7 @@
       if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
         Label L_ok;
         Register temp2_defc = temp2;
-        __ load_heap_oop(member_clazz, temp2_defc);
+        __ load_heap_oop(member_clazz, temp2_defc, temp3);
         load_klass_from_Class(_masm, temp2_defc, temp3, temp4);
         __ verify_klass_ptr(temp2_defc);
         __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, temp4, L_ok);
@@ -389,7 +389,7 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeSpecial, member_reg, temp2);
       }
-      __ load_heap_oop(member_vmtarget, G5_method);
+      __ load_heap_oop(member_vmtarget, G5_method, temp3);
       __ ld_ptr(vmtarget_method, G5_method);
       break;
 
@@ -397,7 +397,7 @@
       if (VerifyMethodHandles) {
         verify_ref_kind(_masm, JVM_REF_invokeStatic, member_reg, temp2);
       }
-      __ load_heap_oop(member_vmtarget, G5_method);
+      __ load_heap_oop(member_vmtarget, G5_method, temp3);
       __ ld_ptr(vmtarget_method, G5_method);
       break;
 
@@ -438,7 +438,7 @@
       }
 
       Register temp2_intf = temp2;
-      __ load_heap_oop(member_clazz, temp2_intf);
+      __ load_heap_oop(member_clazz, temp2_intf, temp3);
       load_klass_from_Class(_masm, temp2_intf, temp3, temp4);
       __ verify_klass_ptr(temp2_intf);
 
--- a/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/sharedRuntime_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -2516,28 +2516,7 @@
 
   // Unbox oop result, e.g. JNIHandles::resolve value in I0.
   if (ret_type == T_OBJECT || ret_type == T_ARRAY) {
-    Label done, not_weak;
-    __ br_null(I0, false, Assembler::pn, done); // Use NULL as-is.
-    __ delayed()->andcc(I0, JNIHandles::weak_tag_mask, G0); // Test for jweak
-    __ brx(Assembler::zero, true, Assembler::pt, not_weak);
-    __ delayed()->ld_ptr(I0, 0, I0); // Maybe resolve (untagged) jobject.
-    // Resolve jweak.
-    __ ld_ptr(I0, -JNIHandles::weak_tag_value, I0);
-#if INCLUDE_ALL_GCS
-    if (UseG1GC) {
-      // Copy to O0 because macro doesn't allow pre_val in input reg.
-      __ mov(I0, O0);
-      __ g1_write_barrier_pre(noreg /* obj */,
-                              noreg /* index */,
-                              0 /* offset */,
-                              O0 /* pre_val */,
-                              G3_scratch /* tmp */,
-                              true /* preserve_o_regs */);
-    }
-#endif // INCLUDE_ALL_GCS
-    __ bind(not_weak);
-    __ verify_oop(I0);
-    __ bind(done);
+    __ resolve_jobject(I0, G3_scratch);
   }
 
   if (CheckJNICalls) {
--- a/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/stubGenerator_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -2277,7 +2277,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
 
     assert_clean_int(count, O3);     // Make sure 'count' is clean int.
@@ -2334,7 +2334,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, from, to, count);
 
     if (UseCompressedOops) {
@@ -2451,7 +2451,7 @@
       decorators |= AS_DEST_NOT_INITIALIZED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, T_OBJECT, O0_from, O1_to, O2_count);
 
     Label load_element, store_element, do_epilogue, fail, done;
@@ -2474,14 +2474,14 @@
 
     __ BIND(store_element);
     __ deccc(G1_remain);                // decrement the count
-    __ store_heap_oop(G3_oop, O1_to, O5_offset); // store the oop
+    __ store_heap_oop(G3_oop, O1_to, O5_offset, noreg, AS_RAW); // store the oop
     __ inc(O5_offset, heapOopSize);     // step to next offset
     __ brx(Assembler::zero, true, Assembler::pt, do_epilogue);
     __ delayed()->set(0, O0);           // return -1 on success
 
     // ======== loop entry is here ========
     __ BIND(load_element);
-    __ load_heap_oop(O0_from, O5_offset, G3_oop);  // load the oop
+    __ load_heap_oop(O0_from, O5_offset, G3_oop, noreg, AS_RAW);  // load the oop
     __ br_null_short(G3_oop, Assembler::pt, store_element);
 
     __ load_klass(G3_oop, G4_klass); // query the object klass
--- a/src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/templateInterpreterGenerator_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
@@ -827,29 +828,18 @@
 
 // Method entry for java.lang.ref.Reference.get.
 address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
-#if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1
   //
   // The code that gets generated by this routine is split into 2 parts:
-  //    1. The "intrinsified" code for G1 (or any SATB based GC),
+  //    1. The "intrinsified" code performing an ON_WEAK_OOP_REF load,
   //    2. The slow path - which is an expansion of the regular method entry.
   //
   // Notes:-
-  // * In the G1 code we do not check whether we need to block for
-  //   a safepoint. If G1 is enabled then we must execute the specialized
-  //   code for Reference.get (except when the Reference object is null)
-  //   so that we can log the value in the referent field with an SATB
-  //   update buffer.
-  //   If the code for the getfield template is modified so that the
-  //   G1 pre-barrier code is executed when the current method is
-  //   Reference.get() then going through the normal method entry
-  //   will be fine.
-  // * The G1 code can, however, check the receiver object (the instance
-  //   of java.lang.Reference) and jump to the slow path if null. If the
-  //   Reference object is null then we obviously cannot fetch the referent
-  //   and so we don't need to call the G1 pre-barrier. Thus we can use the
-  //   regular method entry code to generate the NPE.
+  // * An intrinsic is always executed, where an ON_WEAK_OOP_REF load is performed.
+  // * We may jump to the slow path iff the receiver is null. If the
+  //   Reference object is null then we no longer perform an ON_WEAK_OOP_REF load
+  //   Thus we can use the regular method entry code to generate the NPE.
   //
   // This code is based on generate_accessor_enty.
 
@@ -858,51 +848,27 @@
   const int referent_offset = java_lang_ref_Reference::referent_offset;
   guarantee(referent_offset > 0, "referent offset not initialized");
 
-  if (UseG1GC) {
-     Label slow_path;
+  Label slow_path;
 
-    // In the G1 code we don't check if we need to reach a safepoint. We
-    // continue and the thread will safepoint at the next bytecode dispatch.
+  // In the G1 code we don't check if we need to reach a safepoint. We
+  // continue and the thread will safepoint at the next bytecode dispatch.
 
-    // Check if local 0 != NULL
-    // If the receiver is null then it is OK to jump to the slow path.
-    __ ld_ptr(Gargs, G0, Otos_i ); // get local 0
-    // check if local 0 == NULL and go the slow path
-    __ cmp_and_brx_short(Otos_i, 0, Assembler::equal, Assembler::pn, slow_path);
-
-
-    // Load the value of the referent field.
-    if (Assembler::is_simm13(referent_offset)) {
-      __ load_heap_oop(Otos_i, referent_offset, Otos_i);
-    } else {
-      __ set(referent_offset, G3_scratch);
-      __ load_heap_oop(Otos_i, G3_scratch, Otos_i);
-    }
+  // Check if local 0 != NULL
+  // If the receiver is null then it is OK to jump to the slow path.
+  __ ld_ptr(Gargs, G0, Otos_i ); // get local 0
+  // check if local 0 == NULL and go the slow path
+  __ cmp_and_brx_short(Otos_i, 0, Assembler::equal, Assembler::pn, slow_path);
 
-    // Generate the G1 pre-barrier code to log the value of
-    // the referent field in an SATB buffer. Note with
-    // these parameters the pre-barrier does not generate
-    // the load of the previous value
-
-    __ g1_write_barrier_pre(noreg /* obj */, noreg /* index */, 0 /* offset */,
-                            Otos_i /* pre_val */,
-                            G3_scratch /* tmp */,
-                            true /* preserve_o_regs */);
+  __ load_heap_oop(Otos_i, referent_offset, Otos_i, G3_scratch, ON_WEAK_OOP_REF);
 
-    // _areturn
-    __ retl();                      // return from leaf routine
-    __ delayed()->mov(O5_savedSP, SP);
+  // _areturn
+  __ retl();                      // return from leaf routine
+  __ delayed()->mov(O5_savedSP, SP);
 
-    // Generate regular method entry
-    __ bind(slow_path);
-    __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
-    return entry;
-  }
-#endif // INCLUDE_ALL_GCS
-
-  // If G1 is not enabled then attempt to go through the accessor entry point
-  // Reference.get is an accessor
-  return NULL;
+  // Generate regular method entry
+  __ bind(slow_path);
+  __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
+  return entry;
 }
 
 /**
@@ -1469,33 +1435,15 @@
   // If we have an oop result store it where it will be safe for any further gc
   // until we return now that we've released the handle it might be protected by
 
-  { Label no_oop, store_result;
+  { Label no_oop;
 
     __ set((intptr_t)AbstractInterpreter::result_handler(T_OBJECT), G3_scratch);
     __ cmp_and_brx_short(G3_scratch, Lscratch, Assembler::notEqual, Assembler::pt, no_oop);
-    // Unbox oop result, e.g. JNIHandles::resolve value in O0.
-    __ br_null(O0, false, Assembler::pn, store_result); // Use NULL as-is.
-    __ delayed()->andcc(O0, JNIHandles::weak_tag_mask, G0); // Test for jweak
-    __ brx(Assembler::zero, true, Assembler::pt, store_result);
-    __ delayed()->ld_ptr(O0, 0, O0); // Maybe resolve (untagged) jobject.
-    // Resolve jweak.
-    __ ld_ptr(O0, -JNIHandles::weak_tag_value, O0);
-#if INCLUDE_ALL_GCS
-    if (UseG1GC) {
-      __ g1_write_barrier_pre(noreg /* obj */,
-                              noreg /* index */,
-                              0 /* offset */,
-                              O0 /* pre_val */,
-                              G3_scratch /* tmp */,
-                              true /* preserve_o_regs */);
-    }
-#endif // INCLUDE_ALL_GCS
-    __ bind(store_result);
+    __ resolve_jobject(O0, G3_scratch);
     // Store it where gc will look for it and result handler expects it.
     __ st_ptr(O0, FP, (frame::interpreter_frame_oop_temp_offset*wordSize) + STACK_BIAS);
 
     __ bind(no_oop);
-
   }
 
 
--- a/src/hotspot/cpu/sparc/templateTable_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/sparc/templateTable_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
 #include "interpreter/interp_masm.hpp"
@@ -51,74 +52,31 @@
                          int offset,
                          Register val,
                          Register tmp,
-                         BarrierSet::Name barrier,
-                         bool precise) {
+                         DecoratorSet decorators = 0) {
   assert(tmp != val && tmp != base && tmp != index, "register collision");
   assert(index == noreg || offset == 0, "only one offset");
-  switch (barrier) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      {
-        // Load and record the previous value.
-        __ g1_write_barrier_pre(base, index, offset,
-                                noreg /* pre_val */,
-                                tmp, true /*preserve_o_regs*/);
-
-        // G1 barrier needs uncompressed oop for region cross check.
-        Register new_val = val;
-        if (UseCompressedOops && val != G0) {
-          new_val = tmp;
-          __ mov(val, new_val);
-        }
-
-        if (index == noreg ) {
-          assert(Assembler::is_simm13(offset), "fix this code");
-          __ store_heap_oop(val, base, offset);
-        } else {
-          __ store_heap_oop(val, base, index);
-        }
-
-        // No need for post barrier if storing NULL
-        if (val != G0) {
-          if (precise) {
-            if (index == noreg) {
-              __ add(base, offset, base);
-            } else {
-              __ add(base, index, base);
-            }
-          }
-          __ g1_write_barrier_post(base, new_val, tmp);
-        }
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-      {
-        if (index == noreg ) {
-          assert(Assembler::is_simm13(offset), "fix this code");
-          __ store_heap_oop(val, base, offset);
-        } else {
-          __ store_heap_oop(val, base, index);
-        }
-        // No need for post barrier if storing NULL
-        if (val != G0) {
-          if (precise) {
-            if (index == noreg) {
-              __ add(base, offset, base);
-            } else {
-              __ add(base, index, base);
-            }
-          }
-          __ card_write_barrier_post(base, val, tmp);
-        }
-      }
-      break;
-    case BarrierSet::ModRef:
-      ShouldNotReachHere();
-      break;
-    default      :
-      ShouldNotReachHere();
-
+  if (index == noreg) {
+    __ store_heap_oop(val, base, offset, tmp, decorators);
+  } else {
+    __ store_heap_oop(val, base, index, tmp, decorators);
+  }
+}
+
+// Do an oop load like val = *(base + index + offset)
+// index can be noreg.
+static void do_oop_load(InterpreterMacroAssembler* _masm,
+                        Register base,
+                        Register index,
+                        int offset,
+                        Register dst,
+                        Register tmp,
+                        DecoratorSet decorators = 0) {
+  assert(tmp != dst && tmp != base && tmp != index, "register collision");
+  assert(index == noreg || offset == 0, "only one offset");
+  if (index == noreg) {
+    __ load_heap_oop(base, offset, dst, tmp, decorators);
+  } else {
+    __ load_heap_oop(base, index, dst, tmp, decorators);
   }
 }
 
@@ -587,7 +545,13 @@
   // Otos_i: index
   // tos: array
   __ index_check(O2, Otos_i, UseCompressedOops ? 2 : LogBytesPerWord, G3_scratch, O3);
-  __ load_heap_oop(O3, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i);
+  do_oop_load(_masm,
+              O3,
+              noreg,
+              arrayOopDesc::base_offset_in_bytes(T_OBJECT),
+              Otos_i,
+              G3_scratch,
+              IN_HEAP_ARRAY);
   __ verify_oop(Otos_i);
 }
 
@@ -887,13 +851,13 @@
 
   // Store is OK.
   __ bind(store_ok);
-  do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, _bs->kind(), true);
+  do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), Otos_i, G3_scratch, IN_HEAP_ARRAY);
 
   __ ba(done);
   __ delayed()->inc(Lesp, 3* Interpreter::stackElementSize); // adj sp (pops array, index and value)
 
   __ bind(is_null);
-  do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, _bs->kind(), true);
+  do_oop_store(_masm, O1, noreg, arrayOopDesc::base_offset_in_bytes(T_OBJECT), G0, G4_scratch, IN_HEAP_ARRAY);
 
   __ profile_null_seen(G3_scratch);
   __ inc(Lesp, 3* Interpreter::stackElementSize);     // adj sp (pops array, index and value)
@@ -2155,7 +2119,7 @@
   __ delayed() ->cmp(Rflags, itos);
 
   // atos
-  __ load_heap_oop(Rclass, Roffset, Otos_i);
+  do_oop_load(_masm, Rclass, Roffset, 0, Otos_i, noreg);
   __ verify_oop(Otos_i);
   __ push(atos);
   if (!is_static && rc == may_rewrite) {
@@ -2354,7 +2318,7 @@
       __ ldf(FloatRegisterImpl::D, Otos_i, Roffset, Ftos_d);
       break;
     case Bytecodes::_fast_agetfield:
-      __ load_heap_oop(Otos_i, Roffset, Otos_i);
+      do_oop_load(_masm, Otos_i, Roffset, 0, Otos_i, noreg);
       break;
     default:
       ShouldNotReachHere();
@@ -2537,7 +2501,7 @@
     {
       __ pop_ptr();
       __ verify_oop(Otos_i);
-      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch);
       __ ba(checkVolatile);
       __ delayed()->tst(Lscratch);
     }
@@ -2582,7 +2546,7 @@
       __ pop_ptr();
       pop_and_check_object(Rclass);
       __ verify_oop(Otos_i);
-      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch);
       if (rc == may_rewrite) patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch, true, byte_no);
       __ ba(checkVolatile);
       __ delayed()->tst(Lscratch);
@@ -2763,7 +2727,7 @@
       __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
       break;
     case Bytecodes::_fast_aputfield:
-      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch);
       break;
     default:
       ShouldNotReachHere();
@@ -2805,7 +2769,7 @@
   __ verify_oop(Rreceiver);
   __ null_check(Rreceiver);
   if (state == atos) {
-    __ load_heap_oop(Rreceiver, Roffset, Otos_i);
+    do_oop_load(_masm, Rreceiver, Roffset, 0, Otos_i, noreg);
   } else if (state == itos) {
     __ ld (Rreceiver, Roffset, Otos_i) ;
   } else if (state == ftos) {
--- a/src/hotspot/cpu/x86/assembler_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/assembler_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -38,7 +38,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,6 +44,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 
@@ -1562,7 +1563,7 @@
         StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);
         // arg0 : previous value of memory
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ movptr(rax, (int)id);
           __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);
@@ -1578,12 +1579,9 @@
 
         NOT_LP64(__ get_thread(thread);)
 
-        Address queue_active(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                              SATBMarkQueue::byte_offset_of_active()));
-        Address queue_index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                             SATBMarkQueue::byte_offset_of_index()));
-        Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                        SATBMarkQueue::byte_offset_of_buf()));
+        Address queue_active(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
+        Address queue_index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
+        Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
 
         Label done;
         Label runtime;
@@ -1632,7 +1630,7 @@
       {
         StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);
 
-        BarrierSet* bs = Universe::heap()->barrier_set();
+        BarrierSet* bs = BarrierSet::barrier_set();
         if (bs->kind() != BarrierSet::G1BarrierSet) {
           __ movptr(rax, (int)id);
           __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), rax);
@@ -1652,10 +1650,8 @@
 
         const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
 
-        Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                             DirtyCardQueue::byte_offset_of_index()));
-        Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                        DirtyCardQueue::byte_offset_of_buf()));
+        Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
+        Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
 
         __ push(rax);
         __ push(rcx);
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -27,11 +27,10 @@
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1BarrierSetAssembler.hpp"
 #include "gc/g1/g1CardTable.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
-#include "gc/shared/collectedHeap.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
-#include "runtime/thread.hpp"
 #include "utilities/macros.hpp"
 
 #define __ masm->
@@ -48,8 +47,7 @@
 #endif
 
     Label filtered;
-    Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                         SATBMarkQueue::byte_offset_of_active()));
+    Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
     // Is marking active?
     if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
       __ cmpl(in_progress, 0);
@@ -111,3 +109,293 @@
 #endif
   __ popa();
 }
+
+void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                    Register dst, Address src, Register tmp1, Register tmp_thread) {
+  bool on_oop = type == T_OBJECT || type == T_ARRAY;
+  bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
+  bool on_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+  bool on_reference = on_weak || on_phantom;
+  ModRefBarrierSetAssembler::load_at(masm, decorators, type, dst, src, tmp1, tmp_thread);
+  if (on_oop && on_reference) {
+    const Register thread = NOT_LP64(tmp_thread) LP64_ONLY(r15_thread);
+    NOT_LP64(__ get_thread(thread));
+
+    // Generate the G1 pre-barrier code to log the value of
+    // the referent field in an SATB buffer.
+    g1_write_barrier_pre(masm /* masm */,
+                         noreg /* obj */,
+                         dst /* pre_val */,
+                         thread /* thread */,
+                         tmp1 /* tmp */,
+                         true /* tosca_live */,
+                         true /* expand_call */);
+  }
+}
+
+void G1BarrierSetAssembler::g1_write_barrier_pre(MacroAssembler* masm,
+                                                 Register obj,
+                                                 Register pre_val,
+                                                 Register thread,
+                                                 Register tmp,
+                                                 bool tosca_live,
+                                                 bool expand_call) {
+  // If expand_call is true then we expand the call_VM_leaf macro
+  // directly to skip generating the check by
+  // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
+
+#ifdef _LP64
+  assert(thread == r15_thread, "must be");
+#endif // _LP64
+
+  Label done;
+  Label runtime;
+
+  assert(pre_val != noreg, "check this code");
+
+  if (obj != noreg) {
+    assert_different_registers(obj, pre_val, tmp);
+    assert(pre_val != rax, "check this code");
+  }
+
+  Address in_progress(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()));
+  Address index(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()));
+  Address buffer(thread, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()));
+
+  // Is marking active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ cmpl(in_progress, 0);
+  } else {
+    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ cmpb(in_progress, 0);
+  }
+  __ jcc(Assembler::equal, done);
+
+  // Do we need to load the previous value?
+  if (obj != noreg) {
+    __ load_heap_oop(pre_val, Address(obj, 0), noreg, noreg, AS_RAW);
+  }
+
+  // Is the previous value null?
+  __ cmpptr(pre_val, (int32_t) NULL_WORD);
+  __ jcc(Assembler::equal, done);
+
+  // Can we store original value in the thread's buffer?
+  // Is index == 0?
+  // (The index field is typed as size_t.)
+
+  __ movptr(tmp, index);                   // tmp := *index_adr
+  __ cmpptr(tmp, 0);                       // tmp == 0?
+  __ jcc(Assembler::equal, runtime);       // If yes, goto runtime
+
+  __ subptr(tmp, wordSize);                // tmp := tmp - wordSize
+  __ movptr(index, tmp);                   // *index_adr := tmp
+  __ addptr(tmp, buffer);                  // tmp := tmp + *buffer_adr
+
+  // Record the previous value
+  __ movptr(Address(tmp, 0), pre_val);
+  __ jmp(done);
+
+  __ bind(runtime);
+  // save the live input values
+  if(tosca_live) __ push(rax);
+
+  if (obj != noreg && obj != rax)
+    __ push(obj);
+
+  if (pre_val != rax)
+    __ push(pre_val);
+
+  // Calling the runtime using the regular call_VM_leaf mechanism generates
+  // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
+  // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
+  //
+  // If we care generating the pre-barrier without a frame (e.g. in the
+  // intrinsified Reference.get() routine) then ebp might be pointing to
+  // the caller frame and so this check will most likely fail at runtime.
+  //
+  // Expanding the call directly bypasses the generation of the check.
+  // So when we do not have have a full interpreter frame on the stack
+  // expand_call should be passed true.
+
+  NOT_LP64( __ push(thread); )
+
+  if (expand_call) {
+    LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
+#ifdef _LP64
+    if (c_rarg1 != thread) {
+      __ mov(c_rarg1, thread);
+    }
+    if (c_rarg0 != pre_val) {
+      __ mov(c_rarg0, pre_val);
+    }
+#else
+    __ push(thread);
+    __ push(pre_val);
+#endif
+    __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2);
+  } else {
+    __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
+  }
+
+  NOT_LP64( __ pop(thread); )
+
+  // save the live input values
+  if (pre_val != rax)
+    __ pop(pre_val);
+
+  if (obj != noreg && obj != rax)
+    __ pop(obj);
+
+  if(tosca_live) __ pop(rax);
+
+  __ bind(done);
+}
+
+void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
+                                                  Register store_addr,
+                                                  Register new_val,
+                                                  Register thread,
+                                                  Register tmp,
+                                                  Register tmp2) {
+#ifdef _LP64
+  assert(thread == r15_thread, "must be");
+#endif // _LP64
+
+  Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
+  Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
+
+  CardTableBarrierSet* ct =
+    barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
+  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  Label done;
+  Label runtime;
+
+  // Does store cross heap regions?
+
+  __ movptr(tmp, store_addr);
+  __ xorptr(tmp, new_val);
+  __ shrptr(tmp, HeapRegion::LogOfHRGrainBytes);
+  __ jcc(Assembler::equal, done);
+
+  // crosses regions, storing NULL?
+
+  __ cmpptr(new_val, (int32_t) NULL_WORD);
+  __ jcc(Assembler::equal, done);
+
+  // storing region crossing non-NULL, is card already dirty?
+
+  const Register card_addr = tmp;
+  const Register cardtable = tmp2;
+
+  __ movptr(card_addr, store_addr);
+  __ shrptr(card_addr, CardTable::card_shift);
+  // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
+  // a valid address and therefore is not properly handled by the relocation code.
+  __ movptr(cardtable, (intptr_t)ct->card_table()->byte_map_base());
+  __ addptr(card_addr, cardtable);
+
+  __ cmpb(Address(card_addr, 0), (int)G1CardTable::g1_young_card_val());
+  __ jcc(Assembler::equal, done);
+
+  __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+  __ cmpb(Address(card_addr, 0), (int)G1CardTable::dirty_card_val());
+  __ jcc(Assembler::equal, done);
+
+
+  // storing a region crossing, non-NULL oop, card is clean.
+  // dirty card and log.
+
+  __ movb(Address(card_addr, 0), (int)G1CardTable::dirty_card_val());
+
+  __ cmpl(queue_index, 0);
+  __ jcc(Assembler::equal, runtime);
+  __ subl(queue_index, wordSize);
+  __ movptr(tmp2, buffer);
+#ifdef _LP64
+  __ movslq(rscratch1, queue_index);
+  __ addq(tmp2, rscratch1);
+  __ movq(Address(tmp2, 0), card_addr);
+#else
+  __ addl(tmp2, queue_index);
+  __ movl(Address(tmp2, 0), card_addr);
+#endif
+  __ jmp(done);
+
+  __ bind(runtime);
+  // save the live input values
+  __ push(store_addr);
+  __ push(new_val);
+#ifdef _LP64
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, r15_thread);
+#else
+  __ push(thread);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
+  __ pop(thread);
+#endif
+  __ pop(new_val);
+  __ pop(store_addr);
+
+  __ bind(done);
+}
+
+void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Address dst, Register val, Register tmp1, Register tmp2) {
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0;
+
+  bool needs_pre_barrier = in_heap || in_concurrent_root;
+  bool needs_post_barrier = val != noreg && in_heap;
+
+  Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);
+  Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
+  // flatten object address if needed
+  // We do it regardless of precise because we need the registers
+  if (dst.index() == noreg && dst.disp() == 0) {
+    if (dst.base() != tmp1) {
+      __ movptr(tmp1, dst.base());
+    }
+  } else {
+    __ lea(tmp1, dst);
+  }
+
+#ifndef _LP64
+  InterpreterMacroAssembler *imasm = static_cast<InterpreterMacroAssembler*>(masm);
+#endif
+
+  NOT_LP64(__ get_thread(rcx));
+  NOT_LP64(imasm->save_bcp());
+
+  if (needs_pre_barrier) {
+    g1_write_barrier_pre(masm /*masm*/,
+                         tmp1 /* obj */,
+                         tmp2 /* pre_val */,
+                         rthread /* thread */,
+                         tmp3  /* tmp */,
+                         val != noreg /* tosca_live */,
+                         false /* expand_call */);
+  }
+  if (val == noreg) {
+    BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg);
+  } else {
+    Register new_val = val;
+    if (needs_post_barrier) {
+      // G1 barrier needs uncompressed oop for region cross check.
+      if (UseCompressedOops) {
+        new_val = tmp2;
+        __ movptr(new_val, val);
+      }
+    }
+    BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg);
+    if (needs_post_barrier) {
+      g1_write_barrier_post(masm /*masm*/,
+                            tmp1 /* store_adr */,
+                            new_val /* new_val */,
+                            rthread /* thread */,
+                            tmp3 /* tmp */,
+                            tmp2 /* tmp2 */);
+    }
+  }
+  NOT_LP64(imasm->restore_bcp());
+}
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,10 +30,30 @@
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
  protected:
-  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                               Register addr, Register count);
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
-                                                Register addr, Register count, Register tmp);
+  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count);
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp);
+
+  void g1_write_barrier_pre(MacroAssembler* masm,
+                            Register obj,
+                            Register pre_val,
+                            Register thread,
+                            Register tmp,
+                            bool tosca_live,
+                            bool expand_call);
+
+  void g1_write_barrier_post(MacroAssembler* masm,
+                             Register store_addr,
+                             Register new_val,
+                             Register thread,
+                             Register tmp,
+                             Register tmp2);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Address dst, Register val, Register tmp1, Register tmp2);
+
+ public:
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Register dst, Address src, Register tmp1, Register tmp_thread);
 };
 
 #endif // CPU_X86_GC_G1_G1BARRIERSETASSEMBLER_X86_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+#include "interpreter/interp_masm.hpp"
+
+#define __ masm->
+
+void BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                  Register dst, Address src, Register tmp1, Register tmp_thread) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+
+  switch (type) {
+  case T_OBJECT:
+  case T_ARRAY: {
+    if (on_heap) {
+#ifdef _LP64
+      if (UseCompressedOops) {
+        __ movl(dst, src);
+        if (oop_not_null) {
+          __ decode_heap_oop_not_null(dst);
+        } else {
+          __ decode_heap_oop(dst);
+        }
+      } else
+#endif
+      {
+        __ movptr(dst, src);
+      }
+    } else {
+      assert(on_root, "why else?");
+      __ movptr(dst, src);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
+
+void BarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                   Address dst, Register val, Register tmp1, Register tmp2) {
+  bool on_heap = (decorators & IN_HEAP) != 0;
+  bool on_root = (decorators & IN_ROOT) != 0;
+  bool oop_not_null = (decorators & OOP_NOT_NULL) != 0;
+
+  switch (type) {
+  case T_OBJECT:
+  case T_ARRAY: {
+    if (on_heap) {
+      if (val == noreg) {
+        assert(!oop_not_null, "inconsistent access");
+#ifdef _LP64
+        if (UseCompressedOops) {
+          __ movl(dst, (int32_t)NULL_WORD);
+        } else {
+          __ movslq(dst, (int32_t)NULL_WORD);
+        }
+#else
+        __ movl(dst, (int32_t)NULL_WORD);
+#endif
+      } else {
+#ifdef _LP64
+        if (UseCompressedOops) {
+          assert(!dst.uses(val), "not enough registers");
+          if (oop_not_null) {
+            __ encode_heap_oop_not_null(val);
+          } else {
+            __ encode_heap_oop(val);
+          }
+          __ movl(dst, val);
+        } else
+#endif
+        {
+          __ movptr(dst, val);
+        }
+      }
+    } else {
+      assert(on_root, "why else?");
+      assert(val != noreg, "not supported");
+      __ movptr(dst, val);
+    }
+    break;
+  }
+  default: Unimplemented();
+  }
+}
--- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -22,8 +22,8 @@
  *
  */
 
-#ifndef CPU_X86_GC_G1_BARRIERSETASSEMBLER_X86_HPP
-#define CPU_X86_GC_G1_BARRIERSETASSEMBLER_X86_HPP
+#ifndef CPU_X86_GC_SHARED_BARRIERSETASSEMBLER_X86_HPP
+#define CPU_X86_GC_SHARED_BARRIERSETASSEMBLER_X86_HPP
 
 #include "asm/macroAssembler.hpp"
 #include "memory/allocation.hpp"
@@ -38,6 +38,13 @@
                                   Register src, Register dst, Register count) {}
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count) {}
+
+  virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                       Register dst, Address src, Register tmp1, Register tmp_thread);
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Address dst, Register val, Register tmp1, Register tmp2);
+
+  virtual void barrier_stubs_init() {}
 };
 
-#endif // CPU_X86_GC_G1_BARRIERSETASSEMBLER_X86_HPP
+#endif // CPU_X86_GC_SHARED_BARRIERSETASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,7 +28,6 @@
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
-#include "gc/shared/collectedHeap.hpp"
 
 #define __ masm->
 
@@ -44,7 +43,7 @@
 
 void CardTableBarrierSetAssembler::gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                                                     Register addr, Register count, Register tmp) {
-  BarrierSet *bs = Universe::heap()->barrier_set();
+  BarrierSet *bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
@@ -85,3 +84,70 @@
 
 __ BIND(L_done);
 }
+
+void CardTableBarrierSetAssembler::store_check(MacroAssembler* masm, Register obj, Address dst) {
+  // Does a store check for the oop in register obj. The content of
+  // register obj is destroyed afterwards.
+  BarrierSet* bs = BarrierSet::barrier_set();
+
+  CardTableBarrierSet* ct = barrier_set_cast<CardTableBarrierSet>(bs);
+  assert(sizeof(*ct->card_table()->byte_map_base()) == sizeof(jbyte), "adjust this code");
+
+  __ shrptr(obj, CardTable::card_shift);
+
+  Address card_addr;
+
+  // The calculation for byte_map_base is as follows:
+  // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
+  // So this essentially converts an address to a displacement and it will
+  // never need to be relocated. On 64bit however the value may be too
+  // large for a 32bit displacement.
+  intptr_t disp = (intptr_t) ct->card_table()->byte_map_base();
+  if (__ is_simm32(disp)) {
+    card_addr = Address(noreg, obj, Address::times_1, disp);
+  } else {
+    // By doing it as an ExternalAddress 'disp' could be converted to a rip-relative
+    // displacement and done in a single instruction given favorable mapping and a
+    // smarter version of as_Address. However, 'ExternalAddress' generates a relocation
+    // entry and that entry is not properly handled by the relocation code.
+    AddressLiteral cardtable((address)ct->card_table()->byte_map_base(), relocInfo::none);
+    Address index(noreg, obj, Address::times_1);
+    card_addr = __ as_Address(ArrayAddress(cardtable, index));
+  }
+
+  int dirty = CardTable::dirty_card_val();
+  if (UseCondCardMark) {
+    Label L_already_dirty;
+    if (UseConcMarkSweepGC) {
+      __ membar(Assembler::StoreLoad);
+    }
+    __ cmpb(card_addr, dirty);
+    __ jcc(Assembler::equal, L_already_dirty);
+    __ movb(card_addr, dirty);
+    __ bind(L_already_dirty);
+  } else {
+    __ movb(card_addr, dirty);
+  }
+}
+
+void CardTableBarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                                Address dst, Register val, Register tmp1, Register tmp2) {
+  bool in_heap = (decorators & IN_HEAP) != 0;
+
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  bool precise = on_array || on_anonymous;
+
+  bool needs_post_barrier = val != noreg && in_heap;
+
+  BarrierSetAssembler::store_at(masm, decorators, type, dst, val, noreg, noreg);
+  if (needs_post_barrier) {
+    // flatten object address if needed
+    if (!precise || (dst.index() == noreg && dst.disp() == 0)) {
+      store_check(masm, dst.base(), dst);
+    } else {
+      __ lea(tmp1, dst);
+      store_check(masm, tmp1, dst);
+    }
+  }
+}
--- a/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/cardTableBarrierSetAssembler_x86.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,8 +30,12 @@
 
 class CardTableBarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr,
-                                                Register count, Register tmp);
+  void store_check(MacroAssembler* masm, Register obj, Address dst);
+
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp);
+
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Address dst, Register val, Register tmp1, Register tmp2);
 };
 
 #endif // CPU_X86_GC_SHARED_CARDTABLEBARRIERSETASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -78,3 +78,12 @@
     gen_write_ref_array_post_barrier(masm, decorators, dst, count, tmp);
   }
 }
+
+void ModRefBarrierSetAssembler::store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                                         Address dst, Register val, Register tmp1, Register tmp2) {
+  if (type == T_OBJECT || type == T_ARRAY) {
+    oop_store_at(masm, decorators, type, dst, val, tmp1, tmp2);
+  } else {
+    BarrierSetAssembler::store_at(masm, decorators, type, dst, val, tmp1, tmp2);
+  }
+}
--- a/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/shared/modRefBarrierSetAssembler_x86.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,16 +28,26 @@
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 
+// The ModRefBarrierSetAssembler filters away accesses on BasicTypes other
+// than T_OBJECT/T_ARRAY (oops). The oop accesses call one of the protected
+// accesses, which are overridden in the concrete BarrierSetAssembler.
+
 class ModRefBarrierSetAssembler: public BarrierSetAssembler {
 protected:
-  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count) {}
-  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count, Register tmp) {}
-
+  virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators,
+                                               Register addr, Register count) {}
+  virtual void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
+                                                Register addr, Register count, Register tmp) {}
+  virtual void oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                            Address dst, Register val, Register tmp1, Register tmp2) = 0;
 public:
   virtual void arraycopy_prologue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count);
   virtual void arraycopy_epilogue(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                                   Register src, Register dst, Register count);
+
+  virtual void store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
+                        Address dst, Register val, Register tmp1, Register tmp2);
 };
 
 #endif // CPU_X86_GC_SHARED_MODREFBARRIERSETASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/x86/interp_masm_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/interp_masm_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -516,9 +516,7 @@
   resolve_oop_handle(result);
   // Add in the index
   addptr(result, tmp);
-  load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
-  // The resulting oop is null if the reference is not yet resolved.
-  // It is Universe::the_null_sentinel() if the reference resolved to NULL via condy.
+  load_heap_oop(result, Address(result, arrayOopDesc::base_offset_in_bytes(T_OBJECT)), tmp);
 }
 
 // load cpool->resolved_klass_at(index)
--- a/src/hotspot/cpu/x86/interp_masm_x86.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/interp_masm_x86.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,12 +35,13 @@
 typedef ByteSize (*OffsetFunction)(uint);
 
 class InterpreterMacroAssembler: public MacroAssembler {
-
- protected:
+ public:
   // Interpreter specific version of call_VM_base
   virtual void call_VM_leaf_base(address entry_point,
                                  int number_of_arguments);
 
+ protected:
+
   virtual void call_VM_base(Register oop_result,
                             Register java_thread,
                             Register last_java_sp,
--- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -27,12 +27,13 @@
 #include "asm/assembler.hpp"
 #include "asm/assembler.inline.hpp"
 #include "compiler/disassembler.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
+#include "oops/access.hpp"
 #include "oops/klass.inline.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/biasedLocking.hpp"
@@ -45,12 +46,6 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
-#include "gc/g1/heapRegion.hpp"
-#endif // INCLUDE_ALL_GCS
 #include "crc32c.h"
 #ifdef COMPILER2
 #include "opto/intrinsicnode.hpp"
@@ -5240,6 +5235,12 @@
   }
 }
 
+void MacroAssembler::clear_jweak_tag(Register possibly_jweak) {
+  const int32_t inverted_jweak_mask = ~static_cast<int32_t>(JNIHandles::weak_tag_mask);
+  STATIC_ASSERT(inverted_jweak_mask == -2); // otherwise check this code
+  // The inverted mask is sign-extended
+  andptr(possibly_jweak, inverted_jweak_mask);
+}
 
 void MacroAssembler::resolve_jobject(Register value,
                                      Register thread,
@@ -5251,296 +5252,18 @@
   testptr(value, JNIHandles::weak_tag_mask); // Test for jweak tag.
   jcc(Assembler::zero, not_weak);
   // Resolve jweak.
-  movptr(value, Address(value, -JNIHandles::weak_tag_value));
+  access_load_at(T_OBJECT, IN_ROOT | ON_PHANTOM_OOP_REF,
+                 value, Address(value, -JNIHandles::weak_tag_value), tmp, thread);
   verify_oop(value);
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) {
-    g1_write_barrier_pre(noreg /* obj */,
-                         value /* pre_val */,
-                         thread /* thread */,
-                         tmp /* tmp */,
-                         true /* tosca_live */,
-                         true /* expand_call */);
-  }
-#endif // INCLUDE_ALL_GCS
   jmp(done);
   bind(not_weak);
   // Resolve (untagged) jobject.
-  movptr(value, Address(value, 0));
+  access_load_at(T_OBJECT, IN_ROOT | IN_CONCURRENT_ROOT,
+                 value, Address(value, 0), tmp, thread);
   verify_oop(value);
   bind(done);
 }
 
-void MacroAssembler::clear_jweak_tag(Register possibly_jweak) {
-  const int32_t inverted_jweak_mask = ~static_cast<int32_t>(JNIHandles::weak_tag_mask);
-  STATIC_ASSERT(inverted_jweak_mask == -2); // otherwise check this code
-  // The inverted mask is sign-extended
-  andptr(possibly_jweak, inverted_jweak_mask);
-}
-
-//////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void MacroAssembler::g1_write_barrier_pre(Register obj,
-                                          Register pre_val,
-                                          Register thread,
-                                          Register tmp,
-                                          bool tosca_live,
-                                          bool expand_call) {
-
-  // If expand_call is true then we expand the call_VM_leaf macro
-  // directly to skip generating the check by
-  // InterpreterMacroAssembler::call_VM_leaf_base that checks _last_sp.
-
-#ifdef _LP64
-  assert(thread == r15_thread, "must be");
-#endif // _LP64
-
-  Label done;
-  Label runtime;
-
-  assert(pre_val != noreg, "check this code");
-
-  if (obj != noreg) {
-    assert_different_registers(obj, pre_val, tmp);
-    assert(pre_val != rax, "check this code");
-  }
-
-  Address in_progress(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_active()));
-  Address index(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_index()));
-  Address buffer(thread, in_bytes(JavaThread::satb_mark_queue_offset() +
-                                       SATBMarkQueue::byte_offset_of_buf()));
-
-
-  // Is marking active?
-  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    cmpl(in_progress, 0);
-  } else {
-    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-    cmpb(in_progress, 0);
-  }
-  jcc(Assembler::equal, done);
-
-  // Do we need to load the previous value?
-  if (obj != noreg) {
-    load_heap_oop(pre_val, Address(obj, 0));
-  }
-
-  // Is the previous value null?
-  cmpptr(pre_val, (int32_t) NULL_WORD);
-  jcc(Assembler::equal, done);
-
-  // Can we store original value in the thread's buffer?
-  // Is index == 0?
-  // (The index field is typed as size_t.)
-
-  movptr(tmp, index);                   // tmp := *index_adr
-  cmpptr(tmp, 0);                       // tmp == 0?
-  jcc(Assembler::equal, runtime);       // If yes, goto runtime
-
-  subptr(tmp, wordSize);                // tmp := tmp - wordSize
-  movptr(index, tmp);                   // *index_adr := tmp
-  addptr(tmp, buffer);                  // tmp := tmp + *buffer_adr
-
-  // Record the previous value
-  movptr(Address(tmp, 0), pre_val);
-  jmp(done);
-
-  bind(runtime);
-  // save the live input values
-  if(tosca_live) push(rax);
-
-  if (obj != noreg && obj != rax)
-    push(obj);
-
-  if (pre_val != rax)
-    push(pre_val);
-
-  // Calling the runtime using the regular call_VM_leaf mechanism generates
-  // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
-  // that checks that the *(ebp+frame::interpreter_frame_last_sp) == NULL.
-  //
-  // If we care generating the pre-barrier without a frame (e.g. in the
-  // intrinsified Reference.get() routine) then ebp might be pointing to
-  // the caller frame and so this check will most likely fail at runtime.
-  //
-  // Expanding the call directly bypasses the generation of the check.
-  // So when we do not have have a full interpreter frame on the stack
-  // expand_call should be passed true.
-
-  NOT_LP64( push(thread); )
-
-  if (expand_call) {
-    LP64_ONLY( assert(pre_val != c_rarg1, "smashed arg"); )
-    pass_arg1(this, thread);
-    pass_arg0(this, pre_val);
-    MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), 2);
-  } else {
-    call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
-  }
-
-  NOT_LP64( pop(thread); )
-
-  // save the live input values
-  if (pre_val != rax)
-    pop(pre_val);
-
-  if (obj != noreg && obj != rax)
-    pop(obj);
-
-  if(tosca_live) pop(rax);
-
-  bind(done);
-}
-
-void MacroAssembler::g1_write_barrier_post(Register store_addr,
-                                           Register new_val,
-                                           Register thread,
-                                           Register tmp,
-                                           Register tmp2) {
-#ifdef _LP64
-  assert(thread == r15_thread, "must be");
-#endif // _LP64
-
-  Address queue_index(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                       DirtyCardQueue::byte_offset_of_index()));
-  Address buffer(thread, in_bytes(JavaThread::dirty_card_queue_offset() +
-                                       DirtyCardQueue::byte_offset_of_buf()));
-
-  CardTableBarrierSet* ctbs =
-    barrier_set_cast<CardTableBarrierSet>(Universe::heap()->barrier_set());
-  CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
-  Label done;
-  Label runtime;
-
-  // Does store cross heap regions?
-
-  movptr(tmp, store_addr);
-  xorptr(tmp, new_val);
-  shrptr(tmp, HeapRegion::LogOfHRGrainBytes);
-  jcc(Assembler::equal, done);
-
-  // crosses regions, storing NULL?
-
-  cmpptr(new_val, (int32_t) NULL_WORD);
-  jcc(Assembler::equal, done);
-
-  // storing region crossing non-NULL, is card already dirty?
-
-  const Register card_addr = tmp;
-  const Register cardtable = tmp2;
-
-  movptr(card_addr, store_addr);
-  shrptr(card_addr, CardTable::card_shift);
-  // Do not use ExternalAddress to load 'byte_map_base', since 'byte_map_base' is NOT
-  // a valid address and therefore is not properly handled by the relocation code.
-  movptr(cardtable, (intptr_t)ct->byte_map_base());
-  addptr(card_addr, cardtable);
-
-  cmpb(Address(card_addr, 0), (int)G1CardTable::g1_young_card_val());
-  jcc(Assembler::equal, done);
-
-  membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
-  cmpb(Address(card_addr, 0), (int)CardTable::dirty_card_val());
-  jcc(Assembler::equal, done);
-
-
-  // storing a region crossing, non-NULL oop, card is clean.
-  // dirty card and log.
-
-  movb(Address(card_addr, 0), (int)CardTable::dirty_card_val());
-
-  cmpl(queue_index, 0);
-  jcc(Assembler::equal, runtime);
-  subl(queue_index, wordSize);
-  movptr(tmp2, buffer);
-#ifdef _LP64
-  movslq(rscratch1, queue_index);
-  addq(tmp2, rscratch1);
-  movq(Address(tmp2, 0), card_addr);
-#else
-  addl(tmp2, queue_index);
-  movl(Address(tmp2, 0), card_addr);
-#endif
-  jmp(done);
-
-  bind(runtime);
-  // save the live input values
-  push(store_addr);
-  push(new_val);
-#ifdef _LP64
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, r15_thread);
-#else
-  push(thread);
-  call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
-  pop(thread);
-#endif
-  pop(new_val);
-  pop(store_addr);
-
-  bind(done);
-}
-
-#endif // INCLUDE_ALL_GCS
-//////////////////////////////////////////////////////////////////////////////////
-
-
-void MacroAssembler::store_check(Register obj, Address dst) {
-  store_check(obj);
-}
-
-void MacroAssembler::store_check(Register obj) {
-  // Does a store check for the oop in register obj. The content of
-  // register obj is destroyed afterwards.
-  BarrierSet* bs = Universe::heap()->barrier_set();
-  assert(bs->kind() == BarrierSet::CardTableBarrierSet,
-         "Wrong barrier set kind");
-
-  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
-  CardTable* ct = ctbs->card_table();
-  assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust this code");
-
-  shrptr(obj, CardTable::card_shift);
-
-  Address card_addr;
-
-  // The calculation for byte_map_base is as follows:
-  // byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
-  // So this essentially converts an address to a displacement and it will
-  // never need to be relocated. On 64bit however the value may be too
-  // large for a 32bit displacement.
-  intptr_t disp = (intptr_t) ct->byte_map_base();
-  if (is_simm32(disp)) {
-    card_addr = Address(noreg, obj, Address::times_1, disp);
-  } else {
-    // By doing it as an ExternalAddress 'disp' could be converted to a rip-relative
-    // displacement and done in a single instruction given favorable mapping and a
-    // smarter version of as_Address. However, 'ExternalAddress' generates a relocation
-    // entry and that entry is not properly handled by the relocation code.
-    AddressLiteral cardtable((address)ct->byte_map_base(), relocInfo::none);
-    Address index(noreg, obj, Address::times_1);
-    card_addr = as_Address(ArrayAddress(cardtable, index));
-  }
-
-  int dirty = CardTable::dirty_card_val();
-  if (UseCondCardMark) {
-    Label L_already_dirty;
-    if (UseConcMarkSweepGC) {
-      membar(Assembler::StoreLoad);
-    }
-    cmpb(card_addr, dirty);
-    jcc(Assembler::equal, L_already_dirty);
-    movb(card_addr, dirty);
-    bind(L_already_dirty);
-  } else {
-    movb(card_addr, dirty);
-  }
-}
-
 void MacroAssembler::subptr(Register dst, int32_t imm32) {
   LP64_ONLY(subq(dst, imm32)) NOT_LP64(subl(dst, imm32));
 }
@@ -6591,69 +6314,47 @@
     movptr(Address(dst, oopDesc::klass_offset_in_bytes()), src);
 }
 
-void MacroAssembler::load_heap_oop(Register dst, Address src) {
-#ifdef _LP64
-  // FIXME: Must change all places where we try to load the klass.
-  if (UseCompressedOops) {
-    movl(dst, src);
-    decode_heap_oop(dst);
-  } else
-#endif
-    movptr(dst, src);
+void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src,
+                                    Register tmp1, Register thread_tmp) {
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp);
+  } else {
+    bs->load_at(this, decorators, type, dst, src, tmp1, thread_tmp);
+  }
+}
+
+void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src,
+                                     Register tmp1, Register tmp2) {
+  BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+  bool as_raw = (decorators & AS_RAW) != 0;
+  if (as_raw) {
+    bs->BarrierSetAssembler::store_at(this, decorators, type, dst, src, tmp1, tmp2);
+  } else {
+    bs->store_at(this, decorators, type, dst, src, tmp1, tmp2);
+  }
+}
+
+void MacroAssembler::load_heap_oop(Register dst, Address src, Register tmp1,
+                                   Register thread_tmp, DecoratorSet decorators) {
+  access_load_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, thread_tmp);
 }
 
 // Doesn't do verfication, generates fixed size code
-void MacroAssembler::load_heap_oop_not_null(Register dst, Address src) {
-#ifdef _LP64
-  if (UseCompressedOops) {
-    movl(dst, src);
-    decode_heap_oop_not_null(dst);
-  } else
-#endif
-    movptr(dst, src);
-}
-
-void MacroAssembler::store_heap_oop(Address dst, Register src) {
-#ifdef _LP64
-  if (UseCompressedOops) {
-    assert(!dst.uses(src), "not enough registers");
-    encode_heap_oop(src);
-    movl(dst, src);
-  } else
-#endif
-    movptr(dst, src);
-}
-
-void MacroAssembler::cmp_heap_oop(Register src1, Address src2, Register tmp) {
-  assert_different_registers(src1, tmp);
-#ifdef _LP64
-  if (UseCompressedOops) {
-    bool did_push = false;
-    if (tmp == noreg) {
-      tmp = rax;
-      push(tmp);
-      did_push = true;
-      assert(!src2.uses(rsp), "can't push");
-    }
-    load_heap_oop(tmp, src2);
-    cmpptr(src1, tmp);
-    if (did_push)  pop(tmp);
-  } else
-#endif
-    cmpptr(src1, src2);
+void MacroAssembler::load_heap_oop_not_null(Register dst, Address src, Register tmp1,
+                                            Register thread_tmp, DecoratorSet decorators) {
+  access_load_at(T_OBJECT, IN_HEAP | OOP_NOT_NULL | decorators, dst, src, tmp1, thread_tmp);
+}
+
+void MacroAssembler::store_heap_oop(Address dst, Register src, Register tmp1,
+                                    Register tmp2, DecoratorSet decorators) {
+  access_store_at(T_OBJECT, IN_HEAP | decorators, dst, src, tmp1, tmp2);
 }
 
 // Used for storing NULLs.
 void MacroAssembler::store_heap_oop_null(Address dst) {
-#ifdef _LP64
-  if (UseCompressedOops) {
-    movl(dst, (int32_t)NULL_WORD);
-  } else {
-    movslq(dst, (int32_t)NULL_WORD);
-  }
-#else
-  movl(dst, (int32_t)NULL_WORD);
-#endif
+  access_store_at(T_OBJECT, IN_HEAP, dst, noreg, noreg, noreg);
 }
 
 #ifdef _LP64
--- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -38,11 +38,7 @@
   friend class LIR_Assembler;
   friend class Runtime1;      // as_Address()
 
- protected:
-
-  Address as_Address(AddressLiteral adr);
-  Address as_Address(ArrayAddress adr);
-
+ public:
   // Support for VM calls
   //
   // This is the base routine called by the different versions of call_VM_leaf. The interpreter
@@ -54,6 +50,7 @@
     int     number_of_arguments        // the number of arguments to pop after the call
   );
 
+ protected:
   // This is the base routine called by the different versions of call_VM. The interpreter
   // may customize this version by overriding it for its purposes (e.g., to save/restore
   // additional registers when doing a VM call).
@@ -87,6 +84,9 @@
  virtual void check_and_handle_popframe(Register java_thread);
  virtual void check_and_handle_earlyret(Register java_thread);
 
+  Address as_Address(AddressLiteral adr);
+  Address as_Address(ArrayAddress adr);
+
   // Support for NULL-checks
   //
   // Generates code that causes a NULL OS exception if the content of reg is NULL.
@@ -293,29 +293,9 @@
   // thread in the default location (r15_thread on 64bit)
   void reset_last_Java_frame(bool clear_fp);
 
-  // Stores
-  void store_check(Register obj);                // store check for obj - register is destroyed afterwards
-  void store_check(Register obj, Address dst);   // same as above, dst is exact store location (reg. is destroyed)
-
-  void resolve_jobject(Register value, Register thread, Register tmp);
+  // jobjects
   void clear_jweak_tag(Register possibly_jweak);
-
-#if INCLUDE_ALL_GCS
-
-  void g1_write_barrier_pre(Register obj,
-                            Register pre_val,
-                            Register thread,
-                            Register tmp,
-                            bool tosca_live,
-                            bool expand_call);
-
-  void g1_write_barrier_post(Register store_addr,
-                             Register new_val,
-                             Register thread,
-                             Register tmp,
-                             Register tmp2);
-
-#endif // INCLUDE_ALL_GCS
+  void resolve_jobject(Register value, Register thread, Register tmp);
 
   // C 'boolean' to Java boolean: x == 0 ? 0 : 1
   void c2bool(Register x);
@@ -334,10 +314,17 @@
   void load_klass(Register dst, Register src);
   void store_klass(Register dst, Register src);
 
-  void load_heap_oop(Register dst, Address src);
-  void load_heap_oop_not_null(Register dst, Address src);
-  void store_heap_oop(Address dst, Register src);
-  void cmp_heap_oop(Register src1, Address src2, Register tmp = noreg);
+  void access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src,
+                      Register tmp1, Register thread_tmp);
+  void access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register src,
+                       Register tmp1, Register tmp2);
+
+  void load_heap_oop(Register dst, Address src, Register tmp1 = noreg,
+                     Register thread_tmp = noreg, DecoratorSet decorators = 0);
+  void load_heap_oop_not_null(Register dst, Address src, Register tmp1 = noreg,
+                              Register thread_tmp = noreg, DecoratorSet decorators = 0);
+  void store_heap_oop(Address dst, Register src, Register tmp1 = noreg,
+                      Register tmp2 = noreg, DecoratorSet decorators = 0);
 
   // Used for storing NULL. All other oop constants should be
   // stored using routines that take a jobject.
--- a/src/hotspot/cpu/x86/methodHandles_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/methodHandles_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -168,11 +168,11 @@
 
   // Load the invoker, as MH -> MH.form -> LF.vmentry
   __ verify_oop(recv);
-  __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())));
+  __ load_heap_oop(method_temp, Address(recv, NONZERO(java_lang_invoke_MethodHandle::form_offset_in_bytes())), temp2);
   __ verify_oop(method_temp);
-  __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())));
+  __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_LambdaForm::vmentry_offset_in_bytes())), temp2);
   __ verify_oop(method_temp);
-  __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())));
+  __ load_heap_oop(method_temp, Address(method_temp, NONZERO(java_lang_invoke_MemberName::method_offset_in_bytes())), temp2);
   __ verify_oop(method_temp);
   __ movptr(method_temp, Address(method_temp, NONZERO(java_lang_invoke_ResolvedMethodName::vmtarget_offset_in_bytes())));
 
@@ -361,7 +361,7 @@
       if (VerifyMethodHandles && iid != vmIntrinsics::_linkToInterface) {
         Label L_ok;
         Register temp2_defc = temp2;
-        __ load_heap_oop(temp2_defc, member_clazz);
+        __ load_heap_oop(temp2_defc, member_clazz, temp3);
         load_klass_from_Class(_masm, temp2_defc);
         __ verify_klass_ptr(temp2_defc);
         __ check_klass_subtype(temp1_recv_klass, temp2_defc, temp3, L_ok);
@@ -437,6 +437,8 @@
         verify_ref_kind(_masm, JVM_REF_invokeInterface, member_reg, temp3);
       }
 
+      BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler();
+
       Register temp3_intf = temp3;
       __ load_heap_oop(temp3_intf, member_clazz);
       load_klass_from_Class(_masm, temp3_intf);
--- a/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_32.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -845,7 +845,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, t, from, to, count);
 
     __ subptr(to, from); // to --> to_from
@@ -1034,7 +1034,7 @@
       decorators |= ARRAYCOPY_ALIGNED;
     }
 
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, t, from, to, count);
 
     // copy from high to low
@@ -1389,7 +1389,7 @@
     }
 
     BasicType type = T_OBJECT;
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
 
     // Copy from low to high addresses, indexed from the end of each array.
--- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1829,7 +1829,7 @@
     }
 
     BasicType type = is_oop ? T_OBJECT : T_INT;
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
 
     // 'from', 'to' and 'count' are now valid
@@ -1923,7 +1923,7 @@
     }
 
     BasicType type = is_oop ? T_OBJECT : T_INT;
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     // no registers are destroyed by this call
     bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
 
@@ -2027,7 +2027,7 @@
     }
 
     BasicType type = is_oop ? T_OBJECT : T_LONG;
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, type, from, to, qword_count);
 
     // Copy from low to high addresses.  Use 'to' as scratch.
@@ -2120,7 +2120,7 @@
     }
 
     BasicType type = is_oop ? T_OBJECT : T_LONG;
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, type, from, to, qword_count);
 
     __ jmp(L_copy_bytes);
@@ -2300,7 +2300,7 @@
     }
 
     BasicType type = T_OBJECT;
-    BarrierSetAssembler *bs = Universe::heap()->barrier_set()->barrier_set_assembler();
+    BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler();
     bs->arraycopy_prologue(_masm, decorators, type, from, to, count);
 
     // Copy from low to high addresses, indexed from the end of each array.
@@ -2323,13 +2323,13 @@
     __ align(OptoLoopAlignment);
 
     __ BIND(L_store_element);
-    __ store_heap_oop(to_element_addr, rax_oop);  // store the oop
+    __ store_heap_oop(to_element_addr, rax_oop, noreg, noreg, AS_RAW);  // store the oop
     __ increment(count);               // increment the count toward zero
     __ jcc(Assembler::zero, L_do_card_marks);
 
     // ======== loop entry is here ========
     __ BIND(L_load_element);
-    __ load_heap_oop(rax_oop, from_element_addr); // load the oop
+    __ load_heap_oop(rax_oop, from_element_addr, noreg, noreg, AS_RAW); // load the oop
     __ testptr(rax_oop, rax_oop);
     __ jcc(Assembler::zero, L_store_element);
 
--- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "interpreter/interpreter.hpp"
@@ -696,29 +697,18 @@
 
 // Method entry for java.lang.ref.Reference.get.
 address TemplateInterpreterGenerator::generate_Reference_get_entry(void) {
-#if INCLUDE_ALL_GCS
   // Code: _aload_0, _getfield, _areturn
   // parameter size = 1
   //
   // The code that gets generated by this routine is split into 2 parts:
-  //    1. The "intrinsified" code for G1 (or any SATB based GC),
+  //    1. The "intrinsified" code performing an ON_WEAK_OOP_REF load,
   //    2. The slow path - which is an expansion of the regular method entry.
   //
   // Notes:-
-  // * In the G1 code we do not check whether we need to block for
-  //   a safepoint. If G1 is enabled then we must execute the specialized
-  //   code for Reference.get (except when the Reference object is null)
-  //   so that we can log the value in the referent field with an SATB
-  //   update buffer.
-  //   If the code for the getfield template is modified so that the
-  //   G1 pre-barrier code is executed when the current method is
-  //   Reference.get() then going through the normal method entry
-  //   will be fine.
-  // * The G1 code can, however, check the receiver object (the instance
-  //   of java.lang.Reference) and jump to the slow path if null. If the
-  //   Reference object is null then we obviously cannot fetch the referent
-  //   and so we don't need to call the G1 pre-barrier. Thus we can use the
-  //   regular method entry code to generate the NPE.
+  // * An intrinsic is always executed, where an ON_WEAK_OOP_REF load is performed.
+  // * We may jump to the slow path iff the receiver is null. If the
+  //   Reference object is null then we no longer perform an ON_WEAK_OOP_REF load
+  //   Thus we can use the regular method entry code to generate the NPE.
   //
   // rbx: Method*
 
@@ -729,63 +719,41 @@
   const int referent_offset = java_lang_ref_Reference::referent_offset;
   guarantee(referent_offset > 0, "referent offset not initialized");
 
-  if (UseG1GC) {
-    Label slow_path;
-    // rbx: method
+  Label slow_path;
+  // rbx: method
 
-    // Check if local 0 != NULL
-    // If the receiver is null then it is OK to jump to the slow path.
-    __ movptr(rax, Address(rsp, wordSize));
-
-    __ testptr(rax, rax);
-    __ jcc(Assembler::zero, slow_path);
+  // Check if local 0 != NULL
+  // If the receiver is null then it is OK to jump to the slow path.
+  __ movptr(rax, Address(rsp, wordSize));
 
-    // rax: local 0
-    // rbx: method (but can be used as scratch now)
-    // rdx: scratch
-    // rdi: scratch
+  __ testptr(rax, rax);
+  __ jcc(Assembler::zero, slow_path);
 
-    // Preserve the sender sp in case the pre-barrier
-    // calls the runtime
-    NOT_LP64(__ push(rsi));
-
-    // Generate the G1 pre-barrier code to log the value of
-    // the referent field in an SATB buffer.
-
-    // Load the value of the referent field.
-    const Address field_address(rax, referent_offset);
-    __ load_heap_oop(rax, field_address);
+  // rax: local 0
+  // rbx: method (but can be used as scratch now)
+  // rdx: scratch
+  // rdi: scratch
 
-    const Register sender_sp = NOT_LP64(rsi) LP64_ONLY(r13);
-    const Register thread = NOT_LP64(rcx) LP64_ONLY(r15_thread);
-    NOT_LP64(__ get_thread(thread));
+  // Preserve the sender sp in case the load barrier
+  // calls the runtime
+  NOT_LP64(__ push(rsi));
 
-    // Generate the G1 pre-barrier code to log the value of
-    // the referent field in an SATB buffer.
-    __ g1_write_barrier_pre(noreg /* obj */,
-                            rax /* pre_val */,
-                            thread /* thread */,
-                            rbx /* tmp */,
-                            true /* tosca_live */,
-                            true /* expand_call */);
+  // Load the value of the referent field.
+  const Address field_address(rax, referent_offset);
+  __ load_heap_oop(rax, field_address, /*tmp1*/ rbx, /*tmp_thread*/ rdx, ON_WEAK_OOP_REF);
 
-    // _areturn
-    NOT_LP64(__ pop(rsi));      // get sender sp
-    __ pop(rdi);                // get return address
-    __ mov(rsp, sender_sp);     // set sp to sender sp
-    __ jmp(rdi);
-    __ ret(0);
+  // _areturn
+  const Register sender_sp = NOT_LP64(rsi) LP64_ONLY(r13);
+  NOT_LP64(__ pop(rsi));      // get sender sp
+  __ pop(rdi);                // get return address
+  __ mov(rsp, sender_sp);     // set sp to sender sp
+  __ jmp(rdi);
+  __ ret(0);
 
-    // generate a vanilla interpreter entry as the slow path
-    __ bind(slow_path);
-    __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
-    return entry;
-  }
-#endif // INCLUDE_ALL_GCS
-
-  // If G1 is not enabled then attempt to go through the accessor entry point
-  // Reference.get is an accessor
-  return NULL;
+  // generate a vanilla interpreter entry as the slow path
+  __ bind(slow_path);
+  __ jump_to_entry(Interpreter::entry_for_kind(Interpreter::zerolocals));
+  return entry;
 }
 
 void TemplateInterpreterGenerator::bang_stack_shadow_pages(bool native_call) {
--- a/src/hotspot/cpu/x86/templateTable_x86.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/x86/templateTable_x86.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -149,84 +149,18 @@
 
 
 static void do_oop_store(InterpreterMacroAssembler* _masm,
-                         Address obj,
+                         Address dst,
                          Register val,
-                         BarrierSet::Name barrier,
-                         bool precise) {
+                         DecoratorSet decorators = 0) {
   assert(val == noreg || val == rax, "parameter is just for looks");
-  switch (barrier) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      {
-        // flatten object address if needed
-        // We do it regardless of precise because we need the registers
-        if (obj.index() == noreg && obj.disp() == 0) {
-          if (obj.base() != rdx) {
-            __ movptr(rdx, obj.base());
-          }
-        } else {
-          __ lea(rdx, obj);
-        }
-
-        Register rtmp    = LP64_ONLY(r8)         NOT_LP64(rsi);
-        Register rthread = LP64_ONLY(r15_thread) NOT_LP64(rcx);
-
-        NOT_LP64(__ get_thread(rcx));
-        NOT_LP64(__ save_bcp());
-
-        __ g1_write_barrier_pre(rdx /* obj */,
-                                rbx /* pre_val */,
-                                rthread /* thread */,
-                                rtmp  /* tmp */,
-                                val != noreg /* tosca_live */,
-                                false /* expand_call */);
-        if (val == noreg) {
-          __ store_heap_oop_null(Address(rdx, 0));
-        } else {
-          // G1 barrier needs uncompressed oop for region cross check.
-          Register new_val = val;
-          if (UseCompressedOops) {
-            new_val = rbx;
-            __ movptr(new_val, val);
-          }
-          __ store_heap_oop(Address(rdx, 0), val);
-          __ g1_write_barrier_post(rdx /* store_adr */,
-                                   new_val /* new_val */,
-                                   rthread /* thread */,
-                                   rtmp /* tmp */,
-                                   rbx /* tmp2 */);
-        }
-        NOT_LP64( __ restore_bcp());
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-      {
-        if (val == noreg) {
-          __ store_heap_oop_null(obj);
-        } else {
-          __ store_heap_oop(obj, val);
-          // flatten object address if needed
-          if (!precise || (obj.index() == noreg && obj.disp() == 0)) {
-            __ store_check(obj.base());
-          } else {
-            __ lea(rdx, obj);
-            __ store_check(rdx);
-          }
-        }
-      }
-      break;
-    case BarrierSet::ModRef:
-      if (val == noreg) {
-        __ store_heap_oop_null(obj);
-      } else {
-        __ store_heap_oop(obj, val);
-      }
-      break;
-    default      :
-      ShouldNotReachHere();
-
-  }
+  __ store_heap_oop(dst, val, rdx, rbx, decorators);
+}
+
+static void do_oop_load(InterpreterMacroAssembler* _masm,
+                        Address src,
+                        Register dst,
+                        DecoratorSet decorators = 0) {
+  __ load_heap_oop(dst, src, rdx, rbx, decorators);
 }
 
 Address TemplateTable::at_bcp(int offset) {
@@ -876,9 +810,12 @@
   // rax: index
   // rdx: array
   index_check(rdx, rax); // kills rbx
-  __ load_heap_oop(rax, Address(rdx, rax,
-                                UseCompressedOops ? Address::times_4 : Address::times_ptr,
-                                arrayOopDesc::base_offset_in_bytes(T_OBJECT)));
+  do_oop_load(_masm,
+              Address(rdx, rax,
+                      UseCompressedOops ? Address::times_4 : Address::times_ptr,
+                      arrayOopDesc::base_offset_in_bytes(T_OBJECT)),
+              rax,
+              IN_HEAP_ARRAY);
 }
 
 void TemplateTable::baload() {
@@ -1189,7 +1126,7 @@
   // Get the value we will store
   __ movptr(rax, at_tos());
   // Now store using the appropriate barrier
-  do_oop_store(_masm, Address(rdx, 0), rax, _bs->kind(), true);
+  do_oop_store(_masm, Address(rdx, 0), rax, IN_HEAP_ARRAY);
   __ jmp(done);
 
   // Have a NULL in rax, rdx=array, ecx=index.  Store NULL at ary[idx]
@@ -1197,7 +1134,7 @@
   __ profile_null_seen(rbx);
 
   // Store a NULL
-  do_oop_store(_masm, element_address, noreg, _bs->kind(), true);
+  do_oop_store(_masm, element_address, noreg, IN_HEAP_ARRAY);
 
   // Pop stack arguments
   __ bind(done);
@@ -2951,7 +2888,7 @@
   __ cmpl(flags, atos);
   __ jcc(Assembler::notEqual, notObj);
   // atos
-  __ load_heap_oop(rax, field);
+  do_oop_load(_masm, field, rax);
   __ push(atos);
   if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
@@ -3226,7 +3163,7 @@
     __ pop(atos);
     if (!is_static) pop_and_check_object(obj);
     // Store into the field
-    do_oop_store(_masm, field, rax, _bs->kind(), false);
+    do_oop_store(_masm, field, rax);
     if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
     }
@@ -3479,7 +3416,7 @@
   // access field
   switch (bytecode()) {
   case Bytecodes::_fast_aputfield:
-    do_oop_store(_masm, field, rax, _bs->kind(), false);
+    do_oop_store(_masm, field, rax);
     break;
   case Bytecodes::_fast_lputfield:
 #ifdef _LP64
@@ -3568,7 +3505,7 @@
   // access field
   switch (bytecode()) {
   case Bytecodes::_fast_agetfield:
-    __ load_heap_oop(rax, field);
+    do_oop_load(_masm, field, rax);
     __ verify_oop(rax);
     break;
   case Bytecodes::_fast_lgetfield:
@@ -3630,7 +3567,7 @@
     __ movl(rax, field);
     break;
   case atos:
-    __ load_heap_oop(rax, field);
+    do_oop_load(_masm, field, rax);
     __ verify_oop(rax);
     break;
   case ftos:
--- a/src/hotspot/cpu/zero/assembler_zero.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/zero/assembler_zero.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -39,7 +39,6 @@
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 
--- a/src/hotspot/cpu/zero/cppInterpreter_zero.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/zero/cppInterpreter_zero.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -275,7 +275,7 @@
     markOop disp = lockee->mark()->set_unlocked();
 
     monitor->lock()->set_displaced_header(disp);
-    if (Atomic::cmpxchg((markOop)monitor, lockee->mark_addr(), disp) != disp) {
+    if (lockee->cas_set_mark((markOop)monitor, disp) != disp) {
       if (thread->is_lock_owned((address) disp->clear_lock_bits())) {
         monitor->lock()->set_displaced_header(NULL);
       }
--- a/src/hotspot/cpu/zero/gc/shared/barrierSetAssembler_zero.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/cpu/zero/gc/shared/barrierSetAssembler_zero.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -22,9 +22,9 @@
  *
  */
 
-#ifndef CPU_ZERO_GC_G1_BARRIERSETASSEMBLER_ZERO_HPP
-#define CPU_ZERO_GC_G1_BARRIERSETASSEMBLER_ZERO_HPP
+#ifndef CPU_ZERO_GC_SHARED_BARRIERSETASSEMBLER_ZERO_HPP
+#define CPU_ZERO_GC_SHARED_BARRIERSETASSEMBLER_ZERO_HPP
 
 class BarrierSetAssembler;
 
-#endif // CPU_ZERO_GC_G1_BARRIERSETASSEMBLER_ZERO_HPP
+#endif // CPU_ZERO_GC_SHARED_BARRIERSETASSEMBLER_ZERO_HPP
--- a/src/hotspot/os/aix/attachListener_aix.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/aix/attachListener_aix.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2016 SAP SE. All rights reserved.
+ * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,12 +30,12 @@
 #include "services/attachListener.hpp"
 #include "services/dtraceAttacher.hpp"
 
-#include <unistd.h>
 #include <signal.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/socket.h>
 #include <sys/un.h>
-#include <sys/stat.h>
+#include <unistd.h>
 
 #ifndef UNIX_PATH_MAX
 #define UNIX_PATH_MAX   sizeof(((struct sockaddr_un *)0)->sun_path)
@@ -145,10 +145,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
       if (_pos < _end) {
         _pos += 1;
       }
-
       return NULL;
     }
     char* res = _pos;
@@ -233,10 +233,10 @@
   // put in listen mode, set permissions, and rename into place
   res = ::listen(listener, 5);
   if (res == 0) {
-      RESTARTABLE(::chmod(initial_path, (S_IREAD|S_IWRITE) & ~(S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)), res);
-      if (res == 0) {
-          res = ::rename(initial_path, path);
-      }
+    RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+    if (res == 0) {
+      res = ::rename(initial_path, path);
+    }
   }
   if (res == -1) {
     ::close(listener);
@@ -284,10 +284,12 @@
     // Don't block on interrupts because this will
     // hang in the clean-up when shutting down.
     n = read(s, buf+off, left);
+    assert(n <= left, "buffer was too small, impossible!");
+    buf[max_len - 1] = '\0';
     if (n == -1) {
       return NULL;      // reset by peer or other error
     }
-    if (n == 0) {       // end of file reached
+    if (n == 0) {
       break;
     }
     for (int i=0; i<n; i++) {
@@ -362,7 +364,7 @@
     socklen_t len = sizeof(addr);
     memset(&addr, 0, len);
     // We must prevent accept blocking on the socket if it has been shut down.
-    // Therefore we allow interrups and check whether we have been shut down already.
+    // Therefore we allow interrupts and check whether we have been shut down already.
     if (AixAttachListener::is_shutdown()) {
       return NULL;
     }
@@ -371,19 +373,11 @@
       return NULL;      // log a warning?
     }
 
-    // Added timeouts for read and write.  If we get no request within the
-    // next AttachListenerTimeout milliseconds we just finish the connection.
-    struct timeval tv;
-    tv.tv_sec = 0;
-    tv.tv_usec = AttachListenerTimeout * 1000;
-    ::setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
-    ::setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
-
     // get the credentials of the peer and check the effective uid/guid
-    // - check with jeff on this.
     struct peercred_struct cred_info;
     socklen_t optlen = sizeof(cred_info);
     if (::getsockopt(s, SOL_SOCKET, SO_PEERID, (void*)&cred_info, &optlen) == -1) {
+      log_debug(attach)("Failed to get socket option SO_PEERID");
       ::close(s);
       continue;
     }
@@ -391,6 +385,7 @@
     gid_t egid = getegid();
 
     if (cred_info.euid != euid || cred_info.egid != egid) {
+      log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", cred_info.euid, cred_info.egid, euid, egid);
       ::close(s);
       continue;
     }
@@ -532,10 +527,10 @@
   if (init_at_startup() || is_initialized()) {
     return false;               // initialized at startup or already initialized
   }
-  char fn[PATH_MAX+1];
-  sprintf(fn, ".attach_pid%d", os::current_process_id());
+  char fn[PATH_MAX + 1];
   int ret;
   struct stat64 st;
+  sprintf(fn, ".attach_pid%d", os::current_process_id());
   RESTARTABLE(::stat64(fn, &st), ret);
   if (ret == -1) {
     log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
@@ -551,7 +546,7 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
-      log_trace(attach)("Attach trigerred by %s", fn);
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
     } else {
       log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
--- a/src/hotspot/os/aix/globals_aix.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/aix/globals_aix.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2018 SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,10 +51,6 @@
   product(bool, AllowExtshm, false,                                                 \
           "Allow VM to run with EXTSHM=ON.")                                        \
                                                                                     \
-  product(intx, AttachListenerTimeout, 1000,                                        \
-          "Timeout in ms the attach listener waits for a request")                  \
-          range(0, 2147483)                                                         \
-                                                                                    \
   /*  Maximum expected size of the data segment. That correlates with the      */   \
   /*  to the maximum C Heap consumption we expect.                             */   \
   /*  We need to know this because we need to leave "breathing space" for the  */   \
--- a/src/hotspot/os/bsd/attachListener_bsd.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/bsd/attachListener_bsd.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -137,6 +137,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
+      if (_pos < _end) {
+        _pos += 1;
+      }
       return NULL;
     }
     char* res = _pos;
@@ -195,6 +199,7 @@
 
   // bind socket
   struct sockaddr_un addr;
+  memset((void *)&addr, 0, sizeof(addr));
   addr.sun_family = AF_UNIX;
   strcpy(addr.sun_path, initial_path);
   ::unlink(initial_path);
@@ -260,6 +265,8 @@
   do {
     int n;
     RESTARTABLE(read(s, buf+off, left), n);
+    assert(n <= left, "buffer was too small, impossible!");
+    buf[max_len - 1] = '\0';
     if (n == -1) {
       return NULL;      // reset by peer or other error
     }
@@ -342,10 +349,10 @@
     }
 
     // get the credentials of the peer and check the effective uid/guid
-    // - check with jeff on this.
     uid_t puid;
     gid_t pgid;
     if (::getpeereid(s, &puid, &pgid) != 0) {
+      log_debug(attach)("Failed to get peer id");
       ::close(s);
       continue;
     }
@@ -353,6 +360,7 @@
     gid_t egid = getegid();
 
     if (puid != euid || pgid != egid) {
+      log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", puid, pgid, euid, egid);
       ::close(s);
       continue;
     }
@@ -438,7 +446,6 @@
   return op;
 }
 
-
 // Performs initialization at vm startup
 // For BSD we remove any stale .java_pid file which could cause
 // an attaching process to think we are ready to receive on the
@@ -497,7 +504,6 @@
   char fn[PATH_MAX + 1];
   int ret;
   struct stat st;
-
   snprintf(fn, PATH_MAX + 1, "%s/.attach_pid%d",
            os::get_temp_directory(), os::current_process_id());
   RESTARTABLE(::stat(fn, &st), ret);
@@ -509,7 +515,7 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
-      log_trace(attach)("Attach trigerred by %s", fn);
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
     } else {
       log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
--- a/src/hotspot/os/linux/attachListener_linux.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/linux/attachListener_linux.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -138,6 +138,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
+      if (_pos < _end) {
+        _pos += 1;
+      }
       return NULL;
     }
     char* res = _pos;
@@ -196,6 +200,7 @@
 
   // bind socket
   struct sockaddr_un addr;
+  memset((void *)&addr, 0, sizeof(addr));
   addr.sun_family = AF_UNIX;
   strcpy(addr.sun_path, initial_path);
   ::unlink(initial_path);
@@ -208,10 +213,10 @@
   // put in listen mode, set permissions, and rename into place
   res = ::listen(listener, 5);
   if (res == 0) {
-      RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
-      if (res == 0) {
-          res = ::rename(initial_path, path);
-      }
+    RESTARTABLE(::chmod(initial_path, S_IREAD|S_IWRITE), res);
+    if (res == 0) {
+      res = ::rename(initial_path, path);
+    }
   }
   if (res == -1) {
     ::close(listener);
@@ -340,10 +345,10 @@
     }
 
     // get the credentials of the peer and check the effective uid/guid
-    // - check with jeff on this.
     struct ucred cred_info;
     socklen_t optlen = sizeof(cred_info);
     if (::getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void*)&cred_info, &optlen) == -1) {
+      log_debug(attach)("Failed to get socket option SO_PEERCRED");
       ::close(s);
       continue;
     }
@@ -351,6 +356,7 @@
     gid_t egid = getegid();
 
     if (cred_info.uid != euid || cred_info.gid != egid) {
+      log_debug(attach)("euid/egid check failed (%d/%d vs %d/%d)", cred_info.uid, cred_info.gid, euid, egid);
       ::close(s);
       continue;
     }
@@ -436,7 +442,6 @@
   return op;
 }
 
-
 // Performs initialization at vm startup
 // For Linux we remove any stale .java_pid file which could cause
 // an attaching process to think we are ready to receive on the
@@ -492,10 +497,10 @@
   if (init_at_startup() || is_initialized()) {
     return false;               // initialized at startup or already initialized
   }
-  char fn[PATH_MAX+1];
-  sprintf(fn, ".attach_pid%d", os::current_process_id());
+  char fn[PATH_MAX + 1];
   int ret;
   struct stat64 st;
+  sprintf(fn, ".attach_pid%d", os::current_process_id());
   RESTARTABLE(::stat64(fn, &st), ret);
   if (ret == -1) {
     log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
@@ -511,10 +516,10 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
-      log_trace(attach)("Attach trigerred by %s", fn);
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
     } else {
-      log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not trigerred", fn, st.st_uid, geteuid());
+      log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
     }
   }
   return false;
--- a/src/hotspot/os/solaris/attachListener_solaris.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/solaris/attachListener_solaris.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -186,6 +186,10 @@
   }
   char* next() {
     if (*_pos == '\0') {
+      // advance the iterator if possible (null arguments)
+      if (_pos < _end) {
+        _pos += 1;
+      }
       return NULL;
     }
     char* res = _pos;
@@ -644,10 +648,10 @@
   if (init_at_startup() || is_initialized()) {
     return false;               // initialized at startup or already initialized
   }
-  char fn[PATH_MAX+1];
-  sprintf(fn, ".attach_pid%d", os::current_process_id());
+  char fn[PATH_MAX + 1];
   int ret;
   struct stat64 st;
+  sprintf(fn, ".attach_pid%d", os::current_process_id());
   RESTARTABLE(::stat64(fn, &st), ret);
   if (ret == -1) {
     log_trace(attach)("Failed to find attach file: %s, trying alternate", fn);
@@ -663,7 +667,10 @@
     // a bogus user creates the file
     if (st.st_uid == geteuid()) {
       init();
+      log_trace(attach)("Attach triggered by %s", fn);
       return true;
+    } else {
+      log_debug(attach)("File %s has wrong user id %d (vs %d). Attach is not triggered", fn, st.st_uid, geteuid());
     }
   }
   return false;
--- a/src/hotspot/os/windows/attachListener_windows.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/windows/attachListener_windows.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -131,12 +131,12 @@
     pipe_name_max = 256             // maximum pipe name
   };
 
-  char _pipe[pipe_name_max+1];
+  char _pipe[pipe_name_max + 1];
 
   const char* pipe() const                              { return _pipe; }
   void set_pipe(const char* pipe) {
-    assert(strlen(pipe) <= pipe_name_max, "execeds maximum length of pipe name");
-    strcpy(_pipe, pipe);
+    assert(strlen(pipe) <= pipe_name_max, "exceeds maximum length of pipe name");
+    os::snprintf(_pipe, sizeof(_pipe), "%s", pipe);
   }
 
   HANDLE open_pipe();
@@ -329,12 +329,20 @@
 
     fSuccess = write_pipe(hPipe, msg, (int)strlen(msg));
     if (fSuccess) {
-      write_pipe(hPipe, (char*) result_stream->base(), (int)(result_stream->size()));
+      fSuccess = write_pipe(hPipe, (char*)result_stream->base(), (int)(result_stream->size()));
     }
 
     // Need to flush buffers
     FlushFileBuffers(hPipe);
     CloseHandle(hPipe);
+
+    if (fSuccess) {
+      log_debug(attach)("wrote result of attach operation %s to pipe %s", name(), pipe());
+    } else {
+      log_error(attach)("failure writing result of operation %s to pipe %s", name(), pipe());
+    }
+  } else {
+    log_error(attach)("could not open pipe %s to send result of operation %s", pipe(), name());
   }
 
   DWORD res = ::WaitForSingleObject(Win32AttachListener::mutex(), INFINITE);
--- a/src/hotspot/os/windows/os_windows.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os/windows/os_windows.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -99,6 +99,8 @@
 // for enumerating dll libraries
 #include <vdmdbg.h>
 #include <psapi.h>
+#include <mmsystem.h>
+#include <winsock2.h>
 
 // for timer info max values which include all bits
 #define ALL_64_BITS CONST64(-1)
--- a/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os_cpu/linux_arm/thread_linux_arm.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -46,7 +46,7 @@
 }
 
 void JavaThread::cache_global_variables() {
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
 
   const bool allow_shared_alloc =
     Universe::heap()->supports_inline_contig_alloc();
--- a/src/hotspot/os_cpu/linux_sparc/vm_version_linux_sparc.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/os_cpu/linux_sparc/vm_version_linux_sparc.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,7 +56,7 @@
     }
   }
 
-  ~CPUinfo() { os::free((void*)_string); }
+  ~CPUinfo() { free((void*)_string); }
 
   const char* value() const { return _string; }
 
--- a/src/hotspot/share/c1/c1_LIRAssembler.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,7 +30,7 @@
 #include "c1/c1_MacroAssembler.hpp"
 #include "c1/c1_ValueStack.hpp"
 #include "ci/ciInstance.hpp"
-#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "runtime/os.hpp"
 
 void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_code, Register obj, CodeEmitInfo* info) {
@@ -100,7 +100,7 @@
 LIR_Assembler::LIR_Assembler(Compilation* c):
    _compilation(c)
  , _masm(c->masm())
- , _bs(Universe::heap()->barrier_set())
+ , _bs(BarrierSet::barrier_set())
  , _frame_map(c->frame_map())
  , _current_block(NULL)
  , _pending_non_safepoint(NULL)
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,6 +44,7 @@
 #include "utilities/bitMap.inline.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
 #endif // INCLUDE_ALL_GCS
 #ifdef TRACE_HAVE_INTRINSICS
@@ -313,7 +314,7 @@
 
 
 void LIRGenerator::init() {
-  _bs = Universe::heap()->barrier_set();
+  _bs = BarrierSet::barrier_set();
 }
 
 
@@ -1506,10 +1507,7 @@
   }
   LIR_Opr thrd = getThreadPointer();
   LIR_Address* mark_active_flag_addr =
-    new LIR_Address(thrd,
-                    in_bytes(JavaThread::satb_mark_queue_offset() +
-                             SATBMarkQueue::byte_offset_of_active()),
-                    flag_type);
+    new LIR_Address(thrd, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), flag_type);
   // Read the marking-in-progress flag.
   LIR_Opr flag_val = new_register(T_INT);
   __ load(mark_active_flag_addr, flag_val);
@@ -1659,9 +1657,11 @@
     __ move(dirty, card_addr);
     __ branch_destination(L_already_dirty->label());
   } else {
+#if INCLUDE_ALL_GCS
     if (UseConcMarkSweepGC && CMSPrecleaningEnabled) {
       __ membar_storestore();
     }
+#endif
     __ move(dirty, card_addr);
   }
 #endif
--- a/src/hotspot/share/ci/ciInstanceKlass.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/ci/ciInstanceKlass.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -72,7 +72,7 @@
   // by the GC but need to be strong roots if reachable from a current compilation.
   // InstanceKlass are created for both weak and strong metadata.  Ensuring this metadata
   // alive covers the cases where there are weak roots without performance cost.
-  oop holder = ik->klass_holder_phantom();
+  oop holder = ik->holder_phantom();
   if (ik->is_anonymous()) {
     // Though ciInstanceKlass records class loader oop, it's not enough to keep
     // VM anonymous classes alive (loader == NULL). Klass holder should be used instead.
--- a/src/hotspot/share/ci/ciUtilities.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/ci/ciUtilities.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -51,7 +51,7 @@
 // ------------------------------------------------------------------
 // card_table_base
 jbyte *ci_card_table_address() {
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
   CardTable* ct = ctbs->card_table();
   assert(sizeof(*ct->byte_map_base()) == sizeof(jbyte), "adjust users of this code");
--- a/src/hotspot/share/classfile/altHashing.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/altHashing.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -27,6 +27,7 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "oops/markOop.hpp"
+#include "oops/oop.inline.hpp"
 #include "runtime/thread.hpp"
 
 // Get the hash code of the classes mirror if it exists, otherwise just
--- a/src/hotspot/share/classfile/classFileParser.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classFileParser.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -57,6 +57,7 @@
 #include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
 #include "prims/jvmtiThreadState.hpp"
+#include "runtime/arguments.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/perfData.hpp"
@@ -89,6 +90,7 @@
 
 #define JAVA_CLASSFILE_MAGIC              0xCAFEBABE
 #define JAVA_MIN_SUPPORTED_VERSION        45
+#define JAVA_PREVIEW_MINOR_VERSION        65535
 
 // Used for two backward compatibility reasons:
 // - to check for new additions to the class file format in JDK1.5
@@ -4700,12 +4702,63 @@
           (is_protected && is_private));
 }
 
-static bool is_supported_version(u2 major, u2 minor){
+// A legal major_version.minor_version must be one of the following:
+//
+//   Major_version = 45, any minor_version.
+//   Major_version >= 46 and major_version <= current_major_version and minor_version = 0.
+//   Major_version = current_major_version and minor_version = 65535 and --enable-preview is present.
+//
+static void verify_class_version(u2 major, u2 minor, Symbol* class_name, TRAPS){
   const u2 max_version = JVM_CLASSFILE_MAJOR_VERSION;
-  return (major >= JAVA_MIN_SUPPORTED_VERSION) &&
-         (major <= max_version) &&
-         ((major != max_version) ||
-          (minor <= JVM_CLASSFILE_MINOR_VERSION));
+  if (major != JAVA_MIN_SUPPORTED_VERSION) { // All 45.* are ok including 45.65535
+    if (minor == JAVA_PREVIEW_MINOR_VERSION) {
+      if (major != max_version) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_UnsupportedClassVersionError(),
+          "%s (class file version %u.%u) was compiled with preview features that are unsupported. "
+          "This version of the Java Runtime only recognizes preview features for class file version %u.%u",
+          class_name->as_C_string(), major, minor, JVM_CLASSFILE_MAJOR_VERSION, JAVA_PREVIEW_MINOR_VERSION);
+        return;
+      }
+
+      if (!Arguments::enable_preview()) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_UnsupportedClassVersionError(),
+          "Preview features are not enabled for %s (class file version %u.%u). Try running with '--enable-preview'",
+          class_name->as_C_string(), major, minor);
+        return;
+      }
+
+    } else { // minor != JAVA_PREVIEW_MINOR_VERSION
+      if (major > max_version) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_UnsupportedClassVersionError(),
+          "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), "
+          "this version of the Java Runtime only recognizes class file versions up to %u.0",
+          class_name->as_C_string(), major, minor, JVM_CLASSFILE_MAJOR_VERSION);
+      } else if (major < JAVA_MIN_SUPPORTED_VERSION) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_UnsupportedClassVersionError(),
+          "%s (class file version %u.%u) was compiled with an invalid major version",
+          class_name->as_C_string(), major, minor);
+      } else if (minor != 0) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_UnsupportedClassVersionError(),
+          "%s (class file version %u.%u) was compiled with an invalid non-zero minor version",
+          class_name->as_C_string(), major, minor);
+      }
+    }
+  }
 }
 
 void ClassFileParser::verify_legal_field_modifiers(jint flags,
@@ -5551,6 +5604,13 @@
       ik->print_class_load_logging(_loader_data, module_name, _stream);
     }
 
+    if (ik->minor_version() == JAVA_PREVIEW_MINOR_VERSION &&
+        ik->major_version() != JAVA_MIN_SUPPORTED_VERSION &&
+        log_is_enabled(Info, class, preview)) {
+      ResourceMark rm;
+      log_info(class, preview)("Loading preview feature type %s", ik->external_name());
+    }
+
     if (log_is_enabled(Debug, class, resolve))  {
       ResourceMark rm;
       // print out the superclass.
@@ -5866,20 +5926,7 @@
   }
 
   // Check version numbers - we check this even with verifier off
-  if (!is_supported_version(_major_version, _minor_version)) {
-    ResourceMark rm(THREAD);
-    Exceptions::fthrow(
-      THREAD_AND_LOCATION,
-      vmSymbols::java_lang_UnsupportedClassVersionError(),
-      "%s has been compiled by a more recent version of the Java Runtime (class file version %u.%u), "
-      "this version of the Java Runtime only recognizes class file versions up to %u.%u",
-      _class_name->as_C_string(),
-      _major_version,
-      _minor_version,
-      JVM_CLASSFILE_MAJOR_VERSION,
-      JVM_CLASSFILE_MINOR_VERSION);
-    return;
-  }
+  verify_class_version(_major_version, _minor_version, _class_name, CHECK);
 
   stream->guarantee_more(3, CHECK); // length, first cp tag
   u2 cp_size = stream->get_u2_fast();
--- a/src/hotspot/share/classfile/classLoader.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classLoader.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -148,6 +148,8 @@
 #if INCLUDE_CDS
 ClassPathEntry* ClassLoader::_app_classpath_entries = NULL;
 ClassPathEntry* ClassLoader::_last_app_classpath_entry = NULL;
+ClassPathEntry* ClassLoader::_module_path_entries = NULL;
+ClassPathEntry* ClassLoader::_last_module_path_entry = NULL;
 SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
 #endif
 
@@ -721,7 +723,44 @@
   }
 }
 
-#endif
+void ClassLoader::add_to_module_path_entries(const char* path,
+                                             ClassPathEntry* entry) {
+  assert(entry != NULL, "ClassPathEntry should not be NULL");
+  assert(DumpSharedSpaces, "dump time only");
+
+  // The entry does not exist, add to the list
+  if (_module_path_entries == NULL) {
+    assert(_last_module_path_entry == NULL, "Sanity");
+    _module_path_entries = _last_module_path_entry = entry;
+  } else {
+    _last_module_path_entry->set_next(entry);
+    _last_module_path_entry = entry;
+  }
+}
+
+// Add a module path to the _module_path_entries list.
+void ClassLoader::update_module_path_entry_list(const char *path, TRAPS) {
+  assert(DumpSharedSpaces, "dump time only");
+  struct stat st;
+  int ret = os::stat(path, &st);
+  assert(ret == 0, "module path must exist");
+  // File or directory found
+  ClassPathEntry* new_entry = NULL;
+  new_entry = create_class_path_entry(path, &st, true /* throw_exception */,
+                                      false /*is_boot_append */, CHECK);
+  if (new_entry == NULL) {
+    return;
+  }
+
+  add_to_module_path_entries(path, new_entry);
+  return;
+}
+
+void ClassLoader::setup_module_search_path(const char* path, TRAPS) {
+  check_shared_classpath(path);
+  update_module_path_entry_list(path, THREAD);
+}
+#endif // INCLUDE_CDS
 
 // Construct the array of module/path pairs as specified to --patch-module
 // for the boot loader to search ahead of the jimage, if the class being
@@ -758,7 +797,6 @@
       struct stat st;
       if (os::stat(path, &st) == 0) {
         // File or directory found
-        Thread* THREAD = Thread::current();
         ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
         // If the path specification is valid, enter it into this module's list
         if (new_entry != NULL) {
@@ -828,7 +866,6 @@
       struct stat st;
       if (os::stat(path, &st) == 0) {
         // Directory found
-        Thread* THREAD = Thread::current();
         ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
 
         // Check for a jimage
@@ -873,7 +910,7 @@
   const char file_sep = os::file_separator()[0];
   // 10 represents the length of "modules" + 2 file separators + \0
   size_t len = strlen(home) + strlen(module_name) + 10;
-  char *path = NEW_C_HEAP_ARRAY(char, len, mtModule);
+  char *path = NEW_RESOURCE_ARRAY(char, len);
   jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
 
   struct stat st;
@@ -895,7 +932,6 @@
       log_info(class, load)("path: %s", path);
     }
   }
-  FREE_C_HEAP_ARRAY(char, path);
 }
 
 ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
@@ -1512,7 +1548,7 @@
 }
 
 #if INCLUDE_CDS
-static char* skip_uri_protocol(char* source) {
+char* ClassLoader::skip_uri_protocol(char* source) {
   if (strncmp(source, "file:", 5) == 0) {
     // file: protocol path could start with file:/ or file:///
     // locate the char after all the forward slashes
@@ -1533,7 +1569,7 @@
 
 // Record the shared classpath index and loader type for classes loaded
 // by the builtin loaders at dump time.
-void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream) {
+void ClassLoader::record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS) {
   assert(DumpSharedSpaces, "sanity");
   assert(stream != NULL, "sanity");
 
@@ -1542,9 +1578,10 @@
     return;
   }
 
+  oop loader = ik->class_loader();
   char* src = (char*)stream->source();
   if (src == NULL) {
-    if (ik->class_loader() == NULL) {
+    if (loader == NULL) {
       // JFR classes
       ik->set_shared_classpath_index(0);
       ik->set_class_loader_type(ClassLoader::BOOT_LOADER);
@@ -1554,41 +1591,84 @@
 
   assert(has_jrt_entry(), "CDS dumping does not support exploded JDK build");
 
-  ModuleEntry* module = ik->module();
+  ResourceMark rm(THREAD);
   int classpath_index = -1;
-  ResourceMark rm;
-  char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
+  PackageEntry* pkg_entry = ik->package();
+
+  if (FileMapInfo::get_number_of_shared_paths() > 0) {
+    char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN);
 
-  // save the path from the file: protocol or the module name from the jrt: protocol
-  // if no protocol prefix is found, path is the same as stream->source()
-  char* path = skip_uri_protocol(src);
-  for (int i = 0; i < FileMapInfo::get_number_of_share_classpaths(); i++) {
-    SharedClassPathEntry* ent = FileMapInfo::shared_classpath(i);
-    if (get_canonical_path(ent->name(), canonical_path, JVM_MAXPATHLEN)) {
-      // If the path (from the class stream srouce) is the same as the shared
-      // class path, then we have a match. For classes from module image loaded by the
-      // PlatformClassLoader, the stream->source() is not the name of the module image.
-      // Need to look for 'jrt:' explicitly.
-      if (strcmp(canonical_path, os::native_path((char*)path)) == 0 ||
-          (i == 0 && string_starts_with(src, "jrt:"))) {
-        classpath_index = i;
-        break;
+    // save the path from the file: protocol or the module name from the jrt: protocol
+    // if no protocol prefix is found, path is the same as stream->source()
+    char* path = skip_uri_protocol(src);
+    for (int i = 0; i < FileMapInfo::get_number_of_shared_paths(); i++) {
+      SharedClassPathEntry* ent = FileMapInfo::shared_path(i);
+      if (get_canonical_path(ent->name(), canonical_path, JVM_MAXPATHLEN)) {
+        // If the path (from the class stream source) is the same as the shared
+        // class or module path, then we have a match.
+        if (strcmp(canonical_path, os::native_path((char*)path)) == 0) {
+          // NULL pkg_entry and pkg_entry in an unnamed module implies the class
+          // is from the -cp or boot loader append path which consists of -Xbootclasspath/a
+          // and jvmti appended entries.
+          if ((pkg_entry == NULL) || (pkg_entry->in_unnamed_module())) {
+            // Ensure the index is within the -cp range before assigning
+            // to the classpath_index.
+            if (SystemDictionary::is_system_class_loader(loader) &&
+                (i >= ClassLoaderExt::app_class_paths_start_index()) &&
+                (i < ClassLoaderExt::app_module_paths_start_index())) {
+              classpath_index = i;
+              break;
+            } else {
+              if ((i >= 1) &&
+                  (i < ClassLoaderExt::app_class_paths_start_index())) {
+                // The class must be from boot loader append path which consists of
+                // -Xbootclasspath/a and jvmti appended entries.
+                assert(loader == NULL, "sanity");
+                classpath_index = i;
+                break;
+              }
+            }
+          } else {
+            // A class from a named module from the --module-path. Ensure the index is
+            // within the --module-path range before assigning to the classpath_index.
+            if ((pkg_entry != NULL) && !(pkg_entry->in_unnamed_module()) && (i > 0)) {
+              if (i >= ClassLoaderExt::app_module_paths_start_index() &&
+                  i < FileMapInfo::get_number_of_shared_paths()) {
+                classpath_index = i;
+                break;
+              }
+            }
+          }
+        }
+        // for index 0 and the stream->source() is the modules image or has the jrt: protocol.
+        // The class must be from the runtime modules image.
+        if (i == 0 && (is_modules_image(src) || string_starts_with(src, "jrt:"))) {
+          classpath_index = i;
+          break;
+        }
       }
     }
-  }
-  if (classpath_index < 0) {
-    // Shared classpath entry table only contains boot class path and -cp path.
+
     // No path entry found for this class. Must be a shared class loaded by the
     // user defined classloader.
-    assert(ik->shared_classpath_index() < 0, "Sanity");
-    return;
+    if (classpath_index < 0) {
+      assert(ik->shared_classpath_index() < 0, "Sanity");
+      return;
+    }
+  } else {
+    // The shared path table is set up after module system initialization.
+    // The path table contains no entry before that. Any classes loaded prior
+    // to the setup of the shared path table must be from the modules image.
+    assert(is_modules_image(src), "stream must be from modules image");
+    assert(FileMapInfo::get_number_of_shared_paths() == 0, "shared path table must not have been setup");
+    classpath_index = 0;
   }
 
   const char* const class_name = ik->name()->as_C_string();
   const char* const file_name = file_name_for_class_name(class_name,
                                                          ik->name()->utf8_length());
   assert(file_name != NULL, "invariant");
-  Thread* THREAD = Thread::current();
+
   ClassLoaderExt::Context context(class_name, file_name, CATCH);
   context.record_result(ik->name(), classpath_index, ik, THREAD);
 }
@@ -1673,6 +1753,13 @@
     _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
   }
 }
+
+void ClassLoader::initialize_module_path(TRAPS) {
+  if (DumpSharedSpaces) {
+    ClassLoaderExt::setup_module_paths(THREAD);
+    FileMapInfo::allocate_shared_path_table();
+  }
+}
 #endif
 
 jlong ClassLoader::classloader_time_ms() {
--- a/src/hotspot/share/classfile/classLoader.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classLoader.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -238,12 +238,18 @@
 
   CDS_ONLY(static ClassPathEntry* _app_classpath_entries;)
   CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;)
-  CDS_ONLY(static void setup_app_search_path(const char *class_path);)
+  CDS_ONLY(static ClassPathEntry* _module_path_entries;)
+  CDS_ONLY(static ClassPathEntry* _last_module_path_entry;)
+  CDS_ONLY(static void setup_app_search_path(const char* class_path);)
+  CDS_ONLY(static void setup_module_search_path(const char* path, TRAPS);)
   static void add_to_app_classpath_entries(const char* path,
                                            ClassPathEntry* entry,
                                            bool check_for_duplicates);
+  CDS_ONLY(static void add_to_module_path_entries(const char* path,
+                                           ClassPathEntry* entry);)
  public:
   CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;})
+  CDS_ONLY(static ClassPathEntry* module_path_entries() {return _module_path_entries;})
 
  protected:
   // Initialization:
@@ -286,6 +292,7 @@
                                            bool check_for_duplicates,
                                            bool is_boot_append,
                                            bool throw_exception=true);
+  CDS_ONLY(static void update_module_path_entry_list(const char *path, TRAPS);)
   static void print_bootclasspath();
 
   // Timing
@@ -382,6 +389,7 @@
   static void initialize();
   static void classLoader_init2(TRAPS);
   CDS_ONLY(static void initialize_shared_path();)
+  CDS_ONLY(static void initialize_module_path(TRAPS);)
 
   static int compute_Object_vtable();
 
@@ -402,14 +410,28 @@
   // entries during shared classpath setup time.
   static int num_app_classpath_entries();
 
+  // Helper function used by CDS code to get the number of module path
+  // entries during shared classpath setup time.
+  static int num_module_path_entries() {
+    assert(DumpSharedSpaces, "Should only be called at CDS dump time");
+    int num_entries = 0;
+    ClassPathEntry* e= ClassLoader::_module_path_entries;
+    while (e != NULL) {
+      num_entries ++;
+      e = e->next();
+    }
+    return num_entries;
+  }
   static void  check_shared_classpath(const char *path);
   static void  finalize_shared_paths_misc_info();
   static int   get_shared_paths_misc_info_size();
   static void* get_shared_paths_misc_info();
   static bool  check_shared_paths_misc_info(void* info, int size);
+  static int   get_module_paths_misc_info_size();
+  static void* get_module_paths_misc_info();
   static void  exit_with_path_failure(const char* error, const char* message);
-
-  static void record_result(InstanceKlass* ik, const ClassFileStream* stream);
+  static char* skip_uri_protocol(char* source);
+  static void  record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS);
 #endif
   static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name,
                                                 const char* file_name, jlong &size);
--- a/src/hotspot/share/classfile/classLoaderData.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classLoaderData.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -55,26 +55,22 @@
 #include "classfile/moduleEntry.hpp"
 #include "classfile/packageEntry.hpp"
 #include "classfile/systemDictionary.hpp"
-#include "code/codeCache.hpp"
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/metaspaceShared.hpp"
-#include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
+#include "memory/universe.hpp"
 #include "oops/access.inline.hpp"
-#include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/weakHandle.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
-#include "runtime/javaCalls.hpp"
-#include "runtime/jniHandles.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/orderAccess.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/safepointVerifiers.hpp"
-#include "runtime/synchronizer.hpp"
 #include "utilities/growableArray.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/ostream.hpp"
@@ -113,17 +109,21 @@
   // The null-class-loader should always be kept alive.
   _keep_alive((is_anonymous || h_class_loader.is_null()) ? 1 : 0),
   _metaspace(NULL), _unloading(false), _klasses(NULL),
-  _modules(NULL), _packages(NULL),
+  _modules(NULL), _packages(NULL), _unnamed_module(NULL), _dictionary(NULL),
   _claimed(0), _modified_oops(true), _accumulated_modified_oops(false),
   _jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
   _next(NULL),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
                             Monitor::_safepoint_check_never)) {
 
-  // A ClassLoaderData created solely for an anonymous class should never have a
-  // ModuleEntryTable or PackageEntryTable created for it. The defining package
-  // and module for an anonymous class will be found in its host class.
   if (!is_anonymous) {
+    // The holder is initialized later for anonymous classes, and before calling anything
+    // that call class_loader().
+    initialize_holder(h_class_loader);
+
+    // A ClassLoaderData created solely for an anonymous class should never have a
+    // ModuleEntryTable or PackageEntryTable created for it. The defining package
+    // and module for an anonymous class will be found in its host class.
     _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
     if (h_class_loader.is_null()) {
       // Create unnamed module for boot loader
@@ -133,10 +133,6 @@
       _unnamed_module = ModuleEntry::create_unnamed_module(this);
     }
     _dictionary = create_dictionary();
-  } else {
-    _packages = NULL;
-    _unnamed_module = NULL;
-    _dictionary = NULL;
   }
 
   NOT_PRODUCT(_dependency_count = 0); // number of class loader dependencies
@@ -510,6 +506,13 @@
 }
 
 
+void ClassLoaderData::initialize_holder(Handle loader_or_mirror) {
+  if (loader_or_mirror() != NULL) {
+    assert(_holder.is_null(), "never replace holders");
+    _holder = WeakHandle<vm_class_loader_data>::create(loader_or_mirror);
+  }
+}
+
 // Remove a klass from the _klasses list for scratch_class during redefinition
 // or parsed class in the case of an error.
 void ClassLoaderData::remove_class(Klass* scratch_class) {
@@ -611,30 +614,23 @@
 }
 
 // Tell the GC to keep this klass alive while iterating ClassLoaderDataGraph
-oop ClassLoaderData::holder_phantom() {
+oop ClassLoaderData::holder_phantom() const {
   // A klass that was previously considered dead can be looked up in the
   // CLD/SD, and its _java_mirror or _class_loader can be stored in a root
   // or a reachable object making it alive again. The SATB part of G1 needs
   // to get notified about this potential resurrection, otherwise the marking
   // might not find the object.
-  if (!keep_alive()) {
-    oop* o = is_anonymous() ? _klasses->java_mirror_handle().ptr_raw() : &_class_loader;
-    return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(o);
+  if (!_holder.is_null()) {  // NULL class_loader
+    return _holder.resolve();
   } else {
     return NULL;
   }
 }
 
 // Unloading support
-oop ClassLoaderData::keep_alive_object() const {
-  assert_locked_or_safepoint(_metaspace_lock);
-  assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
-  return is_anonymous() ? _klasses->java_mirror() : class_loader();
-}
-
-bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const {
-  bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
-      || is_alive_closure->do_object_b(keep_alive_object());
+bool ClassLoaderData::is_alive() const {
+  bool alive = keep_alive()         // null class loader and incomplete anonymous klasses.
+      || (_holder.peek() != NULL);  // not cleaned by weak reference processing
 
   return alive;
 }
@@ -668,6 +664,9 @@
   ClassLoaderDataGraph::dec_array_classes(cl.array_class_released());
   ClassLoaderDataGraph::dec_instance_classes(cl.instance_class_released());
 
+  // Release the WeakHandle
+  _holder.release();
+
   // Release C heap allocated hashtable for all the packages.
   if (_packages != NULL) {
     // Destroy the table itself
@@ -969,7 +968,6 @@
 
   ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous);
 
-
   if (!is_anonymous) {
     // First, Atomically set it
     ClassLoaderData* old = java_lang_ClassLoader::cmpxchg_loader_data(cld, loader(), NULL);
@@ -1244,6 +1242,8 @@
   ClassLoaderData* data = _head;
   ClassLoaderData* prev = NULL;
   bool seen_dead_loader = false;
+  uint loaders_processed = 0;
+  uint loaders_removed = 0;
 
   // Mark metadata seen on the stack only so we can delete unneeded entries.
   // Only walk all metadata, including the expensive code cache walk, for Full GC
@@ -1260,7 +1260,7 @@
 
   data = _head;
   while (data != NULL) {
-    if (data->is_alive(is_alive_closure)) {
+    if (data->is_alive()) {
       // clean metaspace
       if (walk_all_metadata) {
         data->classes_do(InstanceKlass::purge_previous_versions);
@@ -1268,9 +1268,11 @@
       data->free_deallocate_list();
       prev = data;
       data = data->next();
+      loaders_processed++;
       continue;
     }
     seen_dead_loader = true;
+    loaders_removed++;
     ClassLoaderData* dead = data;
     dead->unload();
     data = data->next();
@@ -1313,6 +1315,8 @@
     post_class_unload_events();
   }
 
+  log_debug(class, loader, data)("do_unloading: loaders processed %u, loaders removed %u", loaders_processed, loaders_removed);
+
   return seen_dead_loader;
 }
 
--- a/src/hotspot/share/classfile/classLoaderData.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classLoaderData.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,6 +30,7 @@
 #include "memory/metaspace.hpp"
 #include "memory/metaspaceCounters.hpp"
 #include "oops/oopHandle.hpp"
+#include "oops/weakHandle.hpp"
 #include "runtime/mutex.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/growableArray.hpp"
@@ -113,7 +114,7 @@
   static void packages_unloading_do(void f(PackageEntry*));
   static void loaded_classes_do(KlassClosure* klass_closure);
   static void classes_unloading_do(void f(Klass* const));
-  static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
+  static bool do_unloading(BoolObjectClosure* is_alive_closure, bool clean_previous_versions);
 
   // dictionary do
   // Iterate over all klasses in dictionary, but
@@ -219,8 +220,9 @@
 
   static ClassLoaderData * _the_null_class_loader_data;
 
-  oop _class_loader;          // oop used to uniquely identify a class loader
-                              // class loader or a canonical class path
+  WeakHandle<vm_class_loader_data> _holder; // The oop that determines lifetime of this class loader
+  oop _class_loader;          // The instance of java/lang/ClassLoader associated with
+                              // this ClassLoaderData
 
   ClassLoaderMetaspace * volatile _metaspace;  // Meta-space where meta-data defined by the
                                     // classes in the class loader are allocated.
@@ -286,7 +288,8 @@
 
   void unload();
   bool keep_alive() const       { return _keep_alive > 0; }
-  oop  holder_phantom();
+
+  oop holder_phantom() const;
   void classes_do(void f(Klass*));
   void loaded_classes_do(KlassClosure* klass_closure);
   void classes_do(void f(InstanceKlass*));
@@ -308,7 +311,7 @@
   bool claimed() const { return _claimed == 1; }
   bool claim();
 
-  bool is_alive(BoolObjectClosure* is_alive_closure) const;
+  bool is_alive() const;
 
   // Accessors
   ClassLoaderMetaspace* metaspace_or_null() const { return _metaspace; }
@@ -348,7 +351,7 @@
   // method will allocate a Metaspace if needed.
   ClassLoaderMetaspace* metaspace_non_null();
 
-  oop class_loader() const      { return _class_loader; }
+  oop class_loader() const { return _class_loader; }
 
   // The object the GC is using to keep this ClassLoaderData alive.
   oop keep_alive_object() const;
@@ -364,6 +367,8 @@
   void inc_keep_alive();
   void dec_keep_alive();
 
+  void initialize_holder(Handle holder);
+
   inline unsigned int identity_hash() const { return (unsigned int)(((intptr_t)this) >> 3); }
 
   void oops_do(OopClosure* f, bool must_claim, bool clear_modified_oops = false);
--- a/src/hotspot/share/classfile/classLoaderExt.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,6 +30,7 @@
 #include "classfile/classLoaderExt.hpp"
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/klassFactory.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/sharedClassUtil.hpp"
 #include "classfile/sharedPathsMiscInfo.hpp"
 #include "classfile/systemDictionaryShared.hpp"
@@ -41,19 +42,21 @@
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "runtime/arguments.hpp"
+#include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/os.hpp"
 #include "services/threadService.hpp"
 #include "utilities/stringUtils.hpp"
 
-jshort ClassLoaderExt::_app_paths_start_index = ClassLoaderExt::max_classpath_index;
+jshort ClassLoaderExt::_app_class_paths_start_index = ClassLoaderExt::max_classpath_index;
+jshort ClassLoaderExt::_app_module_paths_start_index = ClassLoaderExt::max_classpath_index;
 bool ClassLoaderExt::_has_app_classes = false;
 bool ClassLoaderExt::_has_platform_classes = false;
 
 void ClassLoaderExt::setup_app_search_path() {
   assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
-  _app_paths_start_index = ClassLoader::num_boot_classpath_entries();
+  _app_class_paths_start_index = ClassLoader::num_boot_classpath_entries();
   char* app_class_path = os::strdup(Arguments::get_appclasspath());
 
   if (strcmp(app_class_path, ".") == 0) {
@@ -68,6 +71,29 @@
   }
 }
 
+void ClassLoaderExt::process_module_table(ModuleEntryTable* met, TRAPS) {
+  ResourceMark rm;
+  for (int i = 0; i < met->table_size(); i++) {
+    for (ModuleEntry* m = met->bucket(i); m != NULL;) {
+      char* path = m->location()->as_C_string();
+      if (strncmp(path, "file:", 5) == 0 && ClassLoader::string_ends_with(path, ".jar")) {
+        m->print();
+        path = ClassLoader::skip_uri_protocol(path);
+        ClassLoader::setup_module_search_path(path, THREAD);
+      }
+      m = m->next();
+    }
+  }
+}
+void ClassLoaderExt::setup_module_search_path(TRAPS) {
+  assert(DumpSharedSpaces, "this function is only used with -Xshare:dump and -XX:+UseAppCDS");
+  _app_module_paths_start_index = ClassLoader::num_boot_classpath_entries() +
+                              ClassLoader::num_app_classpath_entries();
+  Handle system_class_loader (THREAD, SystemDictionary::java_system_loader());
+  ModuleEntryTable* met = Modules::get_module_entry_table(system_class_loader);
+  process_module_table(met, THREAD);
+}
+
 char* ClassLoaderExt::read_manifest(ClassPathEntry* entry, jint *manifest_size, bool clean_text, TRAPS) {
   const char* name = "META-INF/MANIFEST.MF";
   char* manifest;
@@ -195,6 +221,12 @@
   }
 }
 
+void ClassLoaderExt::setup_module_paths(TRAPS) {
+  if (UseAppCDS) {
+    ClassLoaderExt::setup_module_search_path(THREAD);
+  }
+}
+
 Thread* ClassLoaderExt::Context::_dump_thread = NULL;
 
 void ClassLoaderExt::record_result(ClassLoaderExt::Context *context,
--- a/src/hotspot/share/classfile/classLoaderExt.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/classLoaderExt.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
 
 #include "classfile/classLoader.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "utilities/macros.hpp"
 
 CDS_ONLY(class SharedPathsMiscInfoExt;)
@@ -59,14 +60,14 @@
       _file_name = file_name;
 #if INCLUDE_CDS
       if (!DumpSharedSpaces && !UseSharedSpaces) {
-        // Must not modify _app_paths_start_index if we're not using CDS.
-        assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
+        // Must not modify _app_class_paths_start_index if we're not using CDS.
+        assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
       }
 #endif
     }
 
     bool should_verify(int classpath_index) {
-      CDS_ONLY(return (classpath_index >= _app_paths_start_index);)
+      CDS_ONLY(return (classpath_index >= _app_class_paths_start_index);)
       NOT_CDS(return false;)
     }
 
@@ -82,8 +83,8 @@
     ~Context() {
 #if INCLUDE_CDS
       if (!DumpSharedSpaces && !UseSharedSpaces) {
-        // Must not modify app_paths_start_index if we're not using CDS.
-        assert(_app_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
+        // Must not modify app_class_paths_start_index if we're not using CDS.
+        assert(_app_class_paths_start_index == ClassLoaderExt::max_classpath_index, "must be");
       }
 #endif
     }
@@ -93,10 +94,16 @@
 #if INCLUDE_CDS
   static char* get_class_path_attr(const char* jar_path, char* manifest, jint manifest_size);
   static void setup_app_search_path(); // Only when -Xshare:dump
+  static void process_module_table(ModuleEntryTable* met, TRAPS);
+  static void setup_module_search_path(TRAPS);
   static SharedPathsMiscInfoExt* shared_paths_misc_info() {
     return (SharedPathsMiscInfoExt*)_shared_paths_misc_info;
   }
-  static jshort _app_paths_start_index; // index of first app JAR in shared classpath entry table
+  // index of first app JAR in shared classpath entry table
+  static jshort _app_class_paths_start_index;
+  // index of first modular JAR in shared modulepath entry table
+  static jshort _app_module_paths_start_index;
+
   static bool _has_app_classes;
   static bool _has_platform_classes;
 #endif
@@ -116,6 +123,7 @@
   }
 
   static void setup_search_paths() NOT_CDS_RETURN;
+  static void setup_module_paths(TRAPS) NOT_CDS_RETURN;
 
 #if INCLUDE_CDS
 private:
@@ -137,14 +145,20 @@
 
   static void finalize_shared_paths_misc_info();
 
-  static jshort app_paths_start_index() { return _app_paths_start_index; }
+  static jshort app_class_paths_start_index() { return _app_class_paths_start_index; }
+
+  static jshort app_module_paths_start_index() { return _app_module_paths_start_index; }
 
   static void init_paths_start_index(jshort app_start) {
-    _app_paths_start_index = app_start;
+    _app_class_paths_start_index = app_start;
+  }
+
+  static void init_app_module_paths_start_index(jshort module_start) {
+    _app_module_paths_start_index = module_start;
   }
 
   static bool is_boot_classpath(int classpath_index) {
-    return classpath_index < _app_paths_start_index;
+    return classpath_index < _app_class_paths_start_index;
   }
 
   static bool has_platform_or_app_classes() {
--- a/src/hotspot/share/classfile/klassFactory.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/klassFactory.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -84,7 +84,7 @@
         }
       } else {
         SharedClassPathEntry* ent =
-          (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+          (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
         pathname = ent == NULL ? NULL : ent->name();
       }
       ClassFileStream* stream = new ClassFileStream(ptr,
@@ -232,7 +232,7 @@
 
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
-    ClassLoader::record_result(result, stream);
+    ClassLoader::record_result(result, stream, THREAD);
 #if INCLUDE_JVMTI
     assert(cached_class_file == NULL, "Sanity");
     // Archive the class stream data into the optional data section
--- a/src/hotspot/share/classfile/modules.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/modules.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -85,7 +85,7 @@
   return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
 }
 
-static ModuleEntryTable* get_module_entry_table(Handle h_loader) {
+ModuleEntryTable* Modules::get_module_entry_table(Handle h_loader) {
   // This code can be called during start-up, before the classLoader's classLoader data got
   // created.  So, call register_loader() to make sure the classLoader data gets created.
   ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader);
--- a/src/hotspot/share/classfile/modules.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/modules.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
-* Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #include "memory/allocation.hpp"
 #include "runtime/handles.hpp"
 
+class ModuleEntryTable;
 class Symbol;
 
 class Modules : AllStatic {
@@ -122,6 +123,7 @@
 
   // Return TRUE iff package is defined by loader
   static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
+  static ModuleEntryTable* get_module_entry_table(Handle h_loader);
 };
 
 #endif // SHARE_VM_CLASSFILE_MODULES_HPP
--- a/src/hotspot/share/classfile/sharedClassUtil.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/sharedClassUtil.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -93,6 +93,9 @@
   case APP:
     ClassLoader::trace_class_path("Expecting -Djava.class.path=", path);
     break;
+  case MODULE:
+    ClassLoader::trace_class_path("Checking module path: ", path);
+    break;
   default:
     SharedPathsMiscInfo::print_path(out, type, path);
   }
@@ -167,12 +170,13 @@
 
 void SharedClassUtil::initialize(TRAPS) {
   if (UseSharedSpaces) {
-    int size = FileMapInfo::get_number_of_share_classpaths();
+    int size = FileMapInfo::get_number_of_shared_paths();
     if (size > 0) {
       SystemDictionaryShared::allocate_shared_data_arrays(size, THREAD);
       if (!DumpSharedSpaces) {
         FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
-        ClassLoaderExt::init_paths_start_index(header->_app_paths_start_index);
+        ClassLoaderExt::init_paths_start_index(header->_app_class_paths_start_index);
+        ClassLoaderExt::init_app_module_paths_start_index(header->_app_module_paths_start_index);
       }
     }
   }
@@ -208,7 +212,7 @@
 bool SharedClassUtil::is_classpath_entry_signed(int classpath_index) {
   assert(classpath_index >= 0, "Sanity");
   SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)
-    FileMapInfo::shared_classpath(classpath_index);
+    FileMapInfo::shared_path(classpath_index);
   return ent->_is_signed;
 }
 
@@ -216,7 +220,8 @@
   FileMapInfo::FileMapHeader::populate(mapinfo, alignment);
 
   ClassLoaderExt::finalize_shared_paths_misc_info();
-  _app_paths_start_index = ClassLoaderExt::app_paths_start_index();
+  _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
+  _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
 
   _verify_local = BytecodeVerificationLocal;
   _verify_remote = BytecodeVerificationRemote;
--- a/src/hotspot/share/classfile/sharedClassUtil.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/sharedClassUtil.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,10 +34,11 @@
 
 class FileMapHeaderExt: public FileMapInfo::FileMapHeader {
 public:
-  jshort _app_paths_start_index;    // Index of first app classpath entry
-  bool   _verify_local;             // BytecodeVerificationLocal setting
-  bool   _verify_remote;            // BytecodeVerificationRemote setting
-  bool   _has_platform_or_app_classes;          // Archive contains app classes
+  jshort _app_class_paths_start_index;  // Index of first app classpath entry
+  jshort _app_module_paths_start_index; // Index of first module path entry
+  bool   _verify_local;                 // BytecodeVerificationLocal setting
+  bool   _verify_remote;                // BytecodeVerificationRemote setting
+  bool   _has_platform_or_app_classes;  // Archive contains app classes
 
   FileMapHeaderExt() {
     _has_platform_or_app_classes = true;
@@ -56,12 +57,14 @@
   int   _app_offset;
 public:
   enum {
-    APP       = 5
+    APP       = 5,
+    MODULE    = 6
   };
 
   virtual const char* type_name(int type) {
     switch (type) {
     case APP:     return "APP";
+    case MODULE:  return "MODULE";
     default:      return SharedPathsMiscInfo::type_name(type);
     }
   }
--- a/src/hotspot/share/classfile/stringTable.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/stringTable.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -45,7 +45,6 @@
 #include "utilities/hashtable.inline.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
-#include "gc/g1/g1CollectedHeap.hpp"
 #include "gc/g1/g1StringDedup.hpp"
 #endif
 
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,6 +44,7 @@
 #include "code/codeCache.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"
+#include "gc/shared/oopStorage.inline.hpp"
 #include "interpreter/bytecodeStream.hpp"
 #include "interpreter/interpreter.hpp"
 #include "logging/log.hpp"
@@ -117,6 +118,8 @@
 
 const int defaultProtectionDomainCacheSize = 1009;
 
+OopStorage* SystemDictionary::_vm_weak_oop_storage = NULL;
+
 
 // ----------------------------------------------------------------------------
 // Java-level SystemLoader and PlatformLoader
@@ -1012,7 +1015,9 @@
                                                       CHECK_NULL);
 
   if (host_klass != NULL && k != NULL) {
-    // If it's anonymous, initialize it now, since nobody else will.
+    // Anonymous classes must update ClassLoaderData holder (was host_klass loader)
+    // so that they can be unloaded when the mirror is no longer referenced.
+    k->class_loader_data()->initialize_holder(Handle(THREAD, k->java_mirror()));
 
     {
       MutexLocker mu_r(Compile_lock, THREAD);
@@ -1032,6 +1037,8 @@
     if (cp_patches != NULL) {
       k->constants()->patch_resolved_references(cp_patches);
     }
+
+    // If it's anonymous, initialize it now, since nobody else will.
     k->eager_initialize(CHECK_NULL);
 
     // notify jvmti
@@ -1210,7 +1217,7 @@
     }
   }
   SharedClassPathEntry* ent =
-            (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+            (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
   if (!Universe::is_module_initialized()) {
     assert(ent != NULL && ent->is_modules_image(),
            "Loading non-bootstrap classes before the module system is initialized");
@@ -1848,6 +1855,10 @@
                                     GCTimer* gc_timer,
                                     bool do_cleaning) {
 
+  {
+    GCTraceTime(Debug, gc, phases) t("SystemDictionary WeakHandle cleaning", gc_timer);
+    vm_weak_oop_storage()->weak_oops_do(is_alive, &do_nothing_cl);
+  }
 
   bool unloading_occurred;
   {
@@ -1896,9 +1907,11 @@
     // Only the protection domain oops contain references into the heap. Iterate
     // over all of them.
     _pd_cache_table->oops_do(strong);
+    vm_weak_oop_storage()->oops_do(strong);
   } else {
    if (weak != NULL) {
      _pd_cache_table->oops_do(weak);
+     vm_weak_oop_storage()->oops_do(weak);
    }
   }
 
@@ -1924,6 +1937,8 @@
   invoke_method_table()->oops_do(f);
 
   ResolvedMethodTable::oops_do(f);
+
+  vm_weak_oop_storage()->oops_do(f);
 }
 
 // CDS: scan and relocate all classes in the system dictionary.
@@ -3105,3 +3120,15 @@
   return (loader_data->class_loader() == NULL ? "<bootloader>" :
           SystemDictionary::loader_name(loader_data->class_loader()));
 }
+
+void SystemDictionary::initialize_oop_storage() {
+  _vm_weak_oop_storage =
+    new OopStorage("VM Weak Oop Handles",
+                   VMWeakAlloc_lock,
+                   VMWeakActive_lock);
+}
+
+OopStorage* SystemDictionary::vm_weak_oop_storage() {
+  assert(_vm_weak_oop_storage != NULL, "Uninitialized");
+  return _vm_weak_oop_storage;
+}
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -84,6 +84,7 @@
 class ProtectionDomainCacheTable;
 class ProtectionDomainCacheEntry;
 class GCTimer;
+class OopStorage;
 
 // Certain classes are preloaded, such as java.lang.Object and java.lang.String.
 // They are all "well-known", in the sense that no class loader is allowed
@@ -637,6 +638,9 @@
   // ProtectionDomain cache
   static ProtectionDomainCacheTable*   _pd_cache_table;
 
+  // VM weak OopStorage object.
+  static OopStorage*             _vm_weak_oop_storage;
+
 protected:
   static void validate_protection_domain(InstanceKlass* klass,
                                          Handle class_loader,
@@ -689,6 +693,9 @@
     return !m->is_public() && m->method_holder() == SystemDictionary::Object_klass();
   }
 
+  static void initialize_oop_storage();
+  static OopStorage* vm_weak_oop_storage();
+
 protected:
   static InstanceKlass* find_shared_class(Symbol* class_name);
 
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -92,7 +92,7 @@
   Handle empty;
   Handle manifest ;
   if (shared_jar_manifest(shared_path_index) == NULL) {
-    SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_classpath(shared_path_index);
+    SharedClassPathEntryExt* ent = (SharedClassPathEntryExt*)FileMapInfo::shared_path(shared_path_index);
     long size = ent->manifest_size();
     if (size <= 0) {
       return empty; // No manifest - return NULL handle
@@ -138,7 +138,7 @@
   Handle url_h;
   if (shared_jar_url(shared_path_index) == NULL) {
     JavaValue result(T_OBJECT);
-    const char* path = FileMapInfo::shared_classpath_name(shared_path_index);
+    const char* path = FileMapInfo::shared_path_name(shared_path_index);
     Handle path_string = java_lang_String::create_from_str(path, CHECK_(url_h));
     Klass* classLoaders_klass =
         SystemDictionary::jdk_internal_loader_ClassLoaders_klass();
@@ -304,7 +304,7 @@
     int index = ik->shared_classpath_index();
     assert(index >= 0, "Sanity");
     SharedClassPathEntryExt* ent =
-            (SharedClassPathEntryExt*)FileMapInfo::shared_classpath(index);
+            (SharedClassPathEntryExt*)FileMapInfo::shared_path(index);
     Symbol* class_name = ik->name();
 
     if (ent->is_modules_image()) {
@@ -328,13 +328,13 @@
       // For shared app/platform classes originated from JAR files on the class path:
       //   Each of the 3 SystemDictionaryShared::_shared_xxx arrays has the same length
       //   as the shared classpath table in the shared archive (see
-      //   FileMap::_classpath_entry_table in filemap.hpp for details).
+      //   FileMap::_shared_path_table in filemap.hpp for details).
       //
       //   If a shared InstanceKlass k is loaded from the class path, let
       //
       //     index = k->shared_classpath_index():
       //
-      //   FileMap::_classpath_entry_table[index] identifies the JAR file that contains k.
+      //   FileMap::_shared_path_table[index] identifies the JAR file that contains k.
       //
       //   k's protection domain is:
       //
@@ -358,9 +358,7 @@
 }
 
 // Currently AppCDS only archives classes from the run-time image, the
-// -Xbootclasspath/a path, and the class path. The following rules need to be
-// revised when AppCDS is changed to archive classes from other code sources
-// in the future, for example the module path (specified by -p).
+// -Xbootclasspath/a path, the class path, and the module path.
 //
 // Check if a shared class can be loaded by the specific classloader. Following
 // are the "visible" archived classes for different classloaders.
@@ -368,10 +366,10 @@
 // NULL classloader:
 //   - see SystemDictionary::is_shared_class_visible()
 // Platform classloader:
-//   - Module class from "modules" jimage. ModuleEntry must be defined in the
+//   - Module class from runtime image. ModuleEntry must be defined in the
 //     classloader.
-// App Classloader:
-//   - Module class from "modules" jimage. ModuleEntry must be defined in the
+// App classloader:
+//   - Module Class from runtime image and module path. ModuleEntry must be defined in the
 //     classloader.
 //   - Class from -cp. The class must have no PackageEntry defined in any of the
 //     boot/platform/app classloader, or must be in the unnamed module defined in the
@@ -386,10 +384,11 @@
                                                      TRAPS) {
   assert(class_loader.not_null(), "Class loader should not be NULL");
   assert(Universe::is_module_initialized(), "Module system is not initialized");
+  ResourceMark rm(THREAD);
 
   int path_index = ik->shared_classpath_index();
   SharedClassPathEntry* ent =
-            (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+            (SharedClassPathEntry*)FileMapInfo::shared_path(path_index);
 
   if (SystemDictionary::is_platform_class_loader(class_loader())) {
     assert(ent != NULL, "shared class for PlatformClassLoader should have valid SharedClassPathEntry");
@@ -400,7 +399,7 @@
       // PackageEntry/ModuleEntry is found in the classloader. Check if the
       // ModuleEntry's location agrees with the archived class' origination.
       if (ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) {
-        return true; // Module class from the "modules" jimage
+        return true; // Module class from the runtime image
       }
     }
   } else if (SystemDictionary::is_system_class_loader(class_loader())) {
@@ -409,7 +408,8 @@
       // The archived class is in the unnamed package. Currently, the boot image
       // does not contain any class in the unnamed package.
       assert(!ent->is_modules_image(), "Class in the unnamed package must be from the classpath");
-      if (path_index >= ClassLoaderExt::app_paths_start_index()) {
+      if (path_index >= ClassLoaderExt::app_class_paths_start_index()) {
+        assert(path_index < ClassLoaderExt::app_module_paths_start_index(), "invalid path_index");
         return true;
       }
     } else {
@@ -421,23 +421,37 @@
         if (get_package_entry(pkg_name, ClassLoaderData::class_loader_data_or_null(SystemDictionary::java_platform_loader())) == NULL &&
             get_package_entry(pkg_name, ClassLoaderData::the_null_class_loader_data()) == NULL) {
           // The PackageEntry is not defined in any of the boot/platform/app classloaders.
-          // The archived class must from -cp path and not from the run-time image.
-          if (!ent->is_modules_image() && path_index >= ClassLoaderExt::app_paths_start_index()) {
+          // The archived class must from -cp path and not from the runtime image.
+          if (!ent->is_modules_image() && path_index >= ClassLoaderExt::app_class_paths_start_index() &&
+                                          path_index < ClassLoaderExt::app_module_paths_start_index()) {
             return true;
           }
         }
       } else if (mod_entry != NULL) {
-        // The package/module is defined in the AppClassLoader. Currently we only
-        // support archiving application module class from the run-time image.
+        // The package/module is defined in the AppClassLoader. We support
+        // archiving application module class from the runtime image or from
+        // a named module from a module path.
         // Packages from the -cp path are in the unnamed_module.
-        if ((ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) ||
-            (pkg_entry->in_unnamed_module() && path_index >= ClassLoaderExt::app_paths_start_index())) {
+        if (ent->is_modules_image() && mod_entry->location()->starts_with("jrt:")) {
+          // shared module class from runtime image
+          return true;
+        } else if (pkg_entry->in_unnamed_module() && path_index >= ClassLoaderExt::app_class_paths_start_index() &&
+            path_index < ClassLoaderExt::app_module_paths_start_index()) {
+          // shared class from -cp
           DEBUG_ONLY( \
             ClassLoaderData* loader_data = class_loader_data(class_loader); \
-            if (pkg_entry->in_unnamed_module()) \
-              assert(mod_entry == loader_data->unnamed_module(), "the unnamed module is not defined in the classloader");)
-
+            assert(mod_entry == loader_data->unnamed_module(), "the unnamed module is not defined in the classloader");)
           return true;
+        } else {
+          if(!pkg_entry->in_unnamed_module() &&
+              (path_index >= ClassLoaderExt::app_module_paths_start_index())&&
+              (path_index < FileMapInfo::get_number_of_shared_paths()) &&
+              (strcmp(ent->name(), ClassLoader::skip_uri_protocol(mod_entry->location()->as_C_string())) == 0)) {
+            // shared module class from module path
+            return true;
+          } else {
+            assert(path_index < FileMapInfo::get_number_of_shared_paths(), "invalid path_index");
+          }
         }
       }
     }
--- a/src/hotspot/share/code/codeCache.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/code/codeCache.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -51,6 +51,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/sweeper.hpp"
+#include "runtime/vmThread.hpp"
 #include "services/memoryService.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/align.hpp"
--- a/src/hotspot/share/code/relocInfo_ext.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/code/relocInfo_ext.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -59,7 +59,7 @@
     return (address)Universe::heap()->end_addr();
   }
   case symbolic_Relocation::card_table_reference: {
-    BarrierSet* bs = Universe::heap()->barrier_set();
+    BarrierSet* bs = BarrierSet::barrier_set();
     CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
     CardTable* ct = ctbs->card_table();
     return (address)ct->byte_map_base();
--- a/src/hotspot/share/compiler/disassembler.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/compiler/disassembler.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -318,7 +318,7 @@
       return;
     }
 
-    BarrierSet* bs = Universe::heap()->barrier_set();
+    BarrierSet* bs = BarrierSet::barrier_set();
     if (bs->is_a(BarrierSet::CardTableBarrierSet) &&
         adr == ci_card_table_address_as<address>()) {
       st->print("word_map_base");
--- a/src/hotspot/share/gc/cms/adaptiveFreeList.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/adaptiveFreeList.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,7 @@
 #include "gc/cms/adaptiveFreeList.hpp"
 #include "gc/cms/freeChunk.hpp"
 #include "gc/shared/collectedHeap.hpp"
+#include "memory/freeList.inline.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/orderAccess.inline.hpp"
--- a/src/hotspot/share/gc/cms/cmsArguments.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsArguments.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -82,9 +82,36 @@
 // certainly gain from analysis of platform and environment.
 void CMSArguments::initialize() {
   GCArguments::initialize();
+
   assert(!UseSerialGC && !UseParallelOldGC && !UseParallelGC, "Error");
   assert(UseConcMarkSweepGC, "CMS is expected to be on here");
 
+  // CMS space iteration, which FLSVerifyAllHeapreferences entails,
+  // insists that we hold the requisite locks so that the iteration is
+  // MT-safe. For the verification at start-up and shut-down, we don't
+  // yet have a good way of acquiring and releasing these locks,
+  // which are not visible at the CollectedHeap level. We want to
+  // be able to acquire these locks and then do the iteration rather
+  // than just disable the lock verification. This will be fixed under
+  // bug 4788986.
+  if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) {
+    if (VerifyDuringStartup) {
+      warning("Heap verification at start-up disabled "
+              "(due to current incompatibility with FLSVerifyAllHeapReferences)");
+      VerifyDuringStartup = false; // Disable verification at start-up
+    }
+
+    if (VerifyBeforeExit) {
+      warning("Heap verification at shutdown disabled "
+              "(due to current incompatibility with FLSVerifyAllHeapReferences)");
+      VerifyBeforeExit = false; // Disable verification at shutdown
+    }
+  }
+
+  if (!ClassUnloading) {
+    FLAG_SET_CMDLINE(bool, CMSClassUnloadingEnabled, false);
+  }
+
   // Set CMS global values
   CompactibleFreeListSpace::set_cms_values();
 
--- a/src/hotspot/share/gc/cms/cmsCardTable.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsCardTable.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/cms/cmsCardTable.hpp"
 #include "gc/cms/cmsHeap.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "gc/shared/cardTableRS.hpp"
@@ -36,7 +37,24 @@
 #include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
 
-void CardTableRS::
+CMSCardTable::CMSCardTable(MemRegion whole_heap) :
+    CardTableRS(whole_heap, CMSPrecleaningEnabled /* scanned_concurrently */) {
+}
+
+// Returns the number of chunks necessary to cover "mr".
+size_t CMSCardTable::chunks_to_cover(MemRegion mr) {
+  return (size_t)(addr_to_chunk_index(mr.last()) -
+                  addr_to_chunk_index(mr.start()) + 1);
+}
+
+// Returns the index of the chunk in a stride which
+// covers the given address.
+uintptr_t CMSCardTable::addr_to_chunk_index(const void* addr) {
+  uintptr_t card = (uintptr_t) byte_for(addr);
+  return card / ParGCCardsPerStrideChunk;
+}
+
+void CMSCardTable::
 non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
                                      OopsInGenClosure* cl,
                                      CardTableRS* ct,
@@ -82,7 +100,7 @@
 }
 
 void
-CardTableRS::
+CMSCardTable::
 process_stride(Space* sp,
                MemRegion used,
                jint stride, int n_strides,
@@ -162,7 +180,7 @@
 }
 
 void
-CardTableRS::
+CMSCardTable::
 process_chunk_boundaries(Space* sp,
                          DirtyCardToOopClosure* dcto_cl,
                          MemRegion chunk_mr,
@@ -371,7 +389,7 @@
 }
 
 void
-CardTableRS::
+CMSCardTable::
 get_LNC_array_for_space(Space* sp,
                         jbyte**& lowest_non_clean,
                         uintptr_t& lowest_non_clean_base_chunk_index,
@@ -430,3 +448,26 @@
   lowest_non_clean_base_chunk_index = _lowest_non_clean_base_chunk_index[i];
   lowest_non_clean_chunk_size       = _lowest_non_clean_chunk_size[i];
 }
+
+#ifdef ASSERT
+void CMSCardTable::verify_used_region_at_save_marks(Space* sp) const {
+  MemRegion ur    = sp->used_region();
+  MemRegion urasm = sp->used_region_at_save_marks();
+
+  if (!ur.contains(urasm)) {
+    log_warning(gc)("CMS+ParNew: Did you forget to call save_marks()? "
+                    "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
+                    "[" PTR_FORMAT ", " PTR_FORMAT ")",
+                    p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
+    MemRegion ur2 = sp->used_region();
+    MemRegion urasm2 = sp->used_region_at_save_marks();
+    if (!ur.equals(ur2)) {
+      log_warning(gc)("CMS+ParNew: Flickering used_region()!!");
+    }
+    if (!urasm.equals(urasm2)) {
+      log_warning(gc)("CMS+ParNew: Flickering used_region_at_save_marks()!!");
+    }
+    ShouldNotReachHere();
+  }
+}
+#endif // ASSERT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cmsCardTable.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_CMS_CMSCARDTABLE_HPP
+#define SHARE_GC_CMS_CMSCARDTABLE_HPP
+
+#include "gc/shared/cardTableRS.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class DirtyCardToOopClosure;
+class MemRegion;
+class OopsInGenClosure;
+class Space;
+
+class CMSCardTable : public CardTableRS {
+private:
+  // Returns the number of chunks necessary to cover "mr".
+  size_t chunks_to_cover(MemRegion mr);
+
+  // Returns the index of the chunk in a stride which
+  // covers the given address.
+  uintptr_t addr_to_chunk_index(const void* addr);
+
+  // Initializes "lowest_non_clean" to point to the array for the region
+  // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
+  // index of the corresponding to the first element of that array.
+  // Ensures that these arrays are of sufficient size, allocating if necessary.
+  // May be called by several threads concurrently.
+  void get_LNC_array_for_space(Space* sp,
+                               jbyte**& lowest_non_clean,
+                               uintptr_t& lowest_non_clean_base_chunk_index,
+                               size_t& lowest_non_clean_chunk_size);
+
+  // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
+  // to the cards in the stride (of n_strides) within the given space.
+  void process_stride(Space* sp,
+                      MemRegion used,
+                      jint stride, int n_strides,
+                      OopsInGenClosure* cl,
+                      CardTableRS* ct,
+                      jbyte** lowest_non_clean,
+                      uintptr_t lowest_non_clean_base_chunk_index,
+                      size_t lowest_non_clean_chunk_size);
+
+  // Makes sure that chunk boundaries are handled appropriately, by
+  // adjusting the min_done of dcto_cl, and by using a special card-table
+  // value to indicate how min_done should be set.
+  void process_chunk_boundaries(Space* sp,
+                                DirtyCardToOopClosure* dcto_cl,
+                                MemRegion chunk_mr,
+                                MemRegion used,
+                                jbyte** lowest_non_clean,
+                                uintptr_t lowest_non_clean_base_chunk_index,
+                                size_t    lowest_non_clean_chunk_size);
+
+  virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;
+
+protected:
+  // Work method used to implement non_clean_card_iterate_possibly_parallel()
+  // above in the parallel case.
+  virtual void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                                    OopsInGenClosure* cl, CardTableRS* ct,
+                                                    uint n_threads);
+
+public:
+  CMSCardTable(MemRegion whole_heap);
+};
+
+#endif // SHARE_GC_CMS_CMSCARDTABLE_HPP
--- a/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsCollectorPolicy.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,7 +30,6 @@
 #include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/generationSpec.hpp"
 #include "gc/shared/space.hpp"
 #include "gc/shared/vmGCOperations.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cmsGCStats.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc/cms/cmsGCStats.hpp"
+#include "gc/shared/gcUtil.inline.hpp"
+#include "runtime/globals.hpp"
+
+CMSGCStats::CMSGCStats() {
+    _avg_promoted       = new AdaptivePaddedNoZeroDevAverage(
+                                                  CMSExpAvgFactor,
+                                                  PromotedPadding);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cmsGCStats.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_CMS_CMSGCSTATS_HPP
+#define SHARE_GC_CMS_CMSGCSTATS_HPP
+
+#include "gc/shared/gcStats.hpp"
+
+class CMSGCStats : public GCStats {
+ public:
+  CMSGCStats();
+
+  virtual Name kind() {
+    return CMSGCStatsKind;
+  }
+};
+
+#endif // SHARE_GC_CMS_CMSGCSTATS_HPP
--- a/src/hotspot/share/gc/cms/cmsHeap.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsHeap.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,12 +23,14 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/cms/cmsCardTable.hpp"
 #include "gc/cms/compactibleFreeListSpace.hpp"
 #include "gc/cms/concurrentMarkSweepGeneration.hpp"
 #include "gc/cms/concurrentMarkSweepThread.hpp"
 #include "gc/cms/cmsHeap.hpp"
 #include "gc/cms/parNewGeneration.hpp"
 #include "gc/cms/vmCMSOperations.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/genMemoryPools.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/strongRootsScope.hpp"
@@ -90,6 +92,10 @@
   return JNI_OK;
 }
 
+CardTableRS* CMSHeap::create_rem_set(const MemRegion& reserved_region) {
+  return new CMSCardTable(reserved_region);
+}
+
 void CMSHeap::initialize_serviceability() {
   _young_manager = new GCMemoryManager("ParNew", "end of minor GC");
   _old_manager = new GCMemoryManager("ConcurrentMarkSweep", "end of major GC");
--- a/src/hotspot/share/gc/cms/cmsHeap.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsHeap.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -51,6 +51,7 @@
 
   // Returns JNI_OK on success
   virtual jint initialize();
+  virtual CardTableRS* create_rem_set(const MemRegion& reserved_region);
 
   // Convenience function to be used in situations where the heap type can be
   // asserted to be this type.
--- a/src/hotspot/share/gc/cms/cmsOopClosures.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/cmsOopClosures.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/cms/cmsOopClosures.inline.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
+#include "gc/cms/cms_specialized_oop_closures.hpp"
 #include "memory/iterator.inline.hpp"
 
 // Generate CMS specialized oop_oop_iterate functions.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cms_globals.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_CMS_CMS_GLOBALS_HPP
+#define SHARE_GC_CMS_CMS_GLOBALS_HPP
+
+#define GC_CMS_FLAGS(develop,                                               \
+                     develop_pd,                                            \
+                     product,                                               \
+                     product_pd,                                            \
+                     diagnostic,                                            \
+                     diagnostic_pd,                                         \
+                     experimental,                                          \
+                     notproduct,                                            \
+                     manageable,                                            \
+                     product_rw,                                            \
+                     lp64_product,                                          \
+                     range,                                                 \
+                     constraint,                                            \
+                     writeable)                                             \
+  product(bool, UseCMSBestFit, true,                                        \
+          "Use CMS best fit allocation strategy")                           \
+                                                                            \
+  product(size_t, CMSOldPLABMax, 1024,                                      \
+          "Maximum size of CMS gen promotion LAB caches per worker "        \
+          "per block size")                                                 \
+          range(1, max_uintx)                                               \
+          constraint(CMSOldPLABMaxConstraintFunc,AfterMemoryInit)           \
+                                                                            \
+  product(size_t, CMSOldPLABMin, 16,                                        \
+          "Minimum size of CMS gen promotion LAB caches per worker "        \
+          "per block size")                                                 \
+          range(1, max_uintx)                                               \
+          constraint(CMSOldPLABMinConstraintFunc,AfterMemoryInit)           \
+                                                                            \
+  product(uintx, CMSOldPLABNumRefills, 4,                                   \
+          "Nominal number of refills of CMS gen promotion LAB cache "       \
+          "per worker per block size")                                      \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(bool, CMSOldPLABResizeQuicker, false,                             \
+          "React on-the-fly during a scavenge to a sudden "                 \
+          "change in block demand rate")                                    \
+                                                                            \
+  product(uintx, CMSOldPLABToleranceFactor, 4,                              \
+          "The tolerance of the phase-change detector for on-the-fly "      \
+          "PLAB resizing during a scavenge")                                \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, CMSOldPLABReactivityFactor, 2,                             \
+          "The gain in the feedback loop for on-the-fly PLAB resizing "     \
+          "during a scavenge")                                              \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product_pd(size_t, CMSYoungGenPerWorker,                                  \
+          "The maximum size of young gen chosen by default per GC worker "  \
+          "thread available")                                               \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, CMSIncrementalSafetyFactor, 10,                            \
+          "Percentage (0-100) used to add conservatism when computing the " \
+          "duty cycle")                                                     \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, CMSExpAvgFactor, 50,                                       \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponential averages for CMS statistics")              \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, CMS_FLSWeight, 75,                                         \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponentially decaying averages for CMS FLS "          \
+          "statistics")                                                     \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, CMS_FLSPadding, 1,                                         \
+          "The multiple of deviation from mean to use for buffering "       \
+          "against volatility in free list demand")                         \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, FLSCoalescePolicy, 2,                                      \
+          "CMS: aggressiveness level for coalescing, increasing "           \
+          "from 0 to 4")                                                    \
+          range(0, 4)                                                       \
+                                                                            \
+  product(bool, FLSAlwaysCoalesceLarge, false,                              \
+          "CMS: larger free blocks are always available for coalescing")    \
+                                                                            \
+  product(double, FLSLargestBlockCoalesceProximity, 0.99,                   \
+          "CMS: the smaller the percentage the greater the coalescing "     \
+          "force")                                                          \
+          range(0.0, 1.0)                                                   \
+                                                                            \
+  product(double, CMSSmallCoalSurplusPercent, 1.05,                         \
+          "CMS: the factor by which to inflate estimated demand of small "  \
+          "block sizes to prevent coalescing with an adjoining block")      \
+          range(0.0, DBL_MAX)                                               \
+                                                                            \
+  product(double, CMSLargeCoalSurplusPercent, 0.95,                         \
+          "CMS: the factor by which to inflate estimated demand of large "  \
+          "block sizes to prevent coalescing with an adjoining block")      \
+          range(0.0, DBL_MAX)                                               \
+                                                                            \
+  product(double, CMSSmallSplitSurplusPercent, 1.10,                        \
+          "CMS: the factor by which to inflate estimated demand of small "  \
+          "block sizes to prevent splitting to supply demand for smaller "  \
+          "blocks")                                                         \
+          range(0.0, DBL_MAX)                                               \
+                                                                            \
+  product(double, CMSLargeSplitSurplusPercent, 1.00,                        \
+          "CMS: the factor by which to inflate estimated demand of large "  \
+          "block sizes to prevent splitting to supply demand for smaller "  \
+          "blocks")                                                         \
+          range(0.0, DBL_MAX)                                               \
+                                                                            \
+  product(bool, CMSExtrapolateSweep, false,                                 \
+          "CMS: cushion for block demand during sweep")                     \
+                                                                            \
+  product(uintx, CMS_SweepWeight, 75,                                       \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponentially decaying average for inter-sweep "       \
+          "duration")                                                       \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, CMS_SweepPadding, 1,                                       \
+          "The multiple of deviation from mean to use for buffering "       \
+          "against volatility in inter-sweep duration")                     \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, CMS_SweepTimerThresholdMillis, 10,                         \
+          "Skip block flux-rate sampling for an epoch unless inter-sweep "  \
+          "duration exceeds this threshold in milliseconds")                \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(bool, CMSClassUnloadingEnabled, true,                             \
+          "Whether class unloading enabled when using CMS GC")              \
+                                                                            \
+  product(uintx, CMSClassUnloadingMaxInterval, 0,                           \
+          "When CMS class unloading is enabled, the maximum CMS cycle "     \
+          "count for which classes may not be unloaded")                    \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, CMSIndexedFreeListReplenish, 4,                            \
+          "Replenish an indexed free list with this number of chunks")      \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(bool, CMSReplenishIntermediate, true,                             \
+          "Replenish all intermediate free-list caches")                    \
+                                                                            \
+  product(bool, CMSSplitIndexedFreeListBlocks, true,                        \
+          "When satisfying batched demand, split blocks from the "          \
+          "IndexedFreeList whose size is a multiple of requested size")     \
+                                                                            \
+  product(bool, CMSLoopWarn, false,                                         \
+          "Warn in case of excessive CMS looping")                          \
+                                                                            \
+  notproduct(bool, CMSMarkStackOverflowALot, false,                         \
+          "Simulate frequent marking stack / work queue overflow")          \
+                                                                            \
+  notproduct(uintx, CMSMarkStackOverflowInterval, 1000,                     \
+          "An \"interval\" counter that determines how frequently "         \
+          "to simulate overflow; a smaller number increases frequency")     \
+                                                                            \
+  product(uintx, CMSMaxAbortablePrecleanLoops, 0,                           \
+          "Maximum number of abortable preclean iterations, if > 0")        \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(intx, CMSMaxAbortablePrecleanTime, 5000,                          \
+          "Maximum time in abortable preclean (in milliseconds)")           \
+          range(0, max_intx)                                                \
+                                                                            \
+  product(uintx, CMSAbortablePrecleanMinWorkPerIteration, 100,              \
+          "Nominal minimum work per abortable preclean iteration")          \
+          range(0, max_uintx)                                               \
+                                                                            \
+  manageable(intx, CMSAbortablePrecleanWaitMillis, 100,                     \
+          "Time that we sleep between iterations when not given "           \
+          "enough work per iteration")                                      \
+          range(0, max_intx)                                                \
+                                                                            \
+  /* 4096 = CardTable::card_size_in_words * BitsPerWord */                  \
+  product(size_t, CMSRescanMultiple, 32,                                    \
+          "Size (in cards) of CMS parallel rescan task")                    \
+          range(1, SIZE_MAX / 4096)                                         \
+          constraint(CMSRescanMultipleConstraintFunc,AfterMemoryInit)       \
+                                                                            \
+  /* 4096 = CardTable::card_size_in_words * BitsPerWord */                  \
+  product(size_t, CMSConcMarkMultiple, 32,                                  \
+          "Size (in cards) of CMS concurrent MT marking task")              \
+          range(1, SIZE_MAX / 4096)                                         \
+          constraint(CMSConcMarkMultipleConstraintFunc,AfterMemoryInit)     \
+                                                                            \
+  product(bool, CMSAbortSemantics, false,                                   \
+          "Whether abort-on-overflow semantics is implemented")             \
+                                                                            \
+  product(bool, CMSParallelInitialMarkEnabled, true,                        \
+          "Use the parallel initial mark.")                                 \
+                                                                            \
+  product(bool, CMSParallelRemarkEnabled, true,                             \
+          "Whether parallel remark enabled (only if ParNewGC)")             \
+                                                                            \
+  product(bool, CMSParallelSurvivorRemarkEnabled, true,                     \
+          "Whether parallel remark of survivor space "                      \
+          "enabled (effective only if CMSParallelRemarkEnabled)")           \
+                                                                            \
+  product(bool, CMSPLABRecordAlways, true,                                  \
+          "Always record survivor space PLAB boundaries (effective only "   \
+          "if CMSParallelSurvivorRemarkEnabled)")                           \
+                                                                            \
+  product(bool, CMSEdenChunksRecordAlways, true,                            \
+          "Always record eden chunks used for the parallel initial mark "   \
+          "or remark of eden")                                              \
+                                                                            \
+  product(bool, CMSConcurrentMTEnabled, true,                               \
+          "Whether multi-threaded concurrent work enabled "                 \
+          "(effective only if ParNewGC)")                                   \
+                                                                            \
+  product(bool, CMSPrecleaningEnabled, true,                                \
+          "Whether concurrent precleaning enabled")                         \
+                                                                            \
+  product(uintx, CMSPrecleanIter, 3,                                        \
+          "Maximum number of precleaning iteration passes")                 \
+          range(0, 9)                                                       \
+                                                                            \
+  product(uintx, CMSPrecleanDenominator, 3,                                 \
+          "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
+          "ratio")                                                          \
+          range(1, max_uintx)                                               \
+          constraint(CMSPrecleanDenominatorConstraintFunc,AfterErgo)        \
+                                                                            \
+  product(uintx, CMSPrecleanNumerator, 2,                                   \
+          "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
+          "ratio")                                                          \
+          range(0, max_uintx-1)                                             \
+          constraint(CMSPrecleanNumeratorConstraintFunc,AfterErgo)          \
+                                                                            \
+  product(bool, CMSPrecleanRefLists1, true,                                 \
+          "Preclean ref lists during (initial) preclean phase")             \
+                                                                            \
+  product(bool, CMSPrecleanRefLists2, false,                                \
+          "Preclean ref lists during abortable preclean phase")             \
+                                                                            \
+  product(bool, CMSPrecleanSurvivors1, false,                               \
+          "Preclean survivors during (initial) preclean phase")             \
+                                                                            \
+  product(bool, CMSPrecleanSurvivors2, true,                                \
+          "Preclean survivors during abortable preclean phase")             \
+                                                                            \
+  product(uintx, CMSPrecleanThreshold, 1000,                                \
+          "Do not iterate again if number of dirty cards is less than this")\
+          range(100, max_uintx)                                             \
+                                                                            \
+  product(bool, CMSCleanOnEnter, true,                                      \
+          "Clean-on-enter optimization for reducing number of dirty cards") \
+                                                                            \
+  product(uintx, CMSRemarkVerifyVariant, 1,                                 \
+          "Choose variant (1,2) of verification following remark")          \
+          range(1, 2)                                                       \
+                                                                            \
+  product(size_t, CMSScheduleRemarkEdenSizeThreshold, 2*M,                  \
+          "If Eden size is below this, do not try to schedule remark")      \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, CMSScheduleRemarkEdenPenetration, 50,                      \
+          "The Eden occupancy percentage (0-100) at which "                 \
+          "to try and schedule remark pause")                               \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, CMSScheduleRemarkSamplingRatio, 5,                         \
+          "Start sampling eden top at least before young gen "              \
+          "occupancy reaches 1/<ratio> of the size at which "               \
+          "we plan to schedule remark")                                     \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, CMSSamplingGrain, 16*K,                                    \
+          "The minimum distance between eden samples for CMS (see above)")  \
+          range(ObjectAlignmentInBytes, max_uintx)                          \
+          constraint(CMSSamplingGrainConstraintFunc,AfterMemoryInit)        \
+                                                                            \
+  product(bool, CMSScavengeBeforeRemark, false,                             \
+          "Attempt scavenge before the CMS remark step")                    \
+                                                                            \
+  product(uintx, CMSWorkQueueDrainThreshold, 10,                            \
+          "Don't drain below this size per parallel worker/thief")          \
+          range(1, max_juint)                                               \
+          constraint(CMSWorkQueueDrainThresholdConstraintFunc,AfterErgo)    \
+                                                                            \
+  manageable(intx, CMSWaitDuration, 2000,                                   \
+          "Time in milliseconds that CMS thread waits for young GC")        \
+          range(min_jint, max_jint)                                         \
+                                                                            \
+  develop(uintx, CMSCheckInterval, 1000,                                    \
+          "Interval in milliseconds that CMS thread checks if it "          \
+          "should start a collection cycle")                                \
+                                                                            \
+  product(bool, CMSYield, true,                                             \
+          "Yield between steps of CMS")                                     \
+                                                                            \
+  product(size_t, CMSBitMapYieldQuantum, 10*M,                              \
+          "Bitmap operations should process at most this many bits "        \
+          "between yields")                                                 \
+          range(1, max_uintx)                                               \
+          constraint(CMSBitMapYieldQuantumConstraintFunc,AfterMemoryInit)   \
+                                                                            \
+  product(bool, CMSPrintChunksInDump, false,                                \
+          "If logging for the \"gc\" and \"promotion\" tags is enabled on"  \
+          "trace level include more detailed information about the"         \
+          "free chunks")                                                    \
+                                                                            \
+  product(bool, CMSPrintObjectsInDump, false,                               \
+          "If logging for the \"gc\" and \"promotion\" tags is enabled on"  \
+          "trace level include more detailed information about the"         \
+          "allocated objects")                                              \
+                                                                            \
+  diagnostic(bool, FLSVerifyAllHeapReferences, false,                       \
+          "Verify that all references across the FLS boundary "             \
+          "are to valid objects")                                           \
+                                                                            \
+  diagnostic(bool, FLSVerifyLists, false,                                   \
+          "Do lots of (expensive) FreeListSpace verification")              \
+                                                                            \
+  diagnostic(bool, FLSVerifyIndexTable, false,                              \
+          "Do lots of (expensive) FLS index table verification")            \
+                                                                            \
+  product(uintx, CMSTriggerRatio, 80,                                       \
+          "Percentage of MinHeapFreeRatio in CMS generation that is "       \
+          "allocated before a CMS collection cycle commences")              \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, CMSBootstrapOccupancy, 50,                                 \
+          "Percentage CMS generation occupancy at which to "                \
+          "initiate CMS collection for bootstrapping collection stats")     \
+          range(0, 100)                                                     \
+                                                                            \
+  product(intx, CMSInitiatingOccupancyFraction, -1,                         \
+          "Percentage CMS generation occupancy to start a CMS collection "  \
+          "cycle. A negative value means that CMSTriggerRatio is used")     \
+          range(min_intx, 100)                                              \
+                                                                            \
+  manageable(intx, CMSTriggerInterval, -1,                                  \
+          "Commence a CMS collection cycle (at least) every so many "       \
+          "milliseconds (0 permanently, -1 disabled)")                      \
+          range(-1, max_intx)                                               \
+                                                                            \
+  product(bool, UseCMSInitiatingOccupancyOnly, false,                       \
+          "Only use occupancy as a criterion for starting a CMS collection")\
+                                                                            \
+  product(uintx, CMSIsTooFullPercentage, 98,                                \
+          "An absolute ceiling above which CMS will always consider the "   \
+          "unloading of classes when class unloading is enabled")           \
+          range(0, 100)                                                     \
+                                                                            \
+  develop(bool, CMSTestInFreeList, false,                                   \
+          "Check if the coalesced range is already in the "                 \
+          "free lists as claimed")                                          \
+                                                                            \
+  notproduct(bool, CMSVerifyReturnedBytes, false,                           \
+          "Check that all the garbage collected was returned to the "       \
+          "free lists")                                                     \
+                                                                            \
+  diagnostic(bool, BindCMSThreadToCPU, false,                               \
+          "Bind CMS Thread to CPU if possible")                             \
+                                                                            \
+  diagnostic(uintx, CPUForCMSThread, 0,                                     \
+          "When BindCMSThreadToCPU is true, the CPU to bind CMS thread to") \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, CMSCoordinatorYieldSleepCount, 10,                         \
+          "Number of times the coordinator GC thread will sleep while "     \
+          "yielding before giving up and resuming GC")                      \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, CMSYieldSleepCount, 0,                                     \
+          "Number of times a GC thread (minus the coordinator) "            \
+          "will sleep while yielding before giving up and resuming GC")     \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(bool, ParGCUseLocalOverflow, false,                               \
+          "Instead of a global overflow list, use local overflow stacks")   \
+                                                                            \
+  product(bool, ParGCTrimOverflow, true,                                    \
+          "Eagerly trim the local overflow lists "                          \
+          "(when ParGCUseLocalOverflow)")                                   \
+                                                                            \
+  notproduct(bool, ParGCWorkQueueOverflowALot, false,                       \
+          "Simulate work queue overflow in ParNew")                         \
+                                                                            \
+  notproduct(uintx, ParGCWorkQueueOverflowInterval, 1000,                   \
+          "An `interval' counter that determines how frequently "           \
+          "we simulate overflow; a smaller number increases frequency")     \
+                                                                            \
+  product(uintx, ParGCDesiredObjsFromOverflowList, 20,                      \
+          "The desired number of objects to claim from the overflow list")  \
+          range(0, max_uintx)                                               \
+                                                                            \
+  diagnostic(uintx, ParGCStridesPerThread, 2,                               \
+          "The number of strides per worker thread that we divide up the "  \
+          "card table scanning work into")                                  \
+          range(1, max_uintx)                                               \
+          constraint(ParGCStridesPerThreadConstraintFunc,AfterErgo)         \
+                                                                            \
+  diagnostic(intx, ParGCCardsPerStrideChunk, 256,                           \
+          "The number of cards in each chunk of the parallel chunks used "  \
+          "during card table scanning")                                     \
+          range(1, max_intx)                                                \
+          constraint(ParGCCardsPerStrideChunkConstraintFunc,AfterMemoryInit)
+
+#endif // SHARE_GC_CMS_CMS_GLOBALS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/cms_specialized_oop_closures.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP
+#define SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP
+
+// The following OopClosure types get specialized versions of
+// "oop_oop_iterate" that invoke the closures' do_oop methods
+// non-virtually, using a mechanism defined in this file.  Extend these
+// macros in the obvious way to add specializations for new closures.
+
+// Forward declarations.
+
+// ParNew
+class ParScanWithBarrierClosure;
+class ParScanWithoutBarrierClosure;
+
+// CMS
+class MarkRefsIntoAndScanClosure;
+class ParMarkRefsIntoAndScanClosure;
+class PushAndMarkClosure;
+class ParPushAndMarkClosure;
+class PushOrMarkClosure;
+class ParPushOrMarkClosure;
+class CMSKeepAliveClosure;
+class CMSInnerParMarkAndPushClosure;
+
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)         \
+  f(ParScanWithBarrierClosure,_nv)                        \
+  f(ParScanWithoutBarrierClosure,_nv)
+
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f)       \
+  f(MarkRefsIntoAndScanClosure,_nv)                       \
+  f(ParMarkRefsIntoAndScanClosure,_nv)                    \
+  f(PushAndMarkClosure,_nv)                               \
+  f(ParPushAndMarkClosure,_nv)                            \
+  f(PushOrMarkClosure,_nv)                                \
+  f(ParPushOrMarkClosure,_nv)                             \
+  f(CMSKeepAliveClosure,_nv)                              \
+  f(CMSInnerParMarkAndPushClosure,_nv)
+
+#define SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f)           \
+  f(MarkRefsIntoAndScanClosure,_nv)                       \
+  f(PushAndMarkClosure,_nv)                               \
+  f(ParMarkRefsIntoAndScanClosure,_nv)                    \
+  f(ParPushAndMarkClosure,_nv)
+
+#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f)  \
+  f(ParScanWithBarrierClosure,_nv)                        \
+  f(ParScanWithoutBarrierClosure,_nv)
+
+#endif // SHARE_GC_CMS_CMS_SPECIALIZED_OOP_CLOSURES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/commandLineFlagConstraintsCMS.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,241 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "gc/cms/commandLineFlagConstraintsCMS.hpp"
+#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
+#include "gc/shared/commandLineFlagConstraintsGC.hpp"
+#include "memory/universe.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
+#include "runtime/globals_extension.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+static Flag::Error ParallelGCThreadsAndCMSWorkQueueDrainThreshold(uint threads, uintx threshold, bool verbose) {
+  // CMSWorkQueueDrainThreshold is verified to be less than max_juint
+  if (UseConcMarkSweepGC && (threads > (uint)(max_jint / (uint)threshold))) {
+    CommandLineError::print(verbose,
+                            "ParallelGCThreads (" UINT32_FORMAT ") or CMSWorkQueueDrainThreshold ("
+                            UINTX_FORMAT ") is too large\n",
+                            threads, threshold);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error ParallelGCThreadsConstraintFuncCMS(uint value, bool verbose) {
+  // To avoid overflow at ParScanClosure::do_oop_work.
+  if (UseConcMarkSweepGC && (value > (max_jint / 10))) {
+    CommandLineError::print(verbose,
+                            "ParallelGCThreads (" UINT32_FORMAT ") must be "
+                            "less than or equal to " UINT32_FORMAT " for CMS GC\n",
+                            value, (max_jint / 10));
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(value, CMSWorkQueueDrainThreshold, verbose);
+}
+Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose) {
+  if (UseConcMarkSweepGC && (value > ((uintx)max_jint / (uintx)ParallelGCThreads))) {
+    CommandLineError::print(verbose,
+                            "ParGCStridesPerThread (" UINTX_FORMAT ") must be "
+                            "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
+                            value, ((uintx)max_jint / (uintx)ParallelGCThreads));
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose) {
+  if (UseConcMarkSweepGC) {
+    // ParGCCardsPerStrideChunk should be compared with card table size.
+    size_t heap_size = Universe::heap()->reserved_region().word_size();
+    CardTableRS* ct = GenCollectedHeap::heap()->rem_set();
+    size_t card_table_size = ct->cards_required(heap_size) - 1; // Valid card table size
+
+    if ((size_t)value > card_table_size) {
+      CommandLineError::print(verbose,
+                              "ParGCCardsPerStrideChunk (" INTX_FORMAT ") is too large for the heap size and "
+                              "must be less than or equal to card table size (" SIZE_FORMAT ")\n",
+                              value, card_table_size);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+
+    // ParGCCardsPerStrideChunk is used with n_strides(ParallelGCThreads*ParGCStridesPerThread)
+    // from CardTableRS::process_stride(). Note that ParGCStridesPerThread is already checked
+    // not to make an overflow with ParallelGCThreads from its constraint function.
+    uintx n_strides = ParallelGCThreads * ParGCStridesPerThread;
+    uintx ergo_max = max_uintx / n_strides;
+    if ((uintx)value > ergo_max) {
+      CommandLineError::print(verbose,
+                              "ParGCCardsPerStrideChunk (" INTX_FORMAT ") must be "
+                              "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
+                              value, ergo_max);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) {
+  Flag::Error status = Flag::SUCCESS;
+
+  if (UseConcMarkSweepGC) {
+    if (value > CMSOldPLABMax) {
+      CommandLineError::print(verbose,
+                              "CMSOldPLABMin (" SIZE_FORMAT ") must be "
+                              "less than or equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
+                              value, CMSOldPLABMax);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+    status = MaxPLABSizeBounds("CMSOldPLABMin", value, verbose);
+  }
+  return status;
+}
+
+Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) {
+  Flag::Error status = Flag::SUCCESS;
+
+  if (UseConcMarkSweepGC) {
+    status = MaxPLABSizeBounds("CMSOldPLABMax", value, verbose);
+  }
+  return status;
+}
+
+static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) {
+  if (UseConcMarkSweepGC) {
+    ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
+    const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size();
+    if (value > ergo_max) {
+      CommandLineError::print(verbose,
+                              "%s (" SIZE_FORMAT ") must be "
+                              "less than or equal to ergonomic maximum (" SIZE_FORMAT ") "
+                              "which is based on the maximum size of the old generation of the Java heap\n",
+                              name, value, ergo_max);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) {
+  Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose);
+
+  if (status == Flag::SUCCESS && UseConcMarkSweepGC) {
+    // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size()
+    // to be aligned to CardTable::card_size * BitsPerWord.
+    // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize'
+    // because rescan_task_size() is CardTable::card_size / HeapWordSize * BitsPerWord.
+    if (value % HeapWordSize != 0) {
+      CommandLineError::print(verbose,
+                              "CMSRescanMultiple (" SIZE_FORMAT ") must be "
+                              "a multiple of " SIZE_FORMAT "\n",
+                              value, HeapWordSize);
+      status = Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+
+  return status;
+}
+
+Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) {
+  return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose);
+}
+
+Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) {
+  if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) {
+    CommandLineError::print(verbose,
+                            "CMSPrecleanDenominator (" UINTX_FORMAT ") must be "
+                            "strickly greater than CMSPrecleanNumerator (" UINTX_FORMAT ")\n",
+                            value, CMSPrecleanNumerator);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) {
+  if (UseConcMarkSweepGC && (value >= CMSPrecleanDenominator)) {
+    CommandLineError::print(verbose,
+                            "CMSPrecleanNumerator (" UINTX_FORMAT ") must be "
+                            "less than CMSPrecleanDenominator (" UINTX_FORMAT ")\n",
+                            value, CMSPrecleanDenominator);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose) {
+  if (UseConcMarkSweepGC) {
+    size_t max_capacity = GenCollectedHeap::heap()->young_gen()->max_capacity();
+    if (value > max_uintx - max_capacity) {
+    CommandLineError::print(verbose,
+                            "CMSSamplingGrain (" UINTX_FORMAT ") must be "
+                            "less than or equal to ergonomic maximum (" SIZE_FORMAT ")\n",
+                            value, max_uintx - max_capacity);
+    return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) {
+  if (UseConcMarkSweepGC) {
+    return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(ParallelGCThreads, value, verbose);
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose) {
+  // Skip for current default value.
+  if (UseConcMarkSweepGC && FLAG_IS_CMDLINE(CMSBitMapYieldQuantum)) {
+    // CMSBitMapYieldQuantum should be compared with mark bitmap size.
+    ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
+    size_t bitmap_size = cms->collector()->markBitMap()->sizeInWords();
+
+    if (value > bitmap_size) {
+      CommandLineError::print(verbose,
+                              "CMSBitMapYieldQuantum (" SIZE_FORMAT ") must "
+                              "be less than or equal to bitmap size (" SIZE_FORMAT ") "
+                              "whose size corresponds to the size of old generation of the Java heap\n",
+                              value, bitmap_size);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error OldPLABSizeConstraintFuncCMS(size_t value, bool verbose) {
+  if (value == 0) {
+    CommandLineError::print(verbose,
+                            "OldPLABSize (" SIZE_FORMAT ") must be greater than 0",
+                            value);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  // For CMS, OldPLABSize is the number of free blocks of a given size that are used when
+  // replenishing the local per-worker free list caches.
+  // For more details, please refer to Arguments::set_cms_and_parnew_gc_flags().
+  return MaxPLABSizeBounds("OldPLABSize", value, verbose);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/cms/commandLineFlagConstraintsCMS.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_CMS_COMMANDLINEFLAGCONSTRAINTSCMS_HPP
+#define SHARE_GC_CMS_COMMANDLINEFLAGCONSTRAINTSCMS_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// CMS Flag Constraints
+Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose);
+Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose);
+Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose);
+Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose);
+Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose);
+Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose);
+Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose);
+Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose);
+Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose);
+Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose);
+Flag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose);
+
+// CMS Subconstraints
+Flag::Error ParallelGCThreadsConstraintFuncCMS(uint value, bool verbose);
+Flag::Error OldPLABSizeConstraintFuncCMS(size_t value, bool verbose);
+
+#endif // SHARE_GC_CMS_COMMANDLINEFLAGCONSTRAINTSCMS_HPP
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -35,6 +35,7 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.inline.hpp"
+#include "memory/binaryTreeDictionary.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.hpp"
 #include "oops/access.inline.hpp"
@@ -49,6 +50,244 @@
 #include "utilities/align.hpp"
 #include "utilities/copy.hpp"
 
+// Specialize for AdaptiveFreeList which tries to avoid
+// splitting a chunk of a size that is under populated in favor of
+// an over populated size.  The general get_better_list() just returns
+// the current list.
+template <>
+TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >*
+TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >::get_better_list(
+  BinaryTreeDictionary<FreeChunk, ::AdaptiveFreeList<FreeChunk> >* dictionary) {
+  // A candidate chunk has been found.  If it is already under
+  // populated, get a chunk associated with the hint for this
+  // chunk.
+
+  TreeList<FreeChunk, ::AdaptiveFreeList<FreeChunk> >* curTL = this;
+  if (curTL->surplus() <= 0) {
+    /* Use the hint to find a size with a surplus, and reset the hint. */
+    TreeList<FreeChunk, ::AdaptiveFreeList<FreeChunk> >* hintTL = this;
+    while (hintTL->hint() != 0) {
+      assert(hintTL->hint() > hintTL->size(),
+        "hint points in the wrong direction");
+      hintTL = dictionary->find_list(hintTL->hint());
+      assert(curTL != hintTL, "Infinite loop");
+      if (hintTL == NULL ||
+          hintTL == curTL /* Should not happen but protect against it */ ) {
+        // No useful hint.  Set the hint to NULL and go on.
+        curTL->set_hint(0);
+        break;
+      }
+      assert(hintTL->size() > curTL->size(), "hint is inconsistent");
+      if (hintTL->surplus() > 0) {
+        // The hint led to a list that has a surplus.  Use it.
+        // Set the hint for the candidate to an overpopulated
+        // size.
+        curTL->set_hint(hintTL->size());
+        // Change the candidate.
+        curTL = hintTL;
+        break;
+      }
+    }
+  }
+  return curTL;
+}
+
+void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) {
+  TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >* nd = find_list(size);
+  if (nd) {
+    if (split) {
+      if (birth) {
+        nd->increment_split_births();
+        nd->increment_surplus();
+      }  else {
+        nd->increment_split_deaths();
+        nd->decrement_surplus();
+      }
+    } else {
+      if (birth) {
+        nd->increment_coal_births();
+        nd->increment_surplus();
+      } else {
+        nd->increment_coal_deaths();
+        nd->decrement_surplus();
+      }
+    }
+  }
+  // A list for this size may not be found (nd == 0) if
+  //   This is a death where the appropriate list is now
+  //     empty and has been removed from the list.
+  //   This is a birth associated with a LinAB.  The chunk
+  //     for the LinAB is not in the dictionary.
+}
+
+bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) {
+  if (FLSAlwaysCoalesceLarge) return true;
+
+  TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >* list_of_size = find_list(size);
+  // None of requested size implies overpopulated.
+  return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
+         list_of_size->count() > list_of_size->coal_desired();
+}
+
+// For each list in the tree, calculate the desired, desired
+// coalesce, count before sweep, and surplus before sweep.
+class BeginSweepClosure : public AscendTreeCensusClosure<FreeChunk, AdaptiveFreeList<FreeChunk> > {
+  double _percentage;
+  float _inter_sweep_current;
+  float _inter_sweep_estimate;
+  float _intra_sweep_estimate;
+
+ public:
+  BeginSweepClosure(double p, float inter_sweep_current,
+                              float inter_sweep_estimate,
+                              float intra_sweep_estimate) :
+   _percentage(p),
+   _inter_sweep_current(inter_sweep_current),
+   _inter_sweep_estimate(inter_sweep_estimate),
+   _intra_sweep_estimate(intra_sweep_estimate) { }
+
+  void do_list(AdaptiveFreeList<FreeChunk>* fl) {
+    double coalSurplusPercent = _percentage;
+    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
+    fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent));
+    fl->set_before_sweep(fl->count());
+    fl->set_bfr_surp(fl->surplus());
+  }
+};
+
+void AFLBinaryTreeDictionary::begin_sweep_dict_census(double coalSurplusPercent,
+  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
+  BeginSweepClosure bsc(coalSurplusPercent, inter_sweep_current,
+                        inter_sweep_estimate,
+                        intra_sweep_estimate);
+  bsc.do_tree(root());
+}
+
+// Calculate surpluses for the lists in the tree.
+class setTreeSurplusClosure : public AscendTreeCensusClosure<FreeChunk, AdaptiveFreeList<FreeChunk> > {
+  double percentage;
+ public:
+  setTreeSurplusClosure(double v) { percentage = v; }
+
+  void do_list(AdaptiveFreeList<FreeChunk>* fl) {
+    double splitSurplusPercent = percentage;
+    fl->set_surplus(fl->count() -
+                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
+  }
+};
+
+void AFLBinaryTreeDictionary::set_tree_surplus(double splitSurplusPercent) {
+  setTreeSurplusClosure sts(splitSurplusPercent);
+  sts.do_tree(root());
+}
+
+// Set hints for the lists in the tree.
+class setTreeHintsClosure : public DescendTreeCensusClosure<FreeChunk, AdaptiveFreeList<FreeChunk> > {
+  size_t hint;
+ public:
+  setTreeHintsClosure(size_t v) { hint = v; }
+
+  void do_list(AdaptiveFreeList<FreeChunk>* fl) {
+    fl->set_hint(hint);
+    assert(fl->hint() == 0 || fl->hint() > fl->size(),
+      "Current hint is inconsistent");
+    if (fl->surplus() > 0) {
+      hint = fl->size();
+    }
+  }
+};
+
+void AFLBinaryTreeDictionary::set_tree_hints(void) {
+  setTreeHintsClosure sth(0);
+  sth.do_tree(root());
+}
+
+// Save count before previous sweep and splits and coalesces.
+class clearTreeCensusClosure : public AscendTreeCensusClosure<FreeChunk, AdaptiveFreeList<FreeChunk> > {
+  void do_list(AdaptiveFreeList<FreeChunk>* fl) {
+    fl->set_prev_sweep(fl->count());
+    fl->set_coal_births(0);
+    fl->set_coal_deaths(0);
+    fl->set_split_births(0);
+    fl->set_split_deaths(0);
+  }
+};
+
+void AFLBinaryTreeDictionary::clear_tree_census(void) {
+  clearTreeCensusClosure ctc;
+  ctc.do_tree(root());
+}
+
+// Do reporting and post sweep clean up.
+void AFLBinaryTreeDictionary::end_sweep_dict_census(double splitSurplusPercent) {
+  // Does walking the tree 3 times hurt?
+  set_tree_surplus(splitSurplusPercent);
+  set_tree_hints();
+  LogTarget(Trace, gc, freelist, stats) log;
+  if (log.is_enabled()) {
+    LogStream out(log);
+    report_statistics(&out);
+  }
+  clear_tree_census();
+}
+
+// Print census information - counts, births, deaths, etc.
+// for each list in the tree.  Also print some summary
+// information.
+class PrintTreeCensusClosure : public AscendTreeCensusClosure<FreeChunk, AdaptiveFreeList<FreeChunk> > {
+  int _print_line;
+  size_t _total_free;
+  AdaptiveFreeList<FreeChunk> _total;
+
+ public:
+  PrintTreeCensusClosure() {
+    _print_line = 0;
+    _total_free = 0;
+  }
+  AdaptiveFreeList<FreeChunk>* total() { return &_total; }
+  size_t total_free() { return _total_free; }
+
+  void do_list(AdaptiveFreeList<FreeChunk>* fl) {
+    LogStreamHandle(Debug, gc, freelist, census) out;
+
+    if (++_print_line >= 40) {
+      AdaptiveFreeList<FreeChunk>::print_labels_on(&out, "size");
+      _print_line = 0;
+    }
+    fl->print_on(&out);
+    _total_free +=           fl->count()             * fl->size()        ;
+    total()->set_count(      total()->count()        + fl->count()      );
+    total()->set_bfr_surp(   total()->bfr_surp()     + fl->bfr_surp()    );
+    total()->set_surplus(    total()->split_deaths() + fl->surplus()    );
+    total()->set_desired(    total()->desired()      + fl->desired()    );
+    total()->set_prev_sweep(  total()->prev_sweep()   + fl->prev_sweep()  );
+    total()->set_before_sweep(total()->before_sweep() + fl->before_sweep());
+    total()->set_coal_births( total()->coal_births()  + fl->coal_births() );
+    total()->set_coal_deaths( total()->coal_deaths()  + fl->coal_deaths() );
+    total()->set_split_births(total()->split_births() + fl->split_births());
+    total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
+  }
+};
+
+void AFLBinaryTreeDictionary::print_dict_census(outputStream* st) const {
+
+  st->print_cr("BinaryTree");
+  AdaptiveFreeList<FreeChunk>::print_labels_on(st, "size");
+  PrintTreeCensusClosure ptc;
+  ptc.do_tree(root());
+
+  AdaptiveFreeList<FreeChunk>* total = ptc.total();
+  AdaptiveFreeList<FreeChunk>::print_labels_on(st, " ");
+  total->print_on(st, "TOTAL\t");
+  st->print_cr("total_free(words): " SIZE_FORMAT_W(16) " growth: %8.5f  deficit: %8.5f",
+               ptc.total_free(),
+               (double)(total->split_births() + total->coal_births()
+                      - total->split_deaths() - total->coal_deaths())
+               /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0),
+              (double)(total->desired() - total->count())
+              /(total->desired() != 0 ? (double)total->desired() : 1.0));
+}
+
 /////////////////////////////////////////////////////////////////////////
 //// CompactibleFreeListSpace
 /////////////////////////////////////////////////////////////////////////
@@ -181,7 +420,7 @@
   } else {
     // if the object isn't moving we can just set the mark to the default
     // mark and handle it specially later on.
-    q->init_mark();
+    q->init_mark_raw();
     assert(q->forwardee() == NULL, "should be forwarded to NULL");
   }
 
--- a/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/compactibleFreeListSpace.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -48,6 +48,37 @@
 class ObjectClosureCareful;
 class Klass;
 
+class AFLBinaryTreeDictionary : public BinaryTreeDictionary<FreeChunk, AdaptiveFreeList<FreeChunk> > {
+ public:
+  AFLBinaryTreeDictionary(MemRegion mr)
+      : BinaryTreeDictionary<FreeChunk, AdaptiveFreeList<FreeChunk> >(mr) {}
+
+  // Find the list with size "size" in the binary tree and update
+  // the statistics in the list according to "split" (chunk was
+  // split or coalesce) and "birth" (chunk was added or removed).
+  void       dict_census_update(size_t size, bool split, bool birth);
+  // Return true if the dictionary is overpopulated (more chunks of
+  // this size than desired) for size "size".
+  bool       coal_dict_over_populated(size_t size);
+  // Methods called at the beginning of a sweep to prepare the
+  // statistics for the sweep.
+  void       begin_sweep_dict_census(double coalSurplusPercent,
+                                     float inter_sweep_current,
+                                     float inter_sweep_estimate,
+                                     float intra_sweep_estimate);
+  // Methods called after the end of a sweep to modify the
+  // statistics for the sweep.
+  void       end_sweep_dict_census(double splitSurplusPercent);
+  // Accessors for statistics
+  void       set_tree_surplus(double splitSurplusPercent);
+  void       set_tree_hints(void);
+  // Reset statistics for all the lists in the tree.
+  void       clear_tree_census(void);
+  // Print the statistics for all the lists in the tree.  Also may
+  // print out summaries.
+  void       print_dict_census(outputStream* st) const;
+};
+
 class LinearAllocBlock {
  public:
   LinearAllocBlock() : _ptr(0), _word_size(0), _refillSize(0),
--- a/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/concurrentMarkSweepGeneration.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,6 +29,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/cms/cmsCollectorPolicy.hpp"
+#include "gc/cms/cmsGCStats.hpp"
 #include "gc/cms/cmsHeap.hpp"
 #include "gc/cms/cmsOopClosures.inline.hpp"
 #include "gc/cms/compactibleFreeListSpace.hpp"
@@ -59,6 +60,7 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
+#include "memory/binaryTreeDictionary.inline.hpp"
 #include "memory/iterator.inline.hpp"
 #include "memory/padded.hpp"
 #include "memory/resourceArea.hpp"
@@ -1042,7 +1044,7 @@
   // Except with compressed oops it's the mark word.
   HeapWord* old_ptr = (HeapWord*)old;
   // Restore the mark word copied above.
-  obj->set_mark(m);
+  obj->set_mark_raw(m);
   assert(obj->klass_or_null() == NULL, "Object should be uninitialized here.");
   assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size");
   OrderAccess::storestore();
@@ -7814,8 +7816,8 @@
   const markOop proto = markOopDesc::prototype();
   NOT_PRODUCT(ssize_t n = 0;)
   for (oop next; i > 0 && cur != NULL; cur = next, i--) {
-    next = oop(cur->mark());
-    cur->set_mark(proto);   // until proven otherwise
+    next = oop(cur->mark_raw());
+    cur->set_mark_raw(proto);   // until proven otherwise
     assert(oopDesc::is_oop(cur), "Should be an oop");
     bool res = stack->push(cur);
     assert(res, "Bit off more than can chew?");
@@ -7898,8 +7900,8 @@
   size_t i = num;
   oop cur = prefix;
   // Walk down the first "num" objects, unless we reach the end.
-  for (; i > 1 && cur->mark() != NULL; cur = oop(cur->mark()), i--);
-  if (cur->mark() == NULL) {
+  for (; i > 1 && cur->mark_raw() != NULL; cur = oop(cur->mark_raw()), i--);
+  if (cur->mark_raw() == NULL) {
     // We have "num" or fewer elements in the list, so there
     // is nothing to return to the global list.
     // Write back the NULL in lieu of the BUSY we wrote
@@ -7909,9 +7911,9 @@
     }
   } else {
     // Chop off the suffix and return it to the global list.
-    assert(cur->mark() != BUSY, "Error");
-    oop suffix_head = cur->mark(); // suffix will be put back on global list
-    cur->set_mark(NULL);           // break off suffix
+    assert(cur->mark_raw() != BUSY, "Error");
+    oop suffix_head = cur->mark_raw(); // suffix will be put back on global list
+    cur->set_mark_raw(NULL);           // break off suffix
     // It's possible that the list is still in the empty(busy) state
     // we left it in a short while ago; in that case we may be
     // able to place back the suffix without incurring the cost
@@ -7931,18 +7933,18 @@
       // Too bad, someone else sneaked in (at least) an element; we'll need
       // to do a splice. Find tail of suffix so we can prepend suffix to global
       // list.
-      for (cur = suffix_head; cur->mark() != NULL; cur = (oop)(cur->mark()));
+      for (cur = suffix_head; cur->mark_raw() != NULL; cur = (oop)(cur->mark_raw()));
       oop suffix_tail = cur;
-      assert(suffix_tail != NULL && suffix_tail->mark() == NULL,
+      assert(suffix_tail != NULL && suffix_tail->mark_raw() == NULL,
              "Tautology");
       observed_overflow_list = _overflow_list;
       do {
         cur_overflow_list = observed_overflow_list;
         if (cur_overflow_list != BUSY) {
           // Do the splice ...
-          suffix_tail->set_mark(markOop(cur_overflow_list));
+          suffix_tail->set_mark_raw(markOop(cur_overflow_list));
         } else { // cur_overflow_list == BUSY
-          suffix_tail->set_mark(NULL);
+          suffix_tail->set_mark_raw(NULL);
         }
         // ... and try to place spliced list back on overflow_list ...
         observed_overflow_list =
@@ -7958,8 +7960,8 @@
   oop next;
   NOT_PRODUCT(ssize_t n = 0;)
   for (cur = prefix; cur != NULL; cur = next) {
-    next = oop(cur->mark());
-    cur->set_mark(proto);   // until proven otherwise
+    next = oop(cur->mark_raw());
+    cur->set_mark_raw(proto);   // until proven otherwise
     assert(oopDesc::is_oop(cur), "Should be an oop");
     bool res = work_q->push(cur);
     assert(res, "Bit off more than we can chew?");
@@ -7977,7 +7979,7 @@
   NOT_PRODUCT(_num_par_pushes++;)
   assert(oopDesc::is_oop(p), "Not an oop");
   preserve_mark_if_necessary(p);
-  p->set_mark((markOop)_overflow_list);
+  p->set_mark_raw((markOop)_overflow_list);
   _overflow_list = p;
 }
 
@@ -7991,9 +7993,9 @@
   do {
     cur_overflow_list = observed_overflow_list;
     if (cur_overflow_list != BUSY) {
-      p->set_mark(markOop(cur_overflow_list));
+      p->set_mark_raw(markOop(cur_overflow_list));
     } else {
-      p->set_mark(NULL);
+      p->set_mark_raw(NULL);
     }
     observed_overflow_list =
       Atomic::cmpxchg((oopDesc*)p, &_overflow_list, (oopDesc*)cur_overflow_list);
@@ -8018,21 +8020,21 @@
 void CMSCollector::preserve_mark_work(oop p, markOop m) {
   _preserved_oop_stack.push(p);
   _preserved_mark_stack.push(m);
-  assert(m == p->mark(), "Mark word changed");
+  assert(m == p->mark_raw(), "Mark word changed");
   assert(_preserved_oop_stack.size() == _preserved_mark_stack.size(),
          "bijection");
 }
 
 // Single threaded
 void CMSCollector::preserve_mark_if_necessary(oop p) {
-  markOop m = p->mark();
+  markOop m = p->mark_raw();
   if (m->must_be_preserved(p)) {
     preserve_mark_work(p, m);
   }
 }
 
 void CMSCollector::par_preserve_mark_if_necessary(oop p) {
-  markOop m = p->mark();
+  markOop m = p->mark_raw();
   if (m->must_be_preserved(p)) {
     MutexLockerEx x(ParGCRareEvent_lock, Mutex::_no_safepoint_check_flag);
     // Even though we read the mark word without holding
@@ -8040,7 +8042,7 @@
     // because we "own" this oop, so no other thread can
     // be trying to push it on the overflow list; see
     // the assertion in preserve_mark_work() that checks
-    // that m == p->mark().
+    // that m == p->mark_raw().
     preserve_mark_work(p, m);
   }
 }
@@ -8073,10 +8075,10 @@
     oop p = _preserved_oop_stack.pop();
     assert(oopDesc::is_oop(p), "Should be an oop");
     assert(_span.contains(p), "oop should be in _span");
-    assert(p->mark() == markOopDesc::prototype(),
+    assert(p->mark_raw() == markOopDesc::prototype(),
            "Set when taken from overflow list");
     markOop m = _preserved_mark_stack.pop();
-    p->set_mark(m);
+    p->set_mark_raw(m);
   }
   assert(_preserved_mark_stack.is_empty() && _preserved_oop_stack.is_empty(),
          "stacks were cleared above");
--- a/src/hotspot/share/gc/cms/parNewGeneration.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/parNewGeneration.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1133,7 +1133,7 @@
   // a forwarding pointer by a parallel thread.  So we must save the mark
   // word in a local and then analyze it.
   oopDesc dummyOld;
-  dummyOld.set_mark(m);
+  dummyOld.set_mark_raw(m);
   assert(!dummyOld.is_forwarded(),
          "should not be called with forwarding pointer mark word.");
 
@@ -1181,7 +1181,7 @@
     assert(CMSHeap::heap()->is_in_reserved(new_obj), "illegal forwarding pointer value.");
     forward_ptr = old->forward_to_atomic(new_obj);
     // Restore the mark word copied above.
-    new_obj->set_mark(m);
+    new_obj->set_mark_raw(m);
     // Increment age if obj still in new generation
     new_obj->incr_age();
     par_scan_state->age_table()->add(new_obj, sz);
--- a/src/hotspot/share/gc/cms/parOopClosures.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/parOopClosures.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -24,7 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/cms/parOopClosures.inline.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
+#include "gc/cms/cms_specialized_oop_closures.hpp"
 #include "memory/iterator.inline.hpp"
 
 // Generate ParNew specialized oop_oop_iterate functions.
--- a/src/hotspot/share/gc/cms/parOopClosures.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/parOopClosures.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,7 @@
 #include "logging/logStream.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "oops/oop.inline.hpp"
 
 template <class T> inline void ParScanWeakRefClosure::do_oop_work(T* p) {
   oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
@@ -43,7 +44,7 @@
     // we need to ensure that it is copied (see comment in
     // ParScanClosure::do_oop_work).
     Klass* objK = obj->klass();
-    markOop m = obj->mark();
+    markOop m = obj->mark_raw();
     oop new_obj;
     if (m->is_marked()) { // Contains forwarding pointer.
       new_obj = ParNewGeneration::real_forwardee(obj);
@@ -107,7 +108,7 @@
       // overwritten with an overflow next pointer after the object is
       // forwarded.
       Klass* objK = obj->klass();
-      markOop m = obj->mark();
+      markOop m = obj->mark_raw();
       oop new_obj;
       if (m->is_marked()) { // Contains forwarding pointer.
         new_obj = ParNewGeneration::real_forwardee(obj);
--- a/src/hotspot/share/gc/cms/promotionInfo.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/promotionInfo.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -85,10 +85,10 @@
     }                                                                       \
     if (curObj->hasDisplacedMark()) {                                       \
       /* restore displaced header */                                        \
-      oop(curObj)->set_mark(nextDisplacedHeader());                         \
+      oop(curObj)->set_mark_raw(nextDisplacedHeader());                     \
     } else {                                                                \
       /* restore prototypical header */                                     \
-      oop(curObj)->init_mark();                                             \
+      oop(curObj)->init_mark_raw();                                         \
     }                                                                       \
     /* The "promoted_mark" should now not be set */                         \
     assert(!curObj->hasPromotedMark(),                                      \
@@ -147,7 +147,7 @@
 
 void PromotionInfo::track(PromotedObject* trackOop, Klass* klassOfOop) {
   // make a copy of header as it may need to be spooled
-  markOop mark = oop(trackOop)->mark();
+  markOop mark = oop(trackOop)->mark_raw();
   trackOop->clear_next();
   if (mark->must_be_preserved_for_cms_scavenge(klassOfOop)) {
     // save non-prototypical header, and mark oop
@@ -287,7 +287,7 @@
   // 2. each promoted object lies in this space
   debug_only(
     PromotedObject* junk = NULL;
-    assert(junk->next_addr() == (void*)(oop(junk)->mark_addr()),
+    assert(junk->next_addr() == (void*)(oop(junk)->mark_addr_raw()),
            "Offset of PromotedObject::_next is expected to align with "
            "  the OopDesc::_mark within OopDesc");
   )
--- a/src/hotspot/share/gc/cms/vmStructs_cms.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/cms/vmStructs_cms.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,9 +25,15 @@
 #ifndef SHARE_VM_GC_CMS_VMSTRUCTS_CMS_HPP
 #define SHARE_VM_GC_CMS_VMSTRUCTS_CMS_HPP
 
-#define VM_STRUCTS_CMS(nonstatic_field, \
-                   volatile_nonstatic_field, \
-                   static_field) \
+#include "gc/cms/cmsHeap.hpp"
+#include "gc/cms/compactibleFreeListSpace.hpp"
+#include "gc/cms/concurrentMarkSweepGeneration.hpp"
+#include "gc/cms/concurrentMarkSweepThread.hpp"
+#include "gc/cms/parNewGeneration.hpp"
+
+#define VM_STRUCTS_CMSGC(nonstatic_field,                                                                                            \
+                         volatile_nonstatic_field,                                                                                   \
+                         static_field)                                                                                               \
   nonstatic_field(CompactibleFreeListSpace,    _collector,                                    CMSCollector*)                         \
   nonstatic_field(CompactibleFreeListSpace,    _bt,                                           BlockOffsetArrayNonContigSpace)        \
      static_field(CompactibleFreeListSpace,    _min_chunk_size_in_bytes,                      size_t)                                \
@@ -43,13 +49,22 @@
   nonstatic_field(AFLBinaryTreeDictionary,     _total_size,                                   size_t)                                \
   nonstatic_field(CompactibleFreeListSpace,    _dictionary,                                   AFLBinaryTreeDictionary*)              \
   nonstatic_field(CompactibleFreeListSpace,    _indexedFreeList[0],                           AdaptiveFreeList<FreeChunk>)           \
-  nonstatic_field(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)
+  nonstatic_field(CompactibleFreeListSpace,    _smallLinearAllocBlock,                        LinearAllocBlock)                      \
+  volatile_nonstatic_field(FreeChunk,          _size,                                         size_t)                                \
+  nonstatic_field(FreeChunk,                   _next,                                         FreeChunk*)                            \
+  nonstatic_field(FreeChunk,                   _prev,                                         FreeChunk*)                            \
+  nonstatic_field(AdaptiveFreeList<FreeChunk>, _size,                                         size_t)                                \
+  nonstatic_field(AdaptiveFreeList<FreeChunk>, _count,                                        ssize_t)
 
 
-#define VM_TYPES_CMS(declare_type,                                        \
-                     declare_toplevel_type)                               \
+
+#define VM_TYPES_CMSGC(declare_type,                                      \
+                       declare_toplevel_type,                             \
+                       declare_integer_type)                              \
                                                                           \
+           declare_type(CMSHeap,                      GenCollectedHeap)   \
            declare_type(ConcurrentMarkSweepGeneration,CardGeneration)     \
+           declare_type(ParNewGeneration,             DefNewGeneration)   \
            declare_type(CompactibleFreeListSpace,     CompactibleSpace)   \
            declare_type(ConcurrentMarkSweepThread,    NamedThread)        \
   declare_toplevel_type(CMSCollector)                                     \
@@ -61,10 +76,16 @@
   declare_toplevel_type(CompactibleFreeListSpace*)                        \
   declare_toplevel_type(CMSCollector*)                                    \
   declare_toplevel_type(AFLBinaryTreeDictionary)                          \
-  declare_toplevel_type(LinearAllocBlock)
+  declare_toplevel_type(LinearAllocBlock)                                 \
+  declare_toplevel_type(FreeChunk*)                                       \
+  declare_toplevel_type(AdaptiveFreeList<FreeChunk>*)                     \
+  declare_toplevel_type(AdaptiveFreeList<FreeChunk>)
 
-#define VM_INT_CONSTANTS_CMS(declare_constant)                            \
+
+#define VM_INT_CONSTANTS_CMSGC(declare_constant,                          \
+                               declare_constant_with_value)               \
   declare_constant(CompactibleFreeListSpace::IndexSetSize)                \
   declare_constant(Generation::ConcurrentMarkSweep)                       \
+  declare_constant(Generation::ParNew)
 
 #endif // SHARE_VM_GC_CMS_VMSTRUCTS_CMS_HPP
--- a/src/hotspot/share/gc/cms/vmStructs_parNew.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_GC_CMS_VMSTRUCTS_PARNEW_HPP
-#define SHARE_VM_GC_CMS_VMSTRUCTS_PARNEW_HPP
-
-#define VM_TYPES_PARNEW(declare_type)                                     \
-           declare_type(ParNewGeneration,             DefNewGeneration)
-
-#define VM_INT_CONSTANTS_PARNEW(declare_constant)                         \
-  declare_constant(Generation::ParNew)
-
-#endif // SHARE_VM_GC_CMS_VMSTRUCTS_PARNEW_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/commandLineFlagConstraintsG1.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "gc/g1/heapRegionBounds.inline.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
+#include "runtime/globals_extension.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+Flag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose) {
+  if (!UseG1GC) return Flag::SUCCESS;
+
+  // Default value of G1RSetRegionEntries=0 means will be set ergonomically.
+  // Minimum value is 1.
+  if (FLAG_IS_CMDLINE(G1RSetRegionEntries) && (value < 1)) {
+    CommandLineError::print(verbose,
+                            "G1RSetRegionEntries (" INTX_FORMAT ") must be "
+                            "greater than or equal to 1\n",
+                            value);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose) {
+  if (!UseG1GC) return Flag::SUCCESS;
+
+  // Default value of G1RSetSparseRegionEntries=0 means will be set ergonomically.
+  // Minimum value is 1.
+  if (FLAG_IS_CMDLINE(G1RSetSparseRegionEntries) && (value < 1)) {
+    CommandLineError::print(verbose,
+                            "G1RSetSparseRegionEntries (" INTX_FORMAT ") must be "
+                            "greater than or equal to 1\n",
+                            value);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose) {
+  if (!UseG1GC) return Flag::SUCCESS;
+
+  // Default value of G1HeapRegionSize=0 means will be set ergonomically.
+  if (FLAG_IS_CMDLINE(G1HeapRegionSize) && (value < HeapRegionBounds::min_size())) {
+    CommandLineError::print(verbose,
+                            "G1HeapRegionSize (" SIZE_FORMAT ") must be "
+                            "greater than or equal to ergonomic heap region minimum size\n",
+                            value);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose) {
+  if (!UseG1GC) return Flag::SUCCESS;
+
+  if (value > G1MaxNewSizePercent) {
+    CommandLineError::print(verbose,
+                            "G1NewSizePercent (" UINTX_FORMAT ") must be "
+                            "less than or equal to G1MaxNewSizePercent (" UINTX_FORMAT ")\n",
+                            value, G1MaxNewSizePercent);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose) {
+  if (!UseG1GC) return Flag::SUCCESS;
+
+  if (value < G1NewSizePercent) {
+    CommandLineError::print(verbose,
+                            "G1MaxNewSizePercent (" UINTX_FORMAT ") must be "
+                            "greater than or equal to G1NewSizePercent (" UINTX_FORMAT ")\n",
+                            value, G1NewSizePercent);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxGCPauseMillisConstraintFuncG1(uintx value, bool verbose) {
+  if (UseG1GC && FLAG_IS_CMDLINE(MaxGCPauseMillis) && (value >= GCPauseIntervalMillis)) {
+    CommandLineError::print(verbose,
+                            "MaxGCPauseMillis (" UINTX_FORMAT ") must be "
+                            "less than GCPauseIntervalMillis (" UINTX_FORMAT ")\n",
+                            value, GCPauseIntervalMillis);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error GCPauseIntervalMillisConstraintFuncG1(uintx value, bool verbose) {
+  if (UseG1GC) {
+    if (FLAG_IS_CMDLINE(GCPauseIntervalMillis)) {
+      if (value < 1) {
+        CommandLineError::print(verbose,
+                                "GCPauseIntervalMillis (" UINTX_FORMAT ") must be "
+                                "greater than or equal to 1\n",
+                                value);
+        return Flag::VIOLATES_CONSTRAINT;
+      }
+
+      if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
+        CommandLineError::print(verbose,
+                                "GCPauseIntervalMillis cannot be set "
+                                "without setting MaxGCPauseMillis\n");
+        return Flag::VIOLATES_CONSTRAINT;
+      }
+
+      if (value <= MaxGCPauseMillis) {
+        CommandLineError::print(verbose,
+                                "GCPauseIntervalMillis (" UINTX_FORMAT ") must be "
+                                "greater than MaxGCPauseMillis (" UINTX_FORMAT ")\n",
+                                value, MaxGCPauseMillis);
+        return Flag::VIOLATES_CONSTRAINT;
+      }
+    }
+  }
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error NewSizeConstraintFuncG1(size_t value, bool verbose) {
+#ifdef _LP64
+  // Overflow would happen for uint type variable of YoungGenSizer::_min_desired_young_length
+  // when the value to be assigned exceeds uint range.
+  // i.e. result of '(uint)(NewSize / region size(1~32MB))'
+  // So maximum of NewSize should be 'max_juint * 1M'
+  if (UseG1GC && (value > (max_juint * 1 * M))) {
+    CommandLineError::print(verbose,
+                            "NewSize (" SIZE_FORMAT ") must be less than ergonomic maximum value\n",
+                            value);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+#endif // _LP64
+  return Flag::SUCCESS;
+}
+
+size_t MaxSizeForHeapAlignmentG1() {
+  return HeapRegionBounds::max_size();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/commandLineFlagConstraintsG1.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_G1_COMMANDLINEFLAGCONSTRAINTSG1_HPP
+#define SHARE_GC_G1_COMMANDLINEFLAGCONSTRAINTSG1_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// G1 Flag Constraints
+Flag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose);
+Flag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose);
+Flag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose);
+Flag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose);
+
+// G1 Subconstraints
+Flag::Error MaxGCPauseMillisConstraintFuncG1(uintx value, bool verbose);
+Flag::Error GCPauseIntervalMillisConstraintFuncG1(uintx value, bool verbose);
+Flag::Error MaxSizeForHeapAlignmentG1(const char* name, size_t value, bool verbose);
+Flag::Error NewSizeConstraintFuncG1(size_t value, bool verbose);
+
+size_t MaxSizeForHeapAlignmentG1();
+
+#endif // SHARE_GC_SHARED_COMMANDLINEFLAGCONSTRAINTSG1_HPP
--- a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/dirtyCardQueue.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,7 @@
 #include "gc/g1/dirtyCardQueue.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1RemSet.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/shared/workgroup.hpp"
 #include "runtime/atomic.hpp"
@@ -164,7 +165,7 @@
 }
 
 void DirtyCardQueueSet::handle_zero_index_for_thread(JavaThread* t) {
-  t->dirty_card_queue().handle_zero_index();
+  G1ThreadLocalData::dirty_card_queue(t).handle_zero_index();
 }
 
 bool DirtyCardQueueSet::apply_closure_to_buffer(CardTableEntryClosure* cl,
@@ -321,7 +322,7 @@
   // Since abandon is done only at safepoints, we can safely manipulate
   // these queues.
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    t->dirty_card_queue().reset();
+    G1ThreadLocalData::dirty_card_queue(t).reset();
   }
   shared_dirty_card_queue()->reset();
 }
@@ -340,7 +341,7 @@
   _max_completed_queue = max_jint;
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    concatenate_log(t->dirty_card_queue());
+    concatenate_log(G1ThreadLocalData::dirty_card_queue(t));
   }
   concatenate_log(_shared_dirty_card_queue);
   // Restore the completed buffer queue limit.
--- a/src/hotspot/share/gc/g1/g1Allocator.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1Allocator.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -33,8 +33,8 @@
 #include "gc/g1/heapRegionType.hpp"
 #include "utilities/align.hpp"
 
-G1DefaultAllocator::G1DefaultAllocator(G1CollectedHeap* heap) :
-  G1Allocator(heap),
+G1Allocator::G1Allocator(G1CollectedHeap* heap) :
+  _g1h(heap),
   _survivor_is_full(false),
   _old_is_full(false),
   _retained_old_gc_alloc_region(NULL),
@@ -42,16 +42,20 @@
   _old_gc_alloc_region(heap->alloc_buffer_stats(InCSetState::Old)) {
 }
 
-void G1DefaultAllocator::init_mutator_alloc_region() {
+void G1Allocator::init_mutator_alloc_region() {
   assert(_mutator_alloc_region.get() == NULL, "pre-condition");
   _mutator_alloc_region.init();
 }
 
-void G1DefaultAllocator::release_mutator_alloc_region() {
+void G1Allocator::release_mutator_alloc_region() {
   _mutator_alloc_region.release();
   assert(_mutator_alloc_region.get() == NULL, "post-condition");
 }
 
+bool G1Allocator::is_retained_old_region(HeapRegion* hr) {
+  return _retained_old_gc_alloc_region == hr;
+}
+
 void G1Allocator::reuse_retained_old_region(EvacuationInfo& evacuation_info,
                                             OldGCAllocRegion* old,
                                             HeapRegion** retained_old) {
@@ -87,7 +91,7 @@
   }
 }
 
-void G1DefaultAllocator::init_gc_alloc_regions(EvacuationInfo& evacuation_info) {
+void G1Allocator::init_gc_alloc_regions(EvacuationInfo& evacuation_info) {
   assert_at_safepoint_on_vm_thread();
 
   _survivor_is_full = false;
@@ -100,7 +104,7 @@
                             &_retained_old_gc_alloc_region);
 }
 
-void G1DefaultAllocator::release_gc_alloc_regions(EvacuationInfo& evacuation_info) {
+void G1Allocator::release_gc_alloc_regions(EvacuationInfo& evacuation_info) {
   evacuation_info.set_allocation_regions(survivor_gc_alloc_region()->count() +
                                          old_gc_alloc_region()->count());
   survivor_gc_alloc_region()->release();
@@ -112,25 +116,25 @@
   _retained_old_gc_alloc_region = old_gc_alloc_region()->release();
 }
 
-void G1DefaultAllocator::abandon_gc_alloc_regions() {
+void G1Allocator::abandon_gc_alloc_regions() {
   assert(survivor_gc_alloc_region()->get() == NULL, "pre-condition");
   assert(old_gc_alloc_region()->get() == NULL, "pre-condition");
   _retained_old_gc_alloc_region = NULL;
 }
 
-bool G1DefaultAllocator::survivor_is_full() const {
+bool G1Allocator::survivor_is_full() const {
   return _survivor_is_full;
 }
 
-bool G1DefaultAllocator::old_is_full() const {
+bool G1Allocator::old_is_full() const {
   return _old_is_full;
 }
 
-void G1DefaultAllocator::set_survivor_full() {
+void G1Allocator::set_survivor_full() {
   _survivor_is_full = true;
 }
 
-void G1DefaultAllocator::set_old_full() {
+void G1Allocator::set_old_full() {
   _old_is_full = true;
 }
 
@@ -151,6 +155,19 @@
   }
 }
 
+size_t G1Allocator::used_in_alloc_regions() {
+  assert(Heap_lock->owner() != NULL, "Should be owned on this thread's behalf.");
+  size_t result = 0;
+
+  // Read only once in case it is set to NULL concurrently
+  HeapRegion* hr = mutator_alloc_region()->get();
+  if (hr != NULL) {
+    result += hr->used();
+  }
+  return result;
+}
+
+
 HeapWord* G1Allocator::par_allocate_during_gc(InCSetState dest,
                                               size_t word_size) {
   size_t temp = 0;
@@ -221,13 +238,30 @@
   return result;
 }
 
+uint G1PLABAllocator::calc_survivor_alignment_bytes() {
+  assert(SurvivorAlignmentInBytes >= ObjectAlignmentInBytes, "sanity");
+  if (SurvivorAlignmentInBytes == ObjectAlignmentInBytes) {
+    // No need to align objects in the survivors differently, return 0
+    // which means "survivor alignment is not used".
+    return 0;
+  } else {
+    assert(SurvivorAlignmentInBytes > 0, "sanity");
+    return SurvivorAlignmentInBytes;
+  }
+}
+
 G1PLABAllocator::G1PLABAllocator(G1Allocator* allocator) :
   _g1h(G1CollectedHeap::heap()),
   _allocator(allocator),
+  _surviving_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Young)),
+  _tenured_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Old)),
   _survivor_alignment_bytes(calc_survivor_alignment_bytes()) {
-  for (size_t i = 0; i < ARRAY_SIZE(_direct_allocated); i++) {
-    _direct_allocated[i] = 0;
+  for (uint state = 0; state < InCSetState::Num; state++) {
+    _direct_allocated[state] = 0;
+    _alloc_buffers[state] = NULL;
   }
+  _alloc_buffers[InCSetState::Young] = &_surviving_alloc_buffer;
+  _alloc_buffers[InCSetState::Old]  = &_tenured_alloc_buffer;
 }
 
 bool G1PLABAllocator::may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const {
@@ -282,18 +316,7 @@
   alloc_buffer(dest)->undo_allocation(obj, word_sz);
 }
 
-G1DefaultPLABAllocator::G1DefaultPLABAllocator(G1Allocator* allocator) :
-  G1PLABAllocator(allocator),
-  _surviving_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Young)),
-  _tenured_alloc_buffer(_g1h->desired_plab_sz(InCSetState::Old)) {
-  for (uint state = 0; state < InCSetState::Num; state++) {
-    _alloc_buffers[state] = NULL;
-  }
-  _alloc_buffers[InCSetState::Young] = &_surviving_alloc_buffer;
-  _alloc_buffers[InCSetState::Old]  = &_tenured_alloc_buffer;
-}
-
-void G1DefaultPLABAllocator::flush_and_retire_stats() {
+void G1PLABAllocator::flush_and_retire_stats() {
   for (uint state = 0; state < InCSetState::Num; state++) {
     PLAB* const buf = _alloc_buffers[state];
     if (buf != NULL) {
@@ -305,7 +328,7 @@
   }
 }
 
-void G1DefaultPLABAllocator::waste(size_t& wasted, size_t& undo_wasted) {
+void G1PLABAllocator::waste(size_t& wasted, size_t& undo_wasted) {
   wasted = 0;
   undo_wasted = 0;
   for (uint state = 0; state < InCSetState::Num; state++) {
--- a/src/hotspot/share/gc/g1/g1Allocator.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1Allocator.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -37,82 +37,13 @@
 // Also keeps track of retained regions across GCs.
 class G1Allocator : public CHeapObj<mtGC> {
   friend class VMStructs;
-protected:
+
+private:
   G1CollectedHeap* _g1h;
 
-  virtual MutatorAllocRegion* mutator_alloc_region() = 0;
-
-  virtual bool survivor_is_full() const = 0;
-  virtual bool old_is_full() const = 0;
-
-  virtual void set_survivor_full() = 0;
-  virtual void set_old_full() = 0;
-
-  // Accessors to the allocation regions.
-  virtual SurvivorGCAllocRegion* survivor_gc_alloc_region() = 0;
-  virtual OldGCAllocRegion* old_gc_alloc_region() = 0;
-
-  // Allocation attempt during GC for a survivor object / PLAB.
-  inline HeapWord* survivor_attempt_allocation(size_t min_word_size,
-                                               size_t desired_word_size,
-                                               size_t* actual_word_size);
-  // Allocation attempt during GC for an old object / PLAB.
-  inline HeapWord* old_attempt_allocation(size_t min_word_size,
-                                          size_t desired_word_size,
-                                          size_t* actual_word_size);
-public:
-  G1Allocator(G1CollectedHeap* heap) : _g1h(heap) { }
-  virtual ~G1Allocator() { }
-
-#ifdef ASSERT
-  // Do we currently have an active mutator region to allocate into?
-  bool has_mutator_alloc_region() { return mutator_alloc_region()->get() != NULL; }
-#endif
-  virtual void init_mutator_alloc_region() = 0;
-  virtual void release_mutator_alloc_region() = 0;
-
-  virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0;
-  virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info) = 0;
-  virtual void abandon_gc_alloc_regions() = 0;
-
-  // Management of retained regions.
-
-  virtual bool is_retained_old_region(HeapRegion* hr) = 0;
-  void reuse_retained_old_region(EvacuationInfo& evacuation_info,
-                                 OldGCAllocRegion* old,
-                                 HeapRegion** retained);
-
-  // Allocate blocks of memory during mutator time.
-
-  inline HeapWord* attempt_allocation(size_t word_size);
-  inline HeapWord* attempt_allocation_locked(size_t word_size);
-  inline HeapWord* attempt_allocation_force(size_t word_size);
-
-  size_t unsafe_max_tlab_alloc();
-
-  // Allocate blocks of memory during garbage collection. Will ensure an
-  // allocation region, either by picking one or expanding the
-  // heap, and then allocate a block of the given size. The block
-  // may not be a humongous - it must fit into a single heap region.
-  HeapWord* par_allocate_during_gc(InCSetState dest,
-                                   size_t word_size);
-
-  HeapWord* par_allocate_during_gc(InCSetState dest,
-                                   size_t min_word_size,
-                                   size_t desired_word_size,
-                                   size_t* actual_word_size);
-
-  virtual size_t used_in_alloc_regions() = 0;
-};
-
-// The default allocation region manager for G1. Provides a single mutator, survivor
-// and old generation allocation region.
-// Can retain the (single) old generation allocation region across GCs.
-class G1DefaultAllocator : public G1Allocator {
-private:
   bool _survivor_is_full;
   bool _old_is_full;
-protected:
+
   // Alloc region used to satisfy mutator allocation requests.
   MutatorAllocRegion _mutator_alloc_region;
 
@@ -125,50 +56,67 @@
   OldGCAllocRegion _old_gc_alloc_region;
 
   HeapRegion* _retained_old_gc_alloc_region;
-public:
-  G1DefaultAllocator(G1CollectedHeap* heap);
+
+  bool survivor_is_full() const;
+  bool old_is_full() const;
 
-  virtual bool survivor_is_full() const;
-  virtual bool old_is_full() const ;
+  void set_survivor_full();
+  void set_old_full();
 
-  virtual void set_survivor_full();
-  virtual void set_old_full();
+  void reuse_retained_old_region(EvacuationInfo& evacuation_info,
+                                 OldGCAllocRegion* old,
+                                 HeapRegion** retained);
 
-  virtual void init_mutator_alloc_region();
-  virtual void release_mutator_alloc_region();
+  // Accessors to the allocation regions.
+  inline MutatorAllocRegion* mutator_alloc_region();
+  inline SurvivorGCAllocRegion* survivor_gc_alloc_region();
+  inline OldGCAllocRegion* old_gc_alloc_region();
 
-  virtual void init_gc_alloc_regions(EvacuationInfo& evacuation_info);
-  virtual void release_gc_alloc_regions(EvacuationInfo& evacuation_info);
-  virtual void abandon_gc_alloc_regions();
+  // Allocation attempt during GC for a survivor object / PLAB.
+  HeapWord* survivor_attempt_allocation(size_t min_word_size,
+                                               size_t desired_word_size,
+                                               size_t* actual_word_size);
 
-  virtual bool is_retained_old_region(HeapRegion* hr) {
-    return _retained_old_gc_alloc_region == hr;
-  }
+  // Allocation attempt during GC for an old object / PLAB.
+  HeapWord* old_attempt_allocation(size_t min_word_size,
+                                          size_t desired_word_size,
+                                          size_t* actual_word_size);
+public:
+  G1Allocator(G1CollectedHeap* heap);
 
-  virtual MutatorAllocRegion* mutator_alloc_region() {
-    return &_mutator_alloc_region;
-  }
+#ifdef ASSERT
+  // Do we currently have an active mutator region to allocate into?
+  bool has_mutator_alloc_region() { return mutator_alloc_region()->get() != NULL; }
+#endif
 
-  virtual SurvivorGCAllocRegion* survivor_gc_alloc_region() {
-    return &_survivor_gc_alloc_region;
-  }
+  void init_mutator_alloc_region();
+  void release_mutator_alloc_region();
 
-  virtual OldGCAllocRegion* old_gc_alloc_region() {
-    return &_old_gc_alloc_region;
-  }
+  void init_gc_alloc_regions(EvacuationInfo& evacuation_info);
+  void release_gc_alloc_regions(EvacuationInfo& evacuation_info);
+  void abandon_gc_alloc_regions();
+  bool is_retained_old_region(HeapRegion* hr);
+
+  // Allocate blocks of memory during mutator time.
 
-  virtual size_t used_in_alloc_regions() {
-    assert(Heap_lock->owner() != NULL,
-           "Should be owned on this thread's behalf.");
-    size_t result = 0;
+  inline HeapWord* attempt_allocation(size_t word_size);
+  inline HeapWord* attempt_allocation_locked(size_t word_size);
+  inline HeapWord* attempt_allocation_force(size_t word_size);
+
+  size_t unsafe_max_tlab_alloc();
+  size_t used_in_alloc_regions();
 
-    // Read only once in case it is set to NULL concurrently
-    HeapRegion* hr = mutator_alloc_region()->get();
-    if (hr != NULL) {
-      result += hr->used();
-    }
-    return result;
-  }
+  // Allocate blocks of memory during garbage collection. Will ensure an
+  // allocation region, either by picking one or expanding the
+  // heap, and then allocate a block of the given size. The block
+  // may not be a humongous - it must fit into a single heap region.
+  HeapWord* par_allocate_during_gc(InCSetState dest,
+                                   size_t word_size);
+
+  HeapWord* par_allocate_during_gc(InCSetState dest,
+                                   size_t min_word_size,
+                                   size_t desired_word_size,
+                                   size_t* actual_word_size);
 };
 
 // Manages the PLABs used during garbage collection. Interface for allocation from PLABs.
@@ -176,10 +124,14 @@
 // statistics.
 class G1PLABAllocator : public CHeapObj<mtGC> {
   friend class G1ParScanThreadState;
-protected:
+private:
   G1CollectedHeap* _g1h;
   G1Allocator* _allocator;
 
+  PLAB  _surviving_alloc_buffer;
+  PLAB  _tenured_alloc_buffer;
+  PLAB* _alloc_buffers[InCSetState::Num];
+
   // The survivor alignment in effect in bytes.
   // == 0 : don't align survivors
   // != 0 : align survivors to that alignment
@@ -190,32 +142,18 @@
   // Number of words allocated directly (not counting PLAB allocation).
   size_t _direct_allocated[InCSetState::Num];
 
-  virtual void flush_and_retire_stats() = 0;
-  virtual PLAB* alloc_buffer(InCSetState dest) = 0;
+  void flush_and_retire_stats();
+  inline PLAB* alloc_buffer(InCSetState dest);
 
   // Calculate the survivor space object alignment in bytes. Returns that or 0 if
   // there are no restrictions on survivor alignment.
-  static uint calc_survivor_alignment_bytes() {
-    assert(SurvivorAlignmentInBytes >= ObjectAlignmentInBytes, "sanity");
-    if (SurvivorAlignmentInBytes == ObjectAlignmentInBytes) {
-      // No need to align objects in the survivors differently, return 0
-      // which means "survivor alignment is not used".
-      return 0;
-    } else {
-      assert(SurvivorAlignmentInBytes > 0, "sanity");
-      return SurvivorAlignmentInBytes;
-    }
-  }
-
-  HeapWord* allocate_new_plab(InCSetState dest,
-                              size_t word_sz);
+  static uint calc_survivor_alignment_bytes();
 
   bool may_throw_away_buffer(size_t const allocation_word_sz, size_t const buffer_size) const;
 public:
   G1PLABAllocator(G1Allocator* allocator);
-  virtual ~G1PLABAllocator() { }
 
-  virtual void waste(size_t& wasted, size_t& undo_wasted) = 0;
+  void waste(size_t& wasted, size_t& undo_wasted);
 
   // Allocate word_sz words in dest, either directly into the regions or by
   // allocating a new PLAB. Returns the address of the allocated memory, NULL if
@@ -230,42 +168,13 @@
   inline HeapWord* plab_allocate(InCSetState dest,
                                  size_t word_sz);
 
-  HeapWord* allocate(InCSetState dest,
-                     size_t word_sz,
-                     bool* refill_failed) {
-    HeapWord* const obj = plab_allocate(dest, word_sz);
-    if (obj != NULL) {
-      return obj;
-    }
-    return allocate_direct_or_new_plab(dest, word_sz, refill_failed);
-  }
+  inline HeapWord* allocate(InCSetState dest,
+                            size_t word_sz,
+                            bool* refill_failed);
 
   void undo_allocation(InCSetState dest, HeapWord* obj, size_t word_sz);
 };
 
-// The default PLAB allocator for G1. Keeps the current (single) PLAB for survivor
-// and old generation allocation.
-class G1DefaultPLABAllocator : public G1PLABAllocator {
-  PLAB  _surviving_alloc_buffer;
-  PLAB  _tenured_alloc_buffer;
-  PLAB* _alloc_buffers[InCSetState::Num];
-
-public:
-  G1DefaultPLABAllocator(G1Allocator* _allocator);
-
-  virtual PLAB* alloc_buffer(InCSetState dest) {
-    assert(dest.is_valid(),
-           "Allocation buffer index out-of-bounds: " CSETSTATE_FORMAT, dest.value());
-    assert(_alloc_buffers[dest.value()] != NULL,
-           "Allocation buffer is NULL: " CSETSTATE_FORMAT, dest.value());
-    return _alloc_buffers[dest.value()];
-  }
-
-  virtual void flush_and_retire_stats();
-
-  virtual void waste(size_t& wasted, size_t& undo_wasted);
-};
-
 // G1ArchiveRegionMap is a boolean array used to mark G1 regions as
 // archive regions.  This allows a quick check for whether an object
 // should not be marked because it is in an archive region.
--- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,21 +29,41 @@
 #include "gc/g1/g1AllocRegion.inline.hpp"
 #include "gc/shared/plab.inline.hpp"
 
-HeapWord* G1Allocator::attempt_allocation(size_t word_size) {
+inline MutatorAllocRegion* G1Allocator::mutator_alloc_region() {
+  return &_mutator_alloc_region;
+}
+
+inline SurvivorGCAllocRegion* G1Allocator::survivor_gc_alloc_region() {
+  return &_survivor_gc_alloc_region;
+}
+
+inline OldGCAllocRegion* G1Allocator::old_gc_alloc_region() {
+  return &_old_gc_alloc_region;
+}
+
+inline HeapWord* G1Allocator::attempt_allocation(size_t word_size) {
   return mutator_alloc_region()->attempt_allocation(word_size);
 }
 
-HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) {
+inline HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) {
   HeapWord* result = mutator_alloc_region()->attempt_allocation_locked(word_size);
   assert(result != NULL || mutator_alloc_region()->get() == NULL,
          "Must not have a mutator alloc region if there is no memory, but is " PTR_FORMAT, p2i(mutator_alloc_region()->get()));
   return result;
 }
 
-HeapWord* G1Allocator::attempt_allocation_force(size_t word_size) {
+inline HeapWord* G1Allocator::attempt_allocation_force(size_t word_size) {
   return mutator_alloc_region()->attempt_allocation_force(word_size);
 }
 
+inline PLAB* G1PLABAllocator::alloc_buffer(InCSetState dest) {
+  assert(dest.is_valid(),
+         "Allocation buffer index out-of-bounds: " CSETSTATE_FORMAT, dest.value());
+  assert(_alloc_buffers[dest.value()] != NULL,
+         "Allocation buffer is NULL: " CSETSTATE_FORMAT, dest.value());
+  return _alloc_buffers[dest.value()];
+}
+
 inline HeapWord* G1PLABAllocator::plab_allocate(InCSetState dest,
                                                 size_t word_sz) {
   PLAB* buffer = alloc_buffer(dest);
@@ -54,6 +74,16 @@
   }
 }
 
+inline HeapWord* G1PLABAllocator::allocate(InCSetState dest,
+                                           size_t word_sz,
+                                           bool* refill_failed) {
+  HeapWord* const obj = plab_allocate(dest, word_sz);
+  if (obj != NULL) {
+    return obj;
+  }
+  return allocate_direct_or_new_plab(dest, word_sz, refill_failed);
+}
+
 // Create the maps which is used to identify archive objects.
 inline void G1ArchiveAllocator::enable_archive_object_check() {
   if (_archive_check_enabled) {
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -27,6 +27,7 @@
 #include "gc/g1/g1BarrierSetAssembler.hpp"
 #include "gc/g1/g1CardTable.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.hpp"
 #include "gc/g1/satbMarkQueue.hpp"
 #include "logging/log.hpp"
@@ -37,25 +38,25 @@
 #include "runtime/thread.inline.hpp"
 #include "utilities/macros.hpp"
 
+SATBMarkQueueSet G1BarrierSet::_satb_mark_queue_set;
+DirtyCardQueueSet G1BarrierSet::_dirty_card_queue_set;
+
 G1BarrierSet::G1BarrierSet(G1CardTable* card_table) :
   CardTableBarrierSet(make_barrier_set_assembler<G1BarrierSetAssembler>(),
                       card_table,
-                      BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)),
-  _dcqs(JavaThread::dirty_card_queue_set())
-{ }
+                      BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)) {}
 
 void G1BarrierSet::enqueue(oop pre_val) {
   // Nulls should have been already filtered.
   assert(oopDesc::is_oop(pre_val, true), "Error");
 
-  if (!JavaThread::satb_mark_queue_set().is_active()) return;
+  if (!_satb_mark_queue_set.is_active()) return;
   Thread* thr = Thread::current();
   if (thr->is_Java_thread()) {
-    JavaThread* jt = (JavaThread*)thr;
-    jt->satb_mark_queue().enqueue(pre_val);
+    G1ThreadLocalData::satb_mark_queue(thr).enqueue(pre_val);
   } else {
     MutexLockerEx x(Shared_SATB_Q_lock, Mutex::_no_safepoint_check_flag);
-    JavaThread::satb_mark_queue_set().shared_satb_queue()->enqueue(pre_val);
+    _satb_mark_queue_set.shared_satb_queue()->enqueue(pre_val);
   }
 }
 
@@ -76,7 +77,7 @@
 
 template <class T> void
 G1BarrierSet::write_ref_array_pre_work(T* dst, size_t count) {
-  if (!JavaThread::satb_mark_queue_set().is_active()) return;
+  if (!_satb_mark_queue_set.is_active()) return;
   T* elem_ptr = dst;
   for (size_t i = 0; i < count; i++, elem_ptr++) {
     T heap_oop = RawAccess<>::oop_load(elem_ptr);
@@ -106,12 +107,11 @@
     *byte = G1CardTable::dirty_card_val();
     Thread* thr = Thread::current();
     if (thr->is_Java_thread()) {
-      JavaThread* jt = (JavaThread*)thr;
-      jt->dirty_card_queue().enqueue(byte);
+      G1ThreadLocalData::dirty_card_queue(thr).enqueue(byte);
     } else {
       MutexLockerEx x(Shared_DirtyCardQ_lock,
                       Mutex::_no_safepoint_check_flag);
-      _dcqs.shared_dirty_card_queue()->enqueue(byte);
+      _dirty_card_queue_set.shared_dirty_card_queue()->enqueue(byte);
     }
   }
 }
@@ -130,14 +130,13 @@
     OrderAccess::storeload();
     // Enqueue if necessary.
     if (thr->is_Java_thread()) {
-      JavaThread* jt = (JavaThread*)thr;
       for (; byte <= last_byte; byte++) {
         if (*byte == G1CardTable::g1_young_card_val()) {
           continue;
         }
         if (*byte != G1CardTable::dirty_card_val()) {
           *byte = G1CardTable::dirty_card_val();
-          jt->dirty_card_queue().enqueue(byte);
+          G1ThreadLocalData::dirty_card_queue(thr).enqueue(byte);
         }
       }
     } else {
@@ -149,13 +148,23 @@
         }
         if (*byte != G1CardTable::dirty_card_val()) {
           *byte = G1CardTable::dirty_card_val();
-          _dcqs.shared_dirty_card_queue()->enqueue(byte);
+          _dirty_card_queue_set.shared_dirty_card_queue()->enqueue(byte);
         }
       }
     }
   }
 }
 
+void G1BarrierSet::on_thread_create(Thread* thread) {
+  // Create thread local data
+  G1ThreadLocalData::create(thread);
+}
+
+void G1BarrierSet::on_thread_destroy(Thread* thread) {
+  // Destroy thread local data
+  G1ThreadLocalData::destroy(thread);
+}
+
 void G1BarrierSet::on_thread_attach(JavaThread* thread) {
   // This method initializes the SATB and dirty card queues before a
   // JavaThread is added to the Java thread list. Right now, we don't
@@ -175,20 +184,20 @@
   // thread being added to the Java thread list (an example of this is
   // when the structure for the DestroyJavaVM thread is created).
   assert(!SafepointSynchronize::is_at_safepoint(), "We should not be at a safepoint");
-  assert(!thread->satb_mark_queue().is_active(), "SATB queue should not be active");
-  assert(thread->satb_mark_queue().is_empty(), "SATB queue should be empty");
-  assert(thread->dirty_card_queue().is_active(), "Dirty card queue should be active");
+  assert(!G1ThreadLocalData::satb_mark_queue(thread).is_active(), "SATB queue should not be active");
+  assert(G1ThreadLocalData::satb_mark_queue(thread).is_empty(), "SATB queue should be empty");
+  assert(G1ThreadLocalData::dirty_card_queue(thread).is_active(), "Dirty card queue should be active");
 
   // If we are creating the thread during a marking cycle, we should
   // set the active field of the SATB queue to true.
-  if (thread->satb_mark_queue_set().is_active()) {
-    thread->satb_mark_queue().set_active(true);
+  if (_satb_mark_queue_set.is_active()) {
+    G1ThreadLocalData::satb_mark_queue(thread).set_active(true);
   }
 }
 
 void G1BarrierSet::on_thread_detach(JavaThread* thread) {
   // Flush any deferred card marks, SATB buffers and dirty card queue buffers
   CardTableBarrierSet::on_thread_detach(thread);
-  thread->satb_mark_queue().flush();
-  thread->dirty_card_queue().flush();
+  G1ThreadLocalData::satb_mark_queue(thread).flush();
+  G1ThreadLocalData::dirty_card_queue(thread).flush();
 }
--- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,6 +25,8 @@
 #ifndef SHARE_VM_GC_G1_G1BARRIERSET_HPP
 #define SHARE_VM_GC_G1_G1BARRIERSET_HPP
 
+#include "gc/g1/dirtyCardQueue.hpp"
+#include "gc/g1/satbMarkQueue.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 
 class DirtyCardQueueSet;
@@ -37,7 +39,8 @@
 class G1BarrierSet: public CardTableBarrierSet {
   friend class VMStructs;
  private:
-  DirtyCardQueueSet& _dcqs;
+  static SATBMarkQueueSet  _satb_mark_queue_set;
+  static DirtyCardQueueSet _dirty_card_queue_set;
 
  public:
   G1BarrierSet(G1CardTable* table);
@@ -71,9 +74,19 @@
   void write_ref_field_post(T* field, oop new_val);
   void write_ref_field_post_slow(volatile jbyte* byte);
 
+  virtual void on_thread_create(Thread* thread);
+  virtual void on_thread_destroy(Thread* thread);
   virtual void on_thread_attach(JavaThread* thread);
   virtual void on_thread_detach(JavaThread* thread);
 
+  static SATBMarkQueueSet& satb_mark_queue_set() {
+    return _satb_mark_queue_set;
+  }
+
+  static DirtyCardQueueSet& dirty_card_queue_set() {
+    return _dirty_card_queue_set;
+  }
+
   // Callbacks for runtime accesses.
   template <DecoratorSet decorators, typename BarrierSetT = G1BarrierSet>
   class AccessBarrier: public ModRefBarrierSet::AccessBarrier<decorators, BarrierSetT> {
--- a/src/hotspot/share/gc/g1/g1BarrierSetAssembler.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1BarrierSetAssembler.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -22,11 +22,11 @@
  *
  */
 
-#ifndef SHARE_GC_SHARED_G1BARRIERSETASSEMBLER_HPP
-#define SHARE_GC_SHARED_G1BARRIERSETASSEMBLER_HPP
+#ifndef SHARE_GC_G1_G1BARRIERSETASSEMBLER_HPP
+#define SHARE_GC_G1_G1BARRIERSETASSEMBLER_HPP
 
 #include "utilities/macros.hpp"
 
 #include CPU_HEADER(gc/g1/g1BarrierSetAssembler)
 
-#endif // SHARE_GC_SHARED_G1BARRIERSETASSEMBLER_HPP
+#endif // SHARE_GC_G1_G1BARRIERSETASSEMBLER_HPP
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,6 +30,7 @@
 #include "code/icBuffer.hpp"
 #include "gc/g1/bufferingOopClosure.hpp"
 #include "gc/g1/g1Allocator.inline.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectionSet.hpp"
 #include "gc/g1/g1CollectorPolicy.hpp"
@@ -53,6 +54,7 @@
 #include "gc/g1/g1RootClosures.hpp"
 #include "gc/g1/g1RootProcessor.hpp"
 #include "gc/g1/g1StringDedup.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/g1YCTypes.hpp"
 #include "gc/g1/g1YoungRemSetSamplingThread.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
@@ -1036,7 +1038,7 @@
   }
 
   // Discard all remembered set updates.
-  JavaThread::dirty_card_queue_set().abandon_logs();
+  G1BarrierSet::dirty_card_queue_set().abandon_logs();
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty");
 }
 
@@ -1426,7 +1428,7 @@
   _workers->initialize_workers();
   _verifier = new G1HeapVerifier(this);
 
-  _allocator = new G1DefaultAllocator(this);
+  _allocator = new G1Allocator(this);
 
   _heap_sizing_policy = G1HeapSizingPolicy::create(this, _g1_policy->analytics());
 
@@ -1540,7 +1542,7 @@
   G1BarrierSet* bs = new G1BarrierSet(ct);
   bs->initialize();
   assert(bs->is_a(BarrierSet::G1BarrierSet), "sanity");
-  set_barrier_set(bs);
+  BarrierSet::set_barrier_set(bs);
   _card_table = ct;
 
   // Create the hot card cache.
@@ -1625,7 +1627,7 @@
     vm_shutdown_during_initialization("Could not create/initialize G1ConcurrentMark");
     return JNI_ENOMEM;
   }
-  _cmThread = _cm->cm_thread();
+  _cm_thread = _cm->cm_thread();
 
   // Now expand into the initial heap size.
   if (!expand(init_byte_size, _workers)) {
@@ -1636,10 +1638,10 @@
   // Perform any initialization actions delegated to the policy.
   g1_policy()->init(this, &_collection_set);
 
-  JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
-                                               SATB_Q_FL_lock,
-                                               G1SATBProcessCompletedThreshold,
-                                               Shared_SATB_Q_lock);
+  G1BarrierSet::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
+                                                 SATB_Q_FL_lock,
+                                                 G1SATBProcessCompletedThreshold,
+                                                 Shared_SATB_Q_lock);
 
   jint ecode = initialize_concurrent_refinement();
   if (ecode != JNI_OK) {
@@ -1651,20 +1653,20 @@
     return ecode;
   }
 
-  JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
-                                                DirtyCardQ_FL_lock,
-                                                (int)concurrent_refine()->yellow_zone(),
-                                                (int)concurrent_refine()->red_zone(),
-                                                Shared_DirtyCardQ_lock,
-                                                NULL,  // fl_owner
-                                                true); // init_free_ids
+  G1BarrierSet::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
+                                                  DirtyCardQ_FL_lock,
+                                                  (int)concurrent_refine()->yellow_zone(),
+                                                  (int)concurrent_refine()->red_zone(),
+                                                  Shared_DirtyCardQ_lock,
+                                                  NULL,  // fl_owner
+                                                  true); // init_free_ids
 
   dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
                                     DirtyCardQ_FL_lock,
                                     -1, // never trigger processing
                                     -1, // no limit on length
                                     Shared_DirtyCardQ_lock,
-                                    &JavaThread::dirty_card_queue_set());
+                                    &G1BarrierSet::dirty_card_queue_set());
 
   // Here we allocate the dummy HeapRegion that is required by the
   // G1AllocRegion class.
@@ -1714,7 +1716,7 @@
   // that are destroyed during shutdown.
   _cr->stop();
   _young_gen_sampling_thread->stop();
-  _cmThread->stop();
+  _cm_thread->stop();
   if (G1StringDedup::is_enabled()) {
     G1StringDedup::stop();
   }
@@ -1833,7 +1835,7 @@
 }
 
 void G1CollectedHeap::iterate_dirty_card_closure(CardTableEntryClosure* cl, uint worker_i) {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
   size_t n_completed_buffers = 0;
   while (dcqs.apply_closure_during_gc(cl, worker_i)) {
     n_completed_buffers++;
@@ -1967,7 +1969,7 @@
   // is set) so that if a waiter requests another System.gc() it doesn't
   // incorrectly see that a marking cycle is still in progress.
   if (concurrent) {
-    _cmThread->set_idle();
+    _cm_thread->set_idle();
   }
 
   // This notify_all() will ensure that a thread that called
@@ -2178,11 +2180,11 @@
 }
 
 const char* const* G1CollectedHeap::concurrent_phases() const {
-  return _cmThread->concurrent_phases();
+  return _cm_thread->concurrent_phases();
 }
 
 bool G1CollectedHeap::request_concurrent_phase(const char* phase) {
-  return _cmThread->request_concurrent_phase(phase);
+  return _cm_thread->request_concurrent_phase(phase);
 }
 
 class PrintRegionClosure: public HeapRegionClosure {
@@ -2272,7 +2274,7 @@
 
 void G1CollectedHeap::print_gc_threads_on(outputStream* st) const {
   workers()->print_worker_threads_on(st);
-  _cmThread->print_on(st);
+  _cm_thread->print_on(st);
   st->cr();
   _cm->print_worker_threads_on(st);
   _cr->print_threads_on(st);
@@ -2284,7 +2286,7 @@
 
 void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const {
   workers()->threads_do(tc);
-  tc->do_thread(_cmThread);
+  tc->do_thread(_cm_thread);
   _cm->threads_do(tc);
   _cr->threads_do(tc);
   tc->do_thread(_young_gen_sampling_thread);
@@ -2455,8 +2457,8 @@
 
 void G1CollectedHeap::do_concurrent_mark() {
   MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
-  if (!_cmThread->in_progress()) {
-    _cmThread->set_started();
+  if (!_cm_thread->in_progress()) {
+    _cm_thread->set_started();
     CGC_lock->notify();
   }
 }
@@ -2464,10 +2466,10 @@
 size_t G1CollectedHeap::pending_card_num() {
   size_t extra_cards = 0;
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *curr = jtiwh.next(); ) {
-    DirtyCardQueue& dcq = curr->dirty_card_queue();
+    DirtyCardQueue& dcq = G1ThreadLocalData::dirty_card_queue(curr);
     extra_cards += dcq.size();
   }
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
   size_t buffer_size = dcqs.buffer_size();
   size_t buffer_num = dcqs.completed_buffers_num();
 
@@ -2551,7 +2553,7 @@
   RegisterHumongousWithInCSetFastTestClosure()
   : _total_humongous(0),
     _candidate_humongous(0),
-    _dcq(&JavaThread::dirty_card_queue_set()) {
+    _dcq(&G1BarrierSet::dirty_card_queue_set()) {
   }
 
   virtual bool do_heap_region(HeapRegion* r) {
@@ -2752,7 +2754,7 @@
   _verifier->verify_dirty_young_regions();
 
   // We should not be doing initial mark unless the conc mark thread is running
-  if (!_cmThread->should_terminate()) {
+  if (!_cm_thread->should_terminate()) {
     // This call will decide whether this pause is an initial-mark
     // pause. If it is, in_initial_mark_gc() will return true
     // for the duration of this pause.
@@ -2840,11 +2842,7 @@
       // reference processing currently works in G1.
 
       // Enable discovery in the STW reference processor
-      if (g1_policy()->should_process_references()) {
-        ref_processor_stw()->enable_discovery();
-      } else {
-        ref_processor_stw()->disable_discovery();
-      }
+      ref_processor_stw()->enable_discovery();
 
       {
         // We want to temporarily turn off discovery by the
@@ -3627,7 +3625,7 @@
   dirty_card_queue_set().reset_for_par_iteration();
   workers()->run_task(&redirty_task);
 
-  DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcq = G1BarrierSet::dirty_card_queue_set();
   dcq.merge_bufferlists(&dirty_card_queue_set());
   assert(dirty_card_queue_set().completed_buffers_num() == 0, "All should be consumed");
 
@@ -4193,12 +4191,8 @@
   // as we may have to copy some 'reachable' referent
   // objects (and their reachable sub-graphs) that were
   // not copied during the pause.
-  if (g1_policy()->should_process_references()) {
-    preserve_cm_referents(per_thread_states);
-    process_discovered_references(per_thread_states);
-  } else {
-    ref_processor_stw()->verify_no_references_recorded();
-  }
+  preserve_cm_referents(per_thread_states);
+  process_discovered_references(per_thread_states);
 
   G1STWIsAliveClosure is_alive(this);
   G1KeepAliveClosure keep_alive(this);
@@ -4241,11 +4235,7 @@
   // will log these updates (and dirty their associated
   // cards). We need these updates logged to update any
   // RSets.
-  if (g1_policy()->should_process_references()) {
-    enqueue_discovered_references(per_thread_states);
-  } else {
-    g1_policy()->phase_times()->record_ref_enq_time(0);
-  }
+  enqueue_discovered_references(per_thread_states);
 
   _allocator->release_gc_alloc_regions(evacuation_info);
 
@@ -4691,7 +4681,13 @@
                              obj->is_typeArray()
                             );
 
-    g1h->concurrent_mark()->humongous_object_eagerly_reclaimed(r);
+    G1ConcurrentMark* const cm = g1h->concurrent_mark();
+    cm->humongous_object_eagerly_reclaimed(r);
+    assert(!cm->is_marked_in_prev_bitmap(obj) && !cm->is_marked_in_next_bitmap(obj),
+           "Eagerly reclaimed humongous region %u should not be marked at all but is in prev %s next %s",
+           region_idx,
+           BOOL_TO_STR(cm->is_marked_in_prev_bitmap(obj)),
+           BOOL_TO_STR(cm->is_marked_in_next_bitmap(obj)));
     _humongous_objects_reclaimed++;
     do {
       HeapRegion* next = g1h->next_region_in_humongous(r);
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -766,7 +766,7 @@
 
   // The concurrent marker (and the thread it runs in.)
   G1ConcurrentMark* _cm;
-  G1ConcurrentMarkThread* _cmThread;
+  G1ConcurrentMarkThread* _cm_thread;
 
   // The concurrent refiner.
   G1ConcurrentRefine* _cr;
@@ -1253,7 +1253,7 @@
   // bitmap off to the side.
   void do_concurrent_mark();
 
-  bool isMarkedNext(oop obj) const;
+  bool is_marked_next(oop obj) const;
 
   // Determine if an object is dead, given the object and also
   // the region to which the object belongs. An object is dead
@@ -1271,7 +1271,7 @@
   bool is_obj_ill(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_next_marking(obj) &&
-      !isMarkedNext(obj) &&
+      !is_marked_next(obj) &&
       !hr->is_archive();
   }
 
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -120,7 +120,7 @@
   return _task_queues->queue(i);
 }
 
-inline bool G1CollectedHeap::isMarkedNext(oop obj) const {
+inline bool G1CollectedHeap::is_marked_next(oop obj) const {
   return _cm->next_mark_bitmap()->is_marked((HeapWord*)obj);
 }
 
@@ -242,7 +242,7 @@
 }
 
 inline bool G1CollectedHeap::is_obj_dead_full(const oop obj, const HeapRegion* hr) const {
-   return !isMarkedNext(obj) && !hr->is_archive();
+   return !is_marked_next(obj) && !hr->is_archive();
 }
 
 inline bool G1CollectedHeap::is_obj_dead_full(const oop obj) const {
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,7 @@
 #include "classfile/metadataOnStackMark.hpp"
 #include "classfile/symbolTable.hpp"
 #include "code/codeCache.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorState.hpp"
 #include "gc/g1/g1ConcurrentMark.inline.hpp"
@@ -35,6 +36,7 @@
 #include "gc/g1/g1Policy.hpp"
 #include "gc/g1/g1RegionMarkStatsCache.inline.hpp"
 #include "gc/g1/g1StringDedup.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/g1/heapRegionRemSet.hpp"
 #include "gc/g1/heapRegionSet.inline.hpp"
@@ -405,7 +407,7 @@
 
   assert(CGC_lock != NULL, "CGC_lock must be initialized");
 
-  SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
+  SATBMarkQueueSet& satb_qs = G1BarrierSet::satb_mark_queue_set();
   satb_qs.set_buffer_size(G1SATBBufferSize);
 
   _root_regions.init(_g1h->survivor(), this);
@@ -530,13 +532,18 @@
   }
 }
 
+static void clear_mark_if_set(G1CMBitMap* bitmap, HeapWord* addr) {
+  if (bitmap->is_marked(addr)) {
+    bitmap->clear(addr);
+  }
+}
+
 void G1ConcurrentMark::humongous_object_eagerly_reclaimed(HeapRegion* r) {
   assert_at_safepoint_on_vm_thread();
 
-  // Need to clear mark bit of the humongous object.
-  if (_next_mark_bitmap->is_marked(r->bottom())) {
-    _next_mark_bitmap->clear(r->bottom());
-  }
+  // Need to clear all mark bits of the humongous object.
+  clear_mark_if_set(_prev_mark_bitmap, r->bottom());
+  clear_mark_if_set(_next_mark_bitmap, r->bottom());
 
   if (!_g1h->collector_state()->mark_or_rebuild_in_progress()) {
     return;
@@ -757,7 +764,7 @@
   rp->enable_discovery();
   rp->setup_policy(false); // snapshot the soft ref policy to be used in this cycle
 
-  SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
+  SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set();
   // This is the start of  the marking cycle, we're expected all
   // threads to have SATB queues with active set to false.
   satb_mq_set.set_active_all_threads(true, /* new active value */
@@ -1068,7 +1075,7 @@
   if (mark_finished) {
     weak_refs_work(false /* clear_all_soft_refs */);
 
-    SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
+    SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set();
     // We're done with marking.
     // This is the end of the marking cycle, we're expected all
     // threads to have SATB queues with active set to true.
@@ -1686,11 +1693,11 @@
         // live by the SATB invariant but other oops recorded in nmethods may behave differently.
         jt->nmethods_do(&_code_cl);
 
-        jt->satb_mark_queue().apply_closure_and_empty(&_cm_satb_cl);
+        G1ThreadLocalData::satb_mark_queue(jt).apply_closure_and_empty(&_cm_satb_cl);
       }
     } else if (thread->is_VM_thread()) {
       if (thread->claim_oops_do(true, _thread_parity)) {
-        JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
+        G1BarrierSet::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_satb_cl);
       }
     }
   }
@@ -1750,7 +1757,7 @@
     _g1h->workers()->run_task(&remarkTask);
   }
 
-  SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
+  SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set();
   guarantee(has_overflown() ||
             satb_mq_set.completed_buffers_num() == 0,
             "Invariant: has_overflown = %s, num buffers = " SIZE_FORMAT,
@@ -1932,7 +1939,7 @@
   _second_overflow_barrier_sync.abort();
   _has_aborted = true;
 
-  SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
+  SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set();
   satb_mq_set.abandon_partial_marking();
   // This can be called either during or outside marking, we'll read
   // the expected_active value from the SATB queue set.
@@ -2142,7 +2149,7 @@
 
   // (6) Finally, we check whether there are enough completed STAB
   // buffers available for processing. If there are, we abort.
-  SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
+  SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set();
   if (!_draining_satb_buffers && satb_mq_set.process_completed_buffers()) {
     // we do need to process SATB buffers, we'll abort and restart
     // the marking task to do so
@@ -2297,7 +2304,7 @@
   _draining_satb_buffers = true;
 
   G1CMSATBBufferClosure satb_cl(this, _g1h);
-  SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
+  SATBMarkQueueSet& satb_mq_set = G1BarrierSet::satb_mark_queue_set();
 
   // This keeps claiming and applying the closure to completed buffers
   // until we run out of buffers or we need to abort.
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -589,6 +589,8 @@
   inline bool mark_in_next_bitmap(uint worker_id, HeapRegion* const hr, oop const obj, size_t const obj_size = 0);
   inline bool mark_in_next_bitmap(uint worker_id, oop const obj, size_t const obj_size = 0);
 
+  inline bool is_marked_in_next_bitmap(oop p) const;
+
   // Returns true if initialization was successfully completed.
   bool completed_initialization() const {
     return _completed_initialization;
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -255,6 +255,11 @@
   return _prev_mark_bitmap->is_marked((HeapWord*)p);
 }
 
+bool G1ConcurrentMark::is_marked_in_next_bitmap(oop p) const {
+  assert(p != NULL && oopDesc::is_oop(p), "expected an oop");
+  return _next_mark_bitmap->is_marked((HeapWord*)p);
+}
+
 inline bool G1ConcurrentMark::do_yield_check() {
   if (SuspendibleThreadSet::should_yield()) {
     SuspendibleThreadSet::yield();
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefine.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/g1ConcurrentRefineThread.hpp"
 #include "logging/log.hpp"
@@ -377,7 +378,7 @@
 void G1ConcurrentRefine::adjust(double update_rs_time,
                                 size_t update_rs_processed_buffers,
                                 double goal_ms) {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 
   if (G1UseAdaptiveConcRefinement) {
     update_zones(update_rs_time, update_rs_processed_buffers, goal_ms);
@@ -425,7 +426,7 @@
 }
 
 bool G1ConcurrentRefine::do_refinement_step(uint worker_id) {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
 
   size_t curr_buffer_num = dcqs.completed_buffers_num();
   // If the number of the buffers falls down into the yellow zone,
--- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1ConcurrentRefine.hpp"
 #include "gc/g1/g1ConcurrentRefineThread.hpp"
 #include "gc/shared/suspendibleThreadSet.hpp"
@@ -63,7 +64,7 @@
 }
 
 bool G1ConcurrentRefineThread::is_active() {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
   return is_primary() ? dcqs.process_completed_buffers() : _active;
 }
 
@@ -72,7 +73,7 @@
   if (!is_primary()) {
     set_active(true);
   } else {
-    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+    DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
     dcqs.set_process_completed(true);
   }
   _monitor->notify();
@@ -83,7 +84,7 @@
   if (!is_primary()) {
     set_active(false);
   } else {
-    DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+    DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
     dcqs.set_process_completed(false);
   }
 }
@@ -101,7 +102,7 @@
     size_t buffers_processed = 0;
     log_debug(gc, refine)("Activated worker %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
                           _worker_id, _cr->activation_threshold(_worker_id),
-                           JavaThread::dirty_card_queue_set().completed_buffers_num());
+                           G1BarrierSet::dirty_card_queue_set().completed_buffers_num());
 
     {
       SuspendibleThreadSetJoiner sts_join;
@@ -123,7 +124,7 @@
     log_debug(gc, refine)("Deactivated worker %d, off threshold: " SIZE_FORMAT
                           ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT,
                           _worker_id, _cr->deactivation_threshold(_worker_id),
-                          JavaThread::dirty_card_queue_set().completed_buffers_num(),
+                          G1BarrierSet::dirty_card_queue_set().completed_buffers_num(),
                           buffers_processed);
 
     if (os::supports_vtime()) {
--- a/src/hotspot/share/gc/g1/g1EvacFailure.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1EvacFailure.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -36,6 +36,7 @@
 #include "gc/shared/preservedMarks.inline.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "oops/oop.inline.hpp"
 
 class UpdateRSetDeferred : public ExtendedOopClosure {
 private:
--- a/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactTask.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 #include "gc/g1/heapRegion.inline.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"
 #include "logging/log.hpp"
+#include "oops/oop.inline.hpp"
 #include "utilities/ticks.inline.hpp"
 
 class G1ResetHumongousClosure : public HeapRegionClosure {
@@ -47,7 +48,7 @@
         if (_bitmap->is_marked(obj)) {
           // Clear bitmap and fix mark word.
           _bitmap->clear(obj);
-          obj->init_mark();
+          obj->init_mark_raw();
         } else {
           assert(current->is_empty(), "Should have been cleared in phase 2.");
         }
@@ -70,7 +71,7 @@
   HeapWord* obj_addr = (HeapWord*) obj;
   assert(obj_addr != destination, "everything in this pass should be moving");
   Copy::aligned_conjoint_words(obj_addr, destination, size);
-  oop(destination)->init_mark();
+  oop(destination)->init_mark_raw();
   assert(oop(destination)->klass() != NULL, "should have a class");
 
   return size;
--- a/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FullGCCompactionPoint.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -112,15 +112,15 @@
       // with BiasedLocking, in this case forwardee() will return NULL
       // even if the mark-word is used. This is no problem since
       // forwardee() will return NULL in the compaction phase as well.
-      object->init_mark();
+      object->init_mark_raw();
     } else {
       // Make sure object has the correct mark-word set or that it will be
       // fixed when restoring the preserved marks.
-      assert(object->mark() == markOopDesc::prototype_for_object(object) || // Correct mark
-             object->mark()->must_be_preserved(object) || // Will be restored by PreservedMarksSet
-             (UseBiasedLocking && object->has_bias_pattern()), // Will be restored by BiasedLocking
+      assert(object->mark_raw() == markOopDesc::prototype_for_object(object) || // Correct mark
+             object->mark_raw()->must_be_preserved(object) || // Will be restored by PreservedMarksSet
+             (UseBiasedLocking && object->has_bias_pattern_raw()), // Will be restored by BiasedLocking
              "should have correct prototype obj: " PTR_FORMAT " mark: " PTR_FORMAT " prototype: " PTR_FORMAT,
-             p2i(object), p2i(object->mark()), p2i(markOopDesc::prototype_for_object(object)));
+             p2i(object), p2i(object->mark_raw()), p2i(markOopDesc::prototype_for_object(object)));
     }
     assert(object->forwardee() == NULL, "should be forwarded to NULL");
   }
--- a/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FullGCMarker.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 #include "gc/shared/preservedMarks.inline.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "oops/oop.inline.hpp"
 #include "utilities/debug.hpp"
 
 inline bool G1FullGCMarker::mark_object(oop obj) {
@@ -48,7 +49,7 @@
   }
 
   // Marked by us, preserve if needed.
-  markOop mark = obj->mark();
+  markOop mark = obj->mark_raw();
   if (mark->must_be_preserved(obj) &&
       !G1ArchiveAllocator::is_open_archive_object(obj)) {
     preserved_stack()->push(obj, mark);
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,6 +30,7 @@
 #include "logging/logStream.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "oops/oop.inline.hpp"
 
 void G1MarkAndPushClosure::do_oop(oop* p) {
   do_oop_nv(p);
--- a/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FullGCOopClosures.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -33,6 +33,7 @@
 #include "memory/iterator.inline.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "oops/oop.inline.hpp"
 
 template <typename T>
 inline void G1MarkAndPushClosure::do_oop_nv(T* p) {
@@ -67,11 +68,11 @@
   oop forwardee = obj->forwardee();
   if (forwardee == NULL) {
     // Not forwarded, return current reference.
-    assert(obj->mark() == markOopDesc::prototype_for_object(obj) || // Correct mark
-           obj->mark()->must_be_preserved(obj) || // Will be restored by PreservedMarksSet
-           (UseBiasedLocking && obj->has_bias_pattern()), // Will be restored by BiasedLocking
+    assert(obj->mark_raw() == markOopDesc::prototype_for_object(obj) || // Correct mark
+           obj->mark_raw()->must_be_preserved(obj) || // Will be restored by PreservedMarksSet
+           (UseBiasedLocking && obj->has_bias_pattern_raw()), // Will be restored by BiasedLocking
            "Must have correct prototype or be preserved, obj: " PTR_FORMAT ", mark: " PTR_FORMAT ", prototype: " PTR_FORMAT,
-           p2i(obj), p2i(obj->mark()), p2i(markOopDesc::prototype_for_object(obj)));
+           p2i(obj), p2i(obj->mark_raw()), p2i(markOopDesc::prototype_for_object(obj)));
     return;
   }
 
--- a/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1FullGCPrepareTask.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -35,6 +35,7 @@
 #include "gc/shared/gcTraceTime.inline.hpp"
 #include "gc/shared/referenceProcessor.hpp"
 #include "logging/log.hpp"
+#include "oops/oop.inline.hpp"
 #include "utilities/ticks.inline.hpp"
 
 bool G1FullGCPrepareTask::G1CalculatePointersClosure::do_heap_region(HeapRegion* hr) {
--- a/src/hotspot/share/gc/g1/g1HeapVerifier.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1HeapVerifier.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,6 +28,7 @@
 #include "gc/g1/heapRegionSet.hpp"
 #include "memory/allocation.hpp"
 #include "memory/universe.hpp"
+#include "utilities/macros.hpp"
 
 class G1CollectedHeap;
 
@@ -37,9 +38,6 @@
 
   G1CollectedHeap* _g1h;
 
-  // verify_region_sets() performs verification over the region
-  // lists. It will be compiled in the product code to be used when
-  // necessary (i.e., during heap verification).
   void verify_region_sets();
 
 public:
@@ -76,15 +74,8 @@
   void verify(VerifyOption vo);
 
   // verify_region_sets_optional() is planted in the code for
-  // list verification in non-product builds (and it can be enabled in
-  // product builds by defining HEAP_REGION_SET_FORCE_VERIFY to be 1).
-#if HEAP_REGION_SET_FORCE_VERIFY
-  void verify_region_sets_optional() {
-    verify_region_sets();
-  }
-#else // HEAP_REGION_SET_FORCE_VERIFY
-  void verify_region_sets_optional() { }
-#endif // HEAP_REGION_SET_FORCE_VERIFY
+  // list verification in debug builds.
+  void verify_region_sets_optional() { DEBUG_ONLY(verify_region_sets();) }
 
   void prepare_for_verify();
   double verify(G1VerifyType type, VerifyOption vo, const char* msg);
--- a/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1OopClosures.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -36,6 +36,7 @@
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oopsHierarchy.hpp"
+#include "oops/oop.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
 
 template <class T>
@@ -45,8 +46,8 @@
   // stall. We'll try to prefetch the object (for write, given that
   // we might need to install the forwarding reference) and we'll
   // get back to it when pop it from the queue
-  Prefetch::write(obj->mark_addr(), 0);
-  Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
+  Prefetch::write(obj->mark_addr_raw(), 0);
+  Prefetch::read(obj->mark_addr_raw(), (HeapWordSize*2));
 
   // slightly paranoid test; I'm trying to catch potential
   // problems before we go into push_on_queue to know where the
@@ -240,14 +241,14 @@
   const InCSetState state = _g1->in_cset_state(obj);
   if (state.is_in_cset()) {
     oop forwardee;
-    markOop m = obj->mark();
+    markOop m = obj->mark_raw();
     if (m->is_marked()) {
       forwardee = (oop) m->decode_pointer();
     } else {
       forwardee = _par_scan_state->copy_to_survivor_space(state, obj, m);
     }
     assert(forwardee != NULL, "forwardee should not be NULL");
-    RawAccess<>::oop_store(p, forwardee);
+    RawAccess<OOP_NOT_NULL>::oop_store(p, forwardee);
     if (do_mark_object != G1MarkNone && forwardee != obj) {
       // If the object is self-forwarded we don't need to explicitly
       // mark it, the evacuation failure protocol will do so.
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -66,7 +66,7 @@
   _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
   memset(_surviving_young_words, 0, real_length * sizeof(size_t));
 
-  _plab_allocator = new G1DefaultPLABAllocator(_g1h->allocator());
+  _plab_allocator = new G1PLABAllocator(_g1h->allocator());
 
   _dest[InCSetState::NotInCSet]    = InCSetState::NotInCSet;
   // The dest for Young is used when the objects are aged enough to
@@ -282,15 +282,15 @@
         // In this case, we have to install the mark word first,
         // otherwise obj looks to be forwarded (the old mark word,
         // which contains the forward pointer, was copied)
-        obj->set_mark(old_mark);
+        obj->set_mark_raw(old_mark);
         markOop new_mark = old_mark->displaced_mark_helper()->set_age(age);
         old_mark->set_displaced_mark_helper(new_mark);
       } else {
-        obj->set_mark(old_mark->set_age(age));
+        obj->set_mark_raw(old_mark->set_age(age));
       }
       _age_table.add(age, word_sz);
     } else {
-      obj->set_mark(old_mark);
+      obj->set_mark_raw(old_mark);
     }
 
     if (G1StringDedup::is_enabled()) {
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -161,9 +161,10 @@
   inline void do_oop_partial_array(oop* p);
 
   // This method is applied to the fields of the objects that have just been copied.
-  template <class T> inline void do_oop_evac(T* p, HeapRegion* from);
+  template <class T> inline void do_oop_evac(T* p);
 
-  template <class T> inline void deal_with_reference(T* ref_to_scan);
+  inline void deal_with_reference(oop* ref_to_scan);
+  inline void deal_with_reference(narrowOop* ref_to_scan);
 
   inline void dispatch_reference(StarTask ref);
 
--- a/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ParScanThreadState.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,32 +30,34 @@
 #include "oops/access.inline.hpp"
 #include "oops/oop.inline.hpp"
 
-template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from) {
+template <class T> void G1ParScanThreadState::do_oop_evac(T* p) {
   // Reference should not be NULL here as such are never pushed to the task queue.
   oop obj = RawAccess<OOP_NOT_NULL>::oop_load(p);
 
   // Although we never intentionally push references outside of the collection
   // set, due to (benign) races in the claim mechanism during RSet scanning more
   // than one thread might claim the same card. So the same card may be
-  // processed multiple times. So redo this check.
+  // processed multiple times, and so we might get references into old gen here.
+  // So we need to redo this check.
   const InCSetState in_cset_state = _g1h->in_cset_state(obj);
   if (in_cset_state.is_in_cset()) {
-    markOop m = obj->mark();
+    markOop m = obj->mark_raw();
     if (m->is_marked()) {
       obj = (oop) m->decode_pointer();
     } else {
       obj = copy_to_survivor_space(in_cset_state, obj, m);
     }
-    RawAccess<>::oop_store(p, obj);
+    RawAccess<OOP_NOT_NULL>::oop_store(p, obj);
   } else if (in_cset_state.is_humongous()) {
     _g1h->set_humongous_is_live(obj);
   } else {
     assert(in_cset_state.is_default(),
-         "In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value());
+           "In_cset_state must be NotInCSet here, but is " CSETSTATE_FORMAT, in_cset_state.value());
   }
 
   assert(obj != NULL, "Must be");
   if (!HeapRegion::is_in_same_region(p, obj)) {
+    HeapRegion* from = _g1h->heap_region_containing(p);
     update_rs(from, p, obj);
   }
 }
@@ -114,15 +116,19 @@
   to_obj_array->oop_iterate_range(&_scanner, start, end);
 }
 
-template <class T> inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) {
+inline void G1ParScanThreadState::deal_with_reference(oop* ref_to_scan) {
   if (!has_partial_array_mask(ref_to_scan)) {
-    HeapRegion* r = _g1h->heap_region_containing(ref_to_scan);
-    do_oop_evac(ref_to_scan, r);
+    do_oop_evac(ref_to_scan);
   } else {
-    do_oop_partial_array((oop*)ref_to_scan);
+    do_oop_partial_array(ref_to_scan);
   }
 }
 
+inline void G1ParScanThreadState::deal_with_reference(narrowOop* ref_to_scan) {
+  assert(!has_partial_array_mask(ref_to_scan), "NarrowOop* elements should never be partial arrays.");
+  do_oop_evac(ref_to_scan);
+}
+
 inline void G1ParScanThreadState::dispatch_reference(StarTask ref) {
   assert(verify_task(ref), "sanity");
   if (ref.is_narrow()) {
--- a/src/hotspot/share/gc/g1/g1Policy.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1Policy.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -383,10 +383,6 @@
 
   bool adaptive_young_list_length() const;
 
-  bool should_process_references() const {
-    return true;
-  }
-
   void transfer_survivors_to_cset(const G1SurvivorRegions* survivors);
 
 private:
--- a/src/hotspot/share/gc/g1/g1RemSet.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSet.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc/g1/dirtyCardQueue.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1BlockOffsetTable.inline.hpp"
 #include "gc/g1/g1CardTable.inline.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
@@ -488,7 +489,7 @@
 }
 
 void G1RemSet::prepare_for_oops_into_collection_set_do() {
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
   dcqs.concatenate_logs();
 
   _scan_state->reset();
@@ -641,7 +642,7 @@
       MutexLockerEx x(Shared_DirtyCardQ_lock,
                       Mutex::_no_safepoint_check_flag);
       DirtyCardQueue* sdcq =
-        JavaThread::dirty_card_queue_set().shared_dirty_card_queue();
+        G1BarrierSet::dirty_card_queue_set().shared_dirty_card_queue();
       sdcq->enqueue(card_ptr);
     }
   } else {
--- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -53,7 +53,7 @@
 
 void G1RemSetSummary::update() {
   _num_conc_refined_cards = _rem_set->num_conc_refined_cards();
-  DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
+  DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set();
   _num_processed_buf_mutator = dcqs.processed_buffers_mut();
   _num_processed_buf_rs_threads = dcqs.processed_buffers_rs_thread();
 
--- a/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1RootProcessor.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,6 +29,7 @@
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/g1/bufferingOopClosure.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CodeBlobClosure.hpp"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
 #include "gc/g1/g1CollectorState.hpp"
@@ -134,7 +135,7 @@
   {
     G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::SATBFiltering, worker_i);
     if (!_process_strong_tasks.is_task_claimed(G1RP_PS_filter_satb_buffers) && _g1h->collector_state()->mark_or_rebuild_in_progress()) {
-      JavaThread::satb_mark_queue_set().filter_thread_buffers();
+      G1BarrierSet::satb_mark_queue_set().filter_thread_buffers();
     }
   }
 
--- a/src/hotspot/share/gc/g1/g1StringDedup.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1StringDedup.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@
 #include "gc/g1/g1StringDedupStat.hpp"
 #include "gc/g1/g1StringDedupTable.hpp"
 #include "gc/g1/g1StringDedupThread.hpp"
+#include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 
 bool G1StringDedup::_enabled = false;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_G1_G1THREADLOCALDATA_HPP
+#define SHARE_GC_G1_G1THREADLOCALDATA_HPP
+
+#include "gc/g1/dirtyCardQueue.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/satbMarkQueue.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/sizes.hpp"
+
+class G1ThreadLocalData {
+private:
+  SATBMarkQueue  _satb_mark_queue;
+  DirtyCardQueue _dirty_card_queue;
+
+  G1ThreadLocalData() :
+      _satb_mark_queue(&G1BarrierSet::satb_mark_queue_set()),
+      _dirty_card_queue(&G1BarrierSet::dirty_card_queue_set()) {}
+
+  static G1ThreadLocalData* data(Thread* thread) {
+    assert(UseG1GC, "Sanity");
+    return thread->gc_data<G1ThreadLocalData>();
+  }
+
+  static ByteSize satb_mark_queue_offset() {
+    return Thread::gc_data_offset() + byte_offset_of(G1ThreadLocalData, _satb_mark_queue);
+  }
+
+  static ByteSize dirty_card_queue_offset() {
+    return Thread::gc_data_offset() + byte_offset_of(G1ThreadLocalData, _dirty_card_queue);
+  }
+
+public:
+  static void create(Thread* thread) {
+    new (data(thread)) G1ThreadLocalData();
+  }
+
+  static void destroy(Thread* thread) {
+    data(thread)->~G1ThreadLocalData();
+  }
+
+  static SATBMarkQueue& satb_mark_queue(Thread* thread) {
+    return data(thread)->_satb_mark_queue;
+  }
+
+  static DirtyCardQueue& dirty_card_queue(Thread* thread) {
+    return data(thread)->_dirty_card_queue;
+  }
+
+  static ByteSize satb_mark_queue_active_offset() {
+    return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active();
+  }
+
+  static ByteSize satb_mark_queue_index_offset() {
+    return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index();
+  }
+
+  static ByteSize satb_mark_queue_buffer_offset() {
+    return satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf();
+  }
+
+  static ByteSize dirty_card_queue_index_offset() {
+    return dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index();
+  }
+
+  static ByteSize dirty_card_queue_buffer_offset() {
+    return dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_buf();
+  }
+};
+
+#endif // SHARE_GC_G1_G1THREADLOCALDATA_HPP
--- a/src/hotspot/share/gc/g1/g1_globals.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 2001, 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 "gc/g1/g1_globals.hpp"
-
-G1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
-         MATERIALIZE_PD_DEVELOPER_FLAG, \
-         MATERIALIZE_PRODUCT_FLAG, \
-         MATERIALIZE_PD_PRODUCT_FLAG,     \
-         MATERIALIZE_DIAGNOSTIC_FLAG, \
-         MATERIALIZE_PD_DIAGNOSTIC_FLAG, \
-         MATERIALIZE_EXPERIMENTAL_FLAG, \
-         MATERIALIZE_NOTPRODUCT_FLAG,  \
-         MATERIALIZE_MANAGEABLE_FLAG, \
-         MATERIALIZE_PRODUCT_RW_FLAG, \
-         IGNORE_RANGE, \
-         IGNORE_CONSTRAINT, \
-         IGNORE_WRITEABLE)
--- a/src/hotspot/share/gc/g1/g1_globals.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1_globals.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,25 +25,25 @@
 #ifndef SHARE_VM_GC_G1_G1_GLOBALS_HPP
 #define SHARE_VM_GC_G1_G1_GLOBALS_HPP
 
-#include "runtime/globals.hpp"
 #include <float.h> // for DBL_MAX
 //
 // Defines all globals flags used by the garbage-first compiler.
 //
 
-#define G1_FLAGS(develop, \
-                 develop_pd, \
-                 product, \
-                 product_pd, \
-                 diagnostic, \
-                 diagnostic_pd, \
-                 experimental, \
-                 notproduct, \
-                 manageable, \
-                 product_rw, \
-                 range, \
-                 constraint, \
-                 writeable) \
+#define GC_G1_FLAGS(develop,                                                \
+                    develop_pd,                                             \
+                    product,                                                \
+                    product_pd,                                             \
+                    diagnostic,                                             \
+                    diagnostic_pd,                                          \
+                    experimental,                                           \
+                    notproduct,                                             \
+                    manageable,                                             \
+                    product_rw,                                             \
+                    lp64_product,                                           \
+                    range,                                                  \
+                    constraint,                                             \
+                    writeable)                                              \
                                                                             \
   product(bool, G1UseAdaptiveIHOP, true,                                    \
           "Adaptively adjust the initiating heap occupancy from the "       \
@@ -303,18 +303,4 @@
   develop(bool, G1VerifyBitmaps, false,                                     \
           "Verifies the consistency of the marking bitmaps")
 
-G1_FLAGS(DECLARE_DEVELOPER_FLAG, \
-         DECLARE_PD_DEVELOPER_FLAG, \
-         DECLARE_PRODUCT_FLAG, \
-         DECLARE_PD_PRODUCT_FLAG, \
-         DECLARE_DIAGNOSTIC_FLAG, \
-         DECLARE_PD_DIAGNOSTIC_FLAG, \
-         DECLARE_EXPERIMENTAL_FLAG, \
-         DECLARE_NOTPRODUCT_FLAG, \
-         DECLARE_MANAGEABLE_FLAG, \
-         DECLARE_PRODUCT_RW_FLAG, \
-         IGNORE_RANGE, \
-         IGNORE_CONSTRAINT, \
-         IGNORE_WRITEABLE)
-
 #endif // SHARE_VM_GC_G1_G1_GLOBALS_HPP
--- a/src/hotspot/share/gc/g1/heapRegionSet.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/heapRegionSet.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_G1_HEAPREGIONSET_HPP
 
 #include "gc/g1/heapRegion.hpp"
+#include "utilities/macros.hpp"
 
 #define assert_heap_region_set(p, message) \
   do {                                     \
@@ -46,13 +47,6 @@
   } while (0)
 
 
-// Set verification will be forced either if someone defines
-// HEAP_REGION_SET_FORCE_VERIFY to be 1, or in builds in which
-// asserts are compiled in.
-#ifndef HEAP_REGION_SET_FORCE_VERIFY
-#define HEAP_REGION_SET_FORCE_VERIFY defined(ASSERT)
-#endif // HEAP_REGION_SET_FORCE_VERIFY
-
 class HRSMtSafeChecker : public CHeapObj<mtGC> {
 public:
   virtual void check() = 0;
@@ -122,13 +116,7 @@
   void verify_next_region(HeapRegion* hr);
   void verify_end();
 
-#if HEAP_REGION_SET_FORCE_VERIFY
-  void verify_optional() {
-    verify();
-  }
-#else // HEAP_REGION_SET_FORCE_VERIFY
-  void verify_optional() { }
-#endif // HEAP_REGION_SET_FORCE_VERIFY
+  void verify_optional() { DEBUG_ONLY(verify();) }
 
   virtual void print_on(outputStream* out, bool print_contents = false);
 };
--- a/src/hotspot/share/gc/g1/satbMarkQueue.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/satbMarkQueue.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "jvm.h"
 #include "gc/g1/g1CollectedHeap.inline.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #include "gc/g1/satbMarkQueue.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "memory/allocation.inline.hpp"
@@ -103,7 +104,7 @@
 }
 
 inline bool retain_entry(const void* entry, G1CollectedHeap* heap) {
-  return requires_marking(entry, heap) && !heap->isMarkedNext((oop)entry);
+  return requires_marking(entry, heap) && !heap->is_marked_next((oop)entry);
 }
 
 // This method removes entries from a SATB buffer that will not be
@@ -207,7 +208,7 @@
 }
 
 void SATBMarkQueueSet::handle_zero_index_for_thread(JavaThread* t) {
-  t->satb_mark_queue().handle_zero_index();
+  G1ThreadLocalData::satb_mark_queue(t).handle_zero_index();
 }
 
 #ifdef ASSERT
@@ -216,7 +217,7 @@
   log_error(gc, verify)("Actual SATB active states:");
   log_error(gc, verify)("  Queue set: %s", is_active() ? "ACTIVE" : "INACTIVE");
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    log_error(gc, verify)("  Thread \"%s\" queue: %s", t->name(), t->satb_mark_queue().is_active() ? "ACTIVE" : "INACTIVE");
+    log_error(gc, verify)("  Thread \"%s\" queue: %s", t->name(), G1ThreadLocalData::satb_mark_queue(t).is_active() ? "ACTIVE" : "INACTIVE");
   }
   log_error(gc, verify)("  Shared queue: %s", shared_satb_queue()->is_active() ? "ACTIVE" : "INACTIVE");
 }
@@ -230,7 +231,7 @@
 
   // Verify thread queue states
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    if (t->satb_mark_queue().is_active() != expected_active) {
+    if (G1ThreadLocalData::satb_mark_queue(t).is_active() != expected_active) {
       dump_active_states(expected_active);
       guarantee(false, "Thread SATB queue has an unexpected active state");
     }
@@ -251,14 +252,14 @@
 #endif // ASSERT
   _all_active = active;
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    t->satb_mark_queue().set_active(active);
+    G1ThreadLocalData::satb_mark_queue(t).set_active(active);
   }
   shared_satb_queue()->set_active(active);
 }
 
 void SATBMarkQueueSet::filter_thread_buffers() {
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    t->satb_mark_queue().filter();
+    G1ThreadLocalData::satb_mark_queue(t).filter();
   }
   shared_satb_queue()->filter();
 }
@@ -312,7 +313,7 @@
 
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
     jio_snprintf(buffer, SATB_PRINTER_BUFFER_SIZE, "Thread: %s", t->name());
-    t->satb_mark_queue().print(buffer);
+    G1ThreadLocalData::satb_mark_queue(t).print(buffer);
   }
 
   shared_satb_queue()->print("Shared");
@@ -343,7 +344,7 @@
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   // So we can safely manipulate these queues.
   for (JavaThreadIteratorWithHandle jtiwh; JavaThread *t = jtiwh.next(); ) {
-    t->satb_mark_queue().reset();
+    G1ThreadLocalData::satb_mark_queue(t).reset();
   }
   shared_satb_queue()->reset();
 }
--- a/src/hotspot/share/gc/g1/vmStructs_g1.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,7 +30,9 @@
 #include "gc/g1/heapRegionManager.hpp"
 #include "utilities/macros.hpp"
 
-#define VM_STRUCTS_G1(nonstatic_field, static_field)                          \
+#define VM_STRUCTS_G1GC(nonstatic_field,                                      \
+                        volatile_nonstatic_field,                             \
+                        static_field)                                         \
                                                                               \
   static_field(HeapRegion, GrainBytes,        size_t)                         \
   static_field(HeapRegion, LogOfHRGrainBytes, int)                            \
@@ -67,10 +69,9 @@
                                                                               \
   nonstatic_field(PtrQueue,            _active,         bool)                 \
   nonstatic_field(PtrQueue,            _buf,            void**)               \
-  nonstatic_field(PtrQueue,            _index,          size_t)               \
+  nonstatic_field(PtrQueue,            _index,          size_t)
 
-
-#define VM_INT_CONSTANTS_G1(declare_constant, declare_constant_with_value)    \
+#define VM_INT_CONSTANTS_G1GC(declare_constant, declare_constant_with_value)  \
   declare_constant(HeapRegionType::FreeTag)                                   \
   declare_constant(HeapRegionType::YoungMask)                                 \
   declare_constant(HeapRegionType::EdenTag)                                   \
@@ -80,12 +81,13 @@
   declare_constant(HeapRegionType::ArchiveMask)                               \
   declare_constant(HeapRegionType::StartsHumongousTag)                        \
   declare_constant(HeapRegionType::ContinuesHumongousTag)                     \
-  declare_constant(HeapRegionType::OldMask)
-
+  declare_constant(HeapRegionType::OldMask)                                   \
+  declare_constant(BarrierSet::G1BarrierSet)                                  \
+  declare_constant(G1CardTable::g1_young_gen)
 
-#define VM_TYPES_G1(declare_type,                                             \
-                    declare_toplevel_type,                                    \
-                    declare_integer_type)                                     \
+#define VM_TYPES_G1GC(declare_type,                                           \
+                      declare_toplevel_type,                                  \
+                      declare_integer_type)                                   \
                                                                               \
   declare_toplevel_type(G1HeapRegionTable)                                    \
                                                                               \
@@ -98,6 +100,8 @@
   declare_toplevel_type(G1MonitoringSupport)                                  \
   declare_toplevel_type(PtrQueue)                                             \
   declare_toplevel_type(HeapRegionType)                                       \
+  declare_toplevel_type(SATBMarkQueue)                                        \
+  declare_toplevel_type(DirtyCardQueue)                                       \
                                                                               \
   declare_toplevel_type(G1CollectedHeap*)                                     \
   declare_toplevel_type(HeapRegion*)                                          \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/parallel/commandLineFlagConstraintsParallel.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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/commandLineFlagRangeList.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+Flag::Error ParallelGCThreadsConstraintFuncParallel(uint value, bool verbose) {
+  // Parallel GC passes ParallelGCThreads when creating GrowableArray as 'int' type parameter.
+  // So can't exceed with "max_jint"
+
+  if (UseParallelGC && (value > (uint)max_jint)) {
+    CommandLineError::print(verbose,
+                            "ParallelGCThreads (" UINT32_FORMAT ") must be "
+                            "less than or equal to " UINT32_FORMAT " for Parallel GC\n",
+                            value, max_jint);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error InitialTenuringThresholdConstraintFuncParallel(uintx value, bool verbose) {
+  // InitialTenuringThreshold is only used for ParallelGC.
+  if (UseParallelGC && (value > MaxTenuringThreshold)) {
+      CommandLineError::print(verbose,
+                              "InitialTenuringThreshold (" UINTX_FORMAT ") must be "
+                              "less than or equal to MaxTenuringThreshold (" UINTX_FORMAT ")\n",
+                              value, MaxTenuringThreshold);
+      return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error MaxTenuringThresholdConstraintFuncParallel(uintx value, bool verbose) {
+  // As only ParallelGC uses InitialTenuringThreshold,
+  // we don't need to compare InitialTenuringThreshold with MaxTenuringThreshold.
+  if (UseParallelGC && (value < InitialTenuringThreshold)) {
+    CommandLineError::print(verbose,
+                            "MaxTenuringThreshold (" UINTX_FORMAT ") must be "
+                            "greater than or equal to InitialTenuringThreshold (" UINTX_FORMAT ")\n",
+                            value, InitialTenuringThreshold);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+
+  return Flag::SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/parallel/commandLineFlagConstraintsParallel.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_PARALLEL_COMMANDLINEFLAGCONSTRAINTSPARALLEL_HPP
+#define SHARE_GC_PARALLEL_COMMANDLINEFLAGCONSTRAINTSPARALLEL_HPP
+
+#include "runtime/globals.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// Parallel Subconstraints
+Flag::Error ParallelGCThreadsConstraintFuncParallel(uint value, bool verbose);
+Flag::Error InitialTenuringThresholdConstraintFuncParallel(uintx value, bool verbose);
+Flag::Error MaxTenuringThresholdConstraintFuncParallel(uintx value, bool verbose);
+
+#endif // SHARE_GC_PARALLEL_COMMANDLINEFLAGCONSTRAINTSPARALLEL_HPP
--- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -73,7 +73,7 @@
   card_table->initialize();
   CardTableBarrierSet* const barrier_set = new CardTableBarrierSet(card_table);
   barrier_set->initialize();
-  set_barrier_set(barrier_set);
+  BarrierSet::set_barrier_set(barrier_set);
 
   // Make up the generations
   // Calculate the maximum size that a generation can grow.  This
@@ -627,7 +627,7 @@
 }
 
 CardTableBarrierSet* ParallelScavengeHeap::barrier_set() {
-  return barrier_set_cast<CardTableBarrierSet>(CollectedHeap::barrier_set());
+  return barrier_set_cast<CardTableBarrierSet>(BarrierSet::barrier_set());
 }
 
 PSCardTable* ParallelScavengeHeap::card_table() {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_PARALLEL_PARALLEL_GLOBALS_HPP
+#define SHARE_GC_PARALLEL_PARALLEL_GLOBALS_HPP
+
+#define GC_PARALLEL_FLAGS(develop,                                          \
+                          develop_pd,                                       \
+                          product,                                          \
+                          product_pd,                                       \
+                          diagnostic,                                       \
+                          diagnostic_pd,                                    \
+                          experimental,                                     \
+                          notproduct,                                       \
+                          manageable,                                       \
+                          product_rw,                                       \
+                          lp64_product,                                     \
+                          range,                                            \
+                          constraint,                                       \
+                          writeable)                                        \
+  product(uintx, HeapMaximumCompactionInterval, 20,                         \
+          "How often should we maximally compact the heap (not allowing "   \
+          "any dead space)")                                                \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, HeapFirstMaximumCompactionCount, 3,                        \
+          "The collection count for the first maximum compaction")          \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(bool, UseMaximumCompactionOnSystemGC, true,                       \
+          "Use maximum compaction in the Parallel Old garbage collector "   \
+          "for a system GC")                                                \
+                                                                            \
+  product(uintx, ParallelOldDeadWoodLimiterMean, 50,                        \
+          "The mean used by the parallel compact dead wood "                \
+          "limiter (a number between 0-100)")                               \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, ParallelOldDeadWoodLimiterStdDev, 80,                      \
+          "The standard deviation used by the parallel compact dead wood "  \
+          "limiter (a number between 0-100)")                               \
+          range(0, 100)                                                     \
+                                                                            \
+  develop(bool, TraceGCTaskManager, false,                                  \
+          "Trace actions of the GC task manager")                           \
+                                                                            \
+  develop(bool, TraceGCTaskQueue, false,                                    \
+          "Trace actions of the GC task queues")                            \
+                                                                            \
+  develop(bool, TraceParallelOldGCMarkingPhase, false,                      \
+          "Trace marking phase in ParallelOldGC")                           \
+                                                                            \
+  develop(bool, TraceParallelOldGCDensePrefix, false,                       \
+          "Trace dense prefix computation for ParallelOldGC")               \
+                                                                            \
+  develop(uintx, GCWorkerDelayMillis, 0,                                    \
+          "Delay in scheduling GC workers (in milliseconds)")               \
+                                                                            \
+  product(bool, PSChunkLargeArrays, true,                                   \
+          "Process large arrays in chunks")
+
+#endif // SHARE_GC_PARALLEL_PARALLEL_GLOBALS_HPP
--- a/src/hotspot/share/gc/parallel/psMarkSweepDecorator.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/parallel/psMarkSweepDecorator.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -112,8 +112,8 @@
   const intx interval = PrefetchScanIntervalInBytes;
 
   while (q < t) {
-    assert(oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() ||
-           oop(q)->mark()->has_bias_pattern(),
+    assert(oop(q)->mark_raw()->is_marked() || oop(q)->mark_raw()->is_unlocked() ||
+           oop(q)->mark_raw()->has_bias_pattern(),
            "these are the only valid states during a mark sweep");
     if (oop(q)->is_gc_marked()) {
       /* prefetch beyond q */
@@ -150,7 +150,7 @@
       } else {
         // if the object isn't moving we can just set the mark to the default
         // mark and handle it specially later on.
-        oop(q)->init_mark();
+        oop(q)->init_mark_raw();
         assert(oop(q)->forwardee() == NULL, "should be forwarded to NULL");
       }
 
@@ -210,7 +210,7 @@
           } else {
             // if the object isn't moving we can just set the mark to the default
             // mark and handle it specially later on.
-            oop(q)->init_mark();
+            oop(q)->init_mark_raw();
             assert(oop(q)->forwardee() == NULL, "should be forwarded to NULL");
           }
 
@@ -258,7 +258,7 @@
   if (allowed_deadspace_words >= deadlength) {
     allowed_deadspace_words -= deadlength;
     CollectedHeap::fill_with_object(q, deadlength);
-    oop(q)->set_mark(oop(q)->mark()->set_marked());
+    oop(q)->set_mark_raw(oop(q)->mark_raw()->set_marked());
     assert((int) deadlength == oop(q)->size(), "bad filler object size");
     // Recall that we required "q == compaction_top".
     return true;
@@ -349,7 +349,7 @@
       q = t;
     } else {
       // $$$ Funky
-      q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer();
+      q = (HeapWord*) oop(_first_dead)->mark_raw()->decode_pointer();
     }
   }
 
@@ -360,7 +360,7 @@
     if (!oop(q)->is_gc_marked()) {
       // mark is pointer to next marked oop
       debug_only(prev_q = q);
-      q = (HeapWord*) oop(q)->mark()->decode_pointer();
+      q = (HeapWord*) oop(q)->mark_raw()->decode_pointer();
       assert(q > prev_q, "we should be moving forward through memory");
     } else {
       // prefetch beyond q
@@ -376,7 +376,7 @@
       // copy object and reinit its mark
       assert(q != compaction_top, "everything in this pass should be moving");
       Copy::aligned_conjoint_words(q, compaction_top, size);
-      oop(compaction_top)->init_mark();
+      oop(compaction_top)->init_mark_raw();
       assert(oop(compaction_top)->klass() != NULL, "should have a class");
 
       debug_only(prev_q = q);
--- a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -82,7 +82,7 @@
   // so they can always fill with an array.
   HeapWord* tlab_end = end() + filler_header_size;
   typeArrayOop filler_oop = (typeArrayOop) top();
-  filler_oop->set_mark(markOopDesc::prototype());
+  filler_oop->set_mark_raw(markOopDesc::prototype());
   filler_oop->set_klass(Universe::intArrayKlassObj());
   const size_t array_length =
     pointer_delta(tlab_end, top()) - typeArrayOopDesc::header_size(T_INT);
--- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -116,7 +116,7 @@
   // NOTE! We must be very careful with any methods that access the mark
   // in o. There may be multiple threads racing on it, and it may be forwarded
   // at any time. Do not use oop methods for accessing the mark!
-  markOop test_mark = o->mark();
+  markOop test_mark = o->mark_raw();
 
   // The same test as "o->is_forwarded()"
   if (!test_mark->is_marked()) {
--- a/src/hotspot/share/gc/parallel/psScavenge.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/parallel/psScavenge.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -32,6 +32,7 @@
 #include "memory/iterator.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/access.inline.hpp"
+#include "oops/oop.inline.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 inline void PSScavenge::save_to_space_top_before_gc() {
--- a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,6 +25,16 @@
 #ifndef SHARE_VM_GC_PARALLEL_VMSTRUCTS_PARALLELGC_HPP
 #define SHARE_VM_GC_PARALLEL_VMSTRUCTS_PARALLELGC_HPP
 
+#include "gc/parallel/asPSOldGen.hpp"
+#include "gc/parallel/asPSYoungGen.hpp"
+#include "gc/parallel/immutableSpace.hpp"
+#include "gc/parallel/mutableSpace.hpp"
+#include "gc/parallel/parallelScavengeHeap.hpp"
+#include "gc/parallel/psOldGen.hpp"
+#include "gc/parallel/psVirtualspace.hpp"
+#include "gc/parallel/psYoungGen.hpp"
+#include "gc/parallel/vmStructs_parallelgc.hpp"
+
 #define VM_STRUCTS_PARALLELGC(nonstatic_field, \
                               volatile_nonstatic_field, \
                               static_field) \
@@ -65,7 +75,9 @@
                                                                                                                                      \
 
 #define VM_TYPES_PARALLELGC(declare_type,                                 \
-                            declare_toplevel_type)                        \
+                            declare_toplevel_type,                        \
+                            declare_integer_type)                         \
+                                                                          \
                                                                           \
   /*****************************************/                             \
   /* Parallel GC - space, gen abstractions */                             \
@@ -93,4 +105,7 @@
   declare_toplevel_type(ASPSOldGen*)                                      \
   declare_toplevel_type(ParallelScavengeHeap*)
 
+#define VM_INT_CONSTANTS_PARALLELGC(declare_constant,                     \
+                                    declare_constant_with_value)
+
 #endif // SHARE_VM_GC_PARALLEL_VMSTRUCTS_PARALLELGC_HPP
--- a/src/hotspot/share/gc/serial/defNewGeneration.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -174,9 +174,6 @@
 void ScanWeakRefClosure::do_oop(oop* p)       { ScanWeakRefClosure::do_oop_work(p); }
 void ScanWeakRefClosure::do_oop(narrowOop* p) { ScanWeakRefClosure::do_oop_work(p); }
 
-void FilteringClosure::do_oop(oop* p)       { FilteringClosure::do_oop_work(p); }
-void FilteringClosure::do_oop(narrowOop* p) { FilteringClosure::do_oop_work(p); }
-
 DefNewGeneration::DefNewGeneration(ReservedSpace rs,
                                    size_t initial_size,
                                    const char* policy)
@@ -753,7 +750,7 @@
 
   _promotion_failed = true;
   _promotion_failed_info.register_copy_failure(old->size());
-  _preserved_marks_set.get()->push_if_necessary(old, old->mark());
+  _preserved_marks_set.get()->push_if_necessary(old, old->mark_raw());
   // forward to self
   old->forward_to(old);
 
@@ -1009,9 +1006,11 @@
   // have to use it here, as well.
   HeapWord* result = eden()->par_allocate(word_size);
   if (result != NULL) {
+#if INCLUDE_ALL_GCS
     if (CMSEdenChunksRecordAlways && _old_gen != NULL) {
       _old_gen->sample_eden_chunk();
     }
+#endif
   } else {
     // If the eden is full and the last collection bailed out, we are running
     // out of heap space, and we try to allocate the from-space, too.
@@ -1025,9 +1024,11 @@
 HeapWord* DefNewGeneration::par_allocate(size_t word_size,
                                          bool is_tlab) {
   HeapWord* res = eden()->par_allocate(word_size);
+#if INCLUDE_ALL_GCS
   if (CMSEdenChunksRecordAlways && _old_gen != NULL) {
     _old_gen->sample_eden_chunk();
   }
+#endif
   return res;
 }
 
--- a/src/hotspot/share/gc/serial/markSweep.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/serial/markSweep.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,10 @@
 #include "precompiled.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc/serial/markSweep.inline.hpp"
+#include "gc/serial/serial_specialized_oop_closures.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
 #include "gc/shared/gcTimer.hpp"
 #include "gc/shared/gcTrace.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
 #include "memory/iterator.inline.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
@@ -66,8 +66,8 @@
 inline void MarkSweep::mark_object(oop obj) {
   // some marks may contain information we need to preserve so we store them away
   // and overwrite the mark.  We'll restore it at the end of markSweep.
-  markOop mark = obj->mark();
-  obj->set_mark(markOopDesc::prototype()->set_marked());
+  markOop mark = obj->mark_raw();
+  obj->set_mark_raw(markOopDesc::prototype()->set_marked());
 
   if (mark->must_be_preserved(obj)) {
     preserve_mark(obj, mark);
@@ -78,7 +78,7 @@
   T heap_oop = RawAccess<>::oop_load(p);
   if (!CompressedOops::is_null(heap_oop)) {
     oop obj = CompressedOops::decode_not_null(heap_oop);
-    if (!obj->mark()->is_marked()) {
+    if (!obj->mark_raw()->is_marked()) {
       mark_object(obj);
       _marking_stack.push(obj);
     }
@@ -174,7 +174,7 @@
   T heap_oop = RawAccess<>::oop_load(p);
   if (!CompressedOops::is_null(heap_oop)) {
     oop obj = CompressedOops::decode_not_null(heap_oop);
-    if (!obj->mark()->is_marked()) {
+    if (!obj->mark_raw()->is_marked()) {
       mark_object(obj);
       follow_object(obj);
     }
@@ -190,7 +190,7 @@
 }
 
 void PreservedMark::restore() {
-  _obj->set_mark(_mark);
+  _obj->set_mark_raw(_mark);
 }
 
 // We preserve the mark which should be replaced at the end and the location
@@ -252,7 +252,7 @@
   while (!_preserved_oop_stack.is_empty()) {
     oop obj       = _preserved_oop_stack.pop();
     markOop mark  = _preserved_mark_stack.pop();
-    obj->set_mark(mark);
+    obj->set_mark_raw(mark);
   }
 }
 
--- a/src/hotspot/share/gc/serial/markSweep.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/serial/markSweep.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,11 +43,11 @@
     oop obj = CompressedOops::decode_not_null(heap_oop);
     assert(Universe::heap()->is_in(obj), "should be in heap");
 
-    oop new_obj = oop(obj->mark()->decode_pointer());
+    oop new_obj = oop(obj->mark_raw()->decode_pointer());
 
     assert(new_obj != NULL ||                         // is forwarding ptr?
-           obj->mark() == markOopDesc::prototype() || // not gc marked?
-           (UseBiasedLocking && obj->mark()->has_bias_pattern()),
+           obj->mark_raw() == markOopDesc::prototype() || // not gc marked?
+           (UseBiasedLocking && obj->mark_raw()->has_bias_pattern()),
            // not gc marked?
            "should be forwarded");
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/serial/serial_globals.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SERIAL_SERIAL_GLOBALS_HPP
+#define SHARE_GC_SERIAL_SERIAL_GLOBALS_HPP
+
+#define GC_SERIAL_FLAGS(develop,                                            \
+                        develop_pd,                                         \
+                        product,                                            \
+                        product_pd,                                         \
+                        diagnostic,                                         \
+                        diagnostic_pd,                                      \
+                        experimental,                                       \
+                        notproduct,                                         \
+                        manageable,                                         \
+                        product_rw,                                         \
+                        lp64_product,                                       \
+                        range,                                              \
+                        constraint,                                         \
+                        writeable)
+
+#endif // SHARE_GC_SERIAL_SERIAL_GLOBALS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/serial/serial_specialized_oop_closures.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP
+#define SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP
+
+// The following OopClosure types get specialized versions of
+// "oop_oop_iterate" that invoke the closures' do_oop methods
+// non-virtually, using a mechanism defined in this file.  Extend these
+// macros in the obvious way to add specializations for new closures.
+
+// Forward declarations.
+
+// DefNew
+class ScanClosure;
+class FastScanClosure;
+class FilteringClosure;
+
+// MarkSweep
+class MarkAndPushClosure;
+class AdjustPointerClosure;
+
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f)         \
+  f(ScanClosure,_nv)                                      \
+  f(FastScanClosure,_nv)                                  \
+  f(FilteringClosure,_nv)
+
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)        \
+  f(MarkAndPushClosure,_nv)                               \
+  f(AdjustPointerClosure,_nv)
+
+#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f)  \
+  f(ScanClosure,_nv)                                      \
+  f(FastScanClosure,_nv)
+
+#endif // SHARE_GC_SERIAL_SERIAL_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,6 +30,7 @@
 #include "gc/shared/collectorCounters.hpp"
 #include "gc/shared/gcTimer.hpp"
 #include "gc/shared/gcTrace.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/generationSpec.hpp"
 #include "gc/shared/space.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/serial/vmStructs_serial.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2007, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SERIAL_VMSTRUCTS_HPP
+#define SHARE_GC_SERIAL_VMSTRUCTS_HPP
+
+#include "gc/serial/serialHeap.hpp"
+#include "gc/serial/tenuredGeneration.hpp"
+
+#define VM_STRUCTS_SERIALGC(nonstatic_field,                                  \
+                            volatile_nonstatic_field,                         \
+                            static_field)                                     \
+  nonstatic_field(TenuredGeneration, _min_heap_delta_bytes, size_t)           \
+  nonstatic_field(TenuredGeneration, _the_space,            ContiguousSpace*)
+
+#define VM_TYPES_SERIALGC(declare_type,                                       \
+                          declare_toplevel_type,                              \
+                          declare_integer_type)                               \
+  declare_type(SerialHeap,                   GenCollectedHeap)                \
+  declare_type(TenuredGeneration,            CardGeneration)                  \
+  declare_type(TenuredSpace,                 OffsetTableContigSpace)          \
+                                                                              \
+  declare_toplevel_type(TenuredGeneration*)
+
+#define VM_INT_CONSTANTS_SERIALGC(declare_constant,                           \
+                                  declare_constant_with_value)
+
+#endif // SHARE_GC_SERIAL_VMSTRUCTS_SERIAL_HPP
--- a/src/hotspot/share/gc/shared/barrierSet.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/barrierSet.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -24,5 +24,27 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/barrierSet.hpp"
+#include "gc/shared/barrierSetAssembler.hpp"
+#include "runtime/thread.hpp"
+#include "utilities/macros.hpp"
 
-BarrierSet* BarrierSet::_bs = NULL;
+BarrierSet* BarrierSet::_barrier_set = NULL;
+
+void BarrierSet::set_barrier_set(BarrierSet* barrier_set) {
+  assert(_barrier_set == NULL, "Already initialized");
+  _barrier_set = barrier_set;
+
+  // The barrier set was not initialized when the this thread (the main thread)
+  // was created, so the call to BarrierSet::on_thread_create() had to be deferred
+  // until we have a barrier set. Now we have a barrier set, so we make the call.
+  _barrier_set->on_thread_create(Thread::current());
+}
+
+// Called from init.cpp
+void gc_barrier_stubs_init() {
+  BarrierSet* bs = BarrierSet::barrier_set();
+#ifndef ZERO
+  BarrierSetAssembler* bs_assembler = bs->barrier_set_assembler();
+  bs_assembler->barrier_stubs_init();
+#endif
+}
--- a/src/hotspot/share/gc/shared/barrierSet.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -42,7 +42,7 @@
 class BarrierSet: public CHeapObj<mtGC> {
   friend class VMStructs;
 
-  static BarrierSet* _bs;
+  static BarrierSet* _barrier_set;
 
 public:
   enum Name {
@@ -52,8 +52,6 @@
     UnknownBS
   };
 
-  static BarrierSet* barrier_set() { return _bs; }
-
 protected:
   // Fake RTTI support.  For a derived class T to participate
   // - T must have a corresponding Name entry.
@@ -107,6 +105,8 @@
   // is redone until it succeeds. This can e.g. prevent allocations from the slow path
   // to be in old.
   virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {}
+  virtual void on_thread_create(Thread* thread) {}
+  virtual void on_thread_destroy(Thread* thread) {}
   virtual void on_thread_attach(JavaThread* thread) {}
   virtual void on_thread_detach(JavaThread* thread) {}
   virtual void make_parsable(JavaThread* thread) {}
@@ -115,7 +115,8 @@
   // Print a description of the memory for the barrier set
   virtual void print_on(outputStream* st) const = 0;
 
-  static void set_bs(BarrierSet* bs) { _bs = bs; }
+  static BarrierSet* barrier_set() { return _barrier_set; }
+  static void set_barrier_set(BarrierSet* barrier_set);
 
   BarrierSetAssembler* barrier_set_assembler() {
     assert(_barrier_set_assembler != NULL, "should be set");
--- a/src/hotspot/share/gc/shared/cardGeneration.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardGeneration.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,6 +28,7 @@
 #include "gc/shared/cardGeneration.inline.hpp"
 #include "gc/shared/cardTableRS.hpp"
 #include "gc/shared/gcLocker.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
 #include "gc/shared/generationSpec.hpp"
 #include "gc/shared/space.inline.hpp"
--- a/src/hotspot/share/gc/shared/cardGeneration.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardGeneration.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,6 +31,7 @@
 #include "gc/shared/generation.hpp"
 
 class BlockOffsetSharedArray;
+class CardTableRS;
 class CompactibleSpace;
 
 class CardGeneration: public Generation {
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,7 +26,6 @@
 #include "gc/shared/cardTableBarrierSetAssembler.hpp"
 #include "gc/shared/cardTableBarrierSet.inline.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/space.inline.hpp"
 #include "logging/log.hpp"
 #include "memory/virtualspace.hpp"
--- a/src/hotspot/share/gc/shared/cardTableRS.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardTableRS.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -279,36 +279,24 @@
 void CardTableRS::younger_refs_in_space_iterate(Space* sp,
                                                 OopsInGenClosure* cl,
                                                 uint n_threads) {
+  verify_used_region_at_save_marks(sp);
+
   const MemRegion urasm = sp->used_region_at_save_marks();
+  non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);
+}
+
 #ifdef ASSERT
-  // Convert the assertion check to a warning if we are running
-  // CMS+ParNew until related bug is fixed.
+void CardTableRS::verify_used_region_at_save_marks(Space* sp) const {
   MemRegion ur    = sp->used_region();
-  assert(ur.contains(urasm) || (UseConcMarkSweepGC),
+  MemRegion urasm = sp->used_region_at_save_marks();
+
+  assert(ur.contains(urasm),
          "Did you forget to call save_marks()? "
          "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
          "[" PTR_FORMAT ", " PTR_FORMAT ")",
          p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
-  // In the case of CMS+ParNew, issue a warning
-  if (!ur.contains(urasm)) {
-    assert(UseConcMarkSweepGC, "Tautology: see assert above");
-    log_warning(gc)("CMS+ParNew: Did you forget to call save_marks()? "
-                    "[" PTR_FORMAT ", " PTR_FORMAT ") is not contained in "
-                    "[" PTR_FORMAT ", " PTR_FORMAT ")",
-                    p2i(urasm.start()), p2i(urasm.end()), p2i(ur.start()), p2i(ur.end()));
-    MemRegion ur2 = sp->used_region();
-    MemRegion urasm2 = sp->used_region_at_save_marks();
-    if (!ur.equals(ur2)) {
-      log_warning(gc)("CMS+ParNew: Flickering used_region()!!");
-    }
-    if (!urasm.equals(urasm2)) {
-      log_warning(gc)("CMS+ParNew: Flickering used_region_at_save_marks()!!");
-    }
-    ShouldNotReachHere();
-  }
+}
 #endif
-  non_clean_card_iterate_possibly_parallel(sp, urasm, cl, this, n_threads);
-}
 
 void CardTableRS::clear_into_younger(Generation* old_gen) {
   assert(GenCollectedHeap::heap()->is_old_gen(old_gen),
@@ -611,8 +599,8 @@
   CardTable::verify();
 }
 
-CardTableRS::CardTableRS(MemRegion whole_heap) :
-  CardTable(whole_heap, /* scanned concurrently */ UseConcMarkSweepGC && CMSPrecleaningEnabled),
+CardTableRS::CardTableRS(MemRegion whole_heap, bool scanned_concurrently) :
+  CardTable(whole_heap, scanned_concurrently),
   _cur_youngergen_card_val(youngergenP1_card),
   // LNC functionality
   _lowest_non_clean(NULL),
@@ -698,11 +686,7 @@
 {
   if (!mr.is_empty()) {
     if (n_threads > 0) {
-#if INCLUDE_ALL_GCS
       non_clean_card_iterate_parallel_work(sp, mr, cl, ct, n_threads);
-#else  // INCLUDE_ALL_GCS
-      fatal("Parallel gc not supported here.");
-#endif // INCLUDE_ALL_GCS
     } else {
       // clear_cl finds contiguous dirty ranges of cards to process and clear.
 
@@ -717,6 +701,12 @@
   }
 }
 
+void CardTableRS::non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                                       OopsInGenClosure* cl, CardTableRS* ct,
+                                                       uint n_threads) {
+  fatal("Parallel gc not supported here.");
+}
+
 bool CardTableRS::is_in_young(oop obj) const {
   return GenCollectedHeap::heap()->is_in_young(obj);
 }
--- a/src/hotspot/share/gc/shared/cardTableRS.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/cardTableRS.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -99,13 +99,15 @@
   jbyte find_unused_youngergenP_card_value();
 
 public:
-  CardTableRS(MemRegion whole_heap);
+  CardTableRS(MemRegion whole_heap, bool scanned_concurrently);
   ~CardTableRS();
 
   CLDRemSet* cld_rem_set() { return &_cld_rem_set; }
 
   void younger_refs_in_space_iterate(Space* sp, OopsInGenClosure* cl, uint n_threads);
 
+  virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN;
+
   // Override.
   void prepare_for_younger_refs_iterate(bool parallel);
 
@@ -174,9 +176,9 @@
 
   // Work method used to implement non_clean_card_iterate_possibly_parallel()
   // above in the parallel case.
-  void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
-                                            OopsInGenClosure* cl, CardTableRS* ct,
-                                            uint n_threads);
+  virtual void non_clean_card_iterate_parallel_work(Space* sp, MemRegion mr,
+                                                    OopsInGenClosure* cl, CardTableRS* ct,
+                                                    uint n_threads);
 
   // This is an array, one element per covered region of the card table.
   // Each entry is itself an array, with one element per chunk in the
@@ -190,53 +192,7 @@
   uintptr_t* _lowest_non_clean_base_chunk_index;
   volatile int* _last_LNC_resizing_collection;
 
-  // Initializes "lowest_non_clean" to point to the array for the region
-  // covering "sp", and "lowest_non_clean_base_chunk_index" to the chunk
-  // index of the corresponding to the first element of that array.
-  // Ensures that these arrays are of sufficient size, allocating if necessary.
-  // May be called by several threads concurrently.
-  void get_LNC_array_for_space(Space* sp,
-                               jbyte**& lowest_non_clean,
-                               uintptr_t& lowest_non_clean_base_chunk_index,
-                               size_t& lowest_non_clean_chunk_size);
-
-  // Returns the number of chunks necessary to cover "mr".
-  size_t chunks_to_cover(MemRegion mr) {
-    return (size_t)(addr_to_chunk_index(mr.last()) -
-                    addr_to_chunk_index(mr.start()) + 1);
-  }
-
-  // Returns the index of the chunk in a stride which
-  // covers the given address.
-  uintptr_t addr_to_chunk_index(const void* addr) {
-    uintptr_t card = (uintptr_t) byte_for(addr);
-    return card / ParGCCardsPerStrideChunk;
-  }
-
-  // Apply cl, which must either itself apply dcto_cl or be dcto_cl,
-  // to the cards in the stride (of n_strides) within the given space.
-  void process_stride(Space* sp,
-                      MemRegion used,
-                      jint stride, int n_strides,
-                      OopsInGenClosure* cl,
-                      CardTableRS* ct,
-                      jbyte** lowest_non_clean,
-                      uintptr_t lowest_non_clean_base_chunk_index,
-                      size_t lowest_non_clean_chunk_size);
-
-  // Makes sure that chunk boundaries are handled appropriately, by
-  // adjusting the min_done of dcto_cl, and by using a special card-table
-  // value to indicate how min_done should be set.
-  void process_chunk_boundaries(Space* sp,
-                                DirtyCardToOopClosure* dcto_cl,
-                                MemRegion chunk_mr,
-                                MemRegion used,
-                                jbyte** lowest_non_clean,
-                                uintptr_t lowest_non_clean_base_chunk_index,
-                                size_t    lowest_non_clean_chunk_size);
-
   virtual bool is_in_young(oop obj) const;
-
 };
 
 class ClearNoncleanCardWrapper: public MemRegionClosure {
--- a/src/hotspot/share/gc/shared/collectedHeap.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -137,7 +137,7 @@
   print_extended_on(st);
   st->cr();
 
-  _barrier_set->print_on(st);
+  BarrierSet::barrier_set()->print_on(st);
 }
 
 void CollectedHeap::trace_heap(GCWhen::Type when, const GCTracer* gc_tracer) {
@@ -176,7 +176,6 @@
 
 
 CollectedHeap::CollectedHeap() :
-  _barrier_set(NULL),
   _is_gc_active(false),
   _total_collections(0),
   _total_full_collections(0),
@@ -311,11 +310,6 @@
   } while (true);  // Until a GC is done
 }
 
-void CollectedHeap::set_barrier_set(BarrierSet* barrier_set) {
-  _barrier_set = barrier_set;
-  BarrierSet::set_bs(barrier_set);
-}
-
 #ifndef PRODUCT
 void CollectedHeap::check_for_bad_heap_word_value(HeapWord* addr, size_t size) {
   if (CheckMemoryInitialization && ZapUnusedHeapArea) {
@@ -522,7 +516,7 @@
   assert(!use_tlab || jtiwh.length() > 0,
          "Attempt to fill tlabs before main thread has been added"
          " to threads list is doomed to failure!");
-  BarrierSet *bs = barrier_set();
+  BarrierSet *bs = BarrierSet::barrier_set();
   for (; JavaThread *thread = jtiwh.next(); ) {
      if (use_tlab) thread->tlab().make_parsable(retire_tlabs);
      bs->make_parsable(thread);
--- a/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -105,7 +105,6 @@
   MemRegion _reserved;
 
  protected:
-  BarrierSet* _barrier_set;
   bool _is_gc_active;
 
   // Used for filler objects (static, but initialized in ctor).
@@ -417,10 +416,6 @@
                                                        size_t size,
                                                        Metaspace::MetadataType mdtype);
 
-  // Returns the barrier set for this heap
-  BarrierSet* barrier_set() { return _barrier_set; }
-  void set_barrier_set(BarrierSet* barrier_set);
-
   // Returns "true" iff there is a stop-world GC in progress.  (I assume
   // that it should answer "false" for the concurrent part of a concurrent
   // collector -- dld).
--- a/src/hotspot/share/gc/shared/collectedHeap.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -61,10 +61,10 @@
 
   assert(obj != NULL, "NULL object pointer");
   if (UseBiasedLocking && (klass != NULL)) {
-    obj->set_mark(klass->prototype_header());
+    obj->set_mark_raw(klass->prototype_header());
   } else {
     // May be bootstrapping
-    obj->set_mark(markOopDesc::prototype());
+    obj->set_mark_raw(markOopDesc::prototype());
   }
 }
 
--- a/src/hotspot/share/gc/shared/collectorPolicy.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectorPolicy.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,7 +28,6 @@
 #include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcLocker.hpp"
 #include "gc/shared/gcPolicyCounters.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/generationSpec.hpp"
 #include "gc/shared/space.hpp"
 #include "gc/shared/vmGCOperations.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/commandLineFlagConstraintsGC.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,470 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "gc/shared/collectedHeap.hpp"
+#include "gc/shared/collectorPolicy.hpp"
+#include "gc/shared/commandLineFlagConstraintsGC.hpp"
+#include "gc/shared/plab.hpp"
+#include "gc/shared/threadLocalAllocBuffer.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/commandLineFlagRangeList.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/globals_extension.hpp"
+#include "runtime/thread.inline.hpp"
+#include "utilities/align.hpp"
+#include "utilities/defaultStream.hpp"
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/cms/commandLineFlagConstraintsCMS.hpp"
+#include "gc/g1/commandLineFlagConstraintsG1.hpp"
+#include "gc/parallel/commandLineFlagConstraintsParallel.hpp"
+#endif
+#ifdef COMPILER1
+#include "c1/c1_globals.hpp"
+#endif // COMPILER1
+#ifdef COMPILER2
+#include "opto/c2_globals.hpp"
+#endif // COMPILER2
+
+// Some flags that have default values that indicate that the
+// JVM should automatically determine an appropriate value
+// for that flag.  In those cases it is only appropriate for the
+// constraint checking to be done if the user has specified the
+// value(s) of the flag(s) on the command line.  In the constraint
+// checking functions,  FLAG_IS_CMDLINE() is used to check if
+// the flag has been set by the user and so should be checked.
+
+// As ParallelGCThreads differs among GC modes, we need constraint function.
+Flag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose) {
+  Flag::Error status = Flag::SUCCESS;
+
+#if INCLUDE_ALL_GCS
+  status = ParallelGCThreadsConstraintFuncParallel(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+
+  status = ParallelGCThreadsConstraintFuncCMS(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+#endif
+
+  return status;
+}
+
+// As ConcGCThreads should be smaller than ParallelGCThreads,
+// we need constraint function.
+Flag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  // CMS and G1 GCs use ConcGCThreads.
+  if ((UseConcMarkSweepGC || UseG1GC) && (value > ParallelGCThreads)) {
+    CommandLineError::print(verbose,
+                            "ConcGCThreads (" UINT32_FORMAT ") must be "
+                            "less than or equal to ParallelGCThreads (" UINT32_FORMAT ")\n",
+                            value, ParallelGCThreads);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+#endif
+  return Flag::SUCCESS;
+}
+
+static Flag::Error MinPLABSizeBounds(const char* name, size_t value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  if ((UseConcMarkSweepGC || UseG1GC || UseParallelGC) && (value < PLAB::min_size())) {
+    CommandLineError::print(verbose,
+                            "%s (" SIZE_FORMAT ") must be "
+                            "greater than or equal to ergonomic PLAB minimum size (" SIZE_FORMAT ")\n",
+                            name, value, PLAB::min_size());
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+#endif // INCLUDE_ALL_GCS
+  return Flag::SUCCESS;
+}
+
+Flag::Error MaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  if ((UseConcMarkSweepGC || UseG1GC || UseParallelGC) && (value > PLAB::max_size())) {
+    CommandLineError::print(verbose,
+                            "%s (" SIZE_FORMAT ") must be "
+                            "less than or equal to ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
+                            name, value, PLAB::max_size());
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+#endif // INCLUDE_ALL_GCS
+  return Flag::SUCCESS;
+}
+
+static Flag::Error MinMaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
+  Flag::Error status = MinPLABSizeBounds(name, value, verbose);
+
+  if (status == Flag::SUCCESS) {
+    return MaxPLABSizeBounds(name, value, verbose);
+  }
+  return status;
+}
+
+Flag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose) {
+  return MinMaxPLABSizeBounds("YoungPLABSize", value, verbose);
+}
+
+Flag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose) {
+  Flag::Error status = Flag::SUCCESS;
+
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC) {
+    return OldPLABSizeConstraintFuncCMS(value, verbose);
+  } else {
+    status = MinMaxPLABSizeBounds("OldPLABSize", value, verbose);
+  }
+#endif
+  return status;
+}
+
+Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
+  if (value > MaxHeapFreeRatio) {
+    CommandLineError::print(verbose,
+                            "MinHeapFreeRatio (" UINTX_FORMAT ") must be "
+                            "less than or equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
+                            value, MaxHeapFreeRatio);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
+  if (value < MinHeapFreeRatio) {
+    CommandLineError::print(verbose,
+                            "MaxHeapFreeRatio (" UINTX_FORMAT ") must be "
+                            "greater than or equal to MinHeapFreeRatio (" UINTX_FORMAT ")\n",
+                            value, MinHeapFreeRatio);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+static Flag::Error CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(size_t maxHeap, intx softRef, bool verbose) {
+  if ((softRef > 0) && ((maxHeap / M) > (max_uintx / softRef))) {
+    CommandLineError::print(verbose,
+                            "Desired lifetime of SoftReferences cannot be expressed correctly. "
+                            "MaxHeapSize (" SIZE_FORMAT ") or SoftRefLRUPolicyMSPerMB "
+                            "(" INTX_FORMAT ") is too large\n",
+                            maxHeap, softRef);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose) {
+  return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(MaxHeapSize, value, verbose);
+}
+
+Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) {
+  if (value > MarkStackSizeMax) {
+    CommandLineError::print(verbose,
+                            "MarkStackSize (" SIZE_FORMAT ") must be "
+                            "less than or equal to MarkStackSizeMax (" SIZE_FORMAT ")\n",
+                            value, MarkStackSizeMax);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
+  if (value > MaxMetaspaceFreeRatio) {
+    CommandLineError::print(verbose,
+                            "MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
+                            "less than or equal to MaxMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
+                            value, MaxMetaspaceFreeRatio);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
+  if (value < MinMetaspaceFreeRatio) {
+    CommandLineError::print(verbose,
+                            "MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
+                            "greater than or equal to MinMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
+                            value, MinMetaspaceFreeRatio);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  Flag::Error status = InitialTenuringThresholdConstraintFuncParallel(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+#endif
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  Flag::Error status = MaxTenuringThresholdConstraintFuncParallel(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+#endif
+
+  // MaxTenuringThreshold=0 means NeverTenure=false && AlwaysTenure=true
+  if ((value == 0) && (NeverTenure || !AlwaysTenure)) {
+    CommandLineError::print(verbose,
+                            "MaxTenuringThreshold (0) should match to NeverTenure=false "
+                            "&& AlwaysTenure=true. But we have NeverTenure=%s "
+                            "AlwaysTenure=%s\n",
+                            NeverTenure ? "true" : "false",
+                            AlwaysTenure ? "true" : "false");
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  Flag::Error status = MaxGCPauseMillisConstraintFuncG1(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+#endif
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  Flag::Error status = GCPauseIntervalMillisConstraintFuncG1(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+#endif
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
+  size_t aligned_max = align_down(max_uintx/2, Metaspace::reserve_alignment_words());
+  if (value > aligned_max) {
+    CommandLineError::print(verbose,
+                            "InitialBootClassLoaderMetaspaceSize (" SIZE_FORMAT ") must be "
+                            "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
+                            value, aligned_max);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+// To avoid an overflow by 'align_up(value, alignment)'.
+static Flag::Error MaxSizeForAlignment(const char* name, size_t value, size_t alignment, bool verbose) {
+  size_t aligned_max = ((max_uintx - alignment) & ~(alignment-1));
+  if (value > aligned_max) {
+    CommandLineError::print(verbose,
+                            "%s (" SIZE_FORMAT ") must be "
+                            "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
+                            name, value, aligned_max);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+static Flag::Error MaxSizeForHeapAlignment(const char* name, size_t value, bool verbose) {
+  size_t heap_alignment;
+
+#if INCLUDE_ALL_GCS
+  if (UseG1GC) {
+    // For G1 GC, we don't know until G1CollectorPolicy is created.
+    heap_alignment = MaxSizeForHeapAlignmentG1();
+  } else
+#endif
+  {
+    heap_alignment = CollectorPolicy::compute_heap_alignment();
+  }
+
+  return MaxSizeForAlignment(name, value, heap_alignment, verbose);
+}
+
+Flag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
+  return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
+}
+
+Flag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose) {
+  Flag::Error status = MaxSizeForHeapAlignment("MaxHeapSize", value, verbose);
+
+  if (status == Flag::SUCCESS) {
+    status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(value, SoftRefLRUPolicyMSPerMB, verbose);
+  }
+  return status;
+}
+
+Flag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose) {
+  // If an overflow happened in Arguments::set_heap_size(), MaxHeapSize will have too large a value.
+  // Check for this by ensuring that MaxHeapSize plus the requested min base address still fit within max_uintx.
+  if (UseCompressedOops && FLAG_IS_ERGO(MaxHeapSize) && (value > (max_uintx - MaxHeapSize))) {
+    CommandLineError::print(verbose,
+                            "HeapBaseMinAddress (" SIZE_FORMAT ") or MaxHeapSize (" SIZE_FORMAT ") is too large. "
+                            "Sum of them must be less than or equal to maximum of size_t (" SIZE_FORMAT ")\n",
+                            value, MaxHeapSize, max_uintx);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+
+  return MaxSizeForHeapAlignment("HeapBaseMinAddress", value, verbose);
+}
+
+Flag::Error NewSizeConstraintFunc(size_t value, bool verbose) {
+#if INCLUDE_ALL_GCS
+  Flag::Error status = NewSizeConstraintFuncG1(value, verbose);
+  if (status != Flag::SUCCESS) {
+    return status;
+  }
+#endif
+
+  return Flag::SUCCESS;
+}
+
+Flag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose) {
+  // At least, alignment reserve area is needed.
+  if (value < ThreadLocalAllocBuffer::alignment_reserve_in_bytes()) {
+    CommandLineError::print(verbose,
+                            "MinTLABSize (" SIZE_FORMAT ") must be "
+                            "greater than or equal to reserved area in TLAB (" SIZE_FORMAT ")\n",
+                            value, ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
+    CommandLineError::print(verbose,
+                            "MinTLABSize (" SIZE_FORMAT ") must be "
+                            "less than or equal to ergonomic TLAB maximum (" SIZE_FORMAT ")\n",
+                            value, ThreadLocalAllocBuffer::max_size() * HeapWordSize);
+    return Flag::VIOLATES_CONSTRAINT;
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose) {
+  // Skip for default value of zero which means set ergonomically.
+  if (FLAG_IS_CMDLINE(TLABSize)) {
+    if (value < MinTLABSize) {
+      CommandLineError::print(verbose,
+                              "TLABSize (" SIZE_FORMAT ") must be "
+                              "greater than or equal to MinTLABSize (" SIZE_FORMAT ")\n",
+                              value, MinTLABSize);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+    if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
+      CommandLineError::print(verbose,
+                              "TLABSize (" SIZE_FORMAT ") must be "
+                              "less than or equal to ergonomic TLAB maximum size (" SIZE_FORMAT ")\n",
+                              value, (ThreadLocalAllocBuffer::max_size() * HeapWordSize));
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
+
+// We will protect overflow from ThreadLocalAllocBuffer::record_slow_allocation(),
+// so AfterMemoryInit type is enough to check.
+Flag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose) {
+  if (UseTLAB) {
+    size_t refill_waste_limit = Thread::current()->tlab().refill_waste_limit();
+
+    // Compare with 'max_uintx' as ThreadLocalAllocBuffer::_refill_waste_limit is 'size_t'.
+    if (refill_waste_limit > (max_uintx - value)) {
+      CommandLineError::print(verbose,
+                              "TLABWasteIncrement (" UINTX_FORMAT ") must be "
+                              "less than or equal to ergonomic TLAB waste increment maximum size(" SIZE_FORMAT ")\n",
+                              value, (max_uintx - refill_waste_limit));
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
+
+Flag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose) {
+  if (FLAG_IS_CMDLINE(SurvivorRatio) &&
+      (value > (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()))) {
+    CommandLineError::print(verbose,
+                            "SurvivorRatio (" UINTX_FORMAT ") must be "
+                            "less than or equal to ergonomic SurvivorRatio maximum (" SIZE_FORMAT ")\n",
+                            value,
+                            (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()));
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose) {
+  if (value > MaxMetaspaceSize) {
+    CommandLineError::print(verbose,
+                            "MetaspaceSize (" SIZE_FORMAT ") must be "
+                            "less than or equal to MaxMetaspaceSize (" SIZE_FORMAT ")\n",
+                            value, MaxMetaspaceSize);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
+  if (value < MetaspaceSize) {
+    CommandLineError::print(verbose,
+                            "MaxMetaspaceSize (" SIZE_FORMAT ") must be "
+                            "greater than or equal to MetaspaceSize (" SIZE_FORMAT ")\n",
+                            value, MaxMetaspaceSize);
+    return Flag::VIOLATES_CONSTRAINT;
+  } else {
+    return Flag::SUCCESS;
+  }
+}
+
+Flag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose) {
+  if (value != 0) {
+    if (!is_power_of_2(value)) {
+      CommandLineError::print(verbose,
+                              "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
+                              "power of 2\n",
+                              value);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+    if (value < ObjectAlignmentInBytes) {
+      CommandLineError::print(verbose,
+                              "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
+                              "greater than or equal to ObjectAlignmentInBytes (" INTX_FORMAT ")\n",
+                              value, ObjectAlignmentInBytes);
+      return Flag::VIOLATES_CONSTRAINT;
+    }
+  }
+  return Flag::SUCCESS;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/commandLineFlagConstraintsGC.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_COMMANDLINEFLAGCONSTRAINTSGC_HPP
+#define SHARE_GC_SHARED_COMMANDLINEFLAGCONSTRAINTSGC_HPP
+
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/cms/commandLineFlagConstraintsCMS.hpp"
+#include "gc/g1/commandLineFlagConstraintsG1.hpp"
+#include "gc/parallel/commandLineFlagConstraintsParallel.hpp"
+#endif
+
+/*
+ * Here we have GC arguments constraints functions, which are called automatically
+ * whenever flag's value changes. If the constraint fails the function should return
+ * an appropriate error value.
+ */
+
+Flag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose);
+Flag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose);
+Flag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose);
+Flag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose);
+Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose);
+Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose);
+Flag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose);
+Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose);
+Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose);
+
+Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose);
+Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose);
+Flag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose);
+Flag::Error NewSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose);
+Flag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose);
+Flag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose);
+Flag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose);
+
+// Internal
+Flag::Error MaxPLABSizeBounds(const char* name, size_t value, bool verbose);
+
+#endif // SHARE_GC_SHARED_COMMANDLINEFLAGCONSTRAINTSGC_HPP
--- a/src/hotspot/share/gc/shared/gcArguments.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/gcArguments.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,16 +31,26 @@
 #include "utilities/macros.hpp"
 
 void GCArguments::initialize() {
-#if INCLUDE_ALL_GCS
+  if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
+    MarkSweepAlwaysCompactCount = 1;  // Move objects every gc.
+  }
+
+  if (!(UseParallelGC || UseParallelOldGC) && FLAG_IS_DEFAULT(ScavengeBeforeFullGC)) {
+    FLAG_SET_DEFAULT(ScavengeBeforeFullGC, false);
+  }
+
+  if (GCTimeLimit == 100) {
+    // Turn off gc-overhead-limit-exceeded checks
+    FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
+  }
+
   if (MinHeapFreeRatio == 100) {
     // Keeping the heap 100% free is hard ;-) so limit it to 99%.
     FLAG_SET_ERGO(uintx, MinHeapFreeRatio, 99);
   }
 
-  // If class unloading is disabled, also disable concurrent class unloading.
   if (!ClassUnloading) {
-    FLAG_SET_CMDLINE(bool, CMSClassUnloadingEnabled, false);
+    // If class unloading is disabled, also disable concurrent class unloading.
     FLAG_SET_CMDLINE(bool, ClassUnloadingWithConcurrentMark, false);
   }
-#endif // INCLUDE_ALL_GCS
 }
--- a/src/hotspot/share/gc/shared/gcStats.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/gcStats.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,9 +31,3 @@
                                                   AdaptiveSizePolicyWeight,
                                                   PromotedPadding);
 }
-
-CMSGCStats::CMSGCStats() {
-    _avg_promoted       = new AdaptivePaddedNoZeroDevAverage(
-                                                  CMSExpAvgFactor,
-                                                  PromotedPadding);
-}
--- a/src/hotspot/share/gc/shared/gcStats.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/gcStats.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -58,13 +58,4 @@
   }
 };
 
-class CMSGCStats : public GCStats {
- public:
-  CMSGCStats();
-
-  virtual Name kind() {
-    return CMSGCStatsKind;
-  }
-};
-
 #endif // SHARE_VM_GC_SHARED_GCSTATS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcThreadLocalData.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#ifndef SHARE_GC_SHARED_GCTHREADLOCALDATA_HPP
+#define SHARE_GC_SHARED_GCTHREADLOCALDATA_HPP
+
+#include "utilities/globalDefinitions.hpp"
+
+// Thread local data area for GC-specific information. Each GC
+// is free to decide the internal structure and contents of this
+// area. It is represented as a 64-bit aligned opaque blob to
+// avoid circular dependencies between Thread and all GCs. For
+// the same reason, the size of the data area is hard coded to
+// provide enough space for all current GCs. Adjust the size if
+// needed, but avoid making it excessively large as it adds to
+// the memory overhead of creating a thread.
+//
+// Use Thread::gc_data<T>() to access the data, where T is the
+// GC-specific type describing the structure of the data. GCs
+// should consider placing frequently accessed fields first in
+// T, so that field offsets relative to Thread are small, which
+// often allows for a more compact instruction encoding.
+typedef uint64_t GCThreadLocalData[14]; // 112 bytes
+
+#endif // SHARE_GC_SHARED_GCTHREADLOCALDATA_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gc_globals.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,771 @@
+/*
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_GC_GLOBALS_HPP
+#define SHARE_GC_SHARED_GC_GLOBALS_HPP
+
+#include "gc/serial/serial_globals.hpp"
+#include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/cms/cms_globals.hpp"
+#include "gc/g1/g1_globals.hpp"
+#include "gc/parallel/parallel_globals.hpp"
+#endif
+
+#define GC_FLAGS(develop,                                                   \
+                 develop_pd,                                                \
+                 product,                                                   \
+                 product_pd,                                                \
+                 diagnostic,                                                \
+                 diagnostic_pd,                                             \
+                 experimental,                                              \
+                 notproduct,                                                \
+                 manageable,                                                \
+                 product_rw,                                                \
+                 lp64_product,                                              \
+                 range,                                                     \
+                 constraint,                                                \
+                 writeable)                                                 \
+                                                                            \
+  ALL_GCS_ONLY(GC_CMS_FLAGS(                                                \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable))                                                             \
+                                                                            \
+  ALL_GCS_ONLY(GC_G1_FLAGS(                                                 \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable))                                                             \
+                                                                            \
+  ALL_GCS_ONLY(GC_PARALLEL_FLAGS(                                           \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable))                                                             \
+                                                                            \
+  GC_SERIAL_FLAGS(                                                          \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable)                                                              \
+                                                                            \
+  /* gc */                                                                  \
+                                                                            \
+  product(bool, UseConcMarkSweepGC, false,                                  \
+          "Use Concurrent Mark-Sweep GC in the old generation")             \
+                                                                            \
+  product(bool, UseSerialGC, false,                                         \
+          "Use the Serial garbage collector")                               \
+                                                                            \
+  product(bool, UseG1GC, false,                                             \
+          "Use the Garbage-First garbage collector")                        \
+                                                                            \
+  product(bool, UseParallelGC, false,                                       \
+          "Use the Parallel Scavenge garbage collector")                    \
+                                                                            \
+  product(bool, UseParallelOldGC, false,                                    \
+          "Use the Parallel Old garbage collector")                         \
+                                                                            \
+  product(uint, ParallelGCThreads, 0,                                       \
+          "Number of parallel threads parallel gc will use")                \
+          constraint(ParallelGCThreadsConstraintFunc,AfterErgo)             \
+                                                                            \
+  diagnostic(bool, UseSemaphoreGCThreadsSynchronization, true,              \
+            "Use semaphore synchronization for the GC Threads, "            \
+            "instead of synchronization based on mutexes")                  \
+                                                                            \
+  product(bool, UseDynamicNumberOfGCThreads, true,                          \
+          "Dynamically choose the number of threads up to a maximum of "    \
+          "ParallelGCThreads parallel collectors will use for garbage "     \
+          "collection work")                                                \
+                                                                            \
+  diagnostic(bool, InjectGCWorkerCreationFailure, false,                    \
+             "Inject thread creation failures for "                         \
+             "UseDynamicNumberOfGCThreads")                                 \
+                                                                            \
+  diagnostic(bool, ForceDynamicNumberOfGCThreads, false,                    \
+          "Force dynamic selection of the number of "                       \
+          "parallel threads parallel gc will use to aid debugging")         \
+                                                                            \
+  product(size_t, HeapSizePerGCThread, ScaleForWordSize(32*M),              \
+          "Size of heap (bytes) per GC thread used in calculating the "     \
+          "number of GC threads")                                           \
+          range((size_t)os::vm_page_size(), (size_t)max_uintx)              \
+                                                                            \
+  product(uint, ConcGCThreads, 0,                                           \
+          "Number of threads concurrent gc will use")                       \
+          constraint(ConcGCThreadsConstraintFunc,AfterErgo)                 \
+                                                                            \
+  product(uint, GCTaskTimeStampEntries, 200,                                \
+          "Number of time stamp entries per gc worker thread")              \
+          range(1, max_jint)                                                \
+                                                                            \
+  product(bool, AlwaysTenure, false,                                        \
+          "Always tenure objects in eden (ParallelGC only)")                \
+                                                                            \
+  product(bool, NeverTenure, false,                                         \
+          "Never tenure objects in eden, may tenure on overflow "           \
+          "(ParallelGC only)")                                              \
+                                                                            \
+  product(bool, ScavengeBeforeFullGC, true,                                 \
+          "Scavenge youngest generation before each full GC.")              \
+                                                                            \
+  product(bool, ExplicitGCInvokesConcurrent, false,                         \
+          "A System.gc() request invokes a concurrent collection; "         \
+          "(effective only when using concurrent collectors)")              \
+                                                                            \
+  product(bool, GCLockerInvokesConcurrent, false,                           \
+          "The exit of a JNI critical section necessitating a scavenge, "   \
+          "also kicks off a background concurrent collection")              \
+                                                                            \
+  product(uintx, GCLockerEdenExpansionPercent, 5,                           \
+          "How much the GC can expand the eden by while the GC locker "     \
+          "is active (as a percentage)")                                    \
+          range(0, 100)                                                     \
+                                                                            \
+  diagnostic(uintx, GCLockerRetryAllocationCount, 2,                        \
+          "Number of times to retry allocations when "                      \
+          "blocked by the GC locker")                                       \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, ParallelGCBufferWastePct, 10,                              \
+          "Wasted fraction of parallel allocation buffer")                  \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, TargetPLABWastePct, 10,                                    \
+          "Target wasted space in last buffer as percent of overall "       \
+          "allocation")                                                     \
+          range(1, 100)                                                     \
+                                                                            \
+  product(uintx, PLABWeight, 75,                                            \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponentially decaying average for ResizePLAB")        \
+          range(0, 100)                                                     \
+                                                                            \
+  product(bool, ResizePLAB, true,                                           \
+          "Dynamically resize (survivor space) promotion LAB's")            \
+                                                                            \
+  product(int, ParGCArrayScanChunk, 50,                                     \
+          "Scan a subset of object array and push remainder, if array is "  \
+          "bigger than this")                                               \
+          range(1, max_jint/3)                                              \
+                                                                            \
+  product(uintx, OldPLABWeight, 50,                                         \
+          "Percentage (0-100) used to weight the current sample when "      \
+          "computing exponentially decaying average for resizing "          \
+          "OldPLABSize")                                                    \
+          range(0, 100)                                                     \
+                                                                            \
+  product(bool, ResizeOldPLAB, true,                                        \
+          "Dynamically resize (old gen) promotion LAB's")                   \
+                                                                            \
+  product(bool, AlwaysPreTouch, false,                                      \
+          "Force all freshly committed pages to be pre-touched")            \
+                                                                            \
+  product(size_t, PreTouchParallelChunkSize, 1 * G,                         \
+          "Per-thread chunk size for parallel memory pre-touch.")           \
+          range(1, SIZE_MAX / 2)                                            \
+                                                                            \
+  /* where does the range max value of (max_jint - 1) come from? */         \
+  product(size_t, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M),         \
+          "Maximum size of marking stack")                                  \
+          range(1, (max_jint - 1))                                          \
+                                                                            \
+  product(size_t, MarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M),             \
+          "Size of marking stack")                                          \
+          constraint(MarkStackSizeConstraintFunc,AfterErgo)                 \
+                                                                            \
+  develop(bool, VerifyBlockOffsetArray, false,                              \
+          "Do (expensive) block offset array verification")                 \
+                                                                            \
+  diagnostic(bool, BlockOffsetArrayUseUnallocatedBlock, false,              \
+          "Maintain _unallocated_block in BlockOffsetArray "                \
+          "(currently applicable only to CMS collector)")                   \
+                                                                            \
+  product(intx, RefDiscoveryPolicy, 0,                                      \
+          "Select type of reference discovery policy: "                     \
+          "reference-based(0) or referent-based(1)")                        \
+          range(ReferenceProcessor::DiscoveryPolicyMin,                     \
+                ReferenceProcessor::DiscoveryPolicyMax)                     \
+                                                                            \
+  product(bool, ParallelRefProcEnabled, false,                              \
+          "Enable parallel reference processing whenever possible")         \
+                                                                            \
+  product(bool, ParallelRefProcBalancingEnabled, true,                      \
+          "Enable balancing of reference processing queues")                \
+                                                                            \
+  product(uintx, InitiatingHeapOccupancyPercent, 45,                        \
+          "The percent occupancy (IHOP) of the current old generation "     \
+          "capacity above which a concurrent mark cycle will be initiated " \
+          "Its value may change over time if adaptive IHOP is enabled, "    \
+          "otherwise the value remains constant. "                          \
+          "In the latter case a value of 0 will result as frequent as "     \
+          "possible concurrent marking cycles. A value of 100 disables "    \
+          "concurrent marking. "                                            \
+          "Fragmentation waste in the old generation is not considered "    \
+          "free space in this calculation. (G1 collector only)")            \
+          range(0, 100)                                                     \
+                                                                            \
+  notproduct(bool, ScavengeALot, false,                                     \
+          "Force scavenge at every Nth exit from the runtime system "       \
+          "(N=ScavengeALotInterval)")                                       \
+                                                                            \
+  develop(bool, FullGCALot, false,                                          \
+          "Force full gc at every Nth exit from the runtime system "        \
+          "(N=FullGCALotInterval)")                                         \
+                                                                            \
+  notproduct(bool, GCALotAtAllSafepoints, false,                            \
+          "Enforce ScavengeALot/GCALot at all potential safepoints")        \
+                                                                            \
+  notproduct(bool, PromotionFailureALot, false,                             \
+          "Use promotion failure handling on every youngest generation "    \
+          "collection")                                                     \
+                                                                            \
+  develop(uintx, PromotionFailureALotCount, 1000,                           \
+          "Number of promotion failures occurring at PLAB "                 \
+          "refill attempts (ParNew) or promotion attempts "                 \
+          "(other young collectors)")                                       \
+                                                                            \
+  develop(uintx, PromotionFailureALotInterval, 5,                           \
+          "Total collections between promotion failures a lot")             \
+                                                                            \
+  experimental(uintx, WorkStealingSleepMillis, 1,                           \
+          "Sleep time when sleep is used for yields")                       \
+                                                                            \
+  experimental(uintx, WorkStealingYieldsBeforeSleep, 5000,                  \
+          "Number of yields before a sleep is done during work stealing")   \
+                                                                            \
+  experimental(uintx, WorkStealingHardSpins, 4096,                          \
+          "Number of iterations in a spin loop between checks on "          \
+          "time out of hard spin")                                          \
+                                                                            \
+  experimental(uintx, WorkStealingSpinToYieldRatio, 10,                     \
+          "Ratio of hard spins to calls to yield")                          \
+                                                                            \
+  develop(uintx, ObjArrayMarkingStride, 2048,                               \
+          "Number of object array elements to push onto the marking stack " \
+          "before pushing a continuation entry")                            \
+                                                                            \
+  develop(bool, MetadataAllocationFailALot, false,                          \
+          "Fail metadata allocations at intervals controlled by "           \
+          "MetadataAllocationFailALotInterval")                             \
+                                                                            \
+  develop(uintx, MetadataAllocationFailALotInterval, 1000,                  \
+          "Metadata allocation failure a lot interval")                     \
+                                                                            \
+  notproduct(bool, ExecuteInternalVMTests, false,                           \
+          "Enable execution of internal VM tests")                          \
+                                                                            \
+  notproduct(bool, VerboseInternalVMTests, false,                           \
+          "Turn on logging for internal VM tests.")                         \
+                                                                            \
+  product(bool, ExecutingUnitTests, false,                                  \
+          "Whether the JVM is running unit tests or not")                   \
+                                                                            \
+  product_pd(bool, UseTLAB, "Use thread-local object allocation")           \
+                                                                            \
+  product_pd(bool, ResizeTLAB,                                              \
+          "Dynamically resize TLAB size for threads")                       \
+                                                                            \
+  product(bool, ZeroTLAB, false,                                            \
+          "Zero out the newly created TLAB")                                \
+                                                                            \
+  product(bool, TLABStats, true,                                            \
+          "Provide more detailed and expensive TLAB statistics.")           \
+                                                                            \
+  product_pd(bool, NeverActAsServerClassMachine,                            \
+          "Never act like a server-class machine")                          \
+                                                                            \
+  product(bool, AlwaysActAsServerClassMachine, false,                       \
+          "Always act like a server-class machine")                         \
+                                                                            \
+  product_pd(uint64_t, MaxRAM,                                              \
+          "Real memory size (in bytes) used to set maximum heap size")      \
+          range(0, 0XFFFFFFFFFFFFFFFF)                                      \
+                                                                            \
+  product(bool, AggressiveHeap, false,                                      \
+          "Optimize heap options for long-running memory intensive apps")   \
+                                                                            \
+  product(size_t, ErgoHeapSizeLimit, 0,                                     \
+          "Maximum ergonomically set heap size (in bytes); zero means use " \
+          "MaxRAM * MaxRAMPercentage / 100")                                \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, MaxRAMFraction, 4,                                         \
+          "Maximum fraction (1/n) of real memory used for maximum heap "    \
+          "size. "                                                          \
+          "Deprecated, use MaxRAMPercentage instead")                       \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, MinRAMFraction, 2,                                         \
+          "Minimum fraction (1/n) of real memory used for maximum heap "    \
+          "size on systems with small physical memory size. "               \
+          "Deprecated, use MinRAMPercentage instead")                       \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, InitialRAMFraction, 64,                                    \
+          "Fraction (1/n) of real memory used for initial heap size. "      \
+          "Deprecated, use InitialRAMPercentage instead")                   \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(double, MaxRAMPercentage, 25.0,                                   \
+          "Maximum percentage of real memory used for maximum heap size")   \
+          range(0.0, 100.0)                                                 \
+                                                                            \
+  product(double, MinRAMPercentage, 50.0,                                   \
+          "Minimum percentage of real memory used for maximum heap"         \
+          "size on systems with small physical memory size")                \
+          range(0.0, 100.0)                                                 \
+                                                                            \
+  product(double, InitialRAMPercentage, 1.5625,                             \
+          "Percentage of real memory used for initial heap size")           \
+          range(0.0, 100.0)                                                 \
+                                                                            \
+  product(int, ActiveProcessorCount, -1,                                    \
+          "Specify the CPU count the VM should use and report as active")   \
+                                                                            \
+  develop(uintx, MaxVirtMemFraction, 2,                                     \
+          "Maximum fraction (1/n) of virtual memory used for ergonomically "\
+          "determining maximum heap size")                                  \
+                                                                            \
+  product(bool, UseAdaptiveSizePolicy, true,                                \
+          "Use adaptive generation sizing policies")                        \
+                                                                            \
+  product(bool, UsePSAdaptiveSurvivorSizePolicy, true,                      \
+          "Use adaptive survivor sizing policies")                          \
+                                                                            \
+  product(bool, UseAdaptiveGenerationSizePolicyAtMinorCollection, true,     \
+          "Use adaptive young-old sizing policies at minor collections")    \
+                                                                            \
+  product(bool, UseAdaptiveGenerationSizePolicyAtMajorCollection, true,     \
+          "Use adaptive young-old sizing policies at major collections")    \
+                                                                            \
+  product(bool, UseAdaptiveSizePolicyWithSystemGC, false,                   \
+          "Include statistics from System.gc() for adaptive size policy")   \
+                                                                            \
+  product(bool, UseAdaptiveGCBoundary, false,                               \
+          "Allow young-old boundary to move")                               \
+                                                                            \
+  develop(intx, PSAdaptiveSizePolicyResizeVirtualSpaceAlot, -1,             \
+          "Resize the virtual spaces of the young or old generations")      \
+          range(-1, 1)                                                      \
+                                                                            \
+  product(uintx, AdaptiveSizeThroughPutPolicy, 0,                           \
+          "Policy for changing generation size for throughput goals")       \
+          range(0, 1)                                                       \
+                                                                            \
+  product(uintx, AdaptiveSizePolicyInitializingSteps, 20,                   \
+          "Number of steps where heuristics is used before data is used")   \
+          range(0, max_uintx)                                               \
+                                                                            \
+  develop(uintx, AdaptiveSizePolicyReadyThreshold, 5,                       \
+          "Number of collections before the adaptive sizing is started")    \
+                                                                            \
+  product(uintx, AdaptiveSizePolicyOutputInterval, 0,                       \
+          "Collection interval for printing information; zero means never") \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(bool, UseAdaptiveSizePolicyFootprintGoal, true,                   \
+          "Use adaptive minimum footprint as a goal")                       \
+                                                                            \
+  product(uintx, AdaptiveSizePolicyWeight, 10,                              \
+          "Weight given to exponential resizing, between 0 and 100")        \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, AdaptiveTimeWeight,       25,                              \
+          "Weight given to time in adaptive policy, between 0 and 100")     \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, PausePadding, 1,                                           \
+          "How much buffer to keep for pause time")                         \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, PromotedPadding, 3,                                        \
+          "How much buffer to keep for promotion failure")                  \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, SurvivorPadding, 3,                                        \
+          "How much buffer to keep for survivor overflow")                  \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, ThresholdTolerance, 10,                                    \
+          "Allowed collection cost difference between generations")         \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, AdaptiveSizePolicyCollectionCostMargin, 50,                \
+          "If collection costs are within margin, reduce both by full "     \
+          "delta")                                                          \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, YoungGenerationSizeIncrement, 20,                          \
+          "Adaptive size percentage change in young generation")            \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, YoungGenerationSizeSupplement, 80,                         \
+          "Supplement to YoungedGenerationSizeIncrement used at startup")   \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, YoungGenerationSizeSupplementDecay, 8,                     \
+          "Decay factor to YoungedGenerationSizeSupplement")                \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, TenuredGenerationSizeIncrement, 20,                        \
+          "Adaptive size percentage change in tenured generation")          \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, TenuredGenerationSizeSupplement, 80,                       \
+          "Supplement to TenuredGenerationSizeIncrement used at startup")   \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, TenuredGenerationSizeSupplementDecay, 2,                   \
+          "Decay factor to TenuredGenerationSizeIncrement")                 \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(uintx, MaxGCPauseMillis, max_uintx - 1,                           \
+          "Adaptive size policy maximum GC pause time goal in millisecond, "\
+          "or (G1 Only) the maximum GC time per MMU time slice")            \
+          range(1, max_uintx - 1)                                           \
+          constraint(MaxGCPauseMillisConstraintFunc,AfterErgo)              \
+                                                                            \
+  product(uintx, GCPauseIntervalMillis, 0,                                  \
+          "Time slice for MMU specification")                               \
+          constraint(GCPauseIntervalMillisConstraintFunc,AfterErgo)         \
+                                                                            \
+  product(uintx, MaxGCMinorPauseMillis, max_uintx,                          \
+          "Adaptive size policy maximum GC minor pause time goal "          \
+          "in millisecond")                                                 \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, GCTimeRatio, 99,                                           \
+          "Adaptive size policy application time to GC time ratio")         \
+          range(0, max_juint)                                               \
+                                                                            \
+  product(uintx, AdaptiveSizeDecrementScaleFactor, 4,                       \
+          "Adaptive size scale down factor for shrinking")                  \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(bool, UseAdaptiveSizeDecayMajorGCCost, true,                      \
+          "Adaptive size decays the major cost for long major intervals")   \
+                                                                            \
+  product(uintx, AdaptiveSizeMajorGCDecayTimeScale, 10,                     \
+          "Time scale over which major costs decay")                        \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, MinSurvivorRatio, 3,                                       \
+          "Minimum ratio of young generation/survivor space size")          \
+          range(3, max_uintx)                                               \
+                                                                            \
+  product(uintx, InitialSurvivorRatio, 8,                                   \
+          "Initial ratio of young generation/survivor space size")          \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(size_t, BaseFootPrintEstimate, 256*M,                             \
+          "Estimate of footprint other than Java Heap")                     \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(bool, UseGCOverheadLimit, true,                                   \
+          "Use policy to limit of proportion of time spent in GC "          \
+          "before an OutOfMemory error is thrown")                          \
+                                                                            \
+  product(uintx, GCTimeLimit, 98,                                           \
+          "Limit of the proportion of time spent in GC before "             \
+          "an OutOfMemoryError is thrown (used with GCHeapFreeLimit)")      \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, GCHeapFreeLimit, 2,                                        \
+          "Minimum percentage of free space after a full GC before an "     \
+          "OutOfMemoryError is thrown (used with GCTimeLimit)")             \
+          range(0, 100)                                                     \
+                                                                            \
+  develop(uintx, AdaptiveSizePolicyGCTimeLimitThreshold, 5,                 \
+          "Number of consecutive collections before gc time limit fires")   \
+          range(1, max_uintx)                                               \
+                                                                            \
+  product(intx, PrefetchCopyIntervalInBytes, -1,                            \
+          "How far ahead to prefetch destination area (<= 0 means off)")    \
+          range(-1, max_jint)                                               \
+                                                                            \
+  product(intx, PrefetchScanIntervalInBytes, -1,                            \
+          "How far ahead to prefetch scan area (<= 0 means off)")           \
+          range(-1, max_jint)                                               \
+                                                                            \
+  product(intx, PrefetchFieldsAhead, -1,                                    \
+          "How many fields ahead to prefetch in oop scan (<= 0 means off)") \
+          range(-1, max_jint)                                               \
+                                                                            \
+  diagnostic(bool, VerifyDuringStartup, false,                              \
+          "Verify memory system before executing any Java code "            \
+          "during VM initialization")                                       \
+                                                                            \
+  diagnostic(bool, VerifyBeforeExit, trueInDebug,                           \
+          "Verify system before exiting")                                   \
+                                                                            \
+  diagnostic(bool, VerifyBeforeGC, false,                                   \
+          "Verify memory system before GC")                                 \
+                                                                            \
+  diagnostic(bool, VerifyAfterGC, false,                                    \
+          "Verify memory system after GC")                                  \
+                                                                            \
+  diagnostic(bool, VerifyDuringGC, false,                                   \
+          "Verify memory system during GC (between phases)")                \
+                                                                            \
+  diagnostic(ccstrlist, VerifyGCType, "",                                   \
+             "GC type(s) to verify when Verify*GC is enabled."              \
+             "Available types are collector specific.")                     \
+                                                                            \
+  diagnostic(ccstrlist, VerifySubSet, "",                                   \
+          "Memory sub-systems to verify when Verify*GC flag(s) "            \
+          "are enabled. One or more sub-systems can be specified "          \
+          "in a comma separated string. Sub-systems are: "                  \
+          "threads, heap, symbol_table, string_table, codecache, "          \
+          "dictionary, classloader_data_graph, metaspace, jni_handles, "    \
+          "codecache_oops")                                                 \
+                                                                            \
+  diagnostic(bool, GCParallelVerificationEnabled, true,                     \
+          "Enable parallel memory system verification")                     \
+                                                                            \
+  diagnostic(bool, DeferInitialCardMark, false,                             \
+          "When +ReduceInitialCardMarks, explicitly defer any that "        \
+          "may arise from new_pre_store_barrier")                           \
+                                                                            \
+  product(bool, UseCondCardMark, false,                                     \
+          "Check for already marked card before updating card table")       \
+                                                                            \
+  diagnostic(bool, VerifyRememberedSets, false,                             \
+          "Verify GC remembered sets")                                      \
+                                                                            \
+  diagnostic(bool, VerifyObjectStartArray, true,                            \
+          "Verify GC object start array if verify before/after")            \
+                                                                            \
+  product(bool, DisableExplicitGC, false,                                   \
+          "Ignore calls to System.gc()")                                    \
+                                                                            \
+  product(bool, BindGCTaskThreadsToCPUs, false,                             \
+          "Bind GCTaskThreads to CPUs if possible")                         \
+                                                                            \
+  product(bool, UseGCTaskAffinity, false,                                   \
+          "Use worker affinity when asking for GCTasks")                    \
+                                                                            \
+  product(bool, PrintGC, false,                                             \
+          "Print message at garbage collection. "                           \
+          "Deprecated, use -Xlog:gc instead.")                              \
+                                                                            \
+  product(bool, PrintGCDetails, false,                                      \
+          "Print more details at garbage collection. "                      \
+          "Deprecated, use -Xlog:gc* instead.")                             \
+                                                                            \
+  develop(intx, ConcGCYieldTimeout, 0,                                      \
+          "If non-zero, assert that GC threads yield within this "          \
+          "number of milliseconds")                                         \
+          range(0, max_intx)                                                \
+                                                                            \
+  notproduct(intx, ScavengeALotInterval,     1,                             \
+          "Interval between which scavenge will occur with +ScavengeALot")  \
+                                                                            \
+  notproduct(intx, FullGCALotInterval,     1,                               \
+          "Interval between which full gc will occur with +FullGCALot")     \
+                                                                            \
+  notproduct(intx, FullGCALotStart,     0,                                  \
+          "For which invocation to start FullGCAlot")                       \
+                                                                            \
+  notproduct(intx, FullGCALotDummies,  32*K,                                \
+          "Dummy object allocated with +FullGCALot, forcing all objects "   \
+          "to move")                                                        \
+                                                                            \
+  /* gc parameters */                                                       \
+  product(size_t, InitialHeapSize, 0,                                       \
+          "Initial heap size (in bytes); zero means use ergonomics")        \
+          constraint(InitialHeapSizeConstraintFunc,AfterErgo)               \
+                                                                            \
+  product(size_t, MaxHeapSize, ScaleForWordSize(96*M),                      \
+          "Maximum heap size (in bytes)")                                   \
+          constraint(MaxHeapSizeConstraintFunc,AfterErgo)                   \
+                                                                            \
+  product(size_t, OldSize, ScaleForWordSize(4*M),                           \
+          "Initial tenured generation size (in bytes)")                     \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(size_t, NewSize, ScaleForWordSize(1*M),                           \
+          "Initial new generation size (in bytes)")                         \
+          constraint(NewSizeConstraintFunc,AfterErgo)                       \
+                                                                            \
+  product(size_t, MaxNewSize, max_uintx,                                    \
+          "Maximum new generation size (in bytes), max_uintx means set "    \
+          "ergonomically")                                                  \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product_pd(size_t, HeapBaseMinAddress,                                    \
+          "OS specific low limit for heap base address")                    \
+          constraint(HeapBaseMinAddressConstraintFunc,AfterErgo)            \
+                                                                            \
+  product(size_t, PretenureSizeThreshold, 0,                                \
+          "Maximum size in bytes of objects allocated in DefNew "           \
+          "generation; zero means no maximum")                              \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(size_t, MinTLABSize, 2*K,                                         \
+          "Minimum allowed TLAB size (in bytes)")                           \
+          range(1, max_uintx/2)                                             \
+          constraint(MinTLABSizeConstraintFunc,AfterMemoryInit)             \
+                                                                            \
+  product(size_t, TLABSize, 0,                                              \
+          "Starting TLAB size (in bytes); zero means set ergonomically")    \
+          constraint(TLABSizeConstraintFunc,AfterMemoryInit)                \
+                                                                            \
+  product(size_t, YoungPLABSize, 4096,                                      \
+          "Size of young gen promotion LAB's (in HeapWords)")               \
+          constraint(YoungPLABSizeConstraintFunc,AfterMemoryInit)           \
+                                                                            \
+  product(size_t, OldPLABSize, 1024,                                        \
+          "Size of old gen promotion LAB's (in HeapWords), or Number "      \
+          "of blocks to attempt to claim when refilling CMS LAB's")         \
+          constraint(OldPLABSizeConstraintFunc,AfterMemoryInit)             \
+                                                                            \
+  product(uintx, TLABAllocationWeight, 35,                                  \
+          "Allocation averaging weight")                                    \
+          range(0, 100)                                                     \
+                                                                            \
+  /* Limit the lower bound of this flag to 1 as it is used  */              \
+  /* in a division expression.                              */              \
+  product(uintx, TLABWasteTargetPercent, 1,                                 \
+          "Percentage of Eden that can be wasted")                          \
+          range(1, 100)                                                     \
+                                                                            \
+  product(uintx, TLABRefillWasteFraction,    64,                            \
+          "Maximum TLAB waste at a refill (internal fragmentation)")        \
+          range(1, max_juint)                                               \
+                                                                            \
+  product(uintx, TLABWasteIncrement,    4,                                  \
+          "Increment allowed waste at slow allocation")                     \
+          range(0, max_jint)                                                \
+          constraint(TLABWasteIncrementConstraintFunc,AfterMemoryInit)      \
+                                                                            \
+  product(uintx, SurvivorRatio, 8,                                          \
+          "Ratio of eden/survivor space size")                              \
+          range(1, max_uintx-2)                                             \
+          constraint(SurvivorRatioConstraintFunc,AfterMemoryInit)           \
+                                                                            \
+  product(uintx, NewRatio, 2,                                               \
+          "Ratio of old/new generation sizes")                              \
+          range(0, max_uintx-1)                                             \
+                                                                            \
+  product_pd(size_t, NewSizeThreadIncrease,                                 \
+          "Additional size added to desired new generation size per "       \
+          "non-daemon thread (in bytes)")                                   \
+          range(0, max_uintx)                                               \
+                                                                            \
+  product(uintx, QueuedAllocationWarningCount, 0,                           \
+          "Number of times an allocation that queues behind a GC "          \
+          "will retry before printing a warning")                           \
+          range(0, max_uintx)                                               \
+                                                                            \
+  diagnostic(uintx, VerifyGCStartAt,   0,                                   \
+          "GC invoke count where +VerifyBefore/AfterGC kicks in")           \
+          range(0, max_uintx)                                               \
+                                                                            \
+  diagnostic(intx, VerifyGCLevel,     0,                                    \
+          "Generation level at which to start +VerifyBefore/AfterGC")       \
+          range(0, 1)                                                       \
+                                                                            \
+  product(uintx, MaxTenuringThreshold,    15,                               \
+          "Maximum value for tenuring threshold")                           \
+          range(0, markOopDesc::max_age + 1)                                \
+          constraint(MaxTenuringThresholdConstraintFunc,AfterErgo)          \
+                                                                            \
+  product(uintx, InitialTenuringThreshold,    7,                            \
+          "Initial value for tenuring threshold")                           \
+          range(0, markOopDesc::max_age + 1)                                \
+          constraint(InitialTenuringThresholdConstraintFunc,AfterErgo)      \
+                                                                            \
+  product(uintx, TargetSurvivorRatio,    50,                                \
+          "Desired percentage of survivor space used after scavenge")       \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uintx, MarkSweepDeadRatio,     5,                                 \
+          "Percentage (0-100) of the old gen allowed as dead wood. "        \
+          "Serial mark sweep treats this as both the minimum and maximum "  \
+          "value. "                                                         \
+          "CMS uses this value only if it falls back to mark sweep. "       \
+          "Par compact uses a variable scale based on the density of the "  \
+          "generation and treats this as the maximum value when the heap "  \
+          "is either completely full or completely empty.  Par compact "    \
+          "also has a smaller default value; see arguments.cpp.")           \
+          range(0, 100)                                                     \
+                                                                            \
+  product(uint, MarkSweepAlwaysCompactCount,     4,                         \
+          "How often should we fully compact the heap (ignoring the dead "  \
+          "space parameters)")                                              \
+          range(1, max_juint)                                               \
+                                                                            \
+  develop(uintx, GCExpandToAllocateDelayMillis, 0,                          \
+          "Delay between expansion and allocation (in milliseconds)")       \
+                                                                            \
+  product(uintx, GCDrainStackTargetSize, 64,                                \
+          "Number of entries we will try to leave on the stack "            \
+          "during parallel gc")                                             \
+          range(0, max_juint)
+
+#endif // SHARE_GC_SHARED_GC_GLOBALS_HPP
--- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -110,11 +110,11 @@
 
   initialize_reserved_region((HeapWord*)heap_rs.base(), (HeapWord*)(heap_rs.base() + heap_rs.size()));
 
-  _rem_set = new CardTableRS(reserved_region());
+  _rem_set = create_rem_set(reserved_region());
   _rem_set->initialize();
   CardTableBarrierSet *bs = new CardTableBarrierSet(_rem_set);
   bs->initialize();
-  set_barrier_set(bs);
+  BarrierSet::set_barrier_set(bs);
 
   ReservedSpace young_rs = heap_rs.first_part(_young_gen_spec->max_size(), false, false);
   _young_gen = _young_gen_spec->init(young_rs, rem_set());
@@ -127,6 +127,10 @@
   return JNI_OK;
 }
 
+CardTableRS* GenCollectedHeap::create_rem_set(const MemRegion& reserved_region) {
+  return new CardTableRS(reserved_region, false /* scan_concurrently */);
+}
+
 void GenCollectedHeap::initialize_size_policy(size_t init_eden_size,
                                               size_t init_promo_size,
                                               size_t init_survivor_size) {
--- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -167,6 +167,7 @@
 
   // Returns JNI_OK on success
   virtual jint initialize();
+  virtual CardTableRS* create_rem_set(const MemRegion& reserved_region);
 
   void initialize_size_policy(size_t init_eden_size,
                               size_t init_promo_size,
--- a/src/hotspot/share/gc/shared/genOopClosures.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/genOopClosures.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -22,9 +22,12 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/serial/serial_specialized_oop_closures.hpp"
 #include "gc/shared/genOopClosures.inline.hpp"
-#include "gc/shared/specialized_oop_closures.hpp"
 #include "memory/iterator.inline.hpp"
 
+void FilteringClosure::do_oop(oop* p)       { do_oop_nv(p); }
+void FilteringClosure::do_oop(narrowOop* p) { do_oop_nv(p); }
+
 // Generate Serial GC specialized oop_oop_iterate functions.
 SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(ALL_KLASS_OOP_OOP_ITERATE_DEFN)
--- a/src/hotspot/share/gc/shared/genOopClosures.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/genOopClosures.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,6 +33,7 @@
 #include "gc/shared/space.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/compressedOops.inline.hpp"
+#include "oops/oop.inline.hpp"
 
 inline OopsInGenClosure::OopsInGenClosure(Generation* gen) :
   ExtendedOopClosure(gen->ref_processor()), _orig_gen(gen), _rs(NULL) {
--- a/src/hotspot/share/gc/shared/memset_with_concurrent_readers.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/memset_with_concurrent_readers.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,9 +30,6 @@
 #include <stddef.h>
 #include <string.h>
 
-// Only used by concurrent collectors.
-#if INCLUDE_ALL_GCS
-
 // Fill a block of memory with value, like memset, but with the
 // understanding that there may be concurrent readers of that memory.
 void memset_with_concurrent_readers(void* to, int value, size_t size);
@@ -50,6 +47,4 @@
 
 #endif // End of target dispatch.
 
-#endif // INCLUDE_ALL_GCS
-
 #endif // SRC_SHARE_VM_GC_SHARED_MEMSETWITHCONCURRENTREADERS_HPP
--- a/src/hotspot/share/gc/shared/oopStorage.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorage.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -687,7 +687,6 @@
 }
 
 // Parallel iteration support
-#if INCLUDE_ALL_GCS
 
 static char* not_started_marker_dummy = NULL;
 static void* const not_started_marker = &not_started_marker_dummy;
@@ -737,8 +736,6 @@
   return static_cast<Block*>(next);
 }
 
-#endif // INCLUDE_ALL_GCS
-
 const char* OopStorage::name() const { return _name; }
 
 #ifndef PRODUCT
--- a/src/hotspot/share/gc/shared/oopStorage.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorage.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -146,11 +146,9 @@
   template<typename IsAliveClosure, typename Closure>
   inline void weak_oops_do(IsAliveClosure* is_alive, Closure* closure);
 
-#if INCLUDE_ALL_GCS
   // Parallel iteration is for the exclusive use of the GC.
   // Other clients must use serial iteration.
   template<bool concurrent, bool is_const> class ParState;
-#endif // INCLUDE_ALL_GCS
 
   // Block cleanup functions are for the exclusive use of the GC.
   // Both stop deleting if there is an in-progress concurrent iteration.
@@ -244,10 +242,8 @@
   template<typename F, typename Storage>
   static bool iterate_impl(F f, Storage* storage);
 
-#if INCLUDE_ALL_GCS
   // Implementation support for parallel iteration
   class BasicParState;
-#endif // INCLUDE_ALL_GCS
 
   // Wrapper for OopClosure-style function, so it can be used with
   // iterate.  Assume p is of type oop*.  Then cl->do_oop(p) must be a
--- a/src/hotspot/share/gc/shared/oopStorageParState.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorageParState.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,8 +28,6 @@
 #include "gc/shared/oopStorage.hpp"
 #include "utilities/macros.hpp"
 
-#if INCLUDE_ALL_GCS
-
 //////////////////////////////////////////////////////////////////////////////
 // Support for parallel and optionally concurrent state iteration.
 //
@@ -192,6 +190,4 @@
   void weak_oops_do(IsAliveClosure* is_alive, Closure* cl);
 };
 
-#endif // INCLUDE_ALL_GCS
-
 #endif // SHARE_GC_SHARED_OOPSTORAGEPARSTATE_HPP
--- a/src/hotspot/share/gc/shared/oopStorageParState.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/oopStorageParState.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -30,8 +30,6 @@
 #include "metaprogramming/conditional.hpp"
 #include "utilities/macros.hpp"
 
-#if INCLUDE_ALL_GCS
-
 template<typename F>
 class OopStorage::BasicParState::AlwaysTrueFn {
   F _f;
@@ -86,6 +84,4 @@
   this->iterate(if_alive_fn(is_alive, oop_fn(cl)));
 }
 
-#endif // INCLUDE_ALL_GCS
-
 #endif // SHARE_GC_SHARED_OOPSTORAGEPARSTATE_INLINE_HPP
--- a/src/hotspot/share/gc/shared/preservedMarks.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/preservedMarks.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 #include "gc/shared/workgroup.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
+#include "oops/oop.inline.hpp"
 #include "utilities/macros.hpp"
 
 void PreservedMarks::restore() {
--- a/src/hotspot/share/gc/shared/preservedMarks.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/preservedMarks.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,7 +44,7 @@
     OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) { }
 
     oop get_oop() { return _o; }
-    void set_mark() const { _o->set_mark(_m); }
+    inline void set_mark() const;
     void set_oop(oop obj) { _o = obj; }
   };
   typedef Stack<OopAndMarkOop, mtGC> OopAndMarkOopStack;
--- a/src/hotspot/share/gc/shared/preservedMarks.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/preservedMarks.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,7 +46,7 @@
 }
 
 inline void PreservedMarks::init_forwarded_mark(oop obj) {
-  obj->init_mark();
+  obj->init_mark_raw();
 }
 
 inline void PreservedMarksSet::restore(RestorePreservedMarksTaskExecutor* executor) {
@@ -78,4 +78,8 @@
              // cache size to 0.
              0 /* max_cache_size */) { }
 
+void PreservedMarks::OopAndMarkOop::set_mark() const {
+  _o->set_mark_raw(_m);
+}
+
 #endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP
--- a/src/hotspot/share/gc/shared/space.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/space.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -397,7 +397,7 @@
   } else {
     // if the object isn't moving we can just set the mark to the default
     // mark and handle it specially later on.
-    q->init_mark();
+    q->init_mark_raw();
     assert(q->forwardee() == NULL, "should be forwarded to NULL");
   }
 
@@ -695,14 +695,14 @@
     // allocate uninitialized int array
     typeArrayOop t = (typeArrayOop) allocate(size);
     assert(t != NULL, "allocation should succeed");
-    t->set_mark(markOopDesc::prototype());
+    t->set_mark_raw(markOopDesc::prototype());
     t->set_klass(Universe::intArrayKlassObj());
     t->set_length((int)length);
   } else {
     assert(size == CollectedHeap::min_fill_size(),
            "size for smallest fake object doesn't match");
     instanceOop obj = (instanceOop) allocate(size);
-    obj->set_mark(markOopDesc::prototype());
+    obj->set_mark_raw(markOopDesc::prototype());
     obj->set_klass_gap(0);
     obj->set_klass(SystemDictionary::Object_klass());
   }
--- a/src/hotspot/share/gc/shared/space.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/space.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,7 @@
 #include "gc/shared/spaceDecorator.hpp"
 #include "memory/universe.hpp"
 #include "oops/oopsHierarchy.hpp"
+#include "oops/oop.inline.hpp"
 #include "runtime/prefetch.inline.hpp"
 #include "runtime/safepoint.hpp"
 
@@ -112,7 +113,7 @@
       _allowed_deadspace_words -= dead_length;
       CollectedHeap::fill_with_object(dead_start, dead_length);
       oop obj = oop(dead_start);
-      obj->set_mark(obj->mark()->set_marked());
+      obj->set_mark_raw(obj->mark_raw()->set_marked());
 
       assert(dead_length == (size_t)obj->size(), "bad filler object size");
       log_develop_trace(gc, compaction)("Inserting object to dead space: " PTR_FORMAT ", " PTR_FORMAT ", " SIZE_FORMAT "b",
@@ -159,8 +160,8 @@
 
   while (cur_obj < scan_limit) {
     assert(!space->scanned_block_is_obj(cur_obj) ||
-           oop(cur_obj)->mark()->is_marked() || oop(cur_obj)->mark()->is_unlocked() ||
-           oop(cur_obj)->mark()->has_bias_pattern(),
+           oop(cur_obj)->mark_raw()->is_marked() || oop(cur_obj)->mark_raw()->is_unlocked() ||
+           oop(cur_obj)->mark_raw()->has_bias_pattern(),
            "these are the only valid states during a mark sweep");
     if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) {
       // prefetch beyond cur_obj
@@ -335,7 +336,7 @@
       // copy object and reinit its mark
       assert(cur_obj != compaction_top, "everything in this pass should be moving");
       Copy::aligned_conjoint_words(cur_obj, compaction_top, size);
-      oop(compaction_top)->init_mark();
+      oop(compaction_top)->init_mark_raw();
       assert(oop(compaction_top)->klass() != NULL, "should have a class");
 
       debug_only(prev_obj = cur_obj);
--- a/src/hotspot/share/gc/shared/specialized_oop_closures.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/specialized_oop_closures.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,8 +25,10 @@
 #ifndef SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP
 #define SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP
 
+#include "gc/serial/serial_specialized_oop_closures.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc/cms/cms_specialized_oop_closures.hpp"
 #include "gc/g1/g1_specialized_oop_closures.hpp"
 #endif // INCLUDE_ALL_GCS
 
@@ -36,29 +38,9 @@
 // macros in the obvious way to add specializations for new closures.
 
 // Forward declarations.
-class OopClosure;
+class ExtendedOopClosure;
+class NoHeaderExtendedOopClosure;
 class OopsInGenClosure;
-// DefNew
-class ScanClosure;
-class FastScanClosure;
-class FilteringClosure;
-// MarkSweep
-class MarkAndPushClosure;
-class AdjustPointerClosure;
-// ParNew
-class ParScanWithBarrierClosure;
-class ParScanWithoutBarrierClosure;
-// CMS
-class MarkRefsIntoAndScanClosure;
-class ParMarkRefsIntoAndScanClosure;
-class PushAndMarkClosure;
-class ParPushAndMarkClosure;
-class PushOrMarkClosure;
-class ParPushOrMarkClosure;
-class CMSKeepAliveClosure;
-class CMSInnerParMarkAndPushClosure;
-// Misc
-class NoHeaderExtendedOopClosure;
 
 // This macro applies an argument macro to all OopClosures for which we
 // want specialized bodies of "oop_oop_iterate".  The arguments to "f" are:
@@ -72,80 +54,38 @@
 // This is split into several because of a Visual C++ 6.0 compiler bug
 // where very long macros cause the compiler to crash
 
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f)       \
-  f(ScanClosure,_nv)                                    \
-  f(FastScanClosure,_nv)                                \
-  f(FilteringClosure,_nv)
-
-#if INCLUDE_ALL_GCS
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)       \
-  f(ParScanWithBarrierClosure,_nv)                      \
-  f(ParScanWithoutBarrierClosure,_nv)
-#else  // INCLUDE_ALL_GCS
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)
-#endif // INCLUDE_ALL_GCS
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f)       \
-  f(NoHeaderExtendedOopClosure,_nv)                     \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f)             \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f)
-
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)      \
-  f(MarkAndPushClosure,_nv)                             \
-  f(AdjustPointerClosure,_nv)
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f)                 \
+  f(NoHeaderExtendedOopClosure,_nv)                               \
+               SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_S(f)          \
+  ALL_GCS_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_P(f))
 
-#if INCLUDE_ALL_GCS
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f)     \
-  f(MarkRefsIntoAndScanClosure,_nv)                     \
-  f(ParMarkRefsIntoAndScanClosure,_nv)                  \
-  f(PushAndMarkClosure,_nv)                             \
-  f(ParPushAndMarkClosure,_nv)                          \
-  f(PushOrMarkClosure,_nv)                              \
-  f(ParPushOrMarkClosure,_nv)                           \
-  f(CMSKeepAliveClosure,_nv)                            \
-  f(CMSInnerParMarkAndPushClosure,_nv)
-#endif
-
-#if INCLUDE_ALL_GCS
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)       \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)            \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f)           \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f)            \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(f)
-#else  // INCLUDE_ALL_GCS
-#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)       \
-  SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)
-#endif // INCLUDE_ALL_GCS
-
+#define SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)                 \
+               SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_MS(f)         \
+  ALL_GCS_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_CMS(f))       \
+  ALL_GCS_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1(f))        \
+  ALL_GCS_ONLY(SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_G1FULL(f))
 
 // We separate these out, because sometime the general one has
 // a different definition from the specialized ones, and sometimes it
 // doesn't.
 
-#define ALL_OOP_OOP_ITERATE_CLOSURES_1(f)               \
-  f(ExtendedOopClosure,_v)                              \
+#define ALL_OOP_OOP_ITERATE_CLOSURES_1(f)                         \
+  f(ExtendedOopClosure,_v)                                        \
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_1(f)
 
-#define ALL_OOP_OOP_ITERATE_CLOSURES_2(f)               \
+#define ALL_OOP_OOP_ITERATE_CLOSURES_2(f)                         \
   SPECIALIZED_OOP_OOP_ITERATE_CLOSURES_2(f)
 
-#if INCLUDE_ALL_GCS
 // This macro applies an argument macro to all OopClosures for which we
 // want specialized bodies of a family of methods related to
 // "par_oop_iterate".  The arguments to f are the same as above.
 // The "root_class" is the most general class to define; this may be
 // "OopClosure" in some applications and "OopsInGenClosure" in others.
 
-#define SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f)        \
-  f(MarkRefsIntoAndScanClosure,_nv)                    \
-  f(PushAndMarkClosure,_nv)                            \
-  f(ParMarkRefsIntoAndScanClosure,_nv)                 \
-  f(ParPushAndMarkClosure,_nv)
 
-#define ALL_PAR_OOP_ITERATE_CLOSURES(f)                \
-  f(ExtendedOopClosure,_v)                             \
-  SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f)
-#endif // INCLUDE_ALL_GCS
+#define ALL_PAR_OOP_ITERATE_CLOSURES(f)                           \
+  f(ExtendedOopClosure,_v)                                        \
+  ALL_GCS_ONLY(SPECIALIZED_PAR_OOP_ITERATE_CLOSURES(f))
 
 // This macro applies an argument macro to all OopClosures for which we
 // want specialized bodies of a family of methods related to
@@ -153,31 +93,19 @@
 // The "root_class" is the most general class to define; this may be
 // "OopClosure" in some applications and "OopsInGenClosure" in others.
 
-#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f) \
-  f(ScanClosure,_nv)                                     \
-  f(FastScanClosure,_nv)
+#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f)  \
+               SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f)   \
+  ALL_GCS_ONLY(SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f))
 
-#if INCLUDE_ALL_GCS
-#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f) \
-  f(ParScanWithBarrierClosure,_nv)                       \
-  f(ParScanWithoutBarrierClosure,_nv)
-#else  // INCLUDE_ALL_GCS
-#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f)
-#endif // INCLUDE_ALL_GCS
-
-#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f)  \
-  SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_S(f)      \
-  SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG_P(f)
-
-#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f)        \
+#define SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f)                  \
   SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES_YOUNG(f)
 
 // We separate these out, because sometime the general one has
 // a different definition from the specialized ones, and sometimes it
 // doesn't.
 
-#define ALL_SINCE_SAVE_MARKS_CLOSURES(f)                \
-  f(OopsInGenClosure,_v)                                \
+#define ALL_SINCE_SAVE_MARKS_CLOSURES(f)                          \
+  f(OopsInGenClosure,_v)                                          \
   SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(f)
 
 #endif // SHARE_VM_GC_SHARED_SPECIALIZED_OOP_CLOSURES_HPP
--- a/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/gc/shared/threadLocalAllocBuffer.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/threadLocalAllocBuffer.inline.hpp"
 #include "logging/log.hpp"
 #include "memory/resourceArea.hpp"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_GC_SHARED_VMSTRUCTS_GC_HPP
+#define SHARE_GC_SHARED_VMSTRUCTS_GC_HPP
+
+#include "gc/shared/cardGeneration.hpp"
+#include "gc/shared/cardTableRS.hpp"
+#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/genCollectedHeap.hpp"
+#include "gc/shared/generation.hpp"
+#include "gc/shared/generationSpec.hpp"
+#include "gc/shared/oopStorage.hpp"
+#include "gc/shared/space.hpp"
+#include "gc/serial/defNewGeneration.hpp"
+#include "gc/serial/vmStructs_serial.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/cms/vmStructs_cms.hpp"
+#include "gc/g1/vmStructs_g1.hpp"
+#include "gc/parallel/vmStructs_parallelgc.hpp"
+#endif
+
+#define VM_STRUCTS_GC(nonstatic_field,                                                                                               \
+                      volatile_nonstatic_field,                                                                                      \
+                      static_field,                                                                                                  \
+                      unchecked_nonstatic_field)                                                                                     \
+  ALL_GCS_ONLY(VM_STRUCTS_CMSGC(nonstatic_field,                                                                                     \
+                                volatile_nonstatic_field,                                                                            \
+                                static_field))                                                                                       \
+  ALL_GCS_ONLY(VM_STRUCTS_G1GC(nonstatic_field,                                                                                      \
+                               volatile_nonstatic_field,                                                                             \
+                               static_field))                                                                                        \
+  ALL_GCS_ONLY(VM_STRUCTS_PARALLELGC(nonstatic_field,                                                                                \
+                                     volatile_nonstatic_field,                                                                       \
+                                     static_field))                                                                                  \
+  VM_STRUCTS_SERIALGC(nonstatic_field,                                                                                               \
+                      volatile_nonstatic_field,                                                                                      \
+                      static_field)                                                                                                  \
+  /**********************************************************************************/                                               \
+  /* Generation and Space hierarchies                                               */                                               \
+  /**********************************************************************************/                                               \
+                                                                                                                                     \
+  unchecked_nonstatic_field(AgeTable,          sizes,                                         sizeof(AgeTable::sizes))               \
+                                                                                                                                     \
+  nonstatic_field(BarrierSet,                  _fake_rtti,                                    BarrierSet::FakeRtti)                  \
+                                                                                                                                     \
+  nonstatic_field(BarrierSet::FakeRtti,        _concrete_tag,                                 BarrierSet::Name)                      \
+                                                                                                                                     \
+  nonstatic_field(BlockOffsetTable,            _bottom,                                       HeapWord*)                             \
+  nonstatic_field(BlockOffsetTable,            _end,                                          HeapWord*)                             \
+                                                                                                                                     \
+  nonstatic_field(BlockOffsetSharedArray,      _reserved,                                     MemRegion)                             \
+  nonstatic_field(BlockOffsetSharedArray,      _end,                                          HeapWord*)                             \
+  nonstatic_field(BlockOffsetSharedArray,      _vs,                                           VirtualSpace)                          \
+  nonstatic_field(BlockOffsetSharedArray,      _offset_array,                                 u_char*)                               \
+                                                                                                                                     \
+  nonstatic_field(BlockOffsetArray,            _array,                                        BlockOffsetSharedArray*)               \
+  nonstatic_field(BlockOffsetArray,            _sp,                                           Space*)                                \
+  nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_threshold,                        HeapWord*)                             \
+  nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_index,                            size_t)                                \
+                                                                                                                                     \
+  nonstatic_field(BlockOffsetArrayNonContigSpace, _unallocated_block,                         HeapWord*)                             \
+                                                                                                                                     \
+  nonstatic_field(CardGeneration,              _rs,                                           CardTableRS*)                          \
+  nonstatic_field(CardGeneration,              _bts,                                          BlockOffsetSharedArray*)               \
+  nonstatic_field(CardGeneration,              _shrink_factor,                                size_t)                                \
+  nonstatic_field(CardGeneration,              _capacity_at_prologue,                         size_t)                                \
+  nonstatic_field(CardGeneration,              _used_at_prologue,                             size_t)                                \
+                                                                                                                                     \
+  nonstatic_field(CardTable,                   _whole_heap,                                   const MemRegion)                       \
+  nonstatic_field(CardTable,                   _guard_index,                                  const size_t)                          \
+  nonstatic_field(CardTable,                   _last_valid_index,                             const size_t)                          \
+  nonstatic_field(CardTable,                   _page_size,                                    const size_t)                          \
+  nonstatic_field(CardTable,                   _byte_map_size,                                const size_t)                          \
+  nonstatic_field(CardTable,                   _byte_map,                                     jbyte*)                                \
+  nonstatic_field(CardTable,                   _cur_covered_regions,                          int)                                   \
+  nonstatic_field(CardTable,                   _covered,                                      MemRegion*)                            \
+  nonstatic_field(CardTable,                   _committed,                                    MemRegion*)                            \
+  nonstatic_field(CardTable,                   _guard_region,                                 MemRegion)                             \
+  nonstatic_field(CardTable,                   _byte_map_base,                                jbyte*)                                \
+  nonstatic_field(CardTableBarrierSet,         _defer_initial_card_mark,                      bool)                                  \
+  nonstatic_field(CardTableBarrierSet,         _card_table,                                   CardTable*)                            \
+                                                                                                                                     \
+  nonstatic_field(CollectedHeap,               _reserved,                                     MemRegion)                             \
+  nonstatic_field(CollectedHeap,               _is_gc_active,                                 bool)                                  \
+  nonstatic_field(CollectedHeap,               _total_collections,                            unsigned int)                          \
+                                                                                                                                     \
+  nonstatic_field(CompactibleSpace,            _compaction_top,                               HeapWord*)                             \
+  nonstatic_field(CompactibleSpace,            _first_dead,                                   HeapWord*)                             \
+  nonstatic_field(CompactibleSpace,            _end_of_live,                                  HeapWord*)                             \
+                                                                                                                                     \
+  nonstatic_field(ContiguousSpace,             _top,                                          HeapWord*)                             \
+  nonstatic_field(ContiguousSpace,             _concurrent_iteration_safe_limit,              HeapWord*)                             \
+  nonstatic_field(ContiguousSpace,             _saved_mark_word,                              HeapWord*)                             \
+                                                                                                                                     \
+  nonstatic_field(DefNewGeneration,            _old_gen,                                      Generation*)                           \
+  nonstatic_field(DefNewGeneration,            _tenuring_threshold,                           uint)                                  \
+  nonstatic_field(DefNewGeneration,            _age_table,                                    AgeTable)                              \
+  nonstatic_field(DefNewGeneration,            _eden_space,                                   ContiguousSpace*)                      \
+  nonstatic_field(DefNewGeneration,            _from_space,                                   ContiguousSpace*)                      \
+  nonstatic_field(DefNewGeneration,            _to_space,                                     ContiguousSpace*)                      \
+                                                                                                                                     \
+  nonstatic_field(Generation,                  _reserved,                                     MemRegion)                             \
+  nonstatic_field(Generation,                  _virtual_space,                                VirtualSpace)                          \
+  nonstatic_field(Generation,                  _stat_record,                                  Generation::StatRecord)                \
+                                                                                                                                     \
+  nonstatic_field(Generation::StatRecord,      invocations,                                   int)                                   \
+  nonstatic_field(Generation::StatRecord,      accumulated_time,                              elapsedTimer)                          \
+                                                                                                                                     \
+  nonstatic_field(GenerationSpec,              _name,                                         Generation::Name)                      \
+  nonstatic_field(GenerationSpec,              _init_size,                                    size_t)                                \
+  nonstatic_field(GenerationSpec,              _max_size,                                     size_t)                                \
+                                                                                                                                     \
+  nonstatic_field(GenCollectedHeap,            _young_gen,                                    Generation*)                           \
+  nonstatic_field(GenCollectedHeap,            _old_gen,                                      Generation*)                           \
+  nonstatic_field(GenCollectedHeap,            _young_gen_spec,                               GenerationSpec*)                       \
+  nonstatic_field(GenCollectedHeap,            _old_gen_spec,                                 GenerationSpec*)                       \
+                                                                                                                                     \
+  nonstatic_field(HeapWord,                    i,                                             char*)                                 \
+                                                                                                                                     \
+  nonstatic_field(MemRegion,                   _start,                                        HeapWord*)                             \
+  nonstatic_field(MemRegion,                   _word_size,                                    size_t)                                \
+                                                                                                                                     \
+  nonstatic_field(OffsetTableContigSpace,      _offsets,                                      BlockOffsetArray)                      \
+                                                                                                                                     \
+  nonstatic_field(Space,                       _bottom,                                       HeapWord*)                             \
+  nonstatic_field(Space,                       _end,                                          HeapWord*)
+
+#define VM_TYPES_GC(declare_type,                                         \
+                    declare_toplevel_type,                                \
+                    declare_integer_type)                                 \
+  ALL_GCS_ONLY(VM_TYPES_CMSGC(declare_type,                               \
+                             declare_toplevel_type,                       \
+                             declare_integer_type))                       \
+  ALL_GCS_ONLY(VM_TYPES_G1GC(declare_type,                                \
+                             declare_toplevel_type,                       \
+                             declare_integer_type))                       \
+  ALL_GCS_ONLY(VM_TYPES_PARALLELGC(declare_type,                          \
+                                   declare_toplevel_type,                 \
+                                   declare_integer_type))                 \
+  VM_TYPES_SERIALGC(declare_type,                                         \
+                    declare_toplevel_type,                                \
+                    declare_integer_type)                                 \
+  /******************************************/                            \
+  /* Generation and space hierarchies       */                            \
+  /* (needed for run-time type information) */                            \
+  /******************************************/                            \
+                                                                          \
+  declare_toplevel_type(CollectedHeap)                                    \
+           declare_type(GenCollectedHeap,             CollectedHeap)      \
+  declare_toplevel_type(Generation)                                       \
+           declare_type(DefNewGeneration,             Generation)         \
+           declare_type(CardGeneration,               Generation)         \
+  declare_toplevel_type(Space)                                            \
+           declare_type(CompactibleSpace,             Space)              \
+           declare_type(ContiguousSpace,              CompactibleSpace)   \
+           declare_type(OffsetTableContigSpace,       ContiguousSpace)    \
+  declare_toplevel_type(BarrierSet)                                       \
+           declare_type(ModRefBarrierSet,             BarrierSet)         \
+           declare_type(CardTableBarrierSet,          ModRefBarrierSet)   \
+  declare_toplevel_type(CardTable)                                        \
+           declare_type(CardTableRS, CardTable)                           \
+  declare_toplevel_type(BarrierSet::Name)                                 \
+  declare_toplevel_type(BlockOffsetSharedArray)                           \
+  declare_toplevel_type(BlockOffsetTable)                                 \
+           declare_type(BlockOffsetArray,             BlockOffsetTable)   \
+           declare_type(BlockOffsetArrayContigSpace,  BlockOffsetArray)   \
+           declare_type(BlockOffsetArrayNonContigSpace, BlockOffsetArray) \
+                                                                          \
+  /* Miscellaneous other GC types */                                      \
+                                                                          \
+  declare_toplevel_type(AgeTable)                                         \
+  declare_toplevel_type(Generation::StatRecord)                           \
+  declare_toplevel_type(GenerationSpec)                                   \
+  declare_toplevel_type(HeapWord)                                         \
+  declare_toplevel_type(MemRegion)                                        \
+  declare_toplevel_type(ThreadLocalAllocBuffer)                           \
+  declare_toplevel_type(VirtualSpace)                                     \
+                                                                          \
+  /* Pointers to Garbage Collection types */                              \
+                                                                          \
+  declare_toplevel_type(BarrierSet*)                                      \
+  declare_toplevel_type(BlockOffsetSharedArray*)                          \
+  declare_toplevel_type(CardTable*)                                       \
+  declare_toplevel_type(CardTable*const)                                  \
+  declare_toplevel_type(CardTableRS*)                                     \
+  declare_toplevel_type(CardTableBarrierSet*)                             \
+  declare_toplevel_type(CardTableBarrierSet**)                            \
+  declare_toplevel_type(CollectedHeap*)                                   \
+  declare_toplevel_type(ContiguousSpace*)                                 \
+  declare_toplevel_type(DefNewGeneration*)                                \
+  declare_toplevel_type(GenCollectedHeap*)                                \
+  declare_toplevel_type(Generation*)                                      \
+  declare_toplevel_type(GenerationSpec**)                                 \
+  declare_toplevel_type(HeapWord*)                                        \
+  declare_toplevel_type(HeapWord* volatile)                               \
+  declare_toplevel_type(MemRegion*)                                       \
+  declare_toplevel_type(OffsetTableContigSpace*)                          \
+  declare_toplevel_type(Space*)                                           \
+  declare_toplevel_type(ThreadLocalAllocBuffer*)                          \
+                                                                          \
+  declare_toplevel_type(BarrierSet::FakeRtti)
+
+#define VM_INT_CONSTANTS_GC(declare_constant,                               \
+                            declare_constant_with_value)                    \
+  ALL_GCS_ONLY(VM_INT_CONSTANTS_CMSGC(declare_constant,                     \
+                                      declare_constant_with_value))         \
+  ALL_GCS_ONLY(VM_INT_CONSTANTS_G1GC(declare_constant,                      \
+                                     declare_constant_with_value))          \
+  ALL_GCS_ONLY(VM_INT_CONSTANTS_PARALLELGC(declare_constant,                \
+                                           declare_constant_with_value))    \
+  VM_INT_CONSTANTS_SERIALGC(declare_constant,                               \
+                            declare_constant_with_value)                    \
+                                                                            \
+  /********************************************/                            \
+  /* Generation and Space Hierarchy Constants */                            \
+  /********************************************/                            \
+                                                                            \
+  declare_constant(AgeTable::table_size)                                    \
+                                                                            \
+  declare_constant(BarrierSet::ModRef)                                      \
+  declare_constant(BarrierSet::CardTableBarrierSet)                         \
+                                                                            \
+  declare_constant(BOTConstants::LogN)                                      \
+  declare_constant(BOTConstants::LogN_words)                                \
+  declare_constant(BOTConstants::N_bytes)                                   \
+  declare_constant(BOTConstants::N_words)                                   \
+  declare_constant(BOTConstants::LogBase)                                   \
+  declare_constant(BOTConstants::Base)                                      \
+  declare_constant(BOTConstants::N_powers)                                  \
+                                                                            \
+  declare_constant(CardTable::clean_card)                                   \
+  declare_constant(CardTable::last_card)                                    \
+  declare_constant(CardTable::dirty_card)                                   \
+  declare_constant(CardTable::Precise)                                      \
+  declare_constant(CardTable::ObjHeadPreciseArray)                          \
+  declare_constant(CardTable::card_shift)                                   \
+  declare_constant(CardTable::card_size)                                    \
+  declare_constant(CardTable::card_size_in_words)                           \
+                                                                            \
+  declare_constant(CardTableRS::youngergen_card)                            \
+                                                                            \
+  declare_constant(CollectedHeap::Serial)                                   \
+  declare_constant(CollectedHeap::Parallel)                                 \
+  declare_constant(CollectedHeap::CMS)                                      \
+  declare_constant(CollectedHeap::G1)                                       \
+                                                                            \
+  /* constants from Generation::Name enum */                                \
+                                                                            \
+  declare_constant(Generation::DefNew)                                      \
+  declare_constant(Generation::MarkSweepCompact)                            \
+  declare_constant(Generation::Other)                                       \
+                                                                            \
+  declare_constant(Generation::LogOfGenGrain)                               \
+  declare_constant(Generation::GenGrain)                                    \
+
+
+#endif // SHARE_GC_SHARED_VMSTRUCTS_GC_HPP
--- a/src/hotspot/share/interpreter/bytecodeInterpreter.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/interpreter/bytecodeInterpreter.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -689,7 +689,7 @@
             if (hash != markOopDesc::no_hash) {
               header = header->copy_set_hash(hash);
             }
-            if (Atomic::cmpxchg(header, rcvr->mark_addr(), mark) == mark) {
+            if (rcvr->cas_set_mark(header, mark) == mark) {
               if (PrintBiasedLockingStatistics)
                 (*BiasedLocking::revoked_lock_entry_count_addr())++;
             }
@@ -699,7 +699,7 @@
             if (hash != markOopDesc::no_hash) {
               new_header = new_header->copy_set_hash(hash);
             }
-            if (Atomic::cmpxchg(new_header, rcvr->mark_addr(), mark) == mark) {
+            if (rcvr->cas_set_mark(new_header, mark) == mark) {
               if (PrintBiasedLockingStatistics) {
                 (* BiasedLocking::rebiased_lock_entry_count_addr())++;
               }
@@ -718,7 +718,7 @@
             markOop new_header = (markOop) ((uintptr_t) header | thread_ident);
             // Debugging hint.
             DEBUG_ONLY(mon->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);)
-            if (Atomic::cmpxchg(new_header, rcvr->mark_addr(), header) == header) {
+            if (rcvr->cas_set_mark(new_header, header) == header) {
               if (PrintBiasedLockingStatistics) {
                 (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
               }
@@ -734,7 +734,7 @@
           markOop displaced = rcvr->mark()->set_unlocked();
           mon->lock()->set_displaced_header(displaced);
           bool call_vm = UseHeavyMonitors;
-          if (call_vm || Atomic::cmpxchg((markOop)mon, rcvr->mark_addr(), displaced) != displaced) {
+          if (call_vm || rcvr->cas_set_mark((markOop)mon, displaced) != displaced) {
             // Is it simple recursive case?
             if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
               mon->lock()->set_displaced_header(NULL);
@@ -875,7 +875,7 @@
           if (hash != markOopDesc::no_hash) {
             header = header->copy_set_hash(hash);
           }
-          if (Atomic::cmpxchg(header, lockee->mark_addr(), mark) == mark) {
+          if (lockee->cas_set_mark(header, mark) == mark) {
             if (PrintBiasedLockingStatistics) {
               (*BiasedLocking::revoked_lock_entry_count_addr())++;
             }
@@ -886,7 +886,7 @@
           if (hash != markOopDesc::no_hash) {
                 new_header = new_header->copy_set_hash(hash);
           }
-          if (Atomic::cmpxchg(new_header, lockee->mark_addr(), mark) == mark) {
+          if (lockee->cas_set_mark(new_header, mark) == mark) {
             if (PrintBiasedLockingStatistics) {
               (* BiasedLocking::rebiased_lock_entry_count_addr())++;
             }
@@ -904,7 +904,7 @@
           markOop new_header = (markOop) ((uintptr_t) header | thread_ident);
           // debugging hint
           DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);)
-          if (Atomic::cmpxchg(new_header, lockee->mark_addr(), header) == header) {
+          if (lockee->cas_set_mark(new_header, header) == header) {
             if (PrintBiasedLockingStatistics) {
               (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
             }
@@ -920,7 +920,7 @@
         markOop displaced = lockee->mark()->set_unlocked();
         entry->lock()->set_displaced_header(displaced);
         bool call_vm = UseHeavyMonitors;
-        if (call_vm || Atomic::cmpxchg((markOop)entry, lockee->mark_addr(), displaced) != displaced) {
+        if (call_vm || lockee->cas_set_mark((markOop)entry, displaced) != displaced) {
           // Is it simple recursive case?
           if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
             entry->lock()->set_displaced_header(NULL);
@@ -1816,7 +1816,7 @@
               if (hash != markOopDesc::no_hash) {
                 header = header->copy_set_hash(hash);
               }
-              if (Atomic::cmpxchg(header, lockee->mark_addr(), mark) == mark) {
+              if (lockee->cas_set_mark(header, mark) == mark) {
                 if (PrintBiasedLockingStatistics)
                   (*BiasedLocking::revoked_lock_entry_count_addr())++;
               }
@@ -1827,7 +1827,7 @@
               if (hash != markOopDesc::no_hash) {
                 new_header = new_header->copy_set_hash(hash);
               }
-              if (Atomic::cmpxchg(new_header, lockee->mark_addr(), mark) == mark) {
+              if (lockee->cas_set_mark(new_header, mark) == mark) {
                 if (PrintBiasedLockingStatistics)
                   (* BiasedLocking::rebiased_lock_entry_count_addr())++;
               }
@@ -1847,7 +1847,7 @@
               markOop new_header = (markOop) ((uintptr_t) header | thread_ident);
               // debugging hint
               DEBUG_ONLY(entry->lock()->set_displaced_header((markOop) (uintptr_t) 0xdeaddead);)
-              if (Atomic::cmpxchg(new_header, lockee->mark_addr(), header) == header) {
+              if (lockee->cas_set_mark(new_header, header) == header) {
                 if (PrintBiasedLockingStatistics)
                   (* BiasedLocking::anonymously_biased_lock_entry_count_addr())++;
               }
@@ -1863,7 +1863,7 @@
             markOop displaced = lockee->mark()->set_unlocked();
             entry->lock()->set_displaced_header(displaced);
             bool call_vm = UseHeavyMonitors;
-            if (call_vm || Atomic::cmpxchg((markOop)entry, lockee->mark_addr(), displaced) != displaced) {
+            if (call_vm || lockee->cas_set_mark((markOop)entry, displaced) != displaced) {
               // Is it simple recursive case?
               if (!call_vm && THREAD->is_lock_owned((address) displaced->clear_lock_bits())) {
                 entry->lock()->set_displaced_header(NULL);
--- a/src/hotspot/share/interpreter/bytecodes.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/interpreter/bytecodes.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -45,7 +45,7 @@
 s_char          Bytecodes::_depth         [Bytecodes::number_of_codes];
 u_char          Bytecodes::_lengths       [Bytecodes::number_of_codes];
 Bytecodes::Code Bytecodes::_java_code     [Bytecodes::number_of_codes];
-u_short         Bytecodes::_flags         [(1<<BitsPerByte)*2];
+unsigned short  Bytecodes::_flags         [(1<<BitsPerByte)*2];
 
 #ifdef ASSERT
 bool Bytecodes::check_method(const Method* method, address bcp) {
--- a/src/hotspot/share/interpreter/templateTable.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/interpreter/templateTable.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,7 +23,7 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "interpreter/templateTable.hpp"
 #include "runtime/timerTrace.hpp"
@@ -247,7 +247,7 @@
   // Initialize table
   TraceTime timer("TemplateTable initialization", TRACETIME_LOG(Info, startuptime));
 
-  _bs = Universe::heap()->barrier_set();
+  _bs = BarrierSet::barrier_set();
 
   // For better readability
   const char _    = ' ';
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
--- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,6 +23,7 @@
 
 // no precompiled headers
 #include "ci/ciUtilities.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "jvmci/jvmciRuntime.hpp"
@@ -120,7 +121,7 @@
   symbol_init = (address) vmSymbols::object_initializer_name();
   symbol_clinit = (address) vmSymbols::class_initializer_name();
 
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   if (bs->is_a(BarrierSet::CardTableBarrierSet)) {
     jbyte* base = ci_card_table_address();
     assert(base != NULL, "unexpected byte_map_base");
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -50,6 +50,9 @@
 #include "utilities/debug.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/macros.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
+#endif // INCLUDE_ALL_GCS
 
 #if defined(_MSC_VER)
 #define strtoll _strtoi64
@@ -454,11 +457,15 @@
 JRT_END
 
 JRT_LEAF(void, JVMCIRuntime::write_barrier_pre(JavaThread* thread, oopDesc* obj))
-  thread->satb_mark_queue().enqueue(obj);
+#if INCLUDE_ALL_GCS
+  G1ThreadLocalData::satb_mark_queue(thread).enqueue(obj);
+#endif // INCLUDE_ALL_GCS
 JRT_END
 
 JRT_LEAF(void, JVMCIRuntime::write_barrier_post(JavaThread* thread, void* card_addr))
-  thread->dirty_card_queue().enqueue(card_addr);
+#if INCLUDE_ALL_GCS
+  G1ThreadLocalData::dirty_card_queue(thread).enqueue(card_addr);
+#endif // INCLUDE_ALL_GCS
 JRT_END
 
 JRT_LEAF(jboolean, JVMCIRuntime::validate_object(JavaThread* thread, oopDesc* parent, oopDesc* child))
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,6 +44,7 @@
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1CardTable.hpp"
 #include "gc/g1/heapRegion.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
 #endif
 
 #define VM_STRUCTS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field) \
@@ -172,8 +173,6 @@
   volatile_nonstatic_field(JavaThread,         _exception_pc,                                 address)                               \
   volatile_nonstatic_field(JavaThread,         _is_method_handle_return,                      int)                                   \
   nonstatic_field(JavaThread,                  _osthread,                                     OSThread*)                             \
-  nonstatic_field(JavaThread,                  _satb_mark_queue,                              SATBMarkQueue)                         \
-  nonstatic_field(JavaThread,                  _dirty_card_queue,                             DirtyCardQueue)                        \
   nonstatic_field(JavaThread,                  _pending_deoptimization,                       int)                                   \
   nonstatic_field(JavaThread,                  _pending_failed_speculation,                   oop)                                   \
   nonstatic_field(JavaThread,                  _pending_transfer_to_interpreter,              bool)                                  \
@@ -515,9 +514,6 @@
   declare_constant(Deoptimization::Reason_jsr_mismatch)                   \
   declare_constant(Deoptimization::Reason_LIMIT)                          \
                                                                           \
-  declare_constant_with_value("dirtyCardQueueBufferOffset", in_bytes(DirtyCardQueue::byte_offset_of_buf())) \
-  declare_constant_with_value("dirtyCardQueueIndexOffset", in_bytes(DirtyCardQueue::byte_offset_of_index())) \
-                                                                          \
   declare_constant(FieldInfo::access_flags_offset)                        \
   declare_constant(FieldInfo::name_index_offset)                          \
   declare_constant(FieldInfo::signature_index_offset)                     \
@@ -573,10 +569,6 @@
   declare_constant(ReceiverTypeData::receiver0_offset)                    \
   declare_constant(ReceiverTypeData::count0_offset)                       \
                                                                           \
-  declare_constant_with_value("satbMarkQueueBufferOffset", in_bytes(SATBMarkQueue::byte_offset_of_buf())) \
-  declare_constant_with_value("satbMarkQueueIndexOffset", in_bytes(SATBMarkQueue::byte_offset_of_index())) \
-  declare_constant_with_value("satbMarkQueueActiveOffset", in_bytes(SATBMarkQueue::byte_offset_of_active())) \
-                                                                          \
   declare_constant(vmIntrinsics::_invokeBasic)                            \
   declare_constant(vmIntrinsics::_linkToVirtual)                          \
   declare_constant(vmIntrinsics::_linkToStatic)                           \
@@ -641,8 +633,8 @@
   declare_function(JVMCIRuntime::log_printf) \
   declare_function(JVMCIRuntime::vm_error) \
   declare_function(JVMCIRuntime::load_and_clear_exception) \
-  declare_function(JVMCIRuntime::write_barrier_pre) \
-  declare_function(JVMCIRuntime::write_barrier_post) \
+  ALL_GCS_ONLY(declare_function(JVMCIRuntime::write_barrier_pre)) \
+  ALL_GCS_ONLY(declare_function(JVMCIRuntime::write_barrier_post)) \
   declare_function(JVMCIRuntime::validate_object) \
   \
   declare_function(JVMCIRuntime::test_deoptimize_call_int)
@@ -650,11 +642,16 @@
 
 #if INCLUDE_ALL_GCS
 
-#define VM_STRUCTS_G1(nonstatic_field, static_field) \
+#define VM_STRUCTS_JVMCI_G1GC(nonstatic_field, static_field) \
   static_field(HeapRegion, LogOfHRGrainBytes, int)
 
-#define VM_INT_CONSTANTS_G1(declare_constant, declare_constant_with_value, declare_preprocessor_constant) \
-  declare_constant_with_value("G1CardTable::g1_young_gen", G1CardTable::g1_young_card_val())
+#define VM_INT_CONSTANTS_JVMCI_G1GC(declare_constant, declare_constant_with_value, declare_preprocessor_constant) \
+  declare_constant_with_value("G1CardTable::g1_young_gen", G1CardTable::g1_young_card_val()) \
+  declare_constant_with_value("G1ThreadLocalData::satb_mark_queue_active_offset", in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset())) \
+  declare_constant_with_value("G1ThreadLocalData::satb_mark_queue_index_offset", in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset())) \
+  declare_constant_with_value("G1ThreadLocalData::satb_mark_queue_buffer_offset", in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())) \
+  declare_constant_with_value("G1ThreadLocalData::dirty_card_queue_index_offset", in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset())) \
+  declare_constant_with_value("G1ThreadLocalData::dirty_card_queue_buffer_offset", in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()))
 
 #endif // INCLUDE_ALL_GCS
 
@@ -873,8 +870,8 @@
                  GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
 
 #if INCLUDE_ALL_GCS
-  VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
-                GENERATE_STATIC_VM_STRUCT_ENTRY)
+  VM_STRUCTS_JVMCI_G1GC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+                        GENERATE_STATIC_VM_STRUCT_ENTRY)
 #endif
 
   GENERATE_VM_STRUCT_LAST_ENTRY()
@@ -925,9 +922,9 @@
                        GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
 
 #if INCLUDE_ALL_GCS
-  VM_INT_CONSTANTS_G1(GENERATE_VM_INT_CONSTANT_ENTRY,
-                      GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
-                      GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
+  VM_INT_CONSTANTS_JVMCI_G1GC(GENERATE_VM_INT_CONSTANT_ENTRY,
+                              GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
+                              GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
 #endif
 
   GENERATE_VM_INT_CONSTANT_LAST_ENTRY()
--- a/src/hotspot/share/logging/logHandle.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/logging/logHandle.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -43,6 +43,10 @@
     return _tagset->is_level(level);
   }
 
+  LogTagSet* tagset() const {
+    return _tagset;
+  }
+
 #define LOG_LEVEL(level, name) ATTRIBUTE_PRINTF(2, 0)   \
   LogHandle& v##name(const char* fmt, va_list args) { \
     _tagset->vwrite(LogLevel::level, fmt, args); \
--- a/src/hotspot/share/logging/logTag.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/logging/logTag.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -112,6 +112,7 @@
   LOG_TAG(perf) \
   LOG_TAG(phases) \
   LOG_TAG(plab) \
+  LOG_TAG(preview)   /* Trace loading of preview feature types */ \
   LOG_TAG(promotion) \
   LOG_TAG(preorder) /* Trace all classes loaded in order referenced (not loaded) */ \
   LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \
--- a/src/hotspot/share/memory/allocation.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/allocation.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/arena.hpp"
--- a/src/hotspot/share/memory/arena.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/arena.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/metaspaceShared.hpp"
--- a/src/hotspot/share/memory/binaryTreeDictionary.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1429 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/cms/allocationStats.hpp"
-#include "gc/shared/spaceDecorator.hpp"
-#include "logging/log.hpp"
-#include "logging/logStream.hpp"
-#include "memory/binaryTreeDictionary.hpp"
-#include "memory/freeList.hpp"
-#include "memory/metachunk.hpp"
-#include "memory/resourceArea.hpp"
-#include "runtime/globals.hpp"
-#include "utilities/macros.hpp"
-#include "utilities/ostream.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/cms/adaptiveFreeList.hpp"
-#include "gc/cms/freeChunk.hpp"
-#endif // INCLUDE_ALL_GCS
-
-////////////////////////////////////////////////////////////////////////////////
-// A binary tree based search structure for free blocks.
-// This is currently used in the Concurrent Mark&Sweep implementation.
-////////////////////////////////////////////////////////////////////////////////
-
-template <class Chunk_t, class FreeList_t>
-TreeChunk<Chunk_t, FreeList_t>* TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(Chunk_t* fc) {
-  // Do some assertion checking here.
-  return (TreeChunk<Chunk_t, FreeList_t>*) fc;
-}
-
-template <class Chunk_t, class FreeList_t>
-void TreeChunk<Chunk_t, FreeList_t>::verify_tree_chunk_list() const {
-  TreeChunk<Chunk_t, FreeList_t>* nextTC = (TreeChunk<Chunk_t, FreeList_t>*)next();
-  if (prev() != NULL) { // interior list node shouldn't have tree fields
-    guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
-              embedded_list()->right()  == NULL, "should be clear");
-  }
-  if (nextTC != NULL) {
-    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
-    guarantee(nextTC->size() == size(), "wrong size");
-    nextTC->verify_tree_chunk_list();
-  }
-}
-
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>::TreeList() : _parent(NULL),
-  _left(NULL), _right(NULL) {}
-
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>*
-TreeList<Chunk_t, FreeList_t>::as_TreeList(TreeChunk<Chunk_t,FreeList_t>* tc) {
-  // This first free chunk in the list will be the tree list.
-  assert((tc->size() >= (TreeChunk<Chunk_t, FreeList_t>::min_size())),
-    "Chunk is too small for a TreeChunk");
-  TreeList<Chunk_t, FreeList_t>* tl = tc->embedded_list();
-  tl->initialize();
-  tc->set_list(tl);
-  tl->set_size(tc->size());
-  tl->link_head(tc);
-  tl->link_tail(tc);
-  tl->set_count(1);
-  assert(tl->parent() == NULL, "Should be clear");
-  return tl;
-}
-
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>*
-TreeList<Chunk_t, FreeList_t>::as_TreeList(HeapWord* addr, size_t size) {
-  TreeChunk<Chunk_t, FreeList_t>* tc = (TreeChunk<Chunk_t, FreeList_t>*) addr;
-  assert((size >= TreeChunk<Chunk_t, FreeList_t>::min_size()),
-    "Chunk is too small for a TreeChunk");
-  // The space will have been mangled initially but
-  // is not remangled when a Chunk_t is returned to the free list
-  // (since it is used to maintain the chunk on the free list).
-  tc->assert_is_mangled();
-  tc->set_size(size);
-  tc->link_prev(NULL);
-  tc->link_next(NULL);
-  TreeList<Chunk_t, FreeList_t>* tl = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
-  return tl;
-}
-
-
-#if INCLUDE_ALL_GCS
-// Specialize for AdaptiveFreeList which tries to avoid
-// splitting a chunk of a size that is under populated in favor of
-// an over populated size.  The general get_better_list() just returns
-// the current list.
-template <>
-TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >*
-TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >::get_better_list(
-  BinaryTreeDictionary<FreeChunk, ::AdaptiveFreeList<FreeChunk> >* dictionary) {
-  // A candidate chunk has been found.  If it is already under
-  // populated, get a chunk associated with the hint for this
-  // chunk.
-
-  TreeList<FreeChunk, ::AdaptiveFreeList<FreeChunk> >* curTL = this;
-  if (curTL->surplus() <= 0) {
-    /* Use the hint to find a size with a surplus, and reset the hint. */
-    TreeList<FreeChunk, ::AdaptiveFreeList<FreeChunk> >* hintTL = this;
-    while (hintTL->hint() != 0) {
-      assert(hintTL->hint() > hintTL->size(),
-        "hint points in the wrong direction");
-      hintTL = dictionary->find_list(hintTL->hint());
-      assert(curTL != hintTL, "Infinite loop");
-      if (hintTL == NULL ||
-          hintTL == curTL /* Should not happen but protect against it */ ) {
-        // No useful hint.  Set the hint to NULL and go on.
-        curTL->set_hint(0);
-        break;
-      }
-      assert(hintTL->size() > curTL->size(), "hint is inconsistent");
-      if (hintTL->surplus() > 0) {
-        // The hint led to a list that has a surplus.  Use it.
-        // Set the hint for the candidate to an overpopulated
-        // size.
-        curTL->set_hint(hintTL->size());
-        // Change the candidate.
-        curTL = hintTL;
-        break;
-      }
-    }
-  }
-  return curTL;
-}
-#endif // INCLUDE_ALL_GCS
-
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>*
-TreeList<Chunk_t, FreeList_t>::get_better_list(
-  BinaryTreeDictionary<Chunk_t, FreeList_t>* dictionary) {
-  return this;
-}
-
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::remove_chunk_replace_if_needed(TreeChunk<Chunk_t, FreeList_t>* tc) {
-
-  TreeList<Chunk_t, FreeList_t>* retTL = this;
-  Chunk_t* list = head();
-  assert(!list || list != list->next(), "Chunk on list twice");
-  assert(tc != NULL, "Chunk being removed is NULL");
-  assert(parent() == NULL || this == parent()->left() ||
-    this == parent()->right(), "list is inconsistent");
-  assert(tc->is_free(), "Header is not marked correctly");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  Chunk_t* prevFC = tc->prev();
-  TreeChunk<Chunk_t, FreeList_t>* nextTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(tc->next());
-  assert(list != NULL, "should have at least the target chunk");
-
-  // Is this the first item on the list?
-  if (tc == list) {
-    // The "getChunk..." functions for a TreeList<Chunk_t, FreeList_t> will not return the
-    // first chunk in the list unless it is the last chunk in the list
-    // because the first chunk is also acting as the tree node.
-    // When coalescing happens, however, the first chunk in the a tree
-    // list can be the start of a free range.  Free ranges are removed
-    // from the free lists so that they are not available to be
-    // allocated when the sweeper yields (giving up the free list lock)
-    // to allow mutator activity.  If this chunk is the first in the
-    // list and is not the last in the list, do the work to copy the
-    // TreeList<Chunk_t, FreeList_t> from the first chunk to the next chunk and update all
-    // the TreeList<Chunk_t, FreeList_t> pointers in the chunks in the list.
-    if (nextTC == NULL) {
-      assert(prevFC == NULL, "Not last chunk in the list");
-      set_tail(NULL);
-      set_head(NULL);
-    } else {
-      // copy embedded list.
-      nextTC->set_embedded_list(tc->embedded_list());
-      retTL = nextTC->embedded_list();
-      // Fix the pointer to the list in each chunk in the list.
-      // This can be slow for a long list.  Consider having
-      // an option that does not allow the first chunk on the
-      // list to be coalesced.
-      for (TreeChunk<Chunk_t, FreeList_t>* curTC = nextTC; curTC != NULL;
-          curTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(curTC->next())) {
-        curTC->set_list(retTL);
-      }
-      // Fix the parent to point to the new TreeList<Chunk_t, FreeList_t>.
-      if (retTL->parent() != NULL) {
-        if (this == retTL->parent()->left()) {
-          retTL->parent()->set_left(retTL);
-        } else {
-          assert(this == retTL->parent()->right(), "Parent is incorrect");
-          retTL->parent()->set_right(retTL);
-        }
-      }
-      // Fix the children's parent pointers to point to the
-      // new list.
-      assert(right() == retTL->right(), "Should have been copied");
-      if (retTL->right() != NULL) {
-        retTL->right()->set_parent(retTL);
-      }
-      assert(left() == retTL->left(), "Should have been copied");
-      if (retTL->left() != NULL) {
-        retTL->left()->set_parent(retTL);
-      }
-      retTL->link_head(nextTC);
-      assert(nextTC->is_free(), "Should be a free chunk");
-    }
-  } else {
-    if (nextTC == NULL) {
-      // Removing chunk at tail of list
-      this->link_tail(prevFC);
-    }
-    // Chunk is interior to the list
-    prevFC->link_after(nextTC);
-  }
-
-  // Below this point the embedded TreeList<Chunk_t, FreeList_t> being used for the
-  // tree node may have changed. Don't use "this"
-  // TreeList<Chunk_t, FreeList_t>*.
-  // chunk should still be a free chunk (bit set in _prev)
-  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
-    "Wrong sized chunk in list");
-  debug_only(
-    tc->link_prev(NULL);
-    tc->link_next(NULL);
-    tc->set_list(NULL);
-    bool prev_found = false;
-    bool next_found = false;
-    for (Chunk_t* curFC = retTL->head();
-         curFC != NULL; curFC = curFC->next()) {
-      assert(curFC != tc, "Chunk is still in list");
-      if (curFC == prevFC) {
-        prev_found = true;
-      }
-      if (curFC == nextTC) {
-        next_found = true;
-      }
-    }
-    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
-    assert(nextTC == NULL || next_found, "Chunk was lost from list");
-    assert(retTL->parent() == NULL ||
-           retTL == retTL->parent()->left() ||
-           retTL == retTL->parent()->right(),
-           "list is inconsistent");
-  )
-  retTL->decrement_count();
-
-  assert(tc->is_free(), "Should still be a free chunk");
-  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
-    "list invariant");
-  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
-    "list invariant");
-  return retTL;
-}
-
-template <class Chunk_t, class FreeList_t>
-void TreeList<Chunk_t, FreeList_t>::return_chunk_at_tail(TreeChunk<Chunk_t, FreeList_t>* chunk) {
-  assert(chunk != NULL, "returning NULL chunk");
-  assert(chunk->list() == this, "list should be set for chunk");
-  assert(tail() != NULL, "The tree list is embedded in the first chunk");
-  // which means that the list can never be empty.
-  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  Chunk_t* fc = tail();
-  fc->link_after(chunk);
-  this->link_tail(chunk);
-
-  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
-  FreeList_t::increment_count();
-  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-}
-
-// Add this chunk at the head of the list.  "At the head of the list"
-// is defined to be after the chunk pointer to by head().  This is
-// because the TreeList<Chunk_t, FreeList_t> is embedded in the first TreeChunk<Chunk_t, FreeList_t> in the
-// list.  See the definition of TreeChunk<Chunk_t, FreeList_t>.
-template <class Chunk_t, class FreeList_t>
-void TreeList<Chunk_t, FreeList_t>::return_chunk_at_head(TreeChunk<Chunk_t, FreeList_t>* chunk) {
-  assert(chunk->list() == this, "list should be set for chunk");
-  assert(head() != NULL, "The tree list is embedded in the first chunk");
-  assert(chunk != NULL, "returning NULL chunk");
-  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  Chunk_t* fc = head()->next();
-  if (fc != NULL) {
-    chunk->link_after(fc);
-  } else {
-    assert(tail() == NULL, "List is inconsistent");
-    this->link_tail(chunk);
-  }
-  head()->link_after(chunk);
-  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
-  FreeList_t::increment_count();
-  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-}
-
-template <class Chunk_t, class FreeList_t>
-void TreeChunk<Chunk_t, FreeList_t>::assert_is_mangled() const {
-  assert((ZapUnusedHeapArea &&
-          SpaceMangler::is_mangled((HeapWord*) Chunk_t::size_addr()) &&
-          SpaceMangler::is_mangled((HeapWord*) Chunk_t::prev_addr()) &&
-          SpaceMangler::is_mangled((HeapWord*) Chunk_t::next_addr())) ||
-          (size() == 0 && prev() == NULL && next() == NULL),
-    "Space should be clear or mangled");
-}
-
-template <class Chunk_t, class FreeList_t>
-TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::head_as_TreeChunk() {
-  assert(head() == NULL || (TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head())->list() == this),
-    "Wrong type of chunk?");
-  return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head());
-}
-
-template <class Chunk_t, class FreeList_t>
-TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::first_available() {
-  assert(head() != NULL, "The head of the list cannot be NULL");
-  Chunk_t* fc = head()->next();
-  TreeChunk<Chunk_t, FreeList_t>* retTC;
-  if (fc == NULL) {
-    retTC = head_as_TreeChunk();
-  } else {
-    retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
-  }
-  assert(retTC->list() == this, "Wrong type of chunk.");
-  return retTC;
-}
-
-// Returns the block with the largest heap address amongst
-// those in the list for this size; potentially slow and expensive,
-// use with caution!
-template <class Chunk_t, class FreeList_t>
-TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::largest_address() {
-  assert(head() != NULL, "The head of the list cannot be NULL");
-  Chunk_t* fc = head()->next();
-  TreeChunk<Chunk_t, FreeList_t>* retTC;
-  if (fc == NULL) {
-    retTC = head_as_TreeChunk();
-  } else {
-    // walk down the list and return the one with the highest
-    // heap address among chunks of this size.
-    Chunk_t* last = fc;
-    while (fc->next() != NULL) {
-      if ((HeapWord*)last < (HeapWord*)fc) {
-        last = fc;
-      }
-      fc = fc->next();
-    }
-    retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(last);
-  }
-  assert(retTC->list() == this, "Wrong type of chunk.");
-  return retTC;
-}
-
-template <class Chunk_t, class FreeList_t>
-BinaryTreeDictionary<Chunk_t, FreeList_t>::BinaryTreeDictionary(MemRegion mr) {
-  assert((mr.byte_size() > min_size()), "minimum chunk size");
-
-  reset(mr);
-  assert(root()->left() == NULL, "reset check failed");
-  assert(root()->right() == NULL, "reset check failed");
-  assert(root()->head()->next() == NULL, "reset check failed");
-  assert(root()->head()->prev() == NULL, "reset check failed");
-  assert(total_size() == root()->size(), "reset check failed");
-  assert(total_free_blocks() == 1, "reset check failed");
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::inc_total_size(size_t inc) {
-  _total_size = _total_size + inc;
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::dec_total_size(size_t dec) {
-  _total_size = _total_size - dec;
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(MemRegion mr) {
-  assert((mr.byte_size() > min_size()), "minimum chunk size");
-  set_root(TreeList<Chunk_t, FreeList_t>::as_TreeList(mr.start(), mr.word_size()));
-  set_total_size(mr.word_size());
-  set_total_free_blocks(1);
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(HeapWord* addr, size_t byte_size) {
-  MemRegion mr(addr, heap_word_size(byte_size));
-  reset(mr);
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset() {
-  set_root(NULL);
-  set_total_size(0);
-  set_total_free_blocks(0);
-}
-
-// Get a free block of size at least size from tree, or NULL.
-template <class Chunk_t, class FreeList_t>
-TreeChunk<Chunk_t, FreeList_t>*
-BinaryTreeDictionary<Chunk_t, FreeList_t>::get_chunk_from_tree(size_t size)
-{
-  TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
-  TreeChunk<Chunk_t, FreeList_t>* retTC = NULL;
-
-  assert((size >= min_size()), "minimum chunk size");
-  if (FLSVerifyDictionary) {
-    verify_tree();
-  }
-  // starting at the root, work downwards trying to find match.
-  // Remember the last node of size too great or too small.
-  for (prevTL = curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size) {        // exact match
-      break;
-    }
-    prevTL = curTL;
-    if (curTL->size() < size) {        // proceed to right sub-tree
-      curTL = curTL->right();
-    } else {                           // proceed to left sub-tree
-      assert(curTL->size() > size, "size inconsistency");
-      curTL = curTL->left();
-    }
-  }
-  if (curTL == NULL) { // couldn't find exact match
-
-    // try and find the next larger size by walking back up the search path
-    for (curTL = prevTL; curTL != NULL;) {
-      if (curTL->size() >= size) break;
-      else curTL = curTL->parent();
-    }
-    assert(curTL == NULL || curTL->count() > 0,
-      "An empty list should not be in the tree");
-  }
-  if (curTL != NULL) {
-    assert(curTL->size() >= size, "size inconsistency");
-
-    curTL = curTL->get_better_list(this);
-
-    retTC = curTL->first_available();
-    assert((retTC != NULL) && (curTL->count() > 0),
-      "A list in the binary tree should not be NULL");
-    assert(retTC->size() >= size,
-      "A chunk of the wrong size was found");
-    remove_chunk_from_tree(retTC);
-    assert(retTC->is_free(), "Header is not marked correctly");
-  }
-
-  if (FLSVerifyDictionary) {
-    verify();
-  }
-  return retTC;
-}
-
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_list(size_t size) const {
-  TreeList<Chunk_t, FreeList_t>* curTL;
-  for (curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size) {        // exact match
-      break;
-    }
-
-    if (curTL->size() < size) {        // proceed to right sub-tree
-      curTL = curTL->right();
-    } else {                           // proceed to left sub-tree
-      assert(curTL->size() > size, "size inconsistency");
-      curTL = curTL->left();
-    }
-  }
-  return curTL;
-}
-
-
-template <class Chunk_t, class FreeList_t>
-bool BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_chunk_in_free_list(Chunk_t* tc) const {
-  size_t size = tc->size();
-  TreeList<Chunk_t, FreeList_t>* tl = find_list(size);
-  if (tl == NULL) {
-    return false;
-  } else {
-    return tl->verify_chunk_in_free_list(tc);
-  }
-}
-
-template <class Chunk_t, class FreeList_t>
-Chunk_t* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_largest_dict() const {
-  TreeList<Chunk_t, FreeList_t> *curTL = root();
-  if (curTL != NULL) {
-    while(curTL->right() != NULL) curTL = curTL->right();
-    return curTL->largest_address();
-  } else {
-    return NULL;
-  }
-}
-
-// Remove the current chunk from the tree.  If it is not the last
-// chunk in a list on a tree node, just unlink it.
-// If it is the last chunk in the list (the next link is NULL),
-// remove the node and repair the tree.
-template <class Chunk_t, class FreeList_t>
-TreeChunk<Chunk_t, FreeList_t>*
-BinaryTreeDictionary<Chunk_t, FreeList_t>::remove_chunk_from_tree(TreeChunk<Chunk_t, FreeList_t>* tc) {
-  assert(tc != NULL, "Should not call with a NULL chunk");
-  assert(tc->is_free(), "Header is not marked correctly");
-
-  TreeList<Chunk_t, FreeList_t> *newTL, *parentTL;
-  TreeChunk<Chunk_t, FreeList_t>* retTC;
-  TreeList<Chunk_t, FreeList_t>* tl = tc->list();
-  debug_only(
-    bool removing_only_chunk = false;
-    if (tl == _root) {
-      if ((_root->left() == NULL) && (_root->right() == NULL)) {
-        if (_root->count() == 1) {
-          assert(_root->head() == tc, "Should only be this one chunk");
-          removing_only_chunk = true;
-        }
-      }
-    }
-  )
-  assert(tl != NULL, "List should be set");
-  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
-         tl == tl->parent()->right(), "list is inconsistent");
-
-  bool complicated_splice = false;
-
-  retTC = tc;
-  // Removing this chunk can have the side effect of changing the node
-  // (TreeList<Chunk_t, FreeList_t>*) in the tree.  If the node is the root, update it.
-  TreeList<Chunk_t, FreeList_t>* replacementTL = tl->remove_chunk_replace_if_needed(tc);
-  assert(tc->is_free(), "Chunk should still be free");
-  assert(replacementTL->parent() == NULL ||
-         replacementTL == replacementTL->parent()->left() ||
-         replacementTL == replacementTL->parent()->right(),
-         "list is inconsistent");
-  if (tl == root()) {
-    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
-    set_root(replacementTL);
-  }
-#ifdef ASSERT
-    if (tl != replacementTL) {
-      assert(replacementTL->head() != NULL,
-        "If the tree list was replaced, it should not be a NULL list");
-      TreeList<Chunk_t, FreeList_t>* rhl = replacementTL->head_as_TreeChunk()->list();
-      TreeList<Chunk_t, FreeList_t>* rtl =
-        TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(replacementTL->tail())->list();
-      assert(rhl == replacementTL, "Broken head");
-      assert(rtl == replacementTL, "Broken tail");
-      assert(replacementTL->size() == tc->size(),  "Broken size");
-    }
-#endif
-
-  // Does the tree need to be repaired?
-  if (replacementTL->count() == 0) {
-    assert(replacementTL->head() == NULL &&
-           replacementTL->tail() == NULL, "list count is incorrect");
-    // Find the replacement node for the (soon to be empty) node being removed.
-    // if we have a single (or no) child, splice child in our stead
-    if (replacementTL->left() == NULL) {
-      // left is NULL so pick right.  right may also be NULL.
-      newTL = replacementTL->right();
-      debug_only(replacementTL->clear_right();)
-    } else if (replacementTL->right() == NULL) {
-      // right is NULL
-      newTL = replacementTL->left();
-      debug_only(replacementTL->clear_left();)
-    } else {  // we have both children, so, by patriarchal convention,
-              // my replacement is least node in right sub-tree
-      complicated_splice = true;
-      newTL = remove_tree_minimum(replacementTL->right());
-      assert(newTL != NULL && newTL->left() == NULL &&
-             newTL->right() == NULL, "sub-tree minimum exists");
-    }
-    // newTL is the replacement for the (soon to be empty) node.
-    // newTL may be NULL.
-    // should verify; we just cleanly excised our replacement
-    if (FLSVerifyDictionary) {
-      verify_tree();
-    }
-    // first make newTL my parent's child
-    if ((parentTL = replacementTL->parent()) == NULL) {
-      // newTL should be root
-      assert(tl == root(), "Incorrectly replacing root");
-      set_root(newTL);
-      if (newTL != NULL) {
-        newTL->clear_parent();
-      }
-    } else if (parentTL->right() == replacementTL) {
-      // replacementTL is a right child
-      parentTL->set_right(newTL);
-    } else {                                // replacementTL is a left child
-      assert(parentTL->left() == replacementTL, "should be left child");
-      parentTL->set_left(newTL);
-    }
-    debug_only(replacementTL->clear_parent();)
-    if (complicated_splice) {  // we need newTL to get replacementTL's
-                              // two children
-      assert(newTL != NULL &&
-             newTL->left() == NULL && newTL->right() == NULL,
-            "newTL should not have encumbrances from the past");
-      // we'd like to assert as below:
-      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
-      //       "else !complicated_splice");
-      // ... however, the above assertion is too strong because we aren't
-      // guaranteed that replacementTL->right() is still NULL.
-      // Recall that we removed
-      // the right sub-tree minimum from replacementTL.
-      // That may well have been its right
-      // child! So we'll just assert half of the above:
-      assert(replacementTL->left() != NULL, "else !complicated_splice");
-      newTL->set_left(replacementTL->left());
-      newTL->set_right(replacementTL->right());
-      debug_only(
-        replacementTL->clear_right();
-        replacementTL->clear_left();
-      )
-    }
-    assert(replacementTL->right() == NULL &&
-           replacementTL->left() == NULL &&
-           replacementTL->parent() == NULL,
-        "delete without encumbrances");
-  }
-
-  assert(total_size() >= retTC->size(), "Incorrect total size");
-  dec_total_size(retTC->size());     // size book-keeping
-  assert(total_free_blocks() > 0, "Incorrect total count");
-  set_total_free_blocks(total_free_blocks() - 1);
-
-  assert(retTC != NULL, "null chunk?");
-  assert(retTC->prev() == NULL && retTC->next() == NULL,
-         "should return without encumbrances");
-  if (FLSVerifyDictionary) {
-    verify_tree();
-  }
-  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
-  return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(retTC);
-}
-
-// Remove the leftmost node (lm) in the tree and return it.
-// If lm has a right child, link it to the left node of
-// the parent of lm.
-template <class Chunk_t, class FreeList_t>
-TreeList<Chunk_t, FreeList_t>* BinaryTreeDictionary<Chunk_t, FreeList_t>::remove_tree_minimum(TreeList<Chunk_t, FreeList_t>* tl) {
-  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
-  // locate the subtree minimum by walking down left branches
-  TreeList<Chunk_t, FreeList_t>* curTL = tl;
-  for (; curTL->left() != NULL; curTL = curTL->left());
-  // obviously curTL now has at most one child, a right child
-  if (curTL != root()) {  // Should this test just be removed?
-    TreeList<Chunk_t, FreeList_t>* parentTL = curTL->parent();
-    if (parentTL->left() == curTL) { // curTL is a left child
-      parentTL->set_left(curTL->right());
-    } else {
-      // If the list tl has no left child, then curTL may be
-      // the right child of parentTL.
-      assert(parentTL->right() == curTL, "should be a right child");
-      parentTL->set_right(curTL->right());
-    }
-  } else {
-    // The only use of this method would not pass the root of the
-    // tree (as indicated by the assertion above that the tree list
-    // has a parent) but the specification does not explicitly exclude the
-    // passing of the root so accommodate it.
-    set_root(NULL);
-  }
-  debug_only(
-    curTL->clear_parent();  // Test if this needs to be cleared
-    curTL->clear_right();    // recall, above, left child is already null
-  )
-  // we just excised a (non-root) node, we should still verify all tree invariants
-  if (FLSVerifyDictionary) {
-    verify_tree();
-  }
-  return curTL;
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::insert_chunk_in_tree(Chunk_t* fc) {
-  TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
-  size_t size = fc->size();
-
-  assert((size >= min_size()),
-         SIZE_FORMAT " is too small to be a TreeChunk<Chunk_t, FreeList_t> " SIZE_FORMAT,
-         size, min_size());
-  if (FLSVerifyDictionary) {
-    verify_tree();
-  }
-
-  fc->clear_next();
-  fc->link_prev(NULL);
-
-  // work down from the _root, looking for insertion point
-  for (prevTL = curTL = root(); curTL != NULL;) {
-    if (curTL->size() == size)  // exact match
-      break;
-    prevTL = curTL;
-    if (curTL->size() > size) { // follow left branch
-      curTL = curTL->left();
-    } else {                    // follow right branch
-      assert(curTL->size() < size, "size inconsistency");
-      curTL = curTL->right();
-    }
-  }
-  TreeChunk<Chunk_t, FreeList_t>* tc = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
-  // This chunk is being returned to the binary tree.  Its embedded
-  // TreeList<Chunk_t, FreeList_t> should be unused at this point.
-  tc->initialize();
-  if (curTL != NULL) {          // exact match
-    tc->set_list(curTL);
-    curTL->return_chunk_at_tail(tc);
-  } else {                     // need a new node in tree
-    tc->clear_next();
-    tc->link_prev(NULL);
-    TreeList<Chunk_t, FreeList_t>* newTL = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
-    assert(((TreeChunk<Chunk_t, FreeList_t>*)tc)->list() == newTL,
-      "List was not initialized correctly");
-    if (prevTL == NULL) {      // we are the only tree node
-      assert(root() == NULL, "control point invariant");
-      set_root(newTL);
-    } else {                   // insert under prevTL ...
-      if (prevTL->size() < size) {   // am right child
-        assert(prevTL->right() == NULL, "control point invariant");
-        prevTL->set_right(newTL);
-      } else {                       // am left child
-        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
-        prevTL->set_left(newTL);
-      }
-    }
-  }
-  assert(tc->list() != NULL, "Tree list should be set");
-
-  inc_total_size(size);
-  // Method 'total_size_in_tree' walks through the every block in the
-  // tree, so it can cause significant performance loss if there are
-  // many blocks in the tree
-  assert(!FLSVerifyDictionary || total_size_in_tree(root()) == total_size(), "_total_size inconsistency");
-  set_total_free_blocks(total_free_blocks() + 1);
-  if (FLSVerifyDictionary) {
-    verify_tree();
-  }
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::max_chunk_size() const {
-  verify_par_locked();
-  TreeList<Chunk_t, FreeList_t>* tc = root();
-  if (tc == NULL) return 0;
-  for (; tc->right() != NULL; tc = tc->right());
-  return tc->size();
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_list_length(TreeList<Chunk_t, FreeList_t>* tl) const {
-  size_t res;
-  res = tl->count();
-#ifdef ASSERT
-  size_t cnt;
-  Chunk_t* tc = tl->head();
-  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
-  assert(res == cnt, "The count is not being maintained correctly");
-#endif
-  return res;
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_size_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
-  if (tl == NULL)
-    return 0;
-  return (tl->size() * total_list_length(tl)) +
-         total_size_in_tree(tl->left())    +
-         total_size_in_tree(tl->right());
-}
-
-template <class Chunk_t, class FreeList_t>
-double BinaryTreeDictionary<Chunk_t, FreeList_t>::sum_of_squared_block_sizes(TreeList<Chunk_t, FreeList_t>* const tl) const {
-  if (tl == NULL) {
-    return 0.0;
-  }
-  double size = (double)(tl->size());
-  double curr = size * size * total_list_length(tl);
-  curr += sum_of_squared_block_sizes(tl->left());
-  curr += sum_of_squared_block_sizes(tl->right());
-  return curr;
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_free_blocks_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
-  if (tl == NULL)
-    return 0;
-  return total_list_length(tl) +
-         total_free_blocks_in_tree(tl->left()) +
-         total_free_blocks_in_tree(tl->right());
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::num_free_blocks() const {
-  assert(total_free_blocks_in_tree(root()) == total_free_blocks(),
-         "_total_free_blocks inconsistency");
-  return total_free_blocks();
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
-  if (tl == NULL)
-    return 0;
-  return 1 + MAX2(tree_height_helper(tl->left()),
-                  tree_height_helper(tl->right()));
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height() const {
-  return tree_height_helper(root());
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_nodes_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
-  if (tl == NULL) {
-    return 0;
-  }
-  return 1 + total_nodes_helper(tl->left()) +
-    total_nodes_helper(tl->right());
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_nodes_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
-  return total_nodes_helper(root());
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::dict_census_update(size_t size, bool split, bool birth){}
-
-#if INCLUDE_ALL_GCS
-template <>
-void AFLBinaryTreeDictionary::dict_census_update(size_t size, bool split, bool birth) {
-  TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >* nd = find_list(size);
-  if (nd) {
-    if (split) {
-      if (birth) {
-        nd->increment_split_births();
-        nd->increment_surplus();
-      }  else {
-        nd->increment_split_deaths();
-        nd->decrement_surplus();
-      }
-    } else {
-      if (birth) {
-        nd->increment_coal_births();
-        nd->increment_surplus();
-      } else {
-        nd->increment_coal_deaths();
-        nd->decrement_surplus();
-      }
-    }
-  }
-  // A list for this size may not be found (nd == 0) if
-  //   This is a death where the appropriate list is now
-  //     empty and has been removed from the list.
-  //   This is a birth associated with a LinAB.  The chunk
-  //     for the LinAB is not in the dictionary.
-}
-#endif // INCLUDE_ALL_GCS
-
-template <class Chunk_t, class FreeList_t>
-bool BinaryTreeDictionary<Chunk_t, FreeList_t>::coal_dict_over_populated(size_t size) {
-  // For the general type of freelists, encourage coalescing by
-  // returning true.
-  return true;
-}
-
-#if INCLUDE_ALL_GCS
-template <>
-bool AFLBinaryTreeDictionary::coal_dict_over_populated(size_t size) {
-  if (FLSAlwaysCoalesceLarge) return true;
-
-  TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >* list_of_size = find_list(size);
-  // None of requested size implies overpopulated.
-  return list_of_size == NULL || list_of_size->coal_desired() <= 0 ||
-         list_of_size->count() > list_of_size->coal_desired();
-}
-#endif // INCLUDE_ALL_GCS
-
-// Closures for walking the binary tree.
-//   do_list() walks the free list in a node applying the closure
-//     to each free chunk in the list
-//   do_tree() walks the nodes in the binary tree applying do_list()
-//     to each list at each node.
-
-template <class Chunk_t, class FreeList_t>
-class TreeCensusClosure : public StackObj {
- protected:
-  virtual void do_list(FreeList_t* fl) = 0;
- public:
-  virtual void do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
-};
-
-template <class Chunk_t, class FreeList_t>
-class AscendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
- public:
-  void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
-    if (tl != NULL) {
-      do_tree(tl->left());
-      this->do_list(tl);
-      do_tree(tl->right());
-    }
-  }
-};
-
-template <class Chunk_t, class FreeList_t>
-class DescendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
- public:
-  void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
-    if (tl != NULL) {
-      do_tree(tl->right());
-      this->do_list(tl);
-      do_tree(tl->left());
-    }
-  }
-};
-
-// For each list in the tree, calculate the desired, desired
-// coalesce, count before sweep, and surplus before sweep.
-template <class Chunk_t, class FreeList_t>
-class BeginSweepClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-  double _percentage;
-  float _inter_sweep_current;
-  float _inter_sweep_estimate;
-  float _intra_sweep_estimate;
-
- public:
-  BeginSweepClosure(double p, float inter_sweep_current,
-                              float inter_sweep_estimate,
-                              float intra_sweep_estimate) :
-   _percentage(p),
-   _inter_sweep_current(inter_sweep_current),
-   _inter_sweep_estimate(inter_sweep_estimate),
-   _intra_sweep_estimate(intra_sweep_estimate) { }
-
-  void do_list(FreeList<Chunk_t>* fl) {}
-
-#if INCLUDE_ALL_GCS
-  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
-    double coalSurplusPercent = _percentage;
-    fl->compute_desired(_inter_sweep_current, _inter_sweep_estimate, _intra_sweep_estimate);
-    fl->set_coal_desired((ssize_t)((double)fl->desired() * coalSurplusPercent));
-    fl->set_before_sweep(fl->count());
-    fl->set_bfr_surp(fl->surplus());
-  }
-#endif // INCLUDE_ALL_GCS
-};
-
-// Used to search the tree until a condition is met.
-// Similar to TreeCensusClosure but searches the
-// tree and returns promptly when found.
-
-template <class Chunk_t, class FreeList_t>
-class TreeSearchClosure : public StackObj {
- protected:
-  virtual bool do_list(FreeList_t* fl) = 0;
- public:
-  virtual bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
-};
-
-#if 0 //  Don't need this yet but here for symmetry.
-template <class Chunk_t, class FreeList_t>
-class AscendTreeSearchClosure : public TreeSearchClosure<Chunk_t> {
- public:
-  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
-    if (tl != NULL) {
-      if (do_tree(tl->left())) return true;
-      if (do_list(tl)) return true;
-      if (do_tree(tl->right())) return true;
-    }
-    return false;
-  }
-};
-#endif
-
-template <class Chunk_t, class FreeList_t>
-class DescendTreeSearchClosure : public TreeSearchClosure<Chunk_t, FreeList_t> {
- public:
-  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
-    if (tl != NULL) {
-      if (do_tree(tl->right())) return true;
-      if (this->do_list(tl)) return true;
-      if (do_tree(tl->left())) return true;
-    }
-    return false;
-  }
-};
-
-// Searches the tree for a chunk that ends at the
-// specified address.
-template <class Chunk_t, class FreeList_t>
-class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk_t, FreeList_t> {
-  HeapWord* _target;
-  Chunk_t* _found;
-
- public:
-  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
-  bool do_list(FreeList_t* fl) {
-    Chunk_t* item = fl->head();
-    while (item != NULL) {
-      if (item->end() == (uintptr_t*) _target) {
-        _found = item;
-        return true;
-      }
-      item = item->next();
-    }
-    return false;
-  }
-  Chunk_t* found() { return _found; }
-};
-
-template <class Chunk_t, class FreeList_t>
-Chunk_t* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_chunk_ends_at(HeapWord* target) const {
-  EndTreeSearchClosure<Chunk_t, FreeList_t> etsc(target);
-  bool found_target = etsc.do_tree(root());
-  assert(found_target || etsc.found() == NULL, "Consistency check");
-  assert(!found_target || etsc.found() != NULL, "Consistency check");
-  return etsc.found();
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::begin_sweep_dict_census(double coalSurplusPercent,
-  float inter_sweep_current, float inter_sweep_estimate, float intra_sweep_estimate) {
-  BeginSweepClosure<Chunk_t, FreeList_t> bsc(coalSurplusPercent, inter_sweep_current,
-                                            inter_sweep_estimate,
-                                            intra_sweep_estimate);
-  bsc.do_tree(root());
-}
-
-// Closures and methods for calculating total bytes returned to the
-// free lists in the tree.
-#ifndef PRODUCT
-template <class Chunk_t, class FreeList_t>
-class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-   public:
-  void do_list(FreeList_t* fl) {
-    fl->set_returned_bytes(0);
-  }
-};
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::initialize_dict_returned_bytes() {
-  InitializeDictReturnedBytesClosure<Chunk_t, FreeList_t> idrb;
-  idrb.do_tree(root());
-}
-
-template <class Chunk_t, class FreeList_t>
-class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-  size_t _dict_returned_bytes;
- public:
-  ReturnedBytesClosure() { _dict_returned_bytes = 0; }
-  void do_list(FreeList_t* fl) {
-    _dict_returned_bytes += fl->returned_bytes();
-  }
-  size_t dict_returned_bytes() { return _dict_returned_bytes; }
-};
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::sum_dict_returned_bytes() {
-  ReturnedBytesClosure<Chunk_t, FreeList_t> rbc;
-  rbc.do_tree(root());
-
-  return rbc.dict_returned_bytes();
-}
-
-// Count the number of entries in the tree.
-template <class Chunk_t, class FreeList_t>
-class treeCountClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
- public:
-  uint count;
-  treeCountClosure(uint c) { count = c; }
-  void do_list(FreeList_t* fl) {
-    count++;
-  }
-};
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_count() {
-  treeCountClosure<Chunk_t, FreeList_t> ctc(0);
-  ctc.do_tree(root());
-  return ctc.count;
-}
-
-template <class Chunk_t, class FreeList_t>
-Mutex* BinaryTreeDictionary<Chunk_t, FreeList_t>::par_lock() const {
-  return _lock;
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::set_par_lock(Mutex* lock) {
-  _lock = lock;
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_par_locked() const {
-#ifdef ASSERT
-  Thread* my_thread = Thread::current();
-  if (my_thread->is_GC_task_thread()) {
-    assert(par_lock() != NULL, "Should be using locking?");
-    assert_lock_strong(par_lock());
-  }
-#endif // ASSERT
-}
-#endif // PRODUCT
-
-// Calculate surpluses for the lists in the tree.
-template <class Chunk_t, class FreeList_t>
-class setTreeSurplusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-  double percentage;
- public:
-  setTreeSurplusClosure(double v) { percentage = v; }
-  void do_list(FreeList<Chunk_t>* fl) {}
-
-#if INCLUDE_ALL_GCS
-  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
-    double splitSurplusPercent = percentage;
-    fl->set_surplus(fl->count() -
-                   (ssize_t)((double)fl->desired() * splitSurplusPercent));
-  }
-#endif // INCLUDE_ALL_GCS
-};
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::set_tree_surplus(double splitSurplusPercent) {
-  setTreeSurplusClosure<Chunk_t, FreeList_t> sts(splitSurplusPercent);
-  sts.do_tree(root());
-}
-
-// Set hints for the lists in the tree.
-template <class Chunk_t, class FreeList_t>
-class setTreeHintsClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
-  size_t hint;
- public:
-  setTreeHintsClosure(size_t v) { hint = v; }
-  void do_list(FreeList<Chunk_t>* fl) {}
-
-#if INCLUDE_ALL_GCS
-  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
-    fl->set_hint(hint);
-    assert(fl->hint() == 0 || fl->hint() > fl->size(),
-      "Current hint is inconsistent");
-    if (fl->surplus() > 0) {
-      hint = fl->size();
-    }
-  }
-#endif // INCLUDE_ALL_GCS
-};
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::set_tree_hints(void) {
-  setTreeHintsClosure<Chunk_t, FreeList_t> sth(0);
-  sth.do_tree(root());
-}
-
-// Save count before previous sweep and splits and coalesces.
-template <class Chunk_t, class FreeList_t>
-class clearTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-  void do_list(FreeList<Chunk_t>* fl) {}
-
-#if INCLUDE_ALL_GCS
-  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
-    fl->set_prev_sweep(fl->count());
-    fl->set_coal_births(0);
-    fl->set_coal_deaths(0);
-    fl->set_split_births(0);
-    fl->set_split_deaths(0);
-  }
-#endif // INCLUDE_ALL_GCS
-};
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::clear_tree_census(void) {
-  clearTreeCensusClosure<Chunk_t, FreeList_t> ctc;
-  ctc.do_tree(root());
-}
-
-// Do reporting and post sweep clean up.
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::end_sweep_dict_census(double splitSurplusPercent) {
-  // Does walking the tree 3 times hurt?
-  set_tree_surplus(splitSurplusPercent);
-  set_tree_hints();
-  LogTarget(Trace, gc, freelist, stats) log;
-  if (log.is_enabled()) {
-    LogStream out(log);
-    report_statistics(&out);
-  }
-  clear_tree_census();
-}
-
-// Print summary statistics
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::report_statistics(outputStream* st) const {
-  verify_par_locked();
-  st->print_cr("Statistics for BinaryTreeDictionary:");
-  st->print_cr("------------------------------------");
-  size_t total_size = total_chunk_size(debug_only(NULL));
-  size_t free_blocks = num_free_blocks();
-  st->print_cr("Total Free Space: " SIZE_FORMAT, total_size);
-  st->print_cr("Max   Chunk Size: " SIZE_FORMAT, max_chunk_size());
-  st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks);
-  if (free_blocks > 0) {
-    st->print_cr("Av.  Block  Size: " SIZE_FORMAT, total_size/free_blocks);
-  }
-  st->print_cr("Tree      Height: " SIZE_FORMAT, tree_height());
-}
-
-// Print census information - counts, births, deaths, etc.
-// for each list in the tree.  Also print some summary
-// information.
-template <class Chunk_t, class FreeList_t>
-class PrintTreeCensusClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-  int _print_line;
-  size_t _total_free;
-  FreeList_t _total;
-
- public:
-  PrintTreeCensusClosure() {
-    _print_line = 0;
-    _total_free = 0;
-  }
-  FreeList_t* total() { return &_total; }
-  size_t total_free() { return _total_free; }
-  void do_list(FreeList<Chunk_t>* fl) {
-    LogStreamHandle(Debug, gc, freelist, census) out;
-
-    if (++_print_line >= 40) {
-      FreeList_t::print_labels_on(&out, "size");
-      _print_line = 0;
-    }
-    fl->print_on(&out);
-    _total_free += fl->count() * fl->size();
-    total()->set_count(total()->count() + fl->count());
-  }
-
-#if INCLUDE_ALL_GCS
-  void do_list(AdaptiveFreeList<Chunk_t>* fl) {
-    LogStreamHandle(Debug, gc, freelist, census) out;
-
-    if (++_print_line >= 40) {
-      FreeList_t::print_labels_on(&out, "size");
-      _print_line = 0;
-    }
-    fl->print_on(&out);
-    _total_free +=           fl->count()             * fl->size()        ;
-    total()->set_count(      total()->count()        + fl->count()      );
-    total()->set_bfr_surp(   total()->bfr_surp()     + fl->bfr_surp()    );
-    total()->set_surplus(    total()->split_deaths() + fl->surplus()    );
-    total()->set_desired(    total()->desired()      + fl->desired()    );
-    total()->set_prev_sweep(  total()->prev_sweep()   + fl->prev_sweep()  );
-    total()->set_before_sweep(total()->before_sweep() + fl->before_sweep());
-    total()->set_coal_births( total()->coal_births()  + fl->coal_births() );
-    total()->set_coal_deaths( total()->coal_deaths()  + fl->coal_deaths() );
-    total()->set_split_births(total()->split_births() + fl->split_births());
-    total()->set_split_deaths(total()->split_deaths() + fl->split_deaths());
-  }
-#endif // INCLUDE_ALL_GCS
-};
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_dict_census(outputStream* st) const {
-
-  st->print("BinaryTree");
-  FreeList_t::print_labels_on(st, "size");
-  PrintTreeCensusClosure<Chunk_t, FreeList_t> ptc;
-  ptc.do_tree(root());
-
-  FreeList_t* total = ptc.total();
-  FreeList_t::print_labels_on(st, " ");
-}
-
-#if INCLUDE_ALL_GCS
-template <>
-void AFLBinaryTreeDictionary::print_dict_census(outputStream* st) const {
-
-  st->print_cr("BinaryTree");
-  AdaptiveFreeList<FreeChunk>::print_labels_on(st, "size");
-  PrintTreeCensusClosure<FreeChunk, AdaptiveFreeList<FreeChunk> > ptc;
-  ptc.do_tree(root());
-
-  AdaptiveFreeList<FreeChunk>* total = ptc.total();
-  AdaptiveFreeList<FreeChunk>::print_labels_on(st, " ");
-  total->print_on(st, "TOTAL\t");
-  st->print_cr("total_free(words): " SIZE_FORMAT_W(16) " growth: %8.5f  deficit: %8.5f",
-               ptc.total_free(),
-               (double)(total->split_births() + total->coal_births()
-                      - total->split_deaths() - total->coal_deaths())
-               /(total->prev_sweep() != 0 ? (double)total->prev_sweep() : 1.0),
-              (double)(total->desired() - total->count())
-              /(total->desired() != 0 ? (double)total->desired() : 1.0));
-}
-#endif // INCLUDE_ALL_GCS
-
-template <class Chunk_t, class FreeList_t>
-class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
-  outputStream* _st;
-  int _print_line;
-
- public:
-  PrintFreeListsClosure(outputStream* st) {
-    _st = st;
-    _print_line = 0;
-  }
-  void do_list(FreeList_t* fl) {
-    if (++_print_line >= 40) {
-      FreeList_t::print_labels_on(_st, "size");
-      _print_line = 0;
-    }
-    fl->print_on(_st);
-    size_t sz = fl->size();
-    for (Chunk_t* fc = fl->head(); fc != NULL;
-         fc = fc->next()) {
-      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
-                    p2i(fc), p2i((HeapWord*)fc + sz),
-                    fc->cantCoalesce() ? "\t CC" : "");
-    }
-  }
-};
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_free_lists(outputStream* st) const {
-
-  FreeList_t::print_labels_on(st, "size");
-  PrintFreeListsClosure<Chunk_t, FreeList_t> pflc(st);
-  pflc.do_tree(root());
-}
-
-// Verify the following tree invariants:
-// . _root has no parent
-// . parent and child point to each other
-// . each node's key correctly related to that of its child(ren)
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree() const {
-  guarantee(root() == NULL || total_free_blocks() == 0 ||
-    total_size() != 0, "_total_size shouldn't be 0?");
-  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
-  verify_tree_helper(root());
-}
-
-template <class Chunk_t, class FreeList_t>
-size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_prev_free_ptrs(TreeList<Chunk_t, FreeList_t>* tl) {
-  size_t ct = 0;
-  for (Chunk_t* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
-    ct++;
-    assert(curFC->prev() == NULL || curFC->prev()->is_free(),
-      "Chunk should be free");
-  }
-  return ct;
-}
-
-// Note: this helper is recursive rather than iterative, so use with
-// caution on very deep trees; and watch out for stack overflow errors;
-// In general, to be used only for debugging.
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
-  if (tl == NULL)
-    return;
-  guarantee(tl->size() != 0, "A list must has a size");
-  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
-         "parent<-/->left");
-  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
-         "parent<-/->right");;
-  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
-         "parent !> left");
-  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
-         "parent !< left");
-  guarantee(tl->head() == NULL || tl->head()->is_free(), "!Free");
-  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
-    "list inconsistency");
-  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
-    "list count is inconsistent");
-  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
-    "list is incorrectly constructed");
-  size_t count = verify_prev_free_ptrs(tl);
-  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
-  if (tl->head() != NULL) {
-    tl->head_as_TreeChunk()->verify_tree_chunk_list();
-  }
-  verify_tree_helper(tl->left());
-  verify_tree_helper(tl->right());
-}
-
-template <class Chunk_t, class FreeList_t>
-void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify() const {
-  verify_tree();
-  guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency");
-}
-
-template class TreeList<Metablock, FreeList<Metablock> >;
-template class BinaryTreeDictionary<Metablock, FreeList<Metablock> >;
-template class TreeChunk<Metablock, FreeList<Metablock> >;
-
-template class TreeList<Metachunk, FreeList<Metachunk> >;
-template class BinaryTreeDictionary<Metachunk, FreeList<Metachunk> >;
-template class TreeChunk<Metachunk, FreeList<Metachunk> >;
-
-
-#if INCLUDE_ALL_GCS
-// Explicitly instantiate these types for FreeChunk.
-template class TreeList<FreeChunk, AdaptiveFreeList<FreeChunk> >;
-template class BinaryTreeDictionary<FreeChunk, AdaptiveFreeList<FreeChunk> >;
-template class TreeChunk<FreeChunk, AdaptiveFreeList<FreeChunk> >;
-
-#endif // INCLUDE_ALL_GCS
--- a/src/hotspot/share/memory/binaryTreeDictionary.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/binaryTreeDictionary.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -42,10 +42,6 @@
 template <class Chunk_t, class FreeList_t> class DescendTreeCensusClosure;
 template <class Chunk_t, class FreeList_t> class DescendTreeSearchClosure;
 
-class FreeChunk;
-template <class> class AdaptiveFreeList;
-typedef BinaryTreeDictionary<FreeChunk, AdaptiveFreeList<FreeChunk> > AFLBinaryTreeDictionary;
-
 template <class Chunk_t, class FreeList_t>
 class TreeList : public FreeList_t {
   friend class TreeChunk<Chunk_t, FreeList_t>;
@@ -177,6 +173,8 @@
 template <class Chunk_t, class FreeList_t>
 class BinaryTreeDictionary: public CHeapObj<mtGC> {
   friend class VMStructs;
+
+ protected:
   size_t     _total_size;
   size_t     _total_free_blocks;
   TreeList<Chunk_t, FreeList_t>* _root;
@@ -298,32 +296,9 @@
 
   Chunk_t* find_chunk_ends_at(HeapWord* target) const;
 
-  // Find the list with size "size" in the binary tree and update
-  // the statistics in the list according to "split" (chunk was
-  // split or coalesce) and "birth" (chunk was added or removed).
-  void       dict_census_update(size_t size, bool split, bool birth);
-  // Return true if the dictionary is overpopulated (more chunks of
-  // this size than desired) for size "size".
-  bool       coal_dict_over_populated(size_t size);
-  // Methods called at the beginning of a sweep to prepare the
-  // statistics for the sweep.
-  void       begin_sweep_dict_census(double coalSurplusPercent,
-                                  float inter_sweep_current,
-                                  float inter_sweep_estimate,
-                                  float intra_sweep_estimate);
-  // Methods called after the end of a sweep to modify the
-  // statistics for the sweep.
-  void       end_sweep_dict_census(double splitSurplusPercent);
   // Return the largest free chunk in the tree.
   Chunk_t* find_largest_dict() const;
-  // Accessors for statistics
-  void       set_tree_surplus(double splitSurplusPercent);
-  void       set_tree_hints(void);
-  // Reset statistics for all the lists in the tree.
-  void       clear_tree_census(void);
-  // Print the statistics for all the lists in the tree.  Also may
-  // print out summaries.
-  void       print_dict_census(outputStream* st) const;
+
   void       print_free_lists(outputStream* st) const;
 
   // For debugging.  Returns the sum of the _returned_bytes for
@@ -343,4 +318,83 @@
   void       verify_par_locked()       const PRODUCT_RETURN;
 };
 
+
+// Closures for walking the binary tree.
+//   do_list() walks the free list in a node applying the closure
+//     to each free chunk in the list
+//   do_tree() walks the nodes in the binary tree applying do_list()
+//     to each list at each node.
+
+template <class Chunk_t, class FreeList_t>
+class TreeCensusClosure : public StackObj {
+ protected:
+  virtual void do_list(FreeList_t* fl) = 0;
+ public:
+  virtual void do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
+};
+
+template <class Chunk_t, class FreeList_t>
+class AscendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
+ public:
+  void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
+    if (tl != NULL) {
+      do_tree(tl->left());
+      this->do_list(tl);
+      do_tree(tl->right());
+    }
+  }
+};
+
+template <class Chunk_t, class FreeList_t>
+class DescendTreeCensusClosure : public TreeCensusClosure<Chunk_t, FreeList_t> {
+ public:
+  void do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
+    if (tl != NULL) {
+      do_tree(tl->right());
+      this->do_list(tl);
+      do_tree(tl->left());
+    }
+  }
+};
+
+// Used to search the tree until a condition is met.
+// Similar to TreeCensusClosure but searches the
+// tree and returns promptly when found.
+
+template <class Chunk_t, class FreeList_t>
+class TreeSearchClosure : public StackObj {
+ protected:
+  virtual bool do_list(FreeList_t* fl) = 0;
+ public:
+  virtual bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) = 0;
+};
+
+#if 0 //  Don't need this yet but here for symmetry.
+template <class Chunk_t, class FreeList_t>
+class AscendTreeSearchClosure : public TreeSearchClosure<Chunk_t> {
+ public:
+  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
+    if (tl != NULL) {
+      if (do_tree(tl->left())) return true;
+      if (do_list(tl)) return true;
+      if (do_tree(tl->right())) return true;
+    }
+    return false;
+  }
+};
+#endif
+
+template <class Chunk_t, class FreeList_t>
+class DescendTreeSearchClosure : public TreeSearchClosure<Chunk_t, FreeList_t> {
+ public:
+  bool do_tree(TreeList<Chunk_t, FreeList_t>* tl) {
+    if (tl != NULL) {
+      if (do_tree(tl->right())) return true;
+      if (this->do_list(tl)) return true;
+      if (do_tree(tl->left())) return true;
+    }
+    return false;
+  }
+};
+
 #endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/binaryTreeDictionary.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,1025 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_BINARYTREEDICTIONARY_INLINE_HPP
+#define SHARE_VM_MEMORY_BINARYTREEDICTIONARY_INLINE_HPP
+
+#include "gc/shared/spaceDecorator.hpp"
+#include "logging/log.hpp"
+#include "logging/logStream.hpp"
+#include "memory/binaryTreeDictionary.hpp"
+#include "memory/freeList.inline.hpp"
+#include "memory/metachunk.hpp"
+#include "memory/resourceArea.hpp"
+#include "runtime/globals.hpp"
+#include "utilities/macros.hpp"
+#include "utilities/ostream.hpp"
+
+////////////////////////////////////////////////////////////////////////////////
+// A binary tree based search structure for free blocks.
+// This is currently used in the Concurrent Mark&Sweep implementation.
+////////////////////////////////////////////////////////////////////////////////
+
+template <class Chunk_t, class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(Chunk_t* fc) {
+  // Do some assertion checking here.
+  return (TreeChunk<Chunk_t, FreeList_t>*) fc;
+}
+
+template <class Chunk_t, class FreeList_t>
+void TreeChunk<Chunk_t, FreeList_t>::verify_tree_chunk_list() const {
+  TreeChunk<Chunk_t, FreeList_t>* nextTC = (TreeChunk<Chunk_t, FreeList_t>*)next();
+  if (prev() != NULL) { // interior list node shouldn't have tree fields
+    guarantee(embedded_list()->parent() == NULL && embedded_list()->left() == NULL &&
+              embedded_list()->right()  == NULL, "should be clear");
+  }
+  if (nextTC != NULL) {
+    guarantee(as_TreeChunk(nextTC->prev()) == this, "broken chain");
+    guarantee(nextTC->size() == size(), "wrong size");
+    nextTC->verify_tree_chunk_list();
+  }
+}
+
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>::TreeList() : _parent(NULL),
+  _left(NULL), _right(NULL) {}
+
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+TreeList<Chunk_t, FreeList_t>::as_TreeList(TreeChunk<Chunk_t,FreeList_t>* tc) {
+  // This first free chunk in the list will be the tree list.
+  assert((tc->size() >= (TreeChunk<Chunk_t, FreeList_t>::min_size())),
+    "Chunk is too small for a TreeChunk");
+  TreeList<Chunk_t, FreeList_t>* tl = tc->embedded_list();
+  tl->initialize();
+  tc->set_list(tl);
+  tl->set_size(tc->size());
+  tl->link_head(tc);
+  tl->link_tail(tc);
+  tl->set_count(1);
+  assert(tl->parent() == NULL, "Should be clear");
+  return tl;
+}
+
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+TreeList<Chunk_t, FreeList_t>::as_TreeList(HeapWord* addr, size_t size) {
+  TreeChunk<Chunk_t, FreeList_t>* tc = (TreeChunk<Chunk_t, FreeList_t>*) addr;
+  assert((size >= TreeChunk<Chunk_t, FreeList_t>::min_size()),
+    "Chunk is too small for a TreeChunk");
+  // The space will have been mangled initially but
+  // is not remangled when a Chunk_t is returned to the free list
+  // (since it is used to maintain the chunk on the free list).
+  tc->assert_is_mangled();
+  tc->set_size(size);
+  tc->link_prev(NULL);
+  tc->link_next(NULL);
+  TreeList<Chunk_t, FreeList_t>* tl = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
+  return tl;
+}
+
+
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>*
+TreeList<Chunk_t, FreeList_t>::get_better_list(
+  BinaryTreeDictionary<Chunk_t, FreeList_t>* dictionary) {
+  return this;
+}
+
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::remove_chunk_replace_if_needed(TreeChunk<Chunk_t, FreeList_t>* tc) {
+
+  TreeList<Chunk_t, FreeList_t>* retTL = this;
+  Chunk_t* list = head();
+  assert(!list || list != list->next(), "Chunk on list twice");
+  assert(tc != NULL, "Chunk being removed is NULL");
+  assert(parent() == NULL || this == parent()->left() ||
+    this == parent()->right(), "list is inconsistent");
+  assert(tc->is_free(), "Header is not marked correctly");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk_t* prevFC = tc->prev();
+  TreeChunk<Chunk_t, FreeList_t>* nextTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(tc->next());
+  assert(list != NULL, "should have at least the target chunk");
+
+  // Is this the first item on the list?
+  if (tc == list) {
+    // The "getChunk..." functions for a TreeList<Chunk_t, FreeList_t> will not return the
+    // first chunk in the list unless it is the last chunk in the list
+    // because the first chunk is also acting as the tree node.
+    // When coalescing happens, however, the first chunk in the a tree
+    // list can be the start of a free range.  Free ranges are removed
+    // from the free lists so that they are not available to be
+    // allocated when the sweeper yields (giving up the free list lock)
+    // to allow mutator activity.  If this chunk is the first in the
+    // list and is not the last in the list, do the work to copy the
+    // TreeList<Chunk_t, FreeList_t> from the first chunk to the next chunk and update all
+    // the TreeList<Chunk_t, FreeList_t> pointers in the chunks in the list.
+    if (nextTC == NULL) {
+      assert(prevFC == NULL, "Not last chunk in the list");
+      set_tail(NULL);
+      set_head(NULL);
+    } else {
+      // copy embedded list.
+      nextTC->set_embedded_list(tc->embedded_list());
+      retTL = nextTC->embedded_list();
+      // Fix the pointer to the list in each chunk in the list.
+      // This can be slow for a long list.  Consider having
+      // an option that does not allow the first chunk on the
+      // list to be coalesced.
+      for (TreeChunk<Chunk_t, FreeList_t>* curTC = nextTC; curTC != NULL;
+          curTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(curTC->next())) {
+        curTC->set_list(retTL);
+      }
+      // Fix the parent to point to the new TreeList<Chunk_t, FreeList_t>.
+      if (retTL->parent() != NULL) {
+        if (this == retTL->parent()->left()) {
+          retTL->parent()->set_left(retTL);
+        } else {
+          assert(this == retTL->parent()->right(), "Parent is incorrect");
+          retTL->parent()->set_right(retTL);
+        }
+      }
+      // Fix the children's parent pointers to point to the
+      // new list.
+      assert(right() == retTL->right(), "Should have been copied");
+      if (retTL->right() != NULL) {
+        retTL->right()->set_parent(retTL);
+      }
+      assert(left() == retTL->left(), "Should have been copied");
+      if (retTL->left() != NULL) {
+        retTL->left()->set_parent(retTL);
+      }
+      retTL->link_head(nextTC);
+      assert(nextTC->is_free(), "Should be a free chunk");
+    }
+  } else {
+    if (nextTC == NULL) {
+      // Removing chunk at tail of list
+      this->link_tail(prevFC);
+    }
+    // Chunk is interior to the list
+    prevFC->link_after(nextTC);
+  }
+
+  // Below this point the embedded TreeList<Chunk_t, FreeList_t> being used for the
+  // tree node may have changed. Don't use "this"
+  // TreeList<Chunk_t, FreeList_t>*.
+  // chunk should still be a free chunk (bit set in _prev)
+  assert(!retTL->head() || retTL->size() == retTL->head()->size(),
+    "Wrong sized chunk in list");
+  debug_only(
+    tc->link_prev(NULL);
+    tc->link_next(NULL);
+    tc->set_list(NULL);
+    bool prev_found = false;
+    bool next_found = false;
+    for (Chunk_t* curFC = retTL->head();
+         curFC != NULL; curFC = curFC->next()) {
+      assert(curFC != tc, "Chunk is still in list");
+      if (curFC == prevFC) {
+        prev_found = true;
+      }
+      if (curFC == nextTC) {
+        next_found = true;
+      }
+    }
+    assert(prevFC == NULL || prev_found, "Chunk was lost from list");
+    assert(nextTC == NULL || next_found, "Chunk was lost from list");
+    assert(retTL->parent() == NULL ||
+           retTL == retTL->parent()->left() ||
+           retTL == retTL->parent()->right(),
+           "list is inconsistent");
+  )
+  retTL->decrement_count();
+
+  assert(tc->is_free(), "Should still be a free chunk");
+  assert(retTL->head() == NULL || retTL->head()->prev() == NULL,
+    "list invariant");
+  assert(retTL->tail() == NULL || retTL->tail()->next() == NULL,
+    "list invariant");
+  return retTL;
+}
+
+template <class Chunk_t, class FreeList_t>
+void TreeList<Chunk_t, FreeList_t>::return_chunk_at_tail(TreeChunk<Chunk_t, FreeList_t>* chunk) {
+  assert(chunk != NULL, "returning NULL chunk");
+  assert(chunk->list() == this, "list should be set for chunk");
+  assert(tail() != NULL, "The tree list is embedded in the first chunk");
+  // which means that the list can never be empty.
+  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk_t* fc = tail();
+  fc->link_after(chunk);
+  this->link_tail(chunk);
+
+  assert(!tail() || size() == tail()->size(), "Wrong sized chunk in list");
+  FreeList_t::increment_count();
+  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+}
+
+// Add this chunk at the head of the list.  "At the head of the list"
+// is defined to be after the chunk pointer to by head().  This is
+// because the TreeList<Chunk_t, FreeList_t> is embedded in the first TreeChunk<Chunk_t, FreeList_t> in the
+// list.  See the definition of TreeChunk<Chunk_t, FreeList_t>.
+template <class Chunk_t, class FreeList_t>
+void TreeList<Chunk_t, FreeList_t>::return_chunk_at_head(TreeChunk<Chunk_t, FreeList_t>* chunk) {
+  assert(chunk->list() == this, "list should be set for chunk");
+  assert(head() != NULL, "The tree list is embedded in the first chunk");
+  assert(chunk != NULL, "returning NULL chunk");
+  assert(!this->verify_chunk_in_free_list(chunk), "Double entry");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk_t* fc = head()->next();
+  if (fc != NULL) {
+    chunk->link_after(fc);
+  } else {
+    assert(tail() == NULL, "List is inconsistent");
+    this->link_tail(chunk);
+  }
+  head()->link_after(chunk);
+  assert(!head() || size() == head()->size(), "Wrong sized chunk in list");
+  FreeList_t::increment_count();
+  debug_only(this->increment_returned_bytes_by(chunk->size()*sizeof(HeapWord));)
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+}
+
+template <class Chunk_t, class FreeList_t>
+void TreeChunk<Chunk_t, FreeList_t>::assert_is_mangled() const {
+  assert((ZapUnusedHeapArea &&
+          SpaceMangler::is_mangled((HeapWord*) Chunk_t::size_addr()) &&
+          SpaceMangler::is_mangled((HeapWord*) Chunk_t::prev_addr()) &&
+          SpaceMangler::is_mangled((HeapWord*) Chunk_t::next_addr())) ||
+          (size() == 0 && prev() == NULL && next() == NULL),
+    "Space should be clear or mangled");
+}
+
+template <class Chunk_t, class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::head_as_TreeChunk() {
+  assert(head() == NULL || (TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head())->list() == this),
+    "Wrong type of chunk?");
+  return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(head());
+}
+
+template <class Chunk_t, class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::first_available() {
+  assert(head() != NULL, "The head of the list cannot be NULL");
+  Chunk_t* fc = head()->next();
+  TreeChunk<Chunk_t, FreeList_t>* retTC;
+  if (fc == NULL) {
+    retTC = head_as_TreeChunk();
+  } else {
+    retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
+  }
+  assert(retTC->list() == this, "Wrong type of chunk.");
+  return retTC;
+}
+
+// Returns the block with the largest heap address amongst
+// those in the list for this size; potentially slow and expensive,
+// use with caution!
+template <class Chunk_t, class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>* TreeList<Chunk_t, FreeList_t>::largest_address() {
+  assert(head() != NULL, "The head of the list cannot be NULL");
+  Chunk_t* fc = head()->next();
+  TreeChunk<Chunk_t, FreeList_t>* retTC;
+  if (fc == NULL) {
+    retTC = head_as_TreeChunk();
+  } else {
+    // walk down the list and return the one with the highest
+    // heap address among chunks of this size.
+    Chunk_t* last = fc;
+    while (fc->next() != NULL) {
+      if ((HeapWord*)last < (HeapWord*)fc) {
+        last = fc;
+      }
+      fc = fc->next();
+    }
+    retTC = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(last);
+  }
+  assert(retTC->list() == this, "Wrong type of chunk.");
+  return retTC;
+}
+
+template <class Chunk_t, class FreeList_t>
+BinaryTreeDictionary<Chunk_t, FreeList_t>::BinaryTreeDictionary(MemRegion mr) {
+  assert((mr.byte_size() > min_size()), "minimum chunk size");
+
+  reset(mr);
+  assert(root()->left() == NULL, "reset check failed");
+  assert(root()->right() == NULL, "reset check failed");
+  assert(root()->head()->next() == NULL, "reset check failed");
+  assert(root()->head()->prev() == NULL, "reset check failed");
+  assert(total_size() == root()->size(), "reset check failed");
+  assert(total_free_blocks() == 1, "reset check failed");
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::inc_total_size(size_t inc) {
+  _total_size = _total_size + inc;
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::dec_total_size(size_t dec) {
+  _total_size = _total_size - dec;
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(MemRegion mr) {
+  assert((mr.byte_size() > min_size()), "minimum chunk size");
+  set_root(TreeList<Chunk_t, FreeList_t>::as_TreeList(mr.start(), mr.word_size()));
+  set_total_size(mr.word_size());
+  set_total_free_blocks(1);
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset(HeapWord* addr, size_t byte_size) {
+  MemRegion mr(addr, heap_word_size(byte_size));
+  reset(mr);
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::reset() {
+  set_root(NULL);
+  set_total_size(0);
+  set_total_free_blocks(0);
+}
+
+// Get a free block of size at least size from tree, or NULL.
+template <class Chunk_t, class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>*
+BinaryTreeDictionary<Chunk_t, FreeList_t>::get_chunk_from_tree(size_t size)
+{
+  TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
+  TreeChunk<Chunk_t, FreeList_t>* retTC = NULL;
+
+  assert((size >= min_size()), "minimum chunk size");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  // starting at the root, work downwards trying to find match.
+  // Remember the last node of size too great or too small.
+  for (prevTL = curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size) {        // exact match
+      break;
+    }
+    prevTL = curTL;
+    if (curTL->size() < size) {        // proceed to right sub-tree
+      curTL = curTL->right();
+    } else {                           // proceed to left sub-tree
+      assert(curTL->size() > size, "size inconsistency");
+      curTL = curTL->left();
+    }
+  }
+  if (curTL == NULL) { // couldn't find exact match
+
+    // try and find the next larger size by walking back up the search path
+    for (curTL = prevTL; curTL != NULL;) {
+      if (curTL->size() >= size) break;
+      else curTL = curTL->parent();
+    }
+    assert(curTL == NULL || curTL->count() > 0,
+      "An empty list should not be in the tree");
+  }
+  if (curTL != NULL) {
+    assert(curTL->size() >= size, "size inconsistency");
+
+    curTL = curTL->get_better_list(this);
+
+    retTC = curTL->first_available();
+    assert((retTC != NULL) && (curTL->count() > 0),
+      "A list in the binary tree should not be NULL");
+    assert(retTC->size() >= size,
+      "A chunk of the wrong size was found");
+    remove_chunk_from_tree(retTC);
+    assert(retTC->is_free(), "Header is not marked correctly");
+  }
+
+  if (FLSVerifyDictionary) {
+    verify();
+  }
+  return retTC;
+}
+
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_list(size_t size) const {
+  TreeList<Chunk_t, FreeList_t>* curTL;
+  for (curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size) {        // exact match
+      break;
+    }
+
+    if (curTL->size() < size) {        // proceed to right sub-tree
+      curTL = curTL->right();
+    } else {                           // proceed to left sub-tree
+      assert(curTL->size() > size, "size inconsistency");
+      curTL = curTL->left();
+    }
+  }
+  return curTL;
+}
+
+
+template <class Chunk_t, class FreeList_t>
+bool BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_chunk_in_free_list(Chunk_t* tc) const {
+  size_t size = tc->size();
+  TreeList<Chunk_t, FreeList_t>* tl = find_list(size);
+  if (tl == NULL) {
+    return false;
+  } else {
+    return tl->verify_chunk_in_free_list(tc);
+  }
+}
+
+template <class Chunk_t, class FreeList_t>
+Chunk_t* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_largest_dict() const {
+  TreeList<Chunk_t, FreeList_t> *curTL = root();
+  if (curTL != NULL) {
+    while(curTL->right() != NULL) curTL = curTL->right();
+    return curTL->largest_address();
+  } else {
+    return NULL;
+  }
+}
+
+// Remove the current chunk from the tree.  If it is not the last
+// chunk in a list on a tree node, just unlink it.
+// If it is the last chunk in the list (the next link is NULL),
+// remove the node and repair the tree.
+template <class Chunk_t, class FreeList_t>
+TreeChunk<Chunk_t, FreeList_t>*
+BinaryTreeDictionary<Chunk_t, FreeList_t>::remove_chunk_from_tree(TreeChunk<Chunk_t, FreeList_t>* tc) {
+  assert(tc != NULL, "Should not call with a NULL chunk");
+  assert(tc->is_free(), "Header is not marked correctly");
+
+  TreeList<Chunk_t, FreeList_t> *newTL, *parentTL;
+  TreeChunk<Chunk_t, FreeList_t>* retTC;
+  TreeList<Chunk_t, FreeList_t>* tl = tc->list();
+  debug_only(
+    bool removing_only_chunk = false;
+    if (tl == _root) {
+      if ((_root->left() == NULL) && (_root->right() == NULL)) {
+        if (_root->count() == 1) {
+          assert(_root->head() == tc, "Should only be this one chunk");
+          removing_only_chunk = true;
+        }
+      }
+    }
+  )
+  assert(tl != NULL, "List should be set");
+  assert(tl->parent() == NULL || tl == tl->parent()->left() ||
+         tl == tl->parent()->right(), "list is inconsistent");
+
+  bool complicated_splice = false;
+
+  retTC = tc;
+  // Removing this chunk can have the side effect of changing the node
+  // (TreeList<Chunk_t, FreeList_t>*) in the tree.  If the node is the root, update it.
+  TreeList<Chunk_t, FreeList_t>* replacementTL = tl->remove_chunk_replace_if_needed(tc);
+  assert(tc->is_free(), "Chunk should still be free");
+  assert(replacementTL->parent() == NULL ||
+         replacementTL == replacementTL->parent()->left() ||
+         replacementTL == replacementTL->parent()->right(),
+         "list is inconsistent");
+  if (tl == root()) {
+    assert(replacementTL->parent() == NULL, "Incorrectly replacing root");
+    set_root(replacementTL);
+  }
+#ifdef ASSERT
+    if (tl != replacementTL) {
+      assert(replacementTL->head() != NULL,
+        "If the tree list was replaced, it should not be a NULL list");
+      TreeList<Chunk_t, FreeList_t>* rhl = replacementTL->head_as_TreeChunk()->list();
+      TreeList<Chunk_t, FreeList_t>* rtl =
+        TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(replacementTL->tail())->list();
+      assert(rhl == replacementTL, "Broken head");
+      assert(rtl == replacementTL, "Broken tail");
+      assert(replacementTL->size() == tc->size(),  "Broken size");
+    }
+#endif
+
+  // Does the tree need to be repaired?
+  if (replacementTL->count() == 0) {
+    assert(replacementTL->head() == NULL &&
+           replacementTL->tail() == NULL, "list count is incorrect");
+    // Find the replacement node for the (soon to be empty) node being removed.
+    // if we have a single (or no) child, splice child in our stead
+    if (replacementTL->left() == NULL) {
+      // left is NULL so pick right.  right may also be NULL.
+      newTL = replacementTL->right();
+      debug_only(replacementTL->clear_right();)
+    } else if (replacementTL->right() == NULL) {
+      // right is NULL
+      newTL = replacementTL->left();
+      debug_only(replacementTL->clear_left();)
+    } else {  // we have both children, so, by patriarchal convention,
+              // my replacement is least node in right sub-tree
+      complicated_splice = true;
+      newTL = remove_tree_minimum(replacementTL->right());
+      assert(newTL != NULL && newTL->left() == NULL &&
+             newTL->right() == NULL, "sub-tree minimum exists");
+    }
+    // newTL is the replacement for the (soon to be empty) node.
+    // newTL may be NULL.
+    // should verify; we just cleanly excised our replacement
+    if (FLSVerifyDictionary) {
+      verify_tree();
+    }
+    // first make newTL my parent's child
+    if ((parentTL = replacementTL->parent()) == NULL) {
+      // newTL should be root
+      assert(tl == root(), "Incorrectly replacing root");
+      set_root(newTL);
+      if (newTL != NULL) {
+        newTL->clear_parent();
+      }
+    } else if (parentTL->right() == replacementTL) {
+      // replacementTL is a right child
+      parentTL->set_right(newTL);
+    } else {                                // replacementTL is a left child
+      assert(parentTL->left() == replacementTL, "should be left child");
+      parentTL->set_left(newTL);
+    }
+    debug_only(replacementTL->clear_parent();)
+    if (complicated_splice) {  // we need newTL to get replacementTL's
+                              // two children
+      assert(newTL != NULL &&
+             newTL->left() == NULL && newTL->right() == NULL,
+            "newTL should not have encumbrances from the past");
+      // we'd like to assert as below:
+      // assert(replacementTL->left() != NULL && replacementTL->right() != NULL,
+      //       "else !complicated_splice");
+      // ... however, the above assertion is too strong because we aren't
+      // guaranteed that replacementTL->right() is still NULL.
+      // Recall that we removed
+      // the right sub-tree minimum from replacementTL.
+      // That may well have been its right
+      // child! So we'll just assert half of the above:
+      assert(replacementTL->left() != NULL, "else !complicated_splice");
+      newTL->set_left(replacementTL->left());
+      newTL->set_right(replacementTL->right());
+      debug_only(
+        replacementTL->clear_right();
+        replacementTL->clear_left();
+      )
+    }
+    assert(replacementTL->right() == NULL &&
+           replacementTL->left() == NULL &&
+           replacementTL->parent() == NULL,
+        "delete without encumbrances");
+  }
+
+  assert(total_size() >= retTC->size(), "Incorrect total size");
+  dec_total_size(retTC->size());     // size book-keeping
+  assert(total_free_blocks() > 0, "Incorrect total count");
+  set_total_free_blocks(total_free_blocks() - 1);
+
+  assert(retTC != NULL, "null chunk?");
+  assert(retTC->prev() == NULL && retTC->next() == NULL,
+         "should return without encumbrances");
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  assert(!removing_only_chunk || _root == NULL, "root should be NULL");
+  return TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(retTC);
+}
+
+// Remove the leftmost node (lm) in the tree and return it.
+// If lm has a right child, link it to the left node of
+// the parent of lm.
+template <class Chunk_t, class FreeList_t>
+TreeList<Chunk_t, FreeList_t>* BinaryTreeDictionary<Chunk_t, FreeList_t>::remove_tree_minimum(TreeList<Chunk_t, FreeList_t>* tl) {
+  assert(tl != NULL && tl->parent() != NULL, "really need a proper sub-tree");
+  // locate the subtree minimum by walking down left branches
+  TreeList<Chunk_t, FreeList_t>* curTL = tl;
+  for (; curTL->left() != NULL; curTL = curTL->left());
+  // obviously curTL now has at most one child, a right child
+  if (curTL != root()) {  // Should this test just be removed?
+    TreeList<Chunk_t, FreeList_t>* parentTL = curTL->parent();
+    if (parentTL->left() == curTL) { // curTL is a left child
+      parentTL->set_left(curTL->right());
+    } else {
+      // If the list tl has no left child, then curTL may be
+      // the right child of parentTL.
+      assert(parentTL->right() == curTL, "should be a right child");
+      parentTL->set_right(curTL->right());
+    }
+  } else {
+    // The only use of this method would not pass the root of the
+    // tree (as indicated by the assertion above that the tree list
+    // has a parent) but the specification does not explicitly exclude the
+    // passing of the root so accommodate it.
+    set_root(NULL);
+  }
+  debug_only(
+    curTL->clear_parent();  // Test if this needs to be cleared
+    curTL->clear_right();    // recall, above, left child is already null
+  )
+  // we just excised a (non-root) node, we should still verify all tree invariants
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+  return curTL;
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::insert_chunk_in_tree(Chunk_t* fc) {
+  TreeList<Chunk_t, FreeList_t> *curTL, *prevTL;
+  size_t size = fc->size();
+
+  assert((size >= min_size()),
+         SIZE_FORMAT " is too small to be a TreeChunk<Chunk_t, FreeList_t> " SIZE_FORMAT,
+         size, min_size());
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+
+  fc->clear_next();
+  fc->link_prev(NULL);
+
+  // work down from the _root, looking for insertion point
+  for (prevTL = curTL = root(); curTL != NULL;) {
+    if (curTL->size() == size)  // exact match
+      break;
+    prevTL = curTL;
+    if (curTL->size() > size) { // follow left branch
+      curTL = curTL->left();
+    } else {                    // follow right branch
+      assert(curTL->size() < size, "size inconsistency");
+      curTL = curTL->right();
+    }
+  }
+  TreeChunk<Chunk_t, FreeList_t>* tc = TreeChunk<Chunk_t, FreeList_t>::as_TreeChunk(fc);
+  // This chunk is being returned to the binary tree.  Its embedded
+  // TreeList<Chunk_t, FreeList_t> should be unused at this point.
+  tc->initialize();
+  if (curTL != NULL) {          // exact match
+    tc->set_list(curTL);
+    curTL->return_chunk_at_tail(tc);
+  } else {                     // need a new node in tree
+    tc->clear_next();
+    tc->link_prev(NULL);
+    TreeList<Chunk_t, FreeList_t>* newTL = TreeList<Chunk_t, FreeList_t>::as_TreeList(tc);
+    assert(((TreeChunk<Chunk_t, FreeList_t>*)tc)->list() == newTL,
+      "List was not initialized correctly");
+    if (prevTL == NULL) {      // we are the only tree node
+      assert(root() == NULL, "control point invariant");
+      set_root(newTL);
+    } else {                   // insert under prevTL ...
+      if (prevTL->size() < size) {   // am right child
+        assert(prevTL->right() == NULL, "control point invariant");
+        prevTL->set_right(newTL);
+      } else {                       // am left child
+        assert(prevTL->size() > size && prevTL->left() == NULL, "cpt pt inv");
+        prevTL->set_left(newTL);
+      }
+    }
+  }
+  assert(tc->list() != NULL, "Tree list should be set");
+
+  inc_total_size(size);
+  // Method 'total_size_in_tree' walks through the every block in the
+  // tree, so it can cause significant performance loss if there are
+  // many blocks in the tree
+  assert(!FLSVerifyDictionary || total_size_in_tree(root()) == total_size(), "_total_size inconsistency");
+  set_total_free_blocks(total_free_blocks() + 1);
+  if (FLSVerifyDictionary) {
+    verify_tree();
+  }
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::max_chunk_size() const {
+  verify_par_locked();
+  TreeList<Chunk_t, FreeList_t>* tc = root();
+  if (tc == NULL) return 0;
+  for (; tc->right() != NULL; tc = tc->right());
+  return tc->size();
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_list_length(TreeList<Chunk_t, FreeList_t>* tl) const {
+  size_t res;
+  res = tl->count();
+#ifdef ASSERT
+  size_t cnt;
+  Chunk_t* tc = tl->head();
+  for (cnt = 0; tc != NULL; tc = tc->next(), cnt++);
+  assert(res == cnt, "The count is not being maintained correctly");
+#endif
+  return res;
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_size_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return (tl->size() * total_list_length(tl)) +
+         total_size_in_tree(tl->left())    +
+         total_size_in_tree(tl->right());
+}
+
+template <class Chunk_t, class FreeList_t>
+double BinaryTreeDictionary<Chunk_t, FreeList_t>::sum_of_squared_block_sizes(TreeList<Chunk_t, FreeList_t>* const tl) const {
+  if (tl == NULL) {
+    return 0.0;
+  }
+  double size = (double)(tl->size());
+  double curr = size * size * total_list_length(tl);
+  curr += sum_of_squared_block_sizes(tl->left());
+  curr += sum_of_squared_block_sizes(tl->right());
+  return curr;
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_free_blocks_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return total_list_length(tl) +
+         total_free_blocks_in_tree(tl->left()) +
+         total_free_blocks_in_tree(tl->right());
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::num_free_blocks() const {
+  assert(total_free_blocks_in_tree(root()) == total_free_blocks(),
+         "_total_free_blocks inconsistency");
+  return total_free_blocks();
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
+  if (tl == NULL)
+    return 0;
+  return 1 + MAX2(tree_height_helper(tl->left()),
+                  tree_height_helper(tl->right()));
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::tree_height() const {
+  return tree_height_helper(root());
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_nodes_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
+  if (tl == NULL) {
+    return 0;
+  }
+  return 1 + total_nodes_helper(tl->left()) +
+    total_nodes_helper(tl->right());
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_nodes_in_tree(TreeList<Chunk_t, FreeList_t>* tl) const {
+  return total_nodes_helper(root());
+}
+
+// Searches the tree for a chunk that ends at the
+// specified address.
+template <class Chunk_t, class FreeList_t>
+class EndTreeSearchClosure : public DescendTreeSearchClosure<Chunk_t, FreeList_t> {
+  HeapWord* _target;
+  Chunk_t* _found;
+
+ public:
+  EndTreeSearchClosure(HeapWord* target) : _target(target), _found(NULL) {}
+  bool do_list(FreeList_t* fl) {
+    Chunk_t* item = fl->head();
+    while (item != NULL) {
+      if (item->end() == (uintptr_t*) _target) {
+        _found = item;
+        return true;
+      }
+      item = item->next();
+    }
+    return false;
+  }
+  Chunk_t* found() { return _found; }
+};
+
+template <class Chunk_t, class FreeList_t>
+Chunk_t* BinaryTreeDictionary<Chunk_t, FreeList_t>::find_chunk_ends_at(HeapWord* target) const {
+  EndTreeSearchClosure<Chunk_t, FreeList_t> etsc(target);
+  bool found_target = etsc.do_tree(root());
+  assert(found_target || etsc.found() == NULL, "Consistency check");
+  assert(!found_target || etsc.found() != NULL, "Consistency check");
+  return etsc.found();
+}
+
+// Closures and methods for calculating total bytes returned to the
+// free lists in the tree.
+#ifndef PRODUCT
+template <class Chunk_t, class FreeList_t>
+class InitializeDictReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
+   public:
+  void do_list(FreeList_t* fl) {
+    fl->set_returned_bytes(0);
+  }
+};
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::initialize_dict_returned_bytes() {
+  InitializeDictReturnedBytesClosure<Chunk_t, FreeList_t> idrb;
+  idrb.do_tree(root());
+}
+
+template <class Chunk_t, class FreeList_t>
+class ReturnedBytesClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
+  size_t _dict_returned_bytes;
+ public:
+  ReturnedBytesClosure() { _dict_returned_bytes = 0; }
+  void do_list(FreeList_t* fl) {
+    _dict_returned_bytes += fl->returned_bytes();
+  }
+  size_t dict_returned_bytes() { return _dict_returned_bytes; }
+};
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::sum_dict_returned_bytes() {
+  ReturnedBytesClosure<Chunk_t, FreeList_t> rbc;
+  rbc.do_tree(root());
+
+  return rbc.dict_returned_bytes();
+}
+
+// Count the number of entries in the tree.
+template <class Chunk_t, class FreeList_t>
+class treeCountClosure : public DescendTreeCensusClosure<Chunk_t, FreeList_t> {
+ public:
+  uint count;
+  treeCountClosure(uint c) { count = c; }
+  void do_list(FreeList_t* fl) {
+    count++;
+  }
+};
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::total_count() {
+  treeCountClosure<Chunk_t, FreeList_t> ctc(0);
+  ctc.do_tree(root());
+  return ctc.count;
+}
+
+template <class Chunk_t, class FreeList_t>
+Mutex* BinaryTreeDictionary<Chunk_t, FreeList_t>::par_lock() const {
+  return _lock;
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::set_par_lock(Mutex* lock) {
+  _lock = lock;
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_par_locked() const {
+#ifdef ASSERT
+  Thread* my_thread = Thread::current();
+  if (my_thread->is_GC_task_thread()) {
+    assert(par_lock() != NULL, "Should be using locking?");
+    assert_lock_strong(par_lock());
+  }
+#endif // ASSERT
+}
+#endif // PRODUCT
+
+// Print summary statistics
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::report_statistics(outputStream* st) const {
+  verify_par_locked();
+  st->print_cr("Statistics for BinaryTreeDictionary:");
+  st->print_cr("------------------------------------");
+  size_t total_size = total_chunk_size(debug_only(NULL));
+  size_t free_blocks = num_free_blocks();
+  st->print_cr("Total Free Space: " SIZE_FORMAT, total_size);
+  st->print_cr("Max   Chunk Size: " SIZE_FORMAT, max_chunk_size());
+  st->print_cr("Number of Blocks: " SIZE_FORMAT, free_blocks);
+  if (free_blocks > 0) {
+    st->print_cr("Av.  Block  Size: " SIZE_FORMAT, total_size/free_blocks);
+  }
+  st->print_cr("Tree      Height: " SIZE_FORMAT, tree_height());
+}
+
+template <class Chunk_t, class FreeList_t>
+class PrintFreeListsClosure : public AscendTreeCensusClosure<Chunk_t, FreeList_t> {
+  outputStream* _st;
+  int _print_line;
+
+ public:
+  PrintFreeListsClosure(outputStream* st) {
+    _st = st;
+    _print_line = 0;
+  }
+  void do_list(FreeList_t* fl) {
+    if (++_print_line >= 40) {
+      FreeList_t::print_labels_on(_st, "size");
+      _print_line = 0;
+    }
+    fl->print_on(_st);
+    size_t sz = fl->size();
+    for (Chunk_t* fc = fl->head(); fc != NULL;
+         fc = fc->next()) {
+      _st->print_cr("\t[" PTR_FORMAT "," PTR_FORMAT ")  %s",
+                    p2i(fc), p2i((HeapWord*)fc + sz),
+                    fc->cantCoalesce() ? "\t CC" : "");
+    }
+  }
+};
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::print_free_lists(outputStream* st) const {
+
+  FreeList_t::print_labels_on(st, "size");
+  PrintFreeListsClosure<Chunk_t, FreeList_t> pflc(st);
+  pflc.do_tree(root());
+}
+
+// Verify the following tree invariants:
+// . _root has no parent
+// . parent and child point to each other
+// . each node's key correctly related to that of its child(ren)
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree() const {
+  guarantee(root() == NULL || total_free_blocks() == 0 ||
+    total_size() != 0, "_total_size shouldn't be 0?");
+  guarantee(root() == NULL || root()->parent() == NULL, "_root shouldn't have parent");
+  verify_tree_helper(root());
+}
+
+template <class Chunk_t, class FreeList_t>
+size_t BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_prev_free_ptrs(TreeList<Chunk_t, FreeList_t>* tl) {
+  size_t ct = 0;
+  for (Chunk_t* curFC = tl->head(); curFC != NULL; curFC = curFC->next()) {
+    ct++;
+    assert(curFC->prev() == NULL || curFC->prev()->is_free(),
+      "Chunk should be free");
+  }
+  return ct;
+}
+
+// Note: this helper is recursive rather than iterative, so use with
+// caution on very deep trees; and watch out for stack overflow errors;
+// In general, to be used only for debugging.
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify_tree_helper(TreeList<Chunk_t, FreeList_t>* tl) const {
+  if (tl == NULL)
+    return;
+  guarantee(tl->size() != 0, "A list must has a size");
+  guarantee(tl->left()  == NULL || tl->left()->parent()  == tl,
+         "parent<-/->left");
+  guarantee(tl->right() == NULL || tl->right()->parent() == tl,
+         "parent<-/->right");;
+  guarantee(tl->left() == NULL  || tl->left()->size()    <  tl->size(),
+         "parent !> left");
+  guarantee(tl->right() == NULL || tl->right()->size()   >  tl->size(),
+         "parent !< left");
+  guarantee(tl->head() == NULL || tl->head()->is_free(), "!Free");
+  guarantee(tl->head() == NULL || tl->head_as_TreeChunk()->list() == tl,
+    "list inconsistency");
+  guarantee(tl->count() > 0 || (tl->head() == NULL && tl->tail() == NULL),
+    "list count is inconsistent");
+  guarantee(tl->count() > 1 || tl->head() == tl->tail(),
+    "list is incorrectly constructed");
+  size_t count = verify_prev_free_ptrs(tl);
+  guarantee(count == (size_t)tl->count(), "Node count is incorrect");
+  if (tl->head() != NULL) {
+    tl->head_as_TreeChunk()->verify_tree_chunk_list();
+  }
+  verify_tree_helper(tl->left());
+  verify_tree_helper(tl->right());
+}
+
+template <class Chunk_t, class FreeList_t>
+void BinaryTreeDictionary<Chunk_t, FreeList_t>::verify() const {
+  verify_tree();
+  guarantee(total_size() == total_size_in_tree(root()), "Total Size inconsistency");
+}
+
+#endif // SHARE_VM_MEMORY_BINARYTREEDICTIONARY_INLINE_HPP
--- a/src/hotspot/share/memory/filemap.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/filemap.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -96,7 +96,7 @@
   va_list ap;
   va_start(ap, msg);
   MetaspaceShared::set_archive_loading_failed();
-  if (PrintSharedArchiveAndExit && _validating_classpath_entry_table) {
+  if (PrintSharedArchiveAndExit && _validating_shared_path_table) {
     // If we are doing PrintSharedArchiveAndExit and some of the classpath entries
     // do not validate, we can still continue "limping" to validate the remaining
     // entries. No need to quit.
@@ -188,9 +188,9 @@
   _max_heap_size = MaxHeapSize;
   _narrow_klass_base = Universe::narrow_klass_base();
   _narrow_klass_shift = Universe::narrow_klass_shift();
-  _classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
-  _classpath_entry_table = mapinfo->_classpath_entry_table;
-  _classpath_entry_size = mapinfo->_classpath_entry_size;
+  _shared_path_table_size = mapinfo->_shared_path_table_size;
+  _shared_path_table = mapinfo->_shared_path_table;
+  _shared_path_entry_size = mapinfo->_shared_path_entry_size;
 
   // The following fields are for sanity checks for whether this archive
   // will function correctly with this JVM and the bootclasspath it's
@@ -231,12 +231,16 @@
   strcpy(_name->data(), name);
 }
 
-bool SharedClassPathEntry::validate() {
+bool SharedClassPathEntry::validate(bool is_class_path) {
   struct stat st;
   const char* name = this->name();
   bool ok = true;
   log_info(class, path)("checking shared classpath entry: %s", name);
-  if (os::stat(name, &st) != 0) {
+  if (os::stat(name, &st) != 0 && is_class_path) {
+    // If the archived module path entry does not exist at runtime, it is not fatal
+    // (no need to invalid the shared archive) because the shared runtime visibility check
+    // filters out any archived module classes that do not have a matching runtime
+    // module path location.
     FileMapInfo::fail_continue("Required classpath entry does not exist: %s", name);
     ok = false;
   } else if (is_dir()) {
@@ -266,7 +270,7 @@
   it->push(&_manifest);
 }
 
-void FileMapInfo::allocate_classpath_entry_table() {
+void FileMapInfo::allocate_shared_path_table() {
   assert(DumpSharedSpaces, "Sanity");
 
   Thread* THREAD = Thread::current();
@@ -279,12 +283,13 @@
   size_t entry_size = SharedClassUtil::shared_class_path_entry_size(); // assert ( should be 8 byte aligned??)
   int num_boot_classpath_entries = ClassLoader::num_boot_classpath_entries();
   int num_app_classpath_entries = ClassLoader::num_app_classpath_entries();
-  int num_entries = num_boot_classpath_entries + num_app_classpath_entries;
+  int num_module_path_entries = ClassLoader::num_module_path_entries();
+  int num_entries = num_boot_classpath_entries + num_app_classpath_entries + num_module_path_entries;
   size_t bytes = entry_size * num_entries;
 
-  _classpath_entry_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
-  _classpath_entry_table_size = num_entries;
-  _classpath_entry_size = entry_size;
+  _shared_path_table = MetadataFactory::new_array<u8>(loader_data, (int)(bytes + 7 / 8), THREAD);
+  _shared_path_table_size = num_entries;
+  _shared_path_entry_size = entry_size;
 
   // 1. boot class path
   int i = 0;
@@ -292,7 +297,7 @@
   while (cpe != NULL) {
     const char* type = ((cpe == jrt) ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
     log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
-    SharedClassPathEntry* ent = shared_classpath(i);
+    SharedClassPathEntry* ent = shared_path(i);
     ent->init(cpe->name(), THREAD);
     if (cpe != jrt) { // No need to do jimage.
       EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
@@ -308,41 +313,66 @@
   ClassPathEntry *acpe = ClassLoader::app_classpath_entries();
   while (acpe != NULL) {
     log_info(class, path)("add app shared path %s", acpe->name());
-    SharedClassPathEntry* ent = shared_classpath(i);
+    SharedClassPathEntry* ent = shared_path(i);
     ent->init(acpe->name(), THREAD);
     EXCEPTION_MARK;
     SharedClassUtil::update_shared_classpath(acpe, ent, THREAD);
     acpe = acpe->next();
-    i ++;
+    i++;
   }
-  assert(i == num_entries, "number of app class path entry mismatch");
+
+  // 3. module path
+  ClassPathEntry *mpe = ClassLoader::module_path_entries();
+  while (mpe != NULL) {
+    log_info(class, path)("add module path %s",mpe->name());
+    SharedClassPathEntry* ent = shared_path(i);
+    ent->init(mpe->name(), THREAD);
+    EXCEPTION_MARK;
+    SharedClassUtil::update_shared_classpath(mpe, ent, THREAD);
+    mpe = mpe->next();
+    i++;
+  }
+  assert(i == num_entries, "number of shared path entry mismatch");
 }
 
-bool FileMapInfo::validate_classpath_entry_table() {
-  _validating_classpath_entry_table = true;
+// This function should only be called during run time with UseSharedSpaces enabled.
+bool FileMapInfo::validate_shared_path_table() {
+  _validating_shared_path_table = true;
+
+  _shared_path_table = _header->_shared_path_table;
+  _shared_path_entry_size = _header->_shared_path_entry_size;
+  _shared_path_table_size = _header->_shared_path_table_size;
 
-  int count = _header->_classpath_entry_table_size;
+  // Note: _app_module_paths_start_index may not have a valid value if the UseAppCDS flag
+  // wasn't enabled during dump time. Therefore, we need to use the smaller of
+  // _shared_path_table_size and _app_module_paths_start_index for the _app_module_paths_start_index.
+  FileMapHeaderExt* header = (FileMapHeaderExt*)FileMapInfo::current_info()->header();
+  int module_paths_start_index = (header->_app_module_paths_start_index >= _shared_path_table_size) ?
+                                  _shared_path_table_size : header->_app_module_paths_start_index;
 
-  _classpath_entry_table = _header->_classpath_entry_table;
-  _classpath_entry_size = _header->_classpath_entry_size;
-  _classpath_entry_table_size = _header->_classpath_entry_table_size;
+  int count = _shared_path_table_size;
 
   for (int i=0; i<count; i++) {
-    if (shared_classpath(i)->validate()) {
-      log_info(class, path)("ok");
+    if (i < module_paths_start_index) {
+      if (shared_path(i)->validate()) {
+        log_info(class, path)("ok");
+      }
+    } else if (i >= module_paths_start_index) {
+      if (shared_path(i)->validate(false /* not a class path entry */)) {
+        log_info(class, path)("ok");
+      }
     } else if (!PrintSharedArchiveAndExit) {
-      _validating_classpath_entry_table = false;
-      _classpath_entry_table = NULL;
-      _classpath_entry_table_size = 0;
+      _validating_shared_path_table = false;
+      _shared_path_table = NULL;
+      _shared_path_table_size = 0;
       return false;
     }
   }
 
-  _validating_classpath_entry_table = false;
+  _validating_shared_path_table = false;
   return true;
 }
 
-
 // Read the FileMapInfo information from the file.
 
 bool FileMapInfo::init_from_file(int fd) {
@@ -925,18 +955,18 @@
 }
 
 void FileMapInfo::metaspace_pointers_do(MetaspaceClosure* it) {
-  it->push(&_classpath_entry_table);
-  for (int i=0; i<_classpath_entry_table_size; i++) {
-    shared_classpath(i)->metaspace_pointers_do(it);
+  it->push(&_shared_path_table);
+  for (int i=0; i<_shared_path_table_size; i++) {
+    shared_path(i)->metaspace_pointers_do(it);
   }
 }
 
 
 FileMapInfo* FileMapInfo::_current_info = NULL;
-Array<u8>* FileMapInfo::_classpath_entry_table = NULL;
-int FileMapInfo::_classpath_entry_table_size = 0;
-size_t FileMapInfo::_classpath_entry_size = 0x1234baad;
-bool FileMapInfo::_validating_classpath_entry_table = false;
+Array<u8>* FileMapInfo::_shared_path_table = NULL;
+int FileMapInfo::_shared_path_table_size = 0;
+size_t FileMapInfo::_shared_path_entry_size = 0x1234baad;
+bool FileMapInfo::_validating_shared_path_table = false;
 
 // Open the shared archive file, read and validate the header
 // information (version, boot classpath, etc.).  If initialization
@@ -946,7 +976,7 @@
 // Validation of the archive is done in two steps:
 //
 // [1] validate_header() - done here. This checks the header, including _paths_misc_info.
-// [2] validate_classpath_entry_table - this is done later, because the table is in the RW
+// [2] validate_shared_path_table - this is done later, because the table is in the RW
 //     region of the archive, which is not mapped yet.
 bool FileMapInfo::initialize() {
   assert(UseSharedSpaces, "UseSharedSpaces expected.");
@@ -980,6 +1010,7 @@
   return crc;
 }
 
+// This function should only be called during run time with UseSharedSpaces enabled.
 bool FileMapInfo::FileMapHeader::validate() {
   if (VerifySharedSpaces && compute_crc() != _crc) {
     fail_continue("Header checksum verification failed.");
--- a/src/hotspot/share/memory/filemap.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/filemap.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -53,7 +53,7 @@
 public:
   void init(const char* name, TRAPS);
   void metaspace_pointers_do(MetaspaceClosure* it);
-  bool validate();
+  bool validate(bool is_class_path = true);
 
   // The _timestamp only gets set for jar files and "modules" jimage.
   bool is_jar_or_bootimage() {
@@ -85,10 +85,10 @@
   size_t  _file_offset;
 
 private:
-  static Array<u8>*            _classpath_entry_table;
-  static int                   _classpath_entry_table_size;
-  static size_t                _classpath_entry_size;
-  static bool                  _validating_classpath_entry_table;
+  static Array<u8>*            _shared_path_table;
+  static int                   _shared_path_table_size;
+  static size_t                _shared_path_entry_size;
+  static bool                  _validating_shared_path_table;
 
   // FileMapHeader describes the shared space data in the file to be
   // mapped.  This structure gets written to a file.  It is not a class, so
@@ -153,7 +153,7 @@
     // checking the validity of the archive and is deallocated after the archive is loaded.
     //
     // Note that the _paths_misc_info does NOT include information for JAR files
-    // that existed during dump time. Their information is stored in _classpath_entry_table.
+    // that existed during dump time. Their information is stored in _shared_path_table.
     int _paths_misc_info_size;
 
     // The following is a table of all the class path entries that were used
@@ -167,9 +167,9 @@
     // FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
     // they should be removed from this table, to save space and to avoid spurious
     // loading failures during runtime.
-    int _classpath_entry_table_size;
-    size_t _classpath_entry_size;
-    Array<u8>* _classpath_entry_table;
+    int _shared_path_table_size;
+    size_t _shared_path_entry_size;
+    Array<u8>* _shared_path_table;
 
     char* region_addr(int idx);
 
@@ -270,25 +270,26 @@
   // Stop CDS sharing and unmap CDS regions.
   static void stop_sharing_and_unmap(const char* msg);
 
-  static void allocate_classpath_entry_table();
-  bool validate_classpath_entry_table();
+  static void allocate_shared_path_table();
+  bool validate_shared_path_table();
 
-  static SharedClassPathEntry* shared_classpath(int index) {
+  static SharedClassPathEntry* shared_path(int index) {
     if (index < 0) {
       return NULL;
     }
-    assert(index < _classpath_entry_table_size, "sanity");
-    char* p = (char*)_classpath_entry_table->data();
-    p += _classpath_entry_size * index;
+    assert(index < _shared_path_table_size, "sanity");
+    char* p = (char*)_shared_path_table->data();
+    p += _shared_path_entry_size * index;
     return (SharedClassPathEntry*)p;
   }
-  static const char* shared_classpath_name(int index) {
+
+  static const char* shared_path_name(int index) {
     assert(index >= 0, "Sanity");
-    return shared_classpath(index)->name();
+    return shared_path(index)->name();
   }
 
-  static int get_number_of_share_classpaths() {
-    return _classpath_entry_table_size;
+  static int get_number_of_shared_paths() {
+    return _shared_path_table_size;
   }
 
  private:
--- a/src/hotspot/share/memory/freeList.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,336 +0,0 @@
-/*
- * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "memory/freeList.hpp"
-#include "memory/metachunk.hpp"
-#include "runtime/globals.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/vmThread.hpp"
-#include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/cms/freeChunk.hpp"
-#endif // INCLUDE_ALL_GCS
-
-// Free list.  A FreeList is used to access a linked list of chunks
-// of space in the heap.  The head and tail are maintained so that
-// items can be (as in the current implementation) added at the
-// at the tail of the list and removed from the head of the list to
-// maintain a FIFO queue.
-
-template <class Chunk>
-FreeList<Chunk>::FreeList() :
-  _head(NULL), _tail(NULL)
-#ifdef ASSERT
-  , _protecting_lock(NULL)
-#endif
-{
-  _size         = 0;
-  _count        = 0;
-}
-
-template <class Chunk>
-void FreeList<Chunk>::link_head(Chunk* v) {
-  assert_proper_lock_protection();
-  set_head(v);
-  // If this method is not used (just set the head instead),
-  // this check can be avoided.
-  if (v != NULL) {
-    v->link_prev(NULL);
-  }
-}
-
-
-
-template <class Chunk>
-void FreeList<Chunk>::reset() {
-  // Don't set the _size to 0 because this method is
-  // used with a existing list that has a size but which has
-  // been emptied.
-  // Don't clear the _protecting_lock of an existing list.
-  set_count(0);
-  set_head(NULL);
-  set_tail(NULL);
-}
-
-template <class Chunk>
-void FreeList<Chunk>::initialize() {
-#ifdef ASSERT
-  // Needed early because it might be checked in other initializing code.
-  set_protecting_lock(NULL);
-#endif
-  reset();
-  set_size(0);
-}
-
-template <class Chunk_t>
-Chunk_t* FreeList<Chunk_t>::get_chunk_at_head() {
-  assert_proper_lock_protection();
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  Chunk_t* fc = head();
-  if (fc != NULL) {
-    Chunk_t* nextFC = fc->next();
-    if (nextFC != NULL) {
-      // The chunk fc being removed has a "next".  Set the "next" to the
-      // "prev" of fc.
-      nextFC->link_prev(NULL);
-    } else { // removed tail of list
-      link_tail(NULL);
-    }
-    link_head(nextFC);
-    decrement_count();
-  }
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  return fc;
-}
-
-
-template <class Chunk>
-void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) {
-  assert_proper_lock_protection();
-  assert(fl->count() == 0, "Precondition");
-  if (count() > 0) {
-    int k = 1;
-    fl->set_head(head()); n--;
-    Chunk* tl = head();
-    while (tl->next() != NULL && n > 0) {
-      tl = tl->next(); n--; k++;
-    }
-    assert(tl != NULL, "Loop Inv.");
-
-    // First, fix up the list we took from.
-    Chunk* new_head = tl->next();
-    set_head(new_head);
-    set_count(count() - k);
-    if (new_head == NULL) {
-      set_tail(NULL);
-    } else {
-      new_head->link_prev(NULL);
-    }
-    // Now we can fix up the tail.
-    tl->link_next(NULL);
-    // And return the result.
-    fl->set_tail(tl);
-    fl->set_count(k);
-  }
-}
-
-// Remove this chunk from the list
-template <class Chunk>
-void FreeList<Chunk>::remove_chunk(Chunk*fc) {
-   assert_proper_lock_protection();
-   assert(head() != NULL, "Remove from empty list");
-   assert(fc != NULL, "Remove a NULL chunk");
-   assert(size() == fc->size(), "Wrong list");
-   assert(head() == NULL || head()->prev() == NULL, "list invariant");
-   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-   Chunk* prevFC = fc->prev();
-   Chunk* nextFC = fc->next();
-   if (nextFC != NULL) {
-     // The chunk fc being removed has a "next".  Set the "next" to the
-     // "prev" of fc.
-     nextFC->link_prev(prevFC);
-   } else { // removed tail of list
-     link_tail(prevFC);
-   }
-   if (prevFC == NULL) { // removed head of list
-     link_head(nextFC);
-     assert(nextFC == NULL || nextFC->prev() == NULL,
-       "Prev of head should be NULL");
-   } else {
-     prevFC->link_next(nextFC);
-     assert(tail() != prevFC || prevFC->next() == NULL,
-       "Next of tail should be NULL");
-   }
-   decrement_count();
-   assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
-          "H/T/C Inconsistency");
-   // clear next and prev fields of fc, debug only
-   NOT_PRODUCT(
-     fc->link_prev(NULL);
-     fc->link_next(NULL);
-   )
-   assert(fc->is_free(), "Should still be a free chunk");
-   assert(head() == NULL || head()->prev() == NULL, "list invariant");
-   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-   assert(head() == NULL || head()->size() == size(), "wrong item on list");
-   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-// Add this chunk at the head of the list.
-template <class Chunk>
-void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk, bool record_return) {
-  assert_proper_lock_protection();
-  assert(chunk != NULL, "insert a NULL chunk");
-  assert(size() == chunk->size(), "Wrong size");
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-
-  Chunk* oldHead = head();
-  assert(chunk != oldHead, "double insertion");
-  chunk->link_after(oldHead);
-  link_head(chunk);
-  if (oldHead == NULL) { // only chunk in list
-    assert(tail() == NULL, "inconsistent FreeList");
-    link_tail(chunk);
-  }
-  increment_count(); // of # of chunks in list
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(head() == NULL || head()->size() == size(), "wrong item on list");
-  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-template <class Chunk>
-void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk) {
-  assert_proper_lock_protection();
-  return_chunk_at_head(chunk, true);
-}
-
-// Add this chunk at the tail of the list.
-template <class Chunk>
-void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk, bool record_return) {
-  assert_proper_lock_protection();
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(chunk != NULL, "insert a NULL chunk");
-  assert(size() == chunk->size(), "wrong size");
-
-  Chunk* oldTail = tail();
-  assert(chunk != oldTail, "double insertion");
-  if (oldTail != NULL) {
-    oldTail->link_after(chunk);
-  } else { // only chunk in list
-    assert(head() == NULL, "inconsistent FreeList");
-    link_head(chunk);
-  }
-  link_tail(chunk);
-  increment_count();  // of # of chunks in list
-  assert(head() == NULL || head()->prev() == NULL, "list invariant");
-  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
-  assert(head() == NULL || head()->size() == size(), "wrong item on list");
-  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
-}
-
-template <class Chunk>
-void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk) {
-  return_chunk_at_tail(chunk, true);
-}
-
-template <class Chunk>
-void FreeList<Chunk>::prepend(FreeList<Chunk>* fl) {
-  assert_proper_lock_protection();
-  if (fl->count() > 0) {
-    if (count() == 0) {
-      set_head(fl->head());
-      set_tail(fl->tail());
-      set_count(fl->count());
-    } else {
-      // Both are non-empty.
-      Chunk* fl_tail = fl->tail();
-      Chunk* this_head = head();
-      assert(fl_tail->next() == NULL, "Well-formedness of fl");
-      fl_tail->link_next(this_head);
-      this_head->link_prev(fl_tail);
-      set_head(fl->head());
-      set_count(count() + fl->count());
-    }
-    fl->set_head(NULL);
-    fl->set_tail(NULL);
-    fl->set_count(0);
-  }
-}
-
-// verify_chunk_in_free_lists() is used to verify that an item is in this free list.
-// It is used as a debugging aid.
-template <class Chunk>
-bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
-  // This is an internal consistency check, not part of the check that the
-  // chunk is in the free lists.
-  guarantee(fc->size() == size(), "Wrong list is being searched");
-  Chunk* curFC = head();
-  while (curFC) {
-    // This is an internal consistency check.
-    guarantee(size() == curFC->size(), "Chunk is in wrong list.");
-    if (fc == curFC) {
-      return true;
-    }
-    curFC = curFC->next();
-  }
-  return false;
-}
-
-#ifdef ASSERT
-template <class Chunk>
-void FreeList<Chunk>::assert_proper_lock_protection_work() const {
-  // Nothing to do if the list has no assigned protecting lock
-  if (protecting_lock() == NULL) {
-    return;
-  }
-
-  Thread* thr = Thread::current();
-  if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
-    // assert that we are holding the freelist lock
-  } else if (thr->is_GC_task_thread()) {
-    assert(protecting_lock()->owned_by_self(), "FreeList RACE DETECTED");
-  } else if (thr->is_Java_thread()) {
-    assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
-  } else {
-    ShouldNotReachHere();  // unaccounted thread type?
-  }
-}
-#endif
-
-// Print the "label line" for free list stats.
-template <class Chunk>
-void FreeList<Chunk>::print_labels_on(outputStream* st, const char* c) {
-  st->print("%16s\t", c);
-  st->print("%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"
-            "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "\n",
-            "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
-            "count",   "cBirths", "cDeaths", "sBirths", "sDeaths");
-}
-
-// Print the AllocationStats for the given free list. If the second argument
-// to the call is a non-null string, it is printed in the first column;
-// otherwise, if the argument is null (the default), then the size of the
-// (free list) block is printed in the first column.
-template <class Chunk_t>
-void FreeList<Chunk_t>::print_on(outputStream* st, const char* c) const {
-  if (c != NULL) {
-    st->print("%16s", c);
-  } else {
-    st->print(SIZE_FORMAT_W(16), size());
-  }
-}
-
-template class FreeList<Metablock>;
-template class FreeList<Metachunk>;
-#if INCLUDE_ALL_GCS
-template class FreeList<FreeChunk>;
-#endif // INCLUDE_ALL_GCS
--- a/src/hotspot/share/memory/freeList.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/freeList.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,10 +25,6 @@
 #ifndef SHARE_VM_MEMORY_FREELIST_HPP
 #define SHARE_VM_MEMORY_FREELIST_HPP
 
-#include "gc/cms/allocationStats.hpp"
-
-class CompactibleFreeListSpace;
-
 // A class for maintaining a free list of Chunk's.  The FreeList
 // maintains a the structure of the list (head, tail, etc.) plus
 // statistics for allocations from the list.  The links between items
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/memory/freeList.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_MEMORY_FREELIST_INLINE_HPP
+#define SHARE_MEMORY_FREELIST_INLINE_HPP
+
+#include "gc/shared/collectedHeap.hpp"
+#include "memory/freeList.hpp"
+#include "memory/metachunk.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/vmThread.hpp"
+#include "utilities/macros.hpp"
+
+// Free list.  A FreeList is used to access a linked list of chunks
+// of space in the heap.  The head and tail are maintained so that
+// items can be (as in the current implementation) added at the
+// at the tail of the list and removed from the head of the list to
+// maintain a FIFO queue.
+
+template <class Chunk>
+FreeList<Chunk>::FreeList() :
+  _head(NULL), _tail(NULL)
+#ifdef ASSERT
+  , _protecting_lock(NULL)
+#endif
+{
+  _size         = 0;
+  _count        = 0;
+}
+
+template <class Chunk>
+void FreeList<Chunk>::link_head(Chunk* v) {
+  assert_proper_lock_protection();
+  set_head(v);
+  // If this method is not used (just set the head instead),
+  // this check can be avoided.
+  if (v != NULL) {
+    v->link_prev(NULL);
+  }
+}
+
+
+
+template <class Chunk>
+void FreeList<Chunk>::reset() {
+  // Don't set the _size to 0 because this method is
+  // used with a existing list that has a size but which has
+  // been emptied.
+  // Don't clear the _protecting_lock of an existing list.
+  set_count(0);
+  set_head(NULL);
+  set_tail(NULL);
+}
+
+template <class Chunk>
+void FreeList<Chunk>::initialize() {
+#ifdef ASSERT
+  // Needed early because it might be checked in other initializing code.
+  set_protecting_lock(NULL);
+#endif
+  reset();
+  set_size(0);
+}
+
+template <class Chunk_t>
+Chunk_t* FreeList<Chunk_t>::get_chunk_at_head() {
+  assert_proper_lock_protection();
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  Chunk_t* fc = head();
+  if (fc != NULL) {
+    Chunk_t* nextFC = fc->next();
+    if (nextFC != NULL) {
+      // The chunk fc being removed has a "next".  Set the "next" to the
+      // "prev" of fc.
+      nextFC->link_prev(NULL);
+    } else { // removed tail of list
+      link_tail(NULL);
+    }
+    link_head(nextFC);
+    decrement_count();
+  }
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  return fc;
+}
+
+
+template <class Chunk>
+void FreeList<Chunk>::getFirstNChunksFromList(size_t n, FreeList<Chunk>* fl) {
+  assert_proper_lock_protection();
+  assert(fl->count() == 0, "Precondition");
+  if (count() > 0) {
+    int k = 1;
+    fl->set_head(head()); n--;
+    Chunk* tl = head();
+    while (tl->next() != NULL && n > 0) {
+      tl = tl->next(); n--; k++;
+    }
+    assert(tl != NULL, "Loop Inv.");
+
+    // First, fix up the list we took from.
+    Chunk* new_head = tl->next();
+    set_head(new_head);
+    set_count(count() - k);
+    if (new_head == NULL) {
+      set_tail(NULL);
+    } else {
+      new_head->link_prev(NULL);
+    }
+    // Now we can fix up the tail.
+    tl->link_next(NULL);
+    // And return the result.
+    fl->set_tail(tl);
+    fl->set_count(k);
+  }
+}
+
+// Remove this chunk from the list
+template <class Chunk>
+void FreeList<Chunk>::remove_chunk(Chunk*fc) {
+   assert_proper_lock_protection();
+   assert(head() != NULL, "Remove from empty list");
+   assert(fc != NULL, "Remove a NULL chunk");
+   assert(size() == fc->size(), "Wrong list");
+   assert(head() == NULL || head()->prev() == NULL, "list invariant");
+   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+   Chunk* prevFC = fc->prev();
+   Chunk* nextFC = fc->next();
+   if (nextFC != NULL) {
+     // The chunk fc being removed has a "next".  Set the "next" to the
+     // "prev" of fc.
+     nextFC->link_prev(prevFC);
+   } else { // removed tail of list
+     link_tail(prevFC);
+   }
+   if (prevFC == NULL) { // removed head of list
+     link_head(nextFC);
+     assert(nextFC == NULL || nextFC->prev() == NULL,
+       "Prev of head should be NULL");
+   } else {
+     prevFC->link_next(nextFC);
+     assert(tail() != prevFC || prevFC->next() == NULL,
+       "Next of tail should be NULL");
+   }
+   decrement_count();
+   assert(((head() == NULL) + (tail() == NULL) + (count() == 0)) % 3 == 0,
+          "H/T/C Inconsistency");
+   // clear next and prev fields of fc, debug only
+   NOT_PRODUCT(
+     fc->link_prev(NULL);
+     fc->link_next(NULL);
+   )
+   assert(fc->is_free(), "Should still be a free chunk");
+   assert(head() == NULL || head()->prev() == NULL, "list invariant");
+   assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+   assert(head() == NULL || head()->size() == size(), "wrong item on list");
+   assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+// Add this chunk at the head of the list.
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk, bool record_return) {
+  assert_proper_lock_protection();
+  assert(chunk != NULL, "insert a NULL chunk");
+  assert(size() == chunk->size(), "Wrong size");
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+
+  Chunk* oldHead = head();
+  assert(chunk != oldHead, "double insertion");
+  chunk->link_after(oldHead);
+  link_head(chunk);
+  if (oldHead == NULL) { // only chunk in list
+    assert(tail() == NULL, "inconsistent FreeList");
+    link_tail(chunk);
+  }
+  increment_count(); // of # of chunks in list
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(head() == NULL || head()->size() == size(), "wrong item on list");
+  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_head(Chunk* chunk) {
+  assert_proper_lock_protection();
+  return_chunk_at_head(chunk, true);
+}
+
+// Add this chunk at the tail of the list.
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk, bool record_return) {
+  assert_proper_lock_protection();
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(chunk != NULL, "insert a NULL chunk");
+  assert(size() == chunk->size(), "wrong size");
+
+  Chunk* oldTail = tail();
+  assert(chunk != oldTail, "double insertion");
+  if (oldTail != NULL) {
+    oldTail->link_after(chunk);
+  } else { // only chunk in list
+    assert(head() == NULL, "inconsistent FreeList");
+    link_head(chunk);
+  }
+  link_tail(chunk);
+  increment_count();  // of # of chunks in list
+  assert(head() == NULL || head()->prev() == NULL, "list invariant");
+  assert(tail() == NULL || tail()->next() == NULL, "list invariant");
+  assert(head() == NULL || head()->size() == size(), "wrong item on list");
+  assert(tail() == NULL || tail()->size() == size(), "wrong item on list");
+}
+
+template <class Chunk>
+void FreeList<Chunk>::return_chunk_at_tail(Chunk* chunk) {
+  return_chunk_at_tail(chunk, true);
+}
+
+template <class Chunk>
+void FreeList<Chunk>::prepend(FreeList<Chunk>* fl) {
+  assert_proper_lock_protection();
+  if (fl->count() > 0) {
+    if (count() == 0) {
+      set_head(fl->head());
+      set_tail(fl->tail());
+      set_count(fl->count());
+    } else {
+      // Both are non-empty.
+      Chunk* fl_tail = fl->tail();
+      Chunk* this_head = head();
+      assert(fl_tail->next() == NULL, "Well-formedness of fl");
+      fl_tail->link_next(this_head);
+      this_head->link_prev(fl_tail);
+      set_head(fl->head());
+      set_count(count() + fl->count());
+    }
+    fl->set_head(NULL);
+    fl->set_tail(NULL);
+    fl->set_count(0);
+  }
+}
+
+// verify_chunk_in_free_lists() is used to verify that an item is in this free list.
+// It is used as a debugging aid.
+template <class Chunk>
+bool FreeList<Chunk>::verify_chunk_in_free_list(Chunk* fc) const {
+  // This is an internal consistency check, not part of the check that the
+  // chunk is in the free lists.
+  guarantee(fc->size() == size(), "Wrong list is being searched");
+  Chunk* curFC = head();
+  while (curFC) {
+    // This is an internal consistency check.
+    guarantee(size() == curFC->size(), "Chunk is in wrong list.");
+    if (fc == curFC) {
+      return true;
+    }
+    curFC = curFC->next();
+  }
+  return false;
+}
+
+#ifdef ASSERT
+template <class Chunk>
+void FreeList<Chunk>::assert_proper_lock_protection_work() const {
+  // Nothing to do if the list has no assigned protecting lock
+  if (protecting_lock() == NULL) {
+    return;
+  }
+
+  Thread* thr = Thread::current();
+  if (thr->is_VM_thread() || thr->is_ConcurrentGC_thread()) {
+    // assert that we are holding the freelist lock
+  } else if (thr->is_GC_task_thread()) {
+    assert(protecting_lock()->owned_by_self(), "FreeList RACE DETECTED");
+  } else if (thr->is_Java_thread()) {
+    assert(!SafepointSynchronize::is_at_safepoint(), "Should not be executing");
+  } else {
+    ShouldNotReachHere();  // unaccounted thread type?
+  }
+}
+#endif
+
+// Print the "label line" for free list stats.
+template <class Chunk>
+void FreeList<Chunk>::print_labels_on(outputStream* st, const char* c) {
+  st->print("%16s\t", c);
+  st->print("%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"
+            "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "%14s\t"    "\n",
+            "bfrsurp", "surplus", "desired", "prvSwep", "bfrSwep",
+            "count",   "cBirths", "cDeaths", "sBirths", "sDeaths");
+}
+
+// Print the AllocationStats for the given free list. If the second argument
+// to the call is a non-null string, it is printed in the first column;
+// otherwise, if the argument is null (the default), then the size of the
+// (free list) block is printed in the first column.
+template <class Chunk_t>
+void FreeList<Chunk_t>::print_on(outputStream* st, const char* c) const {
+  if (c != NULL) {
+    st->print("%16s", c);
+  } else {
+    st->print(SIZE_FORMAT_W(16), size());
+  }
+}
+
+#endif // SHARE_MEMORY_FREELIST_INLINE_HPP
--- a/src/hotspot/share/memory/heapInspection.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/heapInspection.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -27,7 +27,6 @@
 #include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "memory/heapInspection.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
@@ -35,9 +34,6 @@
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/stack.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/parallel/parallelScavengeHeap.hpp"
-#endif // INCLUDE_ALL_GCS
 
 // HeapInspection
 
--- a/src/hotspot/share/memory/metaspace.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/metaspace.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,9 +28,9 @@
 #include "logging/log.hpp"
 #include "logging/logStream.hpp"
 #include "memory/allocation.hpp"
-#include "memory/binaryTreeDictionary.hpp"
+#include "memory/binaryTreeDictionary.inline.hpp"
 #include "memory/filemap.hpp"
-#include "memory/freeList.hpp"
+#include "memory/freeList.inline.hpp"
 #include "memory/metachunk.hpp"
 #include "memory/metaspace.hpp"
 #include "memory/metaspaceGCThresholdUpdater.hpp"
@@ -5342,4 +5342,3 @@
     out->medium_chunk_word_size = ClassMediumChunk;
   }
 }
-
--- a/src/hotspot/share/memory/metaspaceShared.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/metaspaceShared.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1619,7 +1619,6 @@
 void MetaspaceShared::prepare_for_dumping() {
   Arguments::check_unsupported_dumping_properties();
   ClassLoader::initialize_shared_path();
-  FileMapInfo::allocate_classpath_entry_table();
 }
 
 // Preload classes from a list, populate the shared spaces and dump to a
@@ -2001,7 +2000,7 @@
       (md_base = mapinfo->map_region(md, &md_top)) != NULL &&
       (od_base = mapinfo->map_region(od, &od_top)) != NULL &&
       (image_alignment == (size_t)os::vm_allocation_granularity()) &&
-      mapinfo->validate_classpath_entry_table()) {
+      mapinfo->validate_shared_path_table()) {
     // Success -- set up MetaspaceObj::_shared_metaspace_{base,top} for
     // fast checking in MetaspaceShared::is_in_shared_metaspace() and
     // MetaspaceObj::is_shared().
--- a/src/hotspot/share/memory/universe.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/memory/universe.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -689,6 +689,8 @@
     return status;
   }
 
+  SystemDictionary::initialize_oop_storage();
+
   Metaspace::global_initialize();
 
   // Initialize performance counters for metaspaces
--- a/src/hotspot/share/oops/accessBackend.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/accessBackend.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -316,7 +316,7 @@
                                             reinterpret_cast<jlong*>((oopDesc*)dst),
                                             align_object_size(size) / HeapWordsPerLong);
   // Clear the header
-  dst->init_mark();
+  dst->init_mark_raw();
 }
 
 #endif // SHARE_VM_RUNTIME_ACCESSBACKEND_INLINE_HPP
--- a/src/hotspot/share/oops/instanceKlass.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1901,7 +1901,7 @@
 }
 
 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
-  assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
+  assert(class_loader_data()->is_alive(), "this klass should be live");
   if (is_interface()) {
     if (ClassUnloading) {
       Klass* impl = implementor();
@@ -3407,14 +3407,8 @@
   }
 }
 
-oop InstanceKlass::klass_holder_phantom() {
-  oop* addr;
-  if (is_anonymous()) {
-    addr = _java_mirror.ptr_raw();
-  } else {
-    addr = &class_loader_data()->_class_loader;
-  }
-  return RootAccess<IN_CONCURRENT_ROOT | ON_PHANTOM_OOP_REF>::oop_load(addr);
+oop InstanceKlass::holder_phantom() const {
+  return class_loader_data()->holder_phantom();
 }
 
 #ifdef ASSERT
--- a/src/hotspot/share/oops/instanceKlass.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -646,10 +646,10 @@
     return is_anonymous() ? java_mirror() : class_loader();
   }
 
-  // Load the klass_holder as a phantom. This is useful when a weak Klass
+  // Load the klass's holder as a phantom. This is useful when a weak Klass
   // pointer has been "peeked" and then must be kept alive before it may
   // be used safely.
-  oop klass_holder_phantom();
+  oop holder_phantom() const;
 
   bool is_contended() const                {
     return (_misc_flags & _misc_is_contended) != 0;
--- a/src/hotspot/share/oops/klass.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/klass.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -150,7 +150,7 @@
   int _vtable_len;
 
 private:
-  // This is an index into FileMapHeader::_classpath_entry_table[], to
+  // This is an index into FileMapHeader::_shared_path_table[], to
   // associate this class with the JAR file where it's loaded from during
   // dump time. If a class is not loaded from the shared archive, this field is
   // -1.
@@ -166,7 +166,7 @@
 #endif
   // The _archived_mirror is set at CDS dump time pointing to the cached mirror
   // in the open archive heap region when archiving java object is supported.
-  CDS_JAVA_HEAP_ONLY(narrowOop _archived_mirror);
+  CDS_JAVA_HEAP_ONLY(narrowOop _archived_mirror;)
 
   friend class SharedClassUtil;
 protected:
--- a/src/hotspot/share/oops/objArrayOop.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/objArrayOop.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,13 +31,13 @@
 
 oop objArrayOopDesc::atomic_compare_exchange_oop(int index, oop exchange_value,
                                                  oop compare_value) {
-  volatile HeapWord* dest;
+  ptrdiff_t offs;
   if (UseCompressedOops) {
-    dest = (HeapWord*)obj_at_addr<narrowOop>(index);
+    offs = objArrayOopDesc::obj_at_offset<narrowOop>(index);
   } else {
-    dest = (HeapWord*)obj_at_addr<oop>(index);
+    offs = objArrayOopDesc::obj_at_offset<oop>(index);
   }
-  return HeapAccess<>::oop_atomic_cmpxchg(exchange_value, dest, compare_value);
+  return HeapAccess<IN_HEAP_ARRAY>::oop_atomic_cmpxchg_at(exchange_value, as_oop(), offs, compare_value);
 }
 
 Klass* objArrayOopDesc::element_klass() {
--- a/src/hotspot/share/oops/oop.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/oop.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -134,7 +134,7 @@
   if (ignore_mark_word) {
     return true;
   }
-  if (obj->mark() != NULL) {
+  if (obj->mark_raw() != NULL) {
     return true;
   }
   return !SafepointSynchronize::is_at_safepoint();
--- a/src/hotspot/share/oops/oop.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/oop.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -63,17 +63,21 @@
   } _metadata;
 
  public:
-  markOop  mark()      const { return _mark; }
-  markOop* mark_addr() const { return (markOop*) &_mark; }
+  inline markOop  mark()          const;
+  inline markOop  mark_raw()      const;
+  inline markOop* mark_addr_raw() const;
 
-  void set_mark(volatile markOop m) { _mark = m; }
+  inline void set_mark(volatile markOop m);
+  inline void set_mark_raw(volatile markOop m);
 
   inline void release_set_mark(markOop m);
   inline markOop cas_set_mark(markOop new_mark, markOop old_mark);
+  inline markOop cas_set_mark_raw(markOop new_mark, markOop old_mark);
 
   // Used only to re-initialize the mark word (e.g., of promoted
   // objects during a GC) -- requires a valid klass pointer
   inline void init_mark();
+  inline void init_mark_raw();
 
   inline Klass* klass() const;
   inline Klass* klass_or_null() const volatile;
@@ -237,6 +241,7 @@
   inline bool is_locked()   const;
   inline bool is_unlocked() const;
   inline bool has_bias_pattern() const;
+  inline bool has_bias_pattern_raw() const;
 
   // asserts and guarantees
   static bool is_oop(oop obj, bool ignore_mark_word = false);
@@ -323,9 +328,9 @@
   unsigned int new_hash(juint seed);
 
   // marks are forwarded to stack when object is locked
-  inline bool    has_displaced_mark() const;
-  inline markOop displaced_mark() const;
-  inline void    set_displaced_mark(markOop m);
+  inline bool    has_displaced_mark_raw() const;
+  inline markOop displaced_mark_raw() const;
+  inline void    set_displaced_mark_raw(markOop m);
 
   static bool has_klass_gap();
 
--- a/src/hotspot/share/oops/oop.inline.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/oops/oop.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,11 +44,35 @@
 // Implementation of all inlined member functions defined in oop.hpp
 // We need a separate file to avoid circular references
 
+markOop  oopDesc::mark()      const {
+  return HeapAccess<MO_VOLATILE>::load_at(as_oop(), mark_offset_in_bytes());
+}
+
+markOop  oopDesc::mark_raw()  const {
+  return _mark;
+}
+
+markOop* oopDesc::mark_addr_raw() const {
+  return (markOop*) &_mark;
+}
+
+void oopDesc::set_mark(volatile markOop m) {
+  HeapAccess<MO_VOLATILE>::store_at(as_oop(), mark_offset_in_bytes(), m);
+}
+
+void oopDesc::set_mark_raw(volatile markOop m) {
+  _mark = m;
+}
+
 void oopDesc::release_set_mark(markOop m) {
-  OrderAccess::release_store(&_mark, m);
+  HeapAccess<MO_RELEASE>::store_at(as_oop(), mark_offset_in_bytes(), m);
 }
 
 markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark) {
+  return HeapAccess<>::atomic_cmpxchg_at(new_mark, as_oop(), mark_offset_in_bytes(), old_mark);
+}
+
+markOop oopDesc::cas_set_mark_raw(markOop new_mark, markOop old_mark) {
   return Atomic::cmpxchg(new_mark, &_mark, old_mark);
 }
 
@@ -56,6 +80,10 @@
   set_mark(markOopDesc::prototype_for_object(this));
 }
 
+void oopDesc::init_mark_raw() {
+  set_mark_raw(markOopDesc::prototype_for_object(this));
+}
+
 Klass* oopDesc::klass() const {
   if (UseCompressedClassPointers) {
     return Klass::decode_klass_not_null(_metadata._compressed_klass);
@@ -281,16 +309,20 @@
   return mark()->has_bias_pattern();
 }
 
+bool oopDesc::has_bias_pattern_raw() const {
+  return mark_raw()->has_bias_pattern();
+}
+
 // Used only for markSweep, scavenging
 bool oopDesc::is_gc_marked() const {
-  return mark()->is_marked();
+  return mark_raw()->is_marked();
 }
 
 // Used by scavengers
 bool oopDesc::is_forwarded() const {
   // The extra heap check is needed since the obj might be locked, in which case the
   // mark would point to a stack location and have the sentinel bit cleared
-  return mark()->is_marked();
+  return mark_raw()->is_marked();
 }
 
 // Used by scavengers
@@ -304,7 +336,7 @@
          "forwarding archive object");
   markOop m = markOopDesc::encode_pointer_as_mark(p);
   assert(m->decode_pointer() == p, "encoding must be reversable");
-  set_mark(m);
+  set_mark_raw(m);
 }
 
 // Used by parallel scavengers
@@ -315,12 +347,12 @@
          "forwarding to something not in heap");
   markOop m = markOopDesc::encode_pointer_as_mark(p);
   assert(m->decode_pointer() == p, "encoding must be reversable");
-  return cas_set_mark(m, compare) == compare;
+  return cas_set_mark_raw(m, compare) == compare;
 }
 
 #if INCLUDE_ALL_GCS
 oop oopDesc::forward_to_atomic(oop p) {
-  markOop oldMark = mark();
+  markOop oldMark = mark_raw();
   markOop forwardPtrMark = markOopDesc::encode_pointer_as_mark(p);
   markOop curMark;
 
@@ -328,7 +360,7 @@
   assert(sizeof(markOop) == sizeof(intptr_t), "CAS below requires this.");
 
   while (!oldMark->is_marked()) {
-    curMark = Atomic::cmpxchg(forwardPtrMark, &_mark, oldMark);
+    curMark = cas_set_mark_raw(forwardPtrMark, oldMark);
     assert(is_forwarded(), "object should have been forwarded");
     if (curMark == oldMark) {
       return NULL;
@@ -346,25 +378,25 @@
 // The forwardee is used when copying during scavenge and mark-sweep.
 // It does need to clear the low two locking- and GC-related bits.
 oop oopDesc::forwardee() const {
-  return (oop) mark()->decode_pointer();
+  return (oop) mark_raw()->decode_pointer();
 }
 
 // The following method needs to be MT safe.
 uint oopDesc::age() const {
   assert(!is_forwarded(), "Attempt to read age from forwarded mark");
-  if (has_displaced_mark()) {
-    return displaced_mark()->age();
+  if (has_displaced_mark_raw()) {
+    return displaced_mark_raw()->age();
   } else {
-    return mark()->age();
+    return mark_raw()->age();
   }
 }
 
 void oopDesc::incr_age() {
   assert(!is_forwarded(), "Attempt to increment age of forwarded mark");
-  if (has_displaced_mark()) {
-    set_displaced_mark(displaced_mark()->incr_age());
+  if (has_displaced_mark_raw()) {
+    set_displaced_mark_raw(displaced_mark_raw()->incr_age());
   } else {
-    set_mark(mark()->incr_age());
+    set_mark_raw(mark_raw()->incr_age());
   }
 }
 
@@ -465,16 +497,16 @@
   }
 }
 
-bool oopDesc::has_displaced_mark() const {
-  return mark()->has_displaced_mark_helper();
+bool oopDesc::has_displaced_mark_raw() const {
+  return mark_raw()->has_displaced_mark_helper();
 }
 
-markOop oopDesc::displaced_mark() const {
-  return mark()->displaced_mark_helper();
+markOop oopDesc::displaced_mark_raw() const {
+  return mark_raw()->displaced_mark_helper();
 }
 
-void oopDesc::set_displaced_mark(markOop m) {
-  mark()->set_displaced_mark_helper(m);
+void oopDesc::set_displaced_mark_raw(markOop m) {
+  mark_raw()->set_displaced_mark_helper(m);
 }
 
 #endif // SHARE_VM_OOPS_OOP_INLINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/oops/weakHandle.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "gc/shared/oopStorage.hpp"
+#include "oops/access.inline.hpp"
+#include "oops/oop.hpp"
+#include "oops/weakHandle.inline.hpp"
+#include "utilities/debug.hpp"
+#include "utilities/ostream.hpp"
+
+template <> OopStorage* WeakHandle<vm_class_loader_data>::get_storage() {
+  return SystemDictionary::vm_weak_oop_storage();
+}
+
+template <WeakHandleType T>
+WeakHandle<T> WeakHandle<T>::create(Handle obj) {
+  assert(obj() != NULL, "no need to create weak null oop");
+  oop* oop_addr = get_storage()->allocate();
+  if (oop_addr == NULL) {
+    vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR, "Unable to create new weak oop handle in OopStorage");
+  }
+  // Create WeakHandle with address returned and store oop into it.
+  RootAccess<ON_PHANTOM_OOP_REF>::oop_store(oop_addr, obj());
+  return WeakHandle(oop_addr);
+}
+
+template <WeakHandleType T>
+void WeakHandle<T>::release() const {
+  // Only release if the pointer to the object has been created.
+  if (_obj != NULL) {
+    // Clear the WeakHandle.  For class loader data race, the handle may not have
+    // been previously cleared by GC.
+    RootAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, (oop)NULL);
+    get_storage()->release(_obj);
+  }
+}
+
+template <WeakHandleType T>
+void WeakHandle<T>::print() const { print_on(tty); }
+
+template <WeakHandleType T>
+void WeakHandle<T>::print_on(outputStream* st) const {
+  st->print("WeakHandle: " PTR_FORMAT, p2i(peek()));
+}
+
+// Provide instantiation.
+template class WeakHandle<vm_class_loader_data>;
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/oops/weakHandle.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_OOPS_WEAKHANDLE_HPP
+#define SHARE_VM_OOPS_WEAKHANDLE_HPP
+
+#include "oops/oop.hpp"
+#include "runtime/handles.hpp"
+
+class outputStream;
+class OopStorage;
+
+// A WeakHandle is a pointer to an oop that is stored in an OopStorage that is
+// processed weakly by GC.  The runtime structures that point to the oop must
+// either peek or resolve the oop, the latter will keep the oop alive for
+// the GC cycle.  The runtime structures that reference the oop must test
+// if the value is NULL.  If it is NULL, it has been cleaned out by GC.
+// This is the vm version of jweak but has different GC lifetimes and policies,
+// depending on the type.
+
+enum WeakHandleType { vm_class_loader_data, vm_string };
+
+template <WeakHandleType T>
+class WeakHandle {
+ public:
+
+ private:
+  oop* _obj;
+
+  WeakHandle(oop* w) : _obj(w) {}
+  static OopStorage* get_storage();
+ public:
+  WeakHandle() : _obj(NULL) {} // needed for init
+
+  static WeakHandle create(Handle obj);
+  inline oop resolve() const;
+  inline oop peek() const;
+  void release() const;
+  bool is_null() const { return _obj == NULL; }
+
+  void print() const;
+  void print_on(outputStream* st) const;
+};
+
+#endif // SHARE_VM_OOPS_WEAKHANDLE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/oops/weakHandle.inline.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP
+#define SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP
+
+#include "oops/weakHandle.hpp"
+#include "oops/access.inline.hpp"
+
+template <WeakHandleType T>
+oop WeakHandle<T>::resolve() const {
+  assert(!is_null(), "Must be created");
+  return RootAccess<ON_PHANTOM_OOP_REF>::oop_load(_obj);
+}
+
+template <WeakHandleType T>
+oop WeakHandle<T>::peek() const {
+  assert(!is_null(), "Must be created");
+  return RootAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(_obj);
+}
+
+#endif // SHARE_VM_OOPS_WEAKHANDLE_INLINE_HPP
--- a/src/hotspot/share/opto/compile.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/opto/compile.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -73,6 +73,9 @@
 #include "runtime/timer.hpp"
 #include "utilities/align.hpp"
 #include "utilities/copy.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
+#endif // INCLUDE_ALL_GCS
 
 
 // -------------------- Compile::mach_constant_base_node -----------------------
@@ -3752,7 +3755,7 @@
 void Compile::verify_barriers() {
   if (UseG1GC) {
     // Verify G1 pre-barriers
-    const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active());
+    const int marking_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
 
     ResourceArea *area = Thread::current()->resource_area();
     Unique_Node_List visited(area);
--- a/src/hotspot/share/opto/escape.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/opto/escape.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -37,6 +37,9 @@
 #include "opto/phaseX.hpp"
 #include "opto/movenode.hpp"
 #include "opto/rootnode.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
+#endif // INCLUDE_ALL_GCS
 
 ConnectionGraph::ConnectionGraph(Compile * C, PhaseIterGVN *igvn) :
   _nodes(C->comp_arena(), C->unique(), C->unique(), NULL),
@@ -543,12 +546,10 @@
               Node* tls = get_addp_base(adr);
               if (tls->Opcode() == Op_ThreadLocal) {
                 int offs = (int)igvn->find_intptr_t_con(adr->in(AddPNode::Offset), Type::OffsetBot);
-                if (offs == in_bytes(JavaThread::satb_mark_queue_offset() +
-                                     SATBMarkQueue::byte_offset_of_buf())) {
+                if (offs == in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset())) {
                   break; // G1 pre barrier previous oop value store.
                 }
-                if (offs == in_bytes(JavaThread::dirty_card_queue_offset() +
-                                     DirtyCardQueue::byte_offset_of_buf())) {
+                if (offs == in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset())) {
                   break; // G1 post barrier card address store.
                 }
               }
--- a/src/hotspot/share/opto/graphKit.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/opto/graphKit.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -48,6 +48,9 @@
 #include "opto/runtime.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/sharedRuntime.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
+#endif // INCLUDE_ALL_GCS
 
 //----------------------------GraphKit-----------------------------------------
 // Main utility constructor.
@@ -1559,7 +1562,7 @@
                            Node* pre_val,
                            BasicType bt) {
 
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   set_control(ctl);
   switch (bs->kind()) {
     case BarrierSet::G1BarrierSet:
@@ -1576,7 +1579,7 @@
 }
 
 bool GraphKit::can_move_pre_barrier() const {
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   switch (bs->kind()) {
     case BarrierSet::G1BarrierSet:
       return true; // Can move it if no safepoint
@@ -1598,7 +1601,7 @@
                             Node* val,
                             BasicType bt,
                             bool use_precise) {
-  BarrierSet* bs = Universe::heap()->barrier_set();
+  BarrierSet* bs = BarrierSet::barrier_set();
   set_control(ctl);
   switch (bs->kind()) {
     case BarrierSet::G1BarrierSet:
@@ -3811,7 +3814,7 @@
 #define __ ideal.
 
 bool GraphKit::use_ReduceInitialCardMarks() {
-  BarrierSet *bs = Universe::heap()->barrier_set();
+  BarrierSet *bs = BarrierSet::barrier_set();
   return bs->is_a(BarrierSet::CardTableBarrierSet)
          && barrier_set_cast<CardTableBarrierSet>(bs)->can_elide_tlab_store_barriers()
          && ReduceInitialCardMarks;
@@ -3882,7 +3885,7 @@
   Node* cast = __ CastPX(__ ctrl(), adr);
 
   // Divide by card size
-  assert(Universe::heap()->barrier_set()->is_a(BarrierSet::CardTableBarrierSet),
+  assert(BarrierSet::barrier_set()->is_a(BarrierSet::CardTableBarrierSet),
          "Only one we handle so far.");
   Node* card_offset = __ URShiftX( cast, __ ConI(CardTable::card_shift) );
 
@@ -4081,12 +4084,9 @@
   assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 4 || in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "flag width");
 
   // Offsets into the thread
-  const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() +  // 648
-                                          SATBMarkQueue::byte_offset_of_active());
-  const int index_offset   = in_bytes(JavaThread::satb_mark_queue_offset() +  // 656
-                                          SATBMarkQueue::byte_offset_of_index());
-  const int buffer_offset  = in_bytes(JavaThread::satb_mark_queue_offset() +  // 652
-                                          SATBMarkQueue::byte_offset_of_buf());
+  const int marking_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
+  const int index_offset   = in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset());
+  const int buffer_offset  = in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset());
 
   // Now the actual pointers into the thread
   Node* marking_adr = __ AddP(no_base, tls, __ ConX(marking_offset));
@@ -4286,10 +4286,8 @@
   const TypeFunc *tf = OptoRuntime::g1_wb_post_Type();
 
   // Offsets into the thread
-  const int index_offset  = in_bytes(JavaThread::dirty_card_queue_offset() +
-                                     DirtyCardQueue::byte_offset_of_index());
-  const int buffer_offset = in_bytes(JavaThread::dirty_card_queue_offset() +
-                                     DirtyCardQueue::byte_offset_of_buf());
+  const int index_offset  = in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset());
+  const int buffer_offset = in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset());
 
   // Pointers into the thread
 
--- a/src/hotspot/share/opto/macro.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/opto/macro.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -47,6 +47,9 @@
 #include "opto/subnode.hpp"
 #include "opto/type.hpp"
 #include "runtime/sharedRuntime.hpp"
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
+#endif // INCLUDE_ALL_GCS
 
 
 //
@@ -292,8 +295,7 @@
               cmpx->is_Cmp() && cmpx->in(2) == intcon(0) &&
               cmpx->in(1)->is_Load()) {
             Node* adr = cmpx->in(1)->as_Load()->in(MemNode::Address);
-            const int marking_offset = in_bytes(JavaThread::satb_mark_queue_offset() +
-                                                SATBMarkQueue::byte_offset_of_active());
+            const int marking_offset = in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset());
             if (adr->is_AddP() && adr->in(AddPNode::Base) == top() &&
                 adr->in(AddPNode::Address)->Opcode() == Op_ThreadLocal &&
                 adr->in(AddPNode::Offset) == MakeConX(marking_offset)) {
--- a/src/hotspot/share/precompiled/precompiled.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/precompiled/precompiled.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -84,11 +84,6 @@
 # include "compiler/disassembler.hpp"
 # include "compiler/methodLiveness.hpp"
 # include "compiler/oopMap.hpp"
-# include "gc/cms/allocationStats.hpp"
-# include "gc/cms/gSpaceCounters.hpp"
-# include "gc/parallel/immutableSpace.hpp"
-# include "gc/parallel/mutableSpace.hpp"
-# include "gc/parallel/spaceCounters.hpp"
 # include "gc/serial/cSpaceCounters.hpp"
 # include "gc/serial/defNewGeneration.hpp"
 # include "gc/shared/adaptiveSizePolicy.hpp"
@@ -292,9 +287,11 @@
 # include "jvmci/jvmci_globals.hpp"
 #endif // INCLUDE_JVMCI
 #if INCLUDE_ALL_GCS
+# include "gc/cms/allocationStats.hpp"
 # include "gc/cms/compactibleFreeListSpace.hpp"
 # include "gc/cms/concurrentMarkSweepGeneration.hpp"
 # include "gc/cms/freeChunk.hpp"
+# include "gc/cms/gSpaceCounters.hpp"
 # include "gc/cms/parOopClosures.hpp"
 # include "gc/cms/promotionInfo.hpp"
 # include "gc/cms/yieldingWorkgroup.hpp"
@@ -305,6 +302,8 @@
 # include "gc/g1/ptrQueue.hpp"
 # include "gc/g1/satbMarkQueue.hpp"
 # include "gc/parallel/gcAdaptivePolicyCounters.hpp"
+# include "gc/parallel/immutableSpace.hpp"
+# include "gc/parallel/mutableSpace.hpp"
 # include "gc/parallel/objectStartArray.hpp"
 # include "gc/parallel/parMarkBitMap.hpp"
 # include "gc/parallel/parallelScavengeHeap.hpp"
@@ -315,6 +314,7 @@
 # include "gc/parallel/psOldGen.hpp"
 # include "gc/parallel/psVirtualspace.hpp"
 # include "gc/parallel/psYoungGen.hpp"
+# include "gc/parallel/spaceCounters.hpp"
 # include "gc/shared/gcPolicyCounters.hpp"
 # include "gc/shared/plab.hpp"
 #endif // INCLUDE_ALL_GCS
--- a/src/hotspot/share/prims/jvmtiTagMap.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/prims/jvmtiTagMap.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,7 +28,6 @@
 #define SHARE_VM_PRIMS_JVMTITAGMAP_HPP
 
 #include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "jvmtifiles/jvmti.h"
 #include "jvmtifiles/jvmtiEnv.hpp"
 #include "memory/allocation.hpp"
--- a/src/hotspot/share/runtime/arguments.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/arguments.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -29,11 +29,9 @@
 #include "classfile/moduleEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
+#include "gc/shared/collectorPolicy.hpp"
 #include "gc/shared/gcArguments.hpp"
 #include "gc/shared/gcConfig.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/referenceProcessor.hpp"
-#include "gc/shared/taskqueue.hpp"
 #include "logging/log.hpp"
 #include "logging/logConfiguration.hpp"
 #include "logging/logStream.hpp"
@@ -98,6 +96,8 @@
 intx   Arguments::_Tier3InvokeNotifyFreqLog     = Tier3InvokeNotifyFreqLog;
 intx   Arguments::_Tier4InvocationThreshold     = Tier4InvocationThreshold;
 
+bool   Arguments::_enable_preview               = false;
+
 char*  Arguments::SharedArchivePath             = NULL;
 
 AgentLibraryList Arguments::_libraryList;
@@ -1446,35 +1446,23 @@
 }
 
 #if INCLUDE_CDS
+const char* unsupported_properties[] = { "jdk.module.limitmods",
+                                         "jdk.module.upgrade.path",
+                                         "jdk.module.patch.0" };
+const char* unsupported_options[] = { "--limit-modules",
+                                      "--upgrade-module-path",
+                                      "--patch-module"
+                                    };
 void Arguments::check_unsupported_dumping_properties() {
   assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
-  const char* unsupported_properties[] = { "jdk.module.main",
-                                           "jdk.module.limitmods",
-                                           "jdk.module.path",
-                                           "jdk.module.upgrade.path",
-                                           "jdk.module.patch.0" };
-  const char* unsupported_options[] = { "-m", // cannot use at dump time
-                                        "--limit-modules", // ignored at dump time
-                                        "--module-path", // ignored at dump time
-                                        "--upgrade-module-path", // ignored at dump time
-                                        "--patch-module" // ignored at dump time
-                                      };
   assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
-  // If a vm option is found in the unsupported_options array with index less than the info_idx,
-  // vm will exit with an error message. Otherwise, it will print an informational message if
-  // -Xlog:cds is enabled.
-  uint info_idx = 1;
+  // If a vm option is found in the unsupported_options array, vm will exit with an error message.
   SystemProperty* sp = system_properties();
   while (sp != NULL) {
     for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
       if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
-        if (i < info_idx) {
-          vm_exit_during_initialization(
-            "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
-        } else {
-          log_info(cds)("Info: the %s option is ignored when dumping the shared archive",
-                        unsupported_options[i]);
-        }
+        vm_exit_during_initialization(
+          "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
       }
     }
     sp = sp->next();
@@ -1485,6 +1473,20 @@
     vm_exit_during_initialization("Dumping the shared archive is not supported with an exploded module build");
   }
 }
+
+bool Arguments::check_unsupported_cds_runtime_properties() {
+  assert(UseSharedSpaces, "this function is only used with -Xshare:{on,auto}");
+  assert(ARRAY_SIZE(unsupported_properties) == ARRAY_SIZE(unsupported_options), "must be");
+  for (uint i = 0; i < ARRAY_SIZE(unsupported_properties); i++) {
+    if (get_property(unsupported_properties[i]) != NULL) {
+      if (RequireSharedSpaces) {
+        warning("CDS is disabled when the %s option is specified.", unsupported_options[i]);
+      }
+      return true;
+    }
+  }
+  return false;
+}
 #endif
 
 //===========================================================================================================
@@ -2190,41 +2192,6 @@
     status = false;
   }
 
-  if (FullGCALot && FLAG_IS_DEFAULT(MarkSweepAlwaysCompactCount)) {
-    MarkSweepAlwaysCompactCount = 1;  // Move objects every gc.
-  }
-
-  if (!(UseParallelGC || UseParallelOldGC) && FLAG_IS_DEFAULT(ScavengeBeforeFullGC)) {
-    FLAG_SET_DEFAULT(ScavengeBeforeFullGC, false);
-  }
-
-  if (GCTimeLimit == 100) {
-    // Turn off gc-overhead-limit-exceeded checks
-    FLAG_SET_DEFAULT(UseGCOverheadLimit, false);
-  }
-
-  // CMS space iteration, which FLSVerifyAllHeapreferences entails,
-  // insists that we hold the requisite locks so that the iteration is
-  // MT-safe. For the verification at start-up and shut-down, we don't
-  // yet have a good way of acquiring and releasing these locks,
-  // which are not visible at the CollectedHeap level. We want to
-  // be able to acquire these locks and then do the iteration rather
-  // than just disable the lock verification. This will be fixed under
-  // bug 4788986.
-  if (UseConcMarkSweepGC && FLSVerifyAllHeapReferences) {
-    if (VerifyDuringStartup) {
-      warning("Heap verification at start-up disabled "
-              "(due to current incompatibility with FLSVerifyAllHeapReferences)");
-      VerifyDuringStartup = false; // Disable verification at start-up
-    }
-
-    if (VerifyBeforeExit) {
-      warning("Heap verification at shutdown disabled "
-              "(due to current incompatibility with FLSVerifyAllHeapReferences)");
-      VerifyBeforeExit = false; // Disable verification at shutdown
-    }
-  }
-
   if (PrintNMTStatistics) {
 #if INCLUDE_NMT
     if (MemTracker::tracking_level() == NMT_off) {
@@ -2776,6 +2743,9 @@
         }
       }
 #endif // !INCLUDE_JVMTI
+    // --enable_preview
+    } else if (match_option(option, "--enable-preview")) {
+      set_enable_preview();
     // -Xnoclassgc
     } else if (match_option(option, "-Xnoclassgc")) {
       if (FLAG_SET_CMDLINE(bool, ClassUnloading, false) != Flag::SUCCESS) {
@@ -3410,6 +3380,9 @@
   if (UseSharedSpaces && patch_mod_javabase) {
     no_shared_spaces("CDS is disabled when " JAVA_BASE_NAME " module is patched.");
   }
+  if (UseSharedSpaces && !DumpSharedSpaces && check_unsupported_cds_runtime_properties()) {
+    FLAG_SET_DEFAULT(UseSharedSpaces, false);
+  }
 #endif
 
 #ifndef CAN_SHOW_REGISTERS_ON_ASSERT
--- a/src/hotspot/share/runtime/arguments.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/arguments.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -358,6 +358,9 @@
   static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
   static bool xdebug_mode()             { return _xdebug_mode; }
 
+  // preview features
+  static bool _enable_preview;
+
   // Used to save default settings
   static bool _AlwaysCompileLoopMethods;
   static bool _UseOnStackReplacement;
@@ -691,12 +694,17 @@
   static Mode mode()                        { return _mode; }
   static bool is_interpreter_only() { return mode() == _int; }
 
+  // preview features
+  static void set_enable_preview() { _enable_preview = true; }
+  static bool enable_preview() { return _enable_preview; }
 
   // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
   static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
 
   static void check_unsupported_dumping_properties() NOT_CDS_RETURN;
 
+  static bool check_unsupported_cds_runtime_properties() NOT_CDS_RETURN0;
+
   static bool atojulong(const char *s, julong* result);
 };
 
--- a/src/hotspot/share/runtime/biasedLocking.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/biasedLocking.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -616,7 +616,7 @@
       // with it.
       markOop biased_value       = mark;
       markOop res_mark = obj->cas_set_mark(prototype_header, mark);
-      assert(!(*(obj->mark_addr()))->has_bias_pattern(), "even if we raced, should still be revoked");
+      assert(!obj->mark()->has_bias_pattern(), "even if we raced, should still be revoked");
       return BIAS_REVOKED;
     } else if (prototype_header->bias_epoch() != mark->bias_epoch()) {
       // The epoch of this biasing has expired indicating that the
--- a/src/hotspot/share/runtime/commandLineFlagConstraintList.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/commandLineFlagConstraintList.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,17 +25,13 @@
 #include "precompiled.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
-#include "gc/shared/referenceProcessor.hpp"
+#include "gc/shared/commandLineFlagConstraintsGC.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/commandLineFlagConstraintList.hpp"
 #include "runtime/commandLineFlagConstraintsCompiler.hpp"
-#include "runtime/commandLineFlagConstraintsGC.hpp"
 #include "runtime/commandLineFlagConstraintsRuntime.hpp"
 #include "runtime/os.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1_globals.hpp"
-#endif
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif
@@ -280,20 +276,20 @@
 void CommandLineFlagConstraintList::init(void) {
   _constraints = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<CommandLineFlagConstraint*>(INITIAL_CONSTRAINTS_SIZE, true);
 
-  emit_constraint_no(NULL RUNTIME_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
-                                        EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
-                                        EMIT_CONSTRAINT_PRODUCT_FLAG,
-                                        EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
-                                        EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
-                                        EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG,
-                                        EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
-                                        EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
-                                        EMIT_CONSTRAINT_MANAGEABLE_FLAG,
-                                        EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
-                                        EMIT_CONSTRAINT_LP64_PRODUCT_FLAG,
-                                        IGNORE_RANGE,
-                                        EMIT_CONSTRAINT_CHECK,
-                                        IGNORE_WRITEABLE));
+  emit_constraint_no(NULL VM_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG,
+                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
+                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
+                                   EMIT_CONSTRAINT_MANAGEABLE_FLAG,
+                                   EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
+                                   EMIT_CONSTRAINT_LP64_PRODUCT_FLAG,
+                                   IGNORE_RANGE,
+                                   EMIT_CONSTRAINT_CHECK,
+                                   IGNORE_WRITEABLE));
 
   EMIT_CONSTRAINTS_FOR_GLOBALS_EXT
 
@@ -333,22 +329,6 @@
                                    EMIT_CONSTRAINT_CHECK,
                                    IGNORE_WRITEABLE));
 #endif // COMPILER2
-
-#if INCLUDE_ALL_GCS
-  emit_constraint_no(NULL G1_FLAGS(EMIT_CONSTRAINT_DEVELOPER_FLAG,
-                                   EMIT_CONSTRAINT_PD_DEVELOPER_FLAG,
-                                   EMIT_CONSTRAINT_PRODUCT_FLAG,
-                                   EMIT_CONSTRAINT_PD_PRODUCT_FLAG,
-                                   EMIT_CONSTRAINT_DIAGNOSTIC_FLAG,
-                                   EMIT_CONSTRAINT_PD_DIAGNOSTIC_FLAG,
-                                   EMIT_CONSTRAINT_EXPERIMENTAL_FLAG,
-                                   EMIT_CONSTRAINT_NOTPRODUCT_FLAG,
-                                   EMIT_CONSTRAINT_MANAGEABLE_FLAG,
-                                   EMIT_CONSTRAINT_PRODUCT_RW_FLAG,
-                                   IGNORE_RANGE,
-                                   EMIT_CONSTRAINT_CHECK,
-                                   IGNORE_WRITEABLE));
-#endif // INCLUDE_ALL_GCS
 }
 
 CommandLineFlagConstraint* CommandLineFlagConstraintList::find(const char* name) {
--- a/src/hotspot/share/runtime/commandLineFlagConstraintsGC.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,810 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * 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 "gc/shared/collectedHeap.hpp"
-#include "gc/shared/collectorPolicy.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/threadLocalAllocBuffer.hpp"
-#include "runtime/arguments.hpp"
-#include "runtime/commandLineFlagConstraintsGC.hpp"
-#include "runtime/commandLineFlagRangeList.hpp"
-#include "runtime/globals.hpp"
-#include "runtime/globals_extension.hpp"
-#include "runtime/thread.inline.hpp"
-#include "utilities/align.hpp"
-#include "utilities/defaultStream.hpp"
-
-#if INCLUDE_ALL_GCS
-#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
-#include "gc/g1/g1_globals.hpp"
-#include "gc/g1/heapRegionBounds.inline.hpp"
-#include "gc/shared/plab.hpp"
-#endif // INCLUDE_ALL_GCS
-#ifdef COMPILER1
-#include "c1/c1_globals.hpp"
-#endif // COMPILER1
-#ifdef COMPILER2
-#include "opto/c2_globals.hpp"
-#endif // COMPILER2
-
-// Some flags that have default values that indicate that the
-// JVM should automatically determine an appropriate value
-// for that flag.  In those cases it is only appropriate for the
-// constraint checking to be done if the user has specified the
-// value(s) of the flag(s) on the command line.  In the constraint
-// checking functions,  FLAG_IS_CMDLINE() is used to check if
-// the flag has been set by the user and so should be checked.
-
-#if INCLUDE_ALL_GCS
-static Flag::Error ParallelGCThreadsAndCMSWorkQueueDrainThreshold(uint threads, uintx threshold, bool verbose) {
-  // CMSWorkQueueDrainThreshold is verified to be less than max_juint
-  if (UseConcMarkSweepGC && (threads > (uint)(max_jint / (uint)threshold))) {
-    CommandLineError::print(verbose,
-                            "ParallelGCThreads (" UINT32_FORMAT ") or CMSWorkQueueDrainThreshold ("
-                            UINTX_FORMAT ") is too large\n",
-                            threads, threshold);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  return Flag::SUCCESS;
-}
-#endif
-
-// As ParallelGCThreads differs among GC modes, we need constraint function.
-Flag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose) {
-  Flag::Error status = Flag::SUCCESS;
-
-#if INCLUDE_ALL_GCS
-  // Parallel GC passes ParallelGCThreads when creating GrowableArray as 'int' type parameter.
-  // So can't exceed with "max_jint"
-  if (UseParallelGC && (value > (uint)max_jint)) {
-    CommandLineError::print(verbose,
-                            "ParallelGCThreads (" UINT32_FORMAT ") must be "
-                            "less than or equal to " UINT32_FORMAT " for Parallel GC\n",
-                            value, max_jint);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  // To avoid overflow at ParScanClosure::do_oop_work.
-  if (UseConcMarkSweepGC && (value > (max_jint / 10))) {
-    CommandLineError::print(verbose,
-                            "ParallelGCThreads (" UINT32_FORMAT ") must be "
-                            "less than or equal to " UINT32_FORMAT " for CMS GC\n",
-                            value, (max_jint / 10));
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  status = ParallelGCThreadsAndCMSWorkQueueDrainThreshold(value, CMSWorkQueueDrainThreshold, verbose);
-#endif
-  return status;
-}
-
-// As ConcGCThreads should be smaller than ParallelGCThreads,
-// we need constraint function.
-Flag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  // CMS and G1 GCs use ConcGCThreads.
-  if ((UseConcMarkSweepGC || UseG1GC) && (value > ParallelGCThreads)) {
-    CommandLineError::print(verbose,
-                            "ConcGCThreads (" UINT32_FORMAT ") must be "
-                            "less than or equal to ParallelGCThreads (" UINT32_FORMAT ")\n",
-                            value, ParallelGCThreads);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-static Flag::Error MinPLABSizeBounds(const char* name, size_t value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if ((UseConcMarkSweepGC || UseG1GC || UseParallelGC) && (value < PLAB::min_size())) {
-    CommandLineError::print(verbose,
-                            "%s (" SIZE_FORMAT ") must be "
-                            "greater than or equal to ergonomic PLAB minimum size (" SIZE_FORMAT ")\n",
-                            name, value, PLAB::min_size());
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif // INCLUDE_ALL_GCS
-  return Flag::SUCCESS;
-}
-
-static Flag::Error MaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if ((UseConcMarkSweepGC || UseG1GC || UseParallelGC) && (value > PLAB::max_size())) {
-    CommandLineError::print(verbose,
-                            "%s (" SIZE_FORMAT ") must be "
-                            "less than or equal to ergonomic PLAB maximum size (" SIZE_FORMAT ")\n",
-                            name, value, PLAB::max_size());
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif // INCLUDE_ALL_GCS
-  return Flag::SUCCESS;
-}
-
-static Flag::Error MinMaxPLABSizeBounds(const char* name, size_t value, bool verbose) {
-  Flag::Error status = MinPLABSizeBounds(name, value, verbose);
-
-  if (status == Flag::SUCCESS) {
-    return MaxPLABSizeBounds(name, value, verbose);
-  }
-  return status;
-}
-
-Flag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose) {
-  return MinMaxPLABSizeBounds("YoungPLABSize", value, verbose);
-}
-
-Flag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose) {
-  Flag::Error status = Flag::SUCCESS;
-
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    if (value == 0) {
-      CommandLineError::print(verbose,
-                              "OldPLABSize (" SIZE_FORMAT ") must be greater than 0",
-                              value);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-    // For CMS, OldPLABSize is the number of free blocks of a given size that are used when
-    // replenishing the local per-worker free list caches.
-    // For more details, please refer to Arguments::set_cms_and_parnew_gc_flags().
-    status = MaxPLABSizeBounds("OldPLABSize", value, verbose);
-  } else {
-    status = MinMaxPLABSizeBounds("OldPLABSize", value, verbose);
-  }
-#endif
-  return status;
-}
-
-Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
-  if (value > MaxHeapFreeRatio) {
-    CommandLineError::print(verbose,
-                            "MinHeapFreeRatio (" UINTX_FORMAT ") must be "
-                            "less than or equal to MaxHeapFreeRatio (" UINTX_FORMAT ")\n",
-                            value, MaxHeapFreeRatio);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose) {
-  if (value < MinHeapFreeRatio) {
-    CommandLineError::print(verbose,
-                            "MaxHeapFreeRatio (" UINTX_FORMAT ") must be "
-                            "greater than or equal to MinHeapFreeRatio (" UINTX_FORMAT ")\n",
-                            value, MinHeapFreeRatio);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-static Flag::Error CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(size_t maxHeap, intx softRef, bool verbose) {
-  if ((softRef > 0) && ((maxHeap / M) > (max_uintx / softRef))) {
-    CommandLineError::print(verbose,
-                            "Desired lifetime of SoftReferences cannot be expressed correctly. "
-                            "MaxHeapSize (" SIZE_FORMAT ") or SoftRefLRUPolicyMSPerMB "
-                            "(" INTX_FORMAT ") is too large\n",
-                            maxHeap, softRef);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose) {
-  return CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(MaxHeapSize, value, verbose);
-}
-
-Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
-  if (value > MaxMetaspaceFreeRatio) {
-    CommandLineError::print(verbose,
-                            "MinMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
-                            "less than or equal to MaxMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
-                            value, MaxMetaspaceFreeRatio);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose) {
-  if (value < MinMetaspaceFreeRatio) {
-    CommandLineError::print(verbose,
-                            "MaxMetaspaceFreeRatio (" UINTX_FORMAT ") must be "
-                            "greater than or equal to MinMetaspaceFreeRatio (" UINTX_FORMAT ")\n",
-                            value, MinMetaspaceFreeRatio);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  // InitialTenuringThreshold is only used for ParallelGC.
-  if (UseParallelGC && (value > MaxTenuringThreshold)) {
-      CommandLineError::print(verbose,
-                              "InitialTenuringThreshold (" UINTX_FORMAT ") must be "
-                              "less than or equal to MaxTenuringThreshold (" UINTX_FORMAT ")\n",
-                              value, MaxTenuringThreshold);
-      return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  // As only ParallelGC uses InitialTenuringThreshold,
-  // we don't need to compare InitialTenuringThreshold with MaxTenuringThreshold.
-  if (UseParallelGC && (value < InitialTenuringThreshold)) {
-    CommandLineError::print(verbose,
-                            "MaxTenuringThreshold (" UINTX_FORMAT ") must be "
-                            "greater than or equal to InitialTenuringThreshold (" UINTX_FORMAT ")\n",
-                            value, InitialTenuringThreshold);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-
-  // MaxTenuringThreshold=0 means NeverTenure=false && AlwaysTenure=true
-  if ((value == 0) && (NeverTenure || !AlwaysTenure)) {
-    CommandLineError::print(verbose,
-                            "MaxTenuringThreshold (0) should match to NeverTenure=false "
-                            "&& AlwaysTenure=true. But we have NeverTenure=%s "
-                            "AlwaysTenure=%s\n",
-                            NeverTenure ? "true" : "false",
-                            AlwaysTenure ? "true" : "false");
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  return Flag::SUCCESS;
-}
-
-#if INCLUDE_ALL_GCS
-Flag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose) {
-  if (!UseG1GC) return Flag::SUCCESS;
-
-  // Default value of G1RSetRegionEntries=0 means will be set ergonomically.
-  // Minimum value is 1.
-  if (FLAG_IS_CMDLINE(G1RSetRegionEntries) && (value < 1)) {
-    CommandLineError::print(verbose,
-                            "G1RSetRegionEntries (" INTX_FORMAT ") must be "
-                            "greater than or equal to 1\n",
-                            value);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose) {
-  if (!UseG1GC) return Flag::SUCCESS;
-
-  // Default value of G1RSetSparseRegionEntries=0 means will be set ergonomically.
-  // Minimum value is 1.
-  if (FLAG_IS_CMDLINE(G1RSetSparseRegionEntries) && (value < 1)) {
-    CommandLineError::print(verbose,
-                            "G1RSetSparseRegionEntries (" INTX_FORMAT ") must be "
-                            "greater than or equal to 1\n",
-                            value);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose) {
-  if (!UseG1GC) return Flag::SUCCESS;
-
-  // Default value of G1HeapRegionSize=0 means will be set ergonomically.
-  if (FLAG_IS_CMDLINE(G1HeapRegionSize) && (value < HeapRegionBounds::min_size())) {
-    CommandLineError::print(verbose,
-                            "G1HeapRegionSize (" SIZE_FORMAT ") must be "
-                            "greater than or equal to ergonomic heap region minimum size\n",
-                            value);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose) {
-  if (!UseG1GC) return Flag::SUCCESS;
-
-  if (value > G1MaxNewSizePercent) {
-    CommandLineError::print(verbose,
-                            "G1NewSizePercent (" UINTX_FORMAT ") must be "
-                            "less than or equal to G1MaxNewSizePercent (" UINTX_FORMAT ")\n",
-                            value, G1MaxNewSizePercent);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose) {
-  if (!UseG1GC) return Flag::SUCCESS;
-
-  if (value < G1NewSizePercent) {
-    CommandLineError::print(verbose,
-                            "G1MaxNewSizePercent (" UINTX_FORMAT ") must be "
-                            "greater than or equal to G1NewSizePercent (" UINTX_FORMAT ")\n",
-                            value, G1NewSizePercent);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-#endif // INCLUDE_ALL_GCS
-
-Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC && (value > ((uintx)max_jint / (uintx)ParallelGCThreads))) {
-    CommandLineError::print(verbose,
-                            "ParGCStridesPerThread (" UINTX_FORMAT ") must be "
-                            "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
-                            value, ((uintx)max_jint / (uintx)ParallelGCThreads));
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    // ParGCCardsPerStrideChunk should be compared with card table size.
-    size_t heap_size = Universe::heap()->reserved_region().word_size();
-    CardTableRS* ct = GenCollectedHeap::heap()->rem_set();
-    size_t card_table_size = ct->cards_required(heap_size) - 1; // Valid card table size
-
-    if ((size_t)value > card_table_size) {
-      CommandLineError::print(verbose,
-                              "ParGCCardsPerStrideChunk (" INTX_FORMAT ") is too large for the heap size and "
-                              "must be less than or equal to card table size (" SIZE_FORMAT ")\n",
-                              value, card_table_size);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-
-    // ParGCCardsPerStrideChunk is used with n_strides(ParallelGCThreads*ParGCStridesPerThread)
-    // from CardTableRS::process_stride(). Note that ParGCStridesPerThread is already checked
-    // not to make an overflow with ParallelGCThreads from its constraint function.
-    uintx n_strides = ParallelGCThreads * ParGCStridesPerThread;
-    uintx ergo_max = max_uintx / n_strides;
-    if ((uintx)value > ergo_max) {
-      CommandLineError::print(verbose,
-                              "ParGCCardsPerStrideChunk (" INTX_FORMAT ") must be "
-                              "less than or equal to ergonomic maximum (" UINTX_FORMAT ")\n",
-                              value, ergo_max);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose) {
-  Flag::Error status = Flag::SUCCESS;
-
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    if (value > CMSOldPLABMax) {
-      CommandLineError::print(verbose,
-                              "CMSOldPLABMin (" SIZE_FORMAT ") must be "
-                              "less than or equal to CMSOldPLABMax (" SIZE_FORMAT ")\n",
-                              value, CMSOldPLABMax);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-    status = MaxPLABSizeBounds("CMSOldPLABMin", value, verbose);
-  }
-#endif
-  return status;
-}
-
-Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose) {
-  Flag::Error status = Flag::SUCCESS;
-
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    status = MaxPLABSizeBounds("CMSOldPLABMax", value, verbose);
-  }
-#endif
-  return status;
-}
-
-Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose) {
-  if (value > MarkStackSizeMax) {
-    CommandLineError::print(verbose,
-                            "MarkStackSize (" SIZE_FORMAT ") must be "
-                            "less than or equal to MarkStackSizeMax (" SIZE_FORMAT ")\n",
-                            value, MarkStackSizeMax);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-static Flag::Error CMSReservedAreaConstraintFunc(const char* name, size_t value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
-    const size_t ergo_max = cms->cmsSpace()->max_flag_size_for_task_size();
-    if (value > ergo_max) {
-      CommandLineError::print(verbose,
-                              "%s (" SIZE_FORMAT ") must be "
-                              "less than or equal to ergonomic maximum (" SIZE_FORMAT ") "
-                              "which is based on the maximum size of the old generation of the Java heap\n",
-                              name, value, ergo_max);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-#endif
-
-  return Flag::SUCCESS;
-}
-
-Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose) {
-  Flag::Error status = CMSReservedAreaConstraintFunc("CMSRescanMultiple", value, verbose);
-
-#if INCLUDE_ALL_GCS
-  if (status == Flag::SUCCESS && UseConcMarkSweepGC) {
-    // CMSParRemarkTask::do_dirty_card_rescan_tasks requires CompactibleFreeListSpace::rescan_task_size()
-    // to be aligned to CardTable::card_size * BitsPerWord.
-    // Note that rescan_task_size() will be aligned if CMSRescanMultiple is a multiple of 'HeapWordSize'
-    // because rescan_task_size() is CardTable::card_size / HeapWordSize * BitsPerWord.
-    if (value % HeapWordSize != 0) {
-      CommandLineError::print(verbose,
-                              "CMSRescanMultiple (" SIZE_FORMAT ") must be "
-                              "a multiple of " SIZE_FORMAT "\n",
-                              value, HeapWordSize);
-      status = Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-#endif
-
-  return status;
-}
-
-Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose) {
-  return CMSReservedAreaConstraintFunc("CMSConcMarkMultiple", value, verbose);
-}
-
-Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC && (value <= CMSPrecleanNumerator)) {
-    CommandLineError::print(verbose,
-                            "CMSPrecleanDenominator (" UINTX_FORMAT ") must be "
-                            "strickly greater than CMSPrecleanNumerator (" UINTX_FORMAT ")\n",
-                            value, CMSPrecleanNumerator);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC && (value >= CMSPrecleanDenominator)) {
-    CommandLineError::print(verbose,
-                            "CMSPrecleanNumerator (" UINTX_FORMAT ") must be "
-                            "less than CMSPrecleanDenominator (" UINTX_FORMAT ")\n",
-                            value, CMSPrecleanDenominator);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    size_t max_capacity = GenCollectedHeap::heap()->young_gen()->max_capacity();
-    if (value > max_uintx - max_capacity) {
-    CommandLineError::print(verbose,
-                            "CMSSamplingGrain (" UINTX_FORMAT ") must be "
-                            "less than or equal to ergonomic maximum (" SIZE_FORMAT ")\n",
-                            value, max_uintx - max_capacity);
-    return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseConcMarkSweepGC) {
-    return ParallelGCThreadsAndCMSWorkQueueDrainThreshold(ParallelGCThreads, value, verbose);
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  // Skip for current default value.
-  if (UseConcMarkSweepGC && FLAG_IS_CMDLINE(CMSBitMapYieldQuantum)) {
-    // CMSBitMapYieldQuantum should be compared with mark bitmap size.
-    ConcurrentMarkSweepGeneration* cms = (ConcurrentMarkSweepGeneration*)GenCollectedHeap::heap()->old_gen();
-    size_t bitmap_size = cms->collector()->markBitMap()->sizeInWords();
-
-    if (value > bitmap_size) {
-      CommandLineError::print(verbose,
-                              "CMSBitMapYieldQuantum (" SIZE_FORMAT ") must "
-                              "be less than or equal to bitmap size (" SIZE_FORMAT ") "
-                              "whose size corresponds to the size of old generation of the Java heap\n",
-                              value, bitmap_size);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseG1GC && FLAG_IS_CMDLINE(MaxGCPauseMillis) && (value >= GCPauseIntervalMillis)) {
-    CommandLineError::print(verbose,
-                            "MaxGCPauseMillis (" UINTX_FORMAT ") must be "
-                            "less than GCPauseIntervalMillis (" UINTX_FORMAT ")\n",
-                            value, GCPauseIntervalMillis);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif
-
-  return Flag::SUCCESS;
-}
-
-Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose) {
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) {
-    if (FLAG_IS_CMDLINE(GCPauseIntervalMillis)) {
-      if (value < 1) {
-        CommandLineError::print(verbose,
-                                "GCPauseIntervalMillis (" UINTX_FORMAT ") must be "
-                                "greater than or equal to 1\n",
-                                value);
-        return Flag::VIOLATES_CONSTRAINT;
-      }
-
-      if (FLAG_IS_DEFAULT(MaxGCPauseMillis)) {
-        CommandLineError::print(verbose,
-                                "GCPauseIntervalMillis cannot be set "
-                                "without setting MaxGCPauseMillis\n");
-        return Flag::VIOLATES_CONSTRAINT;
-      }
-
-      if (value <= MaxGCPauseMillis) {
-        CommandLineError::print(verbose,
-                                "GCPauseIntervalMillis (" UINTX_FORMAT ") must be "
-                                "greater than MaxGCPauseMillis (" UINTX_FORMAT ")\n",
-                                value, MaxGCPauseMillis);
-        return Flag::VIOLATES_CONSTRAINT;
-      }
-    }
-  }
-#endif
-  return Flag::SUCCESS;
-}
-
-Flag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
-  size_t aligned_max = align_down(max_uintx/2, Metaspace::reserve_alignment_words());
-  if (value > aligned_max) {
-    CommandLineError::print(verbose,
-                            "InitialBootClassLoaderMetaspaceSize (" SIZE_FORMAT ") must be "
-                            "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
-                            value, aligned_max);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  return Flag::SUCCESS;
-}
-
-// To avoid an overflow by 'align_up(value, alignment)'.
-static Flag::Error MaxSizeForAlignment(const char* name, size_t value, size_t alignment, bool verbose) {
-  size_t aligned_max = ((max_uintx - alignment) & ~(alignment-1));
-  if (value > aligned_max) {
-    CommandLineError::print(verbose,
-                            "%s (" SIZE_FORMAT ") must be "
-                            "less than or equal to aligned maximum value (" SIZE_FORMAT ")\n",
-                            name, value, aligned_max);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  return Flag::SUCCESS;
-}
-
-static Flag::Error MaxSizeForHeapAlignment(const char* name, size_t value, bool verbose) {
-  // For G1 GC, we don't know until G1CollectorPolicy is created.
-  size_t heap_alignment;
-
-#if INCLUDE_ALL_GCS
-  if (UseG1GC) {
-    heap_alignment = HeapRegionBounds::max_size();
-  } else
-#endif
-  {
-    heap_alignment = CollectorPolicy::compute_heap_alignment();
-  }
-
-  return MaxSizeForAlignment(name, value, heap_alignment, verbose);
-}
-
-Flag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose) {
-  return MaxSizeForHeapAlignment("InitialHeapSize", value, verbose);
-}
-
-Flag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose) {
-  Flag::Error status = MaxSizeForHeapAlignment("MaxHeapSize", value, verbose);
-
-  if (status == Flag::SUCCESS) {
-    status = CheckMaxHeapSizeAndSoftRefLRUPolicyMSPerMB(value, SoftRefLRUPolicyMSPerMB, verbose);
-  }
-  return status;
-}
-
-Flag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose) {
-  // If an overflow happened in Arguments::set_heap_size(), MaxHeapSize will have too large a value.
-  // Check for this by ensuring that MaxHeapSize plus the requested min base address still fit within max_uintx.
-  if (UseCompressedOops && FLAG_IS_ERGO(MaxHeapSize) && (value > (max_uintx - MaxHeapSize))) {
-    CommandLineError::print(verbose,
-                            "HeapBaseMinAddress (" SIZE_FORMAT ") or MaxHeapSize (" SIZE_FORMAT ") is too large. "
-                            "Sum of them must be less than or equal to maximum of size_t (" SIZE_FORMAT ")\n",
-                            value, MaxHeapSize, max_uintx);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-
-  return MaxSizeForHeapAlignment("HeapBaseMinAddress", value, verbose);
-}
-
-Flag::Error NewSizeConstraintFunc(size_t value, bool verbose) {
-#ifdef _LP64
-#if INCLUDE_ALL_GCS
-  // Overflow would happen for uint type variable of YoungGenSizer::_min_desired_young_length
-  // when the value to be assigned exceeds uint range.
-  // i.e. result of '(uint)(NewSize / region size(1~32MB))'
-  // So maximum of NewSize should be 'max_juint * 1M'
-  if (UseG1GC && (value > (max_juint * 1 * M))) {
-    CommandLineError::print(verbose,
-                            "NewSize (" SIZE_FORMAT ") must be less than ergonomic maximum value\n",
-                            value);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-#endif // INCLUDE_ALL_GCS
-#endif // _LP64
-  return Flag::SUCCESS;
-}
-
-Flag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose) {
-  // At least, alignment reserve area is needed.
-  if (value < ThreadLocalAllocBuffer::alignment_reserve_in_bytes()) {
-    CommandLineError::print(verbose,
-                            "MinTLABSize (" SIZE_FORMAT ") must be "
-                            "greater than or equal to reserved area in TLAB (" SIZE_FORMAT ")\n",
-                            value, ThreadLocalAllocBuffer::alignment_reserve_in_bytes());
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
-    CommandLineError::print(verbose,
-                            "MinTLABSize (" SIZE_FORMAT ") must be "
-                            "less than or equal to ergonomic TLAB maximum (" SIZE_FORMAT ")\n",
-                            value, ThreadLocalAllocBuffer::max_size() * HeapWordSize);
-    return Flag::VIOLATES_CONSTRAINT;
-  }
-  return Flag::SUCCESS;
-}
-
-Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose) {
-  // Skip for default value of zero which means set ergonomically.
-  if (FLAG_IS_CMDLINE(TLABSize)) {
-    if (value < MinTLABSize) {
-      CommandLineError::print(verbose,
-                              "TLABSize (" SIZE_FORMAT ") must be "
-                              "greater than or equal to MinTLABSize (" SIZE_FORMAT ")\n",
-                              value, MinTLABSize);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-    if (value > (ThreadLocalAllocBuffer::max_size() * HeapWordSize)) {
-      CommandLineError::print(verbose,
-                              "TLABSize (" SIZE_FORMAT ") must be "
-                              "less than or equal to ergonomic TLAB maximum size (" SIZE_FORMAT ")\n",
-                              value, (ThreadLocalAllocBuffer::max_size() * HeapWordSize));
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-  return Flag::SUCCESS;
-}
-
-// We will protect overflow from ThreadLocalAllocBuffer::record_slow_allocation(),
-// so AfterMemoryInit type is enough to check.
-Flag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose) {
-  if (UseTLAB) {
-    size_t refill_waste_limit = Thread::current()->tlab().refill_waste_limit();
-
-    // Compare with 'max_uintx' as ThreadLocalAllocBuffer::_refill_waste_limit is 'size_t'.
-    if (refill_waste_limit > (max_uintx - value)) {
-      CommandLineError::print(verbose,
-                              "TLABWasteIncrement (" UINTX_FORMAT ") must be "
-                              "less than or equal to ergonomic TLAB waste increment maximum size(" SIZE_FORMAT ")\n",
-                              value, (max_uintx - refill_waste_limit));
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-  return Flag::SUCCESS;
-}
-
-Flag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose) {
-  if (FLAG_IS_CMDLINE(SurvivorRatio) &&
-      (value > (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()))) {
-    CommandLineError::print(verbose,
-                            "SurvivorRatio (" UINTX_FORMAT ") must be "
-                            "less than or equal to ergonomic SurvivorRatio maximum (" SIZE_FORMAT ")\n",
-                            value,
-                            (MaxHeapSize / Universe::heap()->collector_policy()->space_alignment()));
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose) {
-  if (value > MaxMetaspaceSize) {
-    CommandLineError::print(verbose,
-                            "MetaspaceSize (" SIZE_FORMAT ") must be "
-                            "less than or equal to MaxMetaspaceSize (" SIZE_FORMAT ")\n",
-                            value, MaxMetaspaceSize);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose) {
-  if (value < MetaspaceSize) {
-    CommandLineError::print(verbose,
-                            "MaxMetaspaceSize (" SIZE_FORMAT ") must be "
-                            "greater than or equal to MetaspaceSize (" SIZE_FORMAT ")\n",
-                            value, MaxMetaspaceSize);
-    return Flag::VIOLATES_CONSTRAINT;
-  } else {
-    return Flag::SUCCESS;
-  }
-}
-
-Flag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose) {
-  if (value != 0) {
-    if (!is_power_of_2(value)) {
-      CommandLineError::print(verbose,
-                              "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
-                              "power of 2\n",
-                              value);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-    if (value < ObjectAlignmentInBytes) {
-      CommandLineError::print(verbose,
-                              "SurvivorAlignmentInBytes (" INTX_FORMAT ") must be "
-                              "greater than or equal to ObjectAlignmentInBytes (" INTX_FORMAT ")\n",
-                              value, ObjectAlignmentInBytes);
-      return Flag::VIOLATES_CONSTRAINT;
-    }
-  }
-  return Flag::SUCCESS;
-}
--- a/src/hotspot/share/runtime/commandLineFlagConstraintsGC.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,84 +0,0 @@
-/*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#ifndef SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP
-#define SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP
-
-#include "runtime/globals.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-/*
- * Here we have GC arguments constraints functions, which are called automatically
- * whenever flag's value changes. If the constraint fails the function should return
- * an appropriate error value.
- */
-
-Flag::Error ParallelGCThreadsConstraintFunc(uint value, bool verbose);
-Flag::Error ConcGCThreadsConstraintFunc(uint value, bool verbose);
-Flag::Error YoungPLABSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error OldPLABSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error MinHeapFreeRatioConstraintFunc(uintx value, bool verbose);
-Flag::Error MaxHeapFreeRatioConstraintFunc(uintx value, bool verbose);
-Flag::Error SoftRefLRUPolicyMSPerMBConstraintFunc(intx value, bool verbose);
-Flag::Error MinMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose);
-Flag::Error MaxMetaspaceFreeRatioConstraintFunc(uintx value, bool verbose);
-Flag::Error InitialTenuringThresholdConstraintFunc(uintx value, bool verbose);
-Flag::Error MaxTenuringThresholdConstraintFunc(uintx value, bool verbose);
-
-#if INCLUDE_ALL_GCS
-Flag::Error G1RSetRegionEntriesConstraintFunc(intx value, bool verbose);
-Flag::Error G1RSetSparseRegionEntriesConstraintFunc(intx value, bool verbose);
-Flag::Error G1HeapRegionSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error G1NewSizePercentConstraintFunc(uintx value, bool verbose);
-Flag::Error G1MaxNewSizePercentConstraintFunc(uintx value, bool verbose);
-#endif // INCLUDE_ALL_GCS
-
-Flag::Error ParGCStridesPerThreadConstraintFunc(uintx value, bool verbose);
-Flag::Error ParGCCardsPerStrideChunkConstraintFunc(intx value, bool verbose);
-Flag::Error CMSOldPLABMinConstraintFunc(size_t value, bool verbose);
-Flag::Error CMSOldPLABMaxConstraintFunc(size_t value, bool verbose);
-Flag::Error MarkStackSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error CMSRescanMultipleConstraintFunc(size_t value, bool verbose);
-Flag::Error CMSConcMarkMultipleConstraintFunc(size_t value, bool verbose);
-Flag::Error CMSPrecleanDenominatorConstraintFunc(uintx value, bool verbose);
-Flag::Error CMSPrecleanNumeratorConstraintFunc(uintx value, bool verbose);
-Flag::Error CMSSamplingGrainConstraintFunc(uintx value, bool verbose);
-Flag::Error CMSWorkQueueDrainThresholdConstraintFunc(uintx value, bool verbose);
-Flag::Error CMSBitMapYieldQuantumConstraintFunc(size_t value, bool verbose);
-Flag::Error MaxGCPauseMillisConstraintFunc(uintx value, bool verbose);
-Flag::Error GCPauseIntervalMillisConstraintFunc(uintx value, bool verbose);
-Flag::Error InitialBootClassLoaderMetaspaceSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error InitialHeapSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error MaxHeapSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error HeapBaseMinAddressConstraintFunc(size_t value, bool verbose);
-Flag::Error NewSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error MinTLABSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error TLABSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error TLABWasteIncrementConstraintFunc(uintx value, bool verbose);
-Flag::Error SurvivorRatioConstraintFunc(uintx value, bool verbose);
-Flag::Error MetaspaceSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error MaxMetaspaceSizeConstraintFunc(size_t value, bool verbose);
-Flag::Error SurvivorAlignmentInBytesConstraintFunc(intx value, bool verbose);
-
-#endif /* SHARE_VM_RUNTIME_COMMANDLINEFLAGCONSTRAINTSGC_HPP */
--- a/src/hotspot/share/runtime/commandLineFlagRangeList.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/commandLineFlagRangeList.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -335,20 +335,20 @@
 
   _ranges = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<CommandLineFlagRange*>(INITIAL_RANGES_SIZE, true);
 
-  emit_range_no(NULL RUNTIME_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
-                                   EMIT_RANGE_PD_DEVELOPER_FLAG,
-                                   EMIT_RANGE_PRODUCT_FLAG,
-                                   EMIT_RANGE_PD_PRODUCT_FLAG,
-                                   EMIT_RANGE_DIAGNOSTIC_FLAG,
-                                   EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
-                                   EMIT_RANGE_EXPERIMENTAL_FLAG,
-                                   EMIT_RANGE_NOTPRODUCT_FLAG,
-                                   EMIT_RANGE_MANAGEABLE_FLAG,
-                                   EMIT_RANGE_PRODUCT_RW_FLAG,
-                                   EMIT_RANGE_LP64_PRODUCT_FLAG,
-                                   EMIT_RANGE_CHECK,
-                                   IGNORE_CONSTRAINT,
-                                   IGNORE_WRITEABLE));
+  emit_range_no(NULL VM_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
+                              EMIT_RANGE_PD_DEVELOPER_FLAG,
+                              EMIT_RANGE_PRODUCT_FLAG,
+                              EMIT_RANGE_PD_PRODUCT_FLAG,
+                              EMIT_RANGE_DIAGNOSTIC_FLAG,
+                              EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
+                              EMIT_RANGE_EXPERIMENTAL_FLAG,
+                              EMIT_RANGE_NOTPRODUCT_FLAG,
+                              EMIT_RANGE_MANAGEABLE_FLAG,
+                              EMIT_RANGE_PRODUCT_RW_FLAG,
+                              EMIT_RANGE_LP64_PRODUCT_FLAG,
+                              EMIT_RANGE_CHECK,
+                              IGNORE_CONSTRAINT,
+                              IGNORE_WRITEABLE));
 
   EMIT_RANGES_FOR_GLOBALS_EXT
 
@@ -401,22 +401,6 @@
                               IGNORE_CONSTRAINT,
                               IGNORE_WRITEABLE));
 #endif // COMPILER2
-
-#if INCLUDE_ALL_GCS
-  emit_range_no(NULL G1_FLAGS(EMIT_RANGE_DEVELOPER_FLAG,
-                              EMIT_RANGE_PD_DEVELOPER_FLAG,
-                              EMIT_RANGE_PRODUCT_FLAG,
-                              EMIT_RANGE_PD_PRODUCT_FLAG,
-                              EMIT_RANGE_DIAGNOSTIC_FLAG,
-                              EMIT_RANGE_PD_DIAGNOSTIC_FLAG,
-                              EMIT_RANGE_EXPERIMENTAL_FLAG,
-                              EMIT_RANGE_NOTPRODUCT_FLAG,
-                              EMIT_RANGE_MANAGEABLE_FLAG,
-                              EMIT_RANGE_PRODUCT_RW_FLAG,
-                              EMIT_RANGE_CHECK,
-                              IGNORE_CONSTRAINT,
-                              IGNORE_WRITEABLE));
-#endif // INCLUDE_ALL_GCS
 }
 
 CommandLineFlagRange* CommandLineFlagRangeList::find(const char* name) {
--- a/src/hotspot/share/runtime/commandLineFlagWriteableList.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/commandLineFlagWriteableList.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -23,14 +23,9 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/plab.hpp"
 #include "runtime/commandLineFlagWriteableList.hpp"
 #include "runtime/os.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/cms/concurrentMarkSweepGeneration.inline.hpp"
-#include "gc/g1/g1_globals.hpp"
-#include "gc/g1/heapRegionBounds.inline.hpp"
-#include "gc/shared/plab.hpp"
-#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif // COMPILER1
@@ -122,20 +117,20 @@
 
   _controls = new (ResourceObj::C_HEAP, mtArguments) GrowableArray<CommandLineFlagWriteable*>(INITIAL_WRITEABLES_SIZE, true);
 
-  emit_writeable_no(NULL RUNTIME_FLAGS(EMIT_WRITEABLE_DEVELOPER_FLAG,
-                                   EMIT_WRITEABLE_PD_DEVELOPER_FLAG,
-                                   EMIT_WRITEABLE_PRODUCT_FLAG,
-                                   EMIT_WRITEABLE_PD_PRODUCT_FLAG,
-                                   EMIT_WRITEABLE_DIAGNOSTIC_FLAG,
-                                   EMIT_WRITEABLE_PD_DIAGNOSTIC_FLAG,
-                                   EMIT_WRITEABLE_EXPERIMENTAL_FLAG,
-                                   EMIT_WRITEABLE_NOTPRODUCT_FLAG,
-                                   EMIT_WRITEABLE_MANAGEABLE_FLAG,
-                                   EMIT_WRITEABLE_PRODUCT_RW_FLAG,
-                                   EMIT_WRITEABLE_LP64_PRODUCT_FLAG,
-                                   IGNORE_RANGE,
-                                   IGNORE_CONSTRAINT,
-                                   EMIT_WRITEABLE));
+  emit_writeable_no(NULL VM_FLAGS(EMIT_WRITEABLE_DEVELOPER_FLAG,
+                                  EMIT_WRITEABLE_PD_DEVELOPER_FLAG,
+                                  EMIT_WRITEABLE_PRODUCT_FLAG,
+                                  EMIT_WRITEABLE_PD_PRODUCT_FLAG,
+                                  EMIT_WRITEABLE_DIAGNOSTIC_FLAG,
+                                  EMIT_WRITEABLE_PD_DIAGNOSTIC_FLAG,
+                                  EMIT_WRITEABLE_EXPERIMENTAL_FLAG,
+                                  EMIT_WRITEABLE_NOTPRODUCT_FLAG,
+                                  EMIT_WRITEABLE_MANAGEABLE_FLAG,
+                                  EMIT_WRITEABLE_PRODUCT_RW_FLAG,
+                                  EMIT_WRITEABLE_LP64_PRODUCT_FLAG,
+                                  IGNORE_RANGE,
+                                  IGNORE_CONSTRAINT,
+                                  EMIT_WRITEABLE));
 
   EMIT_WRITEABLES_FOR_GLOBALS_EXT
 
@@ -188,22 +183,6 @@
                               IGNORE_CONSTRAINT,
                               EMIT_WRITEABLE));
 #endif // COMPILER2
-
-#if INCLUDE_ALL_GCS
-  emit_writeable_no(NULL G1_FLAGS(EMIT_WRITEABLE_DEVELOPER_FLAG,
-                              EMIT_WRITEABLE_PD_DEVELOPER_FLAG,
-                              EMIT_WRITEABLE_PRODUCT_FLAG,
-                              EMIT_WRITEABLE_PD_PRODUCT_FLAG,
-                              EMIT_WRITEABLE_DIAGNOSTIC_FLAG,
-                              EMIT_WRITEABLE_PD_DIAGNOSTIC_FLAG,
-                              EMIT_WRITEABLE_EXPERIMENTAL_FLAG,
-                              EMIT_WRITEABLE_NOTPRODUCT_FLAG,
-                              EMIT_WRITEABLE_MANAGEABLE_FLAG,
-                              EMIT_WRITEABLE_PRODUCT_RW_FLAG,
-                              IGNORE_RANGE,
-                              IGNORE_CONSTRAINT,
-                              EMIT_WRITEABLE));
-#endif // INCLUDE_ALL_GCS
 }
 
 CommandLineFlagWriteable* CommandLineFlagWriteableList::find(const char* name) {
--- a/src/hotspot/share/runtime/globals.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/globals.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -39,9 +39,6 @@
 #include "utilities/macros.hpp"
 #include "utilities/ostream.hpp"
 #include "utilities/stringUtils.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1_globals.hpp"
-#endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
 #endif
@@ -52,20 +49,20 @@
 #include "opto/c2_globals.hpp"
 #endif
 
-RUNTIME_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
-              MATERIALIZE_PD_DEVELOPER_FLAG, \
-              MATERIALIZE_PRODUCT_FLAG, \
-              MATERIALIZE_PD_PRODUCT_FLAG, \
-              MATERIALIZE_DIAGNOSTIC_FLAG, \
-              MATERIALIZE_PD_DIAGNOSTIC_FLAG, \
-              MATERIALIZE_EXPERIMENTAL_FLAG, \
-              MATERIALIZE_NOTPRODUCT_FLAG, \
-              MATERIALIZE_MANAGEABLE_FLAG, \
-              MATERIALIZE_PRODUCT_RW_FLAG, \
-              MATERIALIZE_LP64_PRODUCT_FLAG, \
-              IGNORE_RANGE, \
-              IGNORE_CONSTRAINT, \
-              IGNORE_WRITEABLE)
+VM_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
+         MATERIALIZE_PD_DEVELOPER_FLAG, \
+         MATERIALIZE_PRODUCT_FLAG, \
+         MATERIALIZE_PD_PRODUCT_FLAG, \
+         MATERIALIZE_DIAGNOSTIC_FLAG, \
+         MATERIALIZE_PD_DIAGNOSTIC_FLAG, \
+         MATERIALIZE_EXPERIMENTAL_FLAG, \
+         MATERIALIZE_NOTPRODUCT_FLAG, \
+         MATERIALIZE_MANAGEABLE_FLAG, \
+         MATERIALIZE_PRODUCT_RW_FLAG, \
+         MATERIALIZE_LP64_PRODUCT_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT, \
+         IGNORE_WRITEABLE)
 
 RUNTIME_OS_FLAGS(MATERIALIZE_DEVELOPER_FLAG, \
                  MATERIALIZE_PD_DEVELOPER_FLAG, \
@@ -870,20 +867,21 @@
 #define ARCH_NOTPRODUCT_FLAG_STRUCT(     type, name, value, doc) { #type, XSTR(name), (void*) &name, NOT_PRODUCT_ARG(doc) Flag::Flags(Flag::DEFAULT | Flag::KIND_ARCH | Flag::KIND_NOT_PRODUCT) },
 
 static Flag flagTable[] = {
- RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
-               RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
-               RUNTIME_PRODUCT_FLAG_STRUCT, \
-               RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
-               RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
-               RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
-               RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
-               RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
-               RUNTIME_MANAGEABLE_FLAG_STRUCT, \
-               RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
-               RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \
-               IGNORE_RANGE, \
-               IGNORE_CONSTRAINT, \
-               IGNORE_WRITEABLE)
+  VM_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
+           RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
+           RUNTIME_PRODUCT_FLAG_STRUCT, \
+           RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
+           RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
+           RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
+           RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
+           RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
+           RUNTIME_MANAGEABLE_FLAG_STRUCT, \
+           RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
+           RUNTIME_LP64_PRODUCT_FLAG_STRUCT, \
+           IGNORE_RANGE, \
+           IGNORE_CONSTRAINT, \
+           IGNORE_WRITEABLE)
+
  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
                   RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
                   RUNTIME_PRODUCT_FLAG_STRUCT, \
@@ -894,21 +892,6 @@
                   IGNORE_RANGE, \
                   IGNORE_CONSTRAINT, \
                   IGNORE_WRITEABLE)
-#if INCLUDE_ALL_GCS
- G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, \
-          RUNTIME_PD_DEVELOP_FLAG_STRUCT, \
-          RUNTIME_PRODUCT_FLAG_STRUCT, \
-          RUNTIME_PD_PRODUCT_FLAG_STRUCT, \
-          RUNTIME_DIAGNOSTIC_FLAG_STRUCT, \
-          RUNTIME_PD_DIAGNOSTIC_FLAG_STRUCT, \
-          RUNTIME_EXPERIMENTAL_FLAG_STRUCT, \
-          RUNTIME_NOTPRODUCT_FLAG_STRUCT, \
-          RUNTIME_MANAGEABLE_FLAG_STRUCT, \
-          RUNTIME_PRODUCT_RW_FLAG_STRUCT, \
-          IGNORE_RANGE, \
-          IGNORE_CONSTRAINT, \
-          IGNORE_WRITEABLE)
-#endif // INCLUDE_ALL_GCS
 #if INCLUDE_JVMCI
  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_STRUCT, \
              JVMCI_PD_DEVELOP_FLAG_STRUCT, \
--- a/src/hotspot/share/runtime/globals.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/globals.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_RUNTIME_GLOBALS_HPP
 #define SHARE_VM_RUNTIME_GLOBALS_HPP
 
+#include "gc/shared/gc_globals.hpp"
 #include "utilities/align.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
@@ -1385,936 +1386,17 @@
   develop(bool, TraceCompiledIC, false,                                     \
           "Trace changes of compiled IC")                                   \
                                                                             \
-  /* gc */                                                                  \
-                                                                            \
-  product(bool, UseSerialGC, false,                                         \
-          "Use the Serial garbage collector")                               \
-                                                                            \
-  product(bool, UseG1GC, false,                                             \
-          "Use the Garbage-First garbage collector")                        \
-                                                                            \
-  product(bool, UseParallelGC, false,                                       \
-          "Use the Parallel Scavenge garbage collector")                    \
-                                                                            \
-  product(bool, UseParallelOldGC, false,                                    \
-          "Use the Parallel Old garbage collector")                         \
-                                                                            \
-  product(uintx, HeapMaximumCompactionInterval, 20,                         \
-          "How often should we maximally compact the heap (not allowing "   \
-          "any dead space)")                                                \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(uintx, HeapFirstMaximumCompactionCount, 3,                        \
-          "The collection count for the first maximum compaction")          \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(bool, UseMaximumCompactionOnSystemGC, true,                       \
-          "Use maximum compaction in the Parallel Old garbage collector "   \
-          "for a system GC")                                                \
-                                                                            \
-  product(uintx, ParallelOldDeadWoodLimiterMean, 50,                        \
-          "The mean used by the parallel compact dead wood "                \
-          "limiter (a number between 0-100)")                               \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, ParallelOldDeadWoodLimiterStdDev, 80,                      \
-          "The standard deviation used by the parallel compact dead wood "  \
-          "limiter (a number between 0-100)")                               \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uint, ParallelGCThreads, 0,                                       \
-          "Number of parallel threads parallel gc will use")                \
-          constraint(ParallelGCThreadsConstraintFunc,AfterErgo)             \
-                                                                            \
-  diagnostic(bool, UseSemaphoreGCThreadsSynchronization, true,              \
-            "Use semaphore synchronization for the GC Threads, "            \
-            "instead of synchronization based on mutexes")                  \
-                                                                            \
-  product(bool, UseDynamicNumberOfGCThreads, true,                          \
-          "Dynamically choose the number of threads up to a maximum of "    \
-          "ParallelGCThreads parallel collectors will use for garbage "     \
-          "collection work")                                                \
-                                                                            \
-  diagnostic(bool, InjectGCWorkerCreationFailure, false,                    \
-             "Inject thread creation failures for "                         \
-             "UseDynamicNumberOfGCThreads")                                 \
-                                                                            \
-  diagnostic(bool, ForceDynamicNumberOfGCThreads, false,                    \
-          "Force dynamic selection of the number of "                       \
-          "parallel threads parallel gc will use to aid debugging")         \
-                                                                            \
-  product(size_t, HeapSizePerGCThread, ScaleForWordSize(64*M),              \
-          "Size of heap (bytes) per GC thread used in calculating the "     \
-          "number of GC threads")                                           \
-          range((size_t)os::vm_page_size(), (size_t)max_uintx)              \
-                                                                            \
-  product(uint, ConcGCThreads, 0,                                           \
-          "Number of threads concurrent gc will use")                       \
-          constraint(ConcGCThreadsConstraintFunc,AfterErgo)                 \
-                                                                            \
-  product(uint, GCTaskTimeStampEntries, 200,                                \
-          "Number of time stamp entries per gc worker thread")              \
-          range(1, max_jint)                                                \
-                                                                            \
-  product(bool, AlwaysTenure, false,                                        \
-          "Always tenure objects in eden (ParallelGC only)")                \
-                                                                            \
-  product(bool, NeverTenure, false,                                         \
-          "Never tenure objects in eden, may tenure on overflow "           \
-          "(ParallelGC only)")                                              \
-                                                                            \
-  product(bool, ScavengeBeforeFullGC, true,                                 \
-          "Scavenge youngest generation before each full GC.")              \
-                                                                            \
-  product(bool, UseConcMarkSweepGC, false,                                  \
-          "Use Concurrent Mark-Sweep GC in the old generation")             \
-                                                                            \
-  product(bool, ExplicitGCInvokesConcurrent, false,                         \
-          "A System.gc() request invokes a concurrent collection; "         \
-          "(effective only when using concurrent collectors)")              \
-                                                                            \
-  product(bool, GCLockerInvokesConcurrent, false,                           \
-          "The exit of a JNI critical section necessitating a scavenge, "   \
-          "also kicks off a background concurrent collection")              \
-                                                                            \
-  product(uintx, GCLockerEdenExpansionPercent, 5,                           \
-          "How much the GC can expand the eden by while the GC locker "     \
-          "is active (as a percentage)")                                    \
-          range(0, 100)                                                     \
-                                                                            \
-  diagnostic(uintx, GCLockerRetryAllocationCount, 2,                        \
-          "Number of times to retry allocations when "                      \
-          "blocked by the GC locker")                                       \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(bool, UseCMSBestFit, true,                                        \
-          "Use CMS best fit allocation strategy")                           \
-                                                                            \
-  product(uintx, ParallelGCBufferWastePct, 10,                              \
-          "Wasted fraction of parallel allocation buffer")                  \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, TargetPLABWastePct, 10,                                    \
-          "Target wasted space in last buffer as percent of overall "       \
-          "allocation")                                                     \
-          range(1, 100)                                                     \
-                                                                            \
-  product(uintx, PLABWeight, 75,                                            \
-          "Percentage (0-100) used to weight the current sample when "      \
-          "computing exponentially decaying average for ResizePLAB")        \
-          range(0, 100)                                                     \
-                                                                            \
-  product(bool, ResizePLAB, true,                                           \
-          "Dynamically resize (survivor space) promotion LAB's")            \
-                                                                            \
-  product(int, ParGCArrayScanChunk, 50,                                     \
-          "Scan a subset of object array and push remainder, if array is "  \
-          "bigger than this")                                               \
-          range(1, max_jint/3)                                              \
-                                                                            \
-  product(bool, ParGCUseLocalOverflow, false,                               \
-          "Instead of a global overflow list, use local overflow stacks")   \
-                                                                            \
-  product(bool, ParGCTrimOverflow, true,                                    \
-          "Eagerly trim the local overflow lists "                          \
-          "(when ParGCUseLocalOverflow)")                                   \
-                                                                            \
-  notproduct(bool, ParGCWorkQueueOverflowALot, false,                       \
-          "Simulate work queue overflow in ParNew")                         \
-                                                                            \
-  notproduct(uintx, ParGCWorkQueueOverflowInterval, 1000,                   \
-          "An `interval' counter that determines how frequently "           \
-          "we simulate overflow; a smaller number increases frequency")     \
-                                                                            \
-  product(uintx, ParGCDesiredObjsFromOverflowList, 20,                      \
-          "The desired number of objects to claim from the overflow list")  \
-          range(0, max_uintx)                                               \
-                                                                            \
-  diagnostic(uintx, ParGCStridesPerThread, 2,                               \
-          "The number of strides per worker thread that we divide up the "  \
-          "card table scanning work into")                                  \
-          range(1, max_uintx)                                               \
-          constraint(ParGCStridesPerThreadConstraintFunc,AfterErgo)         \
-                                                                            \
-  diagnostic(intx, ParGCCardsPerStrideChunk, 256,                           \
-          "The number of cards in each chunk of the parallel chunks used "  \
-          "during card table scanning")                                     \
-          range(1, max_intx)                                                \
-          constraint(ParGCCardsPerStrideChunkConstraintFunc,AfterMemoryInit)\
-                                                                            \
-  product(uintx, OldPLABWeight, 50,                                         \
-          "Percentage (0-100) used to weight the current sample when "      \
-          "computing exponentially decaying average for resizing "          \
-          "OldPLABSize")                                                    \
-          range(0, 100)                                                     \
-                                                                            \
-  product(bool, ResizeOldPLAB, true,                                        \
-          "Dynamically resize (old gen) promotion LAB's")                   \
-                                                                            \
-  product(size_t, CMSOldPLABMax, 1024,                                      \
-          "Maximum size of CMS gen promotion LAB caches per worker "        \
-          "per block size")                                                 \
-          range(1, max_uintx)                                               \
-          constraint(CMSOldPLABMaxConstraintFunc,AfterMemoryInit)           \
-                                                                            \
-  product(size_t, CMSOldPLABMin, 16,                                        \
-          "Minimum size of CMS gen promotion LAB caches per worker "        \
-          "per block size")                                                 \
-          range(1, max_uintx)                                               \
-          constraint(CMSOldPLABMinConstraintFunc,AfterMemoryInit)           \
-                                                                            \
-  product(uintx, CMSOldPLABNumRefills, 4,                                   \
-          "Nominal number of refills of CMS gen promotion LAB cache "       \
-          "per worker per block size")                                      \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(bool, CMSOldPLABResizeQuicker, false,                             \
-          "React on-the-fly during a scavenge to a sudden "                 \
-          "change in block demand rate")                                    \
-                                                                            \
-  product(uintx, CMSOldPLABToleranceFactor, 4,                              \
-          "The tolerance of the phase-change detector for on-the-fly "      \
-          "PLAB resizing during a scavenge")                                \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, CMSOldPLABReactivityFactor, 2,                             \
-          "The gain in the feedback loop for on-the-fly PLAB resizing "     \
-          "during a scavenge")                                              \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(bool, AlwaysPreTouch, false,                                      \
-          "Force all freshly committed pages to be pre-touched")            \
-                                                                            \
-  product(size_t, PreTouchParallelChunkSize, 1 * G,                         \
-          "Per-thread chunk size for parallel memory pre-touch.")           \
-          range(1, SIZE_MAX / 2)                                            \
-                                                                            \
-  product_pd(size_t, CMSYoungGenPerWorker,                                  \
-          "The maximum size of young gen chosen by default per GC worker "  \
-          "thread available")                                               \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, CMSIncrementalSafetyFactor, 10,                            \
-          "Percentage (0-100) used to add conservatism when computing the " \
-          "duty cycle")                                                     \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, CMSExpAvgFactor, 50,                                       \
-          "Percentage (0-100) used to weight the current sample when "      \
-          "computing exponential averages for CMS statistics")              \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, CMS_FLSWeight, 75,                                         \
-          "Percentage (0-100) used to weight the current sample when "      \
-          "computing exponentially decaying averages for CMS FLS "          \
-          "statistics")                                                     \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, CMS_FLSPadding, 1,                                         \
-          "The multiple of deviation from mean to use for buffering "       \
-          "against volatility in free list demand")                         \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, FLSCoalescePolicy, 2,                                      \
-          "CMS: aggressiveness level for coalescing, increasing "           \
-          "from 0 to 4")                                                    \
-          range(0, 4)                                                       \
-                                                                            \
-  product(bool, FLSAlwaysCoalesceLarge, false,                              \
-          "CMS: larger free blocks are always available for coalescing")    \
-                                                                            \
-  product(double, FLSLargestBlockCoalesceProximity, 0.99,                   \
-          "CMS: the smaller the percentage the greater the coalescing "     \
-          "force")                                                          \
-          range(0.0, 1.0)                                                   \
-                                                                            \
-  product(double, CMSSmallCoalSurplusPercent, 1.05,                         \
-          "CMS: the factor by which to inflate estimated demand of small "  \
-          "block sizes to prevent coalescing with an adjoining block")      \
-          range(0.0, DBL_MAX)                                               \
-                                                                            \
-  product(double, CMSLargeCoalSurplusPercent, 0.95,                         \
-          "CMS: the factor by which to inflate estimated demand of large "  \
-          "block sizes to prevent coalescing with an adjoining block")      \
-          range(0.0, DBL_MAX)                                               \
-                                                                            \
-  product(double, CMSSmallSplitSurplusPercent, 1.10,                        \
-          "CMS: the factor by which to inflate estimated demand of small "  \
-          "block sizes to prevent splitting to supply demand for smaller "  \
-          "blocks")                                                         \
-          range(0.0, DBL_MAX)                                               \
-                                                                            \
-  product(double, CMSLargeSplitSurplusPercent, 1.00,                        \
-          "CMS: the factor by which to inflate estimated demand of large "  \
-          "block sizes to prevent splitting to supply demand for smaller "  \
-          "blocks")                                                         \
-          range(0.0, DBL_MAX)                                               \
-                                                                            \
-  product(bool, CMSExtrapolateSweep, false,                                 \
-          "CMS: cushion for block demand during sweep")                     \
-                                                                            \
-  product(uintx, CMS_SweepWeight, 75,                                       \
-          "Percentage (0-100) used to weight the current sample when "      \
-          "computing exponentially decaying average for inter-sweep "       \
-          "duration")                                                       \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, CMS_SweepPadding, 1,                                       \
-          "The multiple of deviation from mean to use for buffering "       \
-          "against volatility in inter-sweep duration")                     \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, CMS_SweepTimerThresholdMillis, 10,                         \
-          "Skip block flux-rate sampling for an epoch unless inter-sweep "  \
-          "duration exceeds this threshold in milliseconds")                \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(bool, CMSClassUnloadingEnabled, true,                             \
-          "Whether class unloading enabled when using CMS GC")              \
-                                                                            \
-  product(uintx, CMSClassUnloadingMaxInterval, 0,                           \
-          "When CMS class unloading is enabled, the maximum CMS cycle "     \
-          "count for which classes may not be unloaded")                    \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(uintx, CMSIndexedFreeListReplenish, 4,                            \
-          "Replenish an indexed free list with this number of chunks")      \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(bool, CMSReplenishIntermediate, true,                             \
-          "Replenish all intermediate free-list caches")                    \
-                                                                            \
-  product(bool, CMSSplitIndexedFreeListBlocks, true,                        \
-          "When satisfying batched demand, split blocks from the "          \
-          "IndexedFreeList whose size is a multiple of requested size")     \
-                                                                            \
-  product(bool, CMSLoopWarn, false,                                         \
-          "Warn in case of excessive CMS looping")                          \
-                                                                            \
-  /* where does the range max value of (max_jint - 1) come from? */         \
-  product(size_t, MarkStackSizeMax, NOT_LP64(4*M) LP64_ONLY(512*M),         \
-          "Maximum size of marking stack")                                  \
-          range(1, (max_jint - 1))                                          \
-                                                                            \
-  product(size_t, MarkStackSize, NOT_LP64(32*K) LP64_ONLY(4*M),             \
-          "Size of marking stack")                                          \
-          constraint(MarkStackSizeConstraintFunc,AfterErgo)                 \
-                                                                            \
-  notproduct(bool, CMSMarkStackOverflowALot, false,                         \
-          "Simulate frequent marking stack / work queue overflow")          \
-                                                                            \
-  notproduct(uintx, CMSMarkStackOverflowInterval, 1000,                     \
-          "An \"interval\" counter that determines how frequently "         \
-          "to simulate overflow; a smaller number increases frequency")     \
-                                                                            \
-  product(uintx, CMSMaxAbortablePrecleanLoops, 0,                           \
-          "Maximum number of abortable preclean iterations, if > 0")        \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(intx, CMSMaxAbortablePrecleanTime, 5000,                          \
-          "Maximum time in abortable preclean (in milliseconds)")           \
-          range(0, max_intx)                                                \
-                                                                            \
-  product(uintx, CMSAbortablePrecleanMinWorkPerIteration, 100,              \
-          "Nominal minimum work per abortable preclean iteration")          \
-          range(0, max_uintx)                                               \
-                                                                            \
-  manageable(intx, CMSAbortablePrecleanWaitMillis, 100,                     \
-          "Time that we sleep between iterations when not given "           \
-          "enough work per iteration")                                      \
-          range(0, max_intx)                                                \
-                                                                            \
-  /* 4096 = CardTable::card_size_in_words * BitsPerWord */                  \
-  product(size_t, CMSRescanMultiple, 32,                                    \
-          "Size (in cards) of CMS parallel rescan task")                    \
-          range(1, SIZE_MAX / 4096)                                         \
-          constraint(CMSRescanMultipleConstraintFunc,AfterMemoryInit)       \
-                                                                            \
-  /* 4096 = CardTable::card_size_in_words * BitsPerWord */                  \
-  product(size_t, CMSConcMarkMultiple, 32,                                  \
-          "Size (in cards) of CMS concurrent MT marking task")              \
-          range(1, SIZE_MAX / 4096)                                         \
-          constraint(CMSConcMarkMultipleConstraintFunc,AfterMemoryInit)     \
-                                                                            \
-  product(bool, CMSAbortSemantics, false,                                   \
-          "Whether abort-on-overflow semantics is implemented")             \
-                                                                            \
-  product(bool, CMSParallelInitialMarkEnabled, true,                        \
-          "Use the parallel initial mark.")                                 \
-                                                                            \
-  product(bool, CMSParallelRemarkEnabled, true,                             \
-          "Whether parallel remark enabled (only if ParNewGC)")             \
-                                                                            \
-  product(bool, CMSParallelSurvivorRemarkEnabled, true,                     \
-          "Whether parallel remark of survivor space "                      \
-          "enabled (effective only if CMSParallelRemarkEnabled)")           \
-                                                                            \
-  product(bool, CMSPLABRecordAlways, true,                                  \
-          "Always record survivor space PLAB boundaries (effective only "   \
-          "if CMSParallelSurvivorRemarkEnabled)")                           \
-                                                                            \
-  product(bool, CMSEdenChunksRecordAlways, true,                            \
-          "Always record eden chunks used for the parallel initial mark "   \
-          "or remark of eden")                                              \
-                                                                            \
-  product(bool, CMSConcurrentMTEnabled, true,                               \
-          "Whether multi-threaded concurrent work enabled "                 \
-          "(effective only if ParNewGC)")                                   \
-                                                                            \
-  product(bool, CMSPrecleaningEnabled, true,                                \
-          "Whether concurrent precleaning enabled")                         \
-                                                                            \
-  product(uintx, CMSPrecleanIter, 3,                                        \
-          "Maximum number of precleaning iteration passes")                 \
-          range(0, 9)                                                       \
-                                                                            \
-  product(uintx, CMSPrecleanDenominator, 3,                                 \
-          "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
-          "ratio")                                                          \
-          range(1, max_uintx)                                               \
-          constraint(CMSPrecleanDenominatorConstraintFunc,AfterErgo)        \
-                                                                            \
-  product(uintx, CMSPrecleanNumerator, 2,                                   \
-          "CMSPrecleanNumerator:CMSPrecleanDenominator yields convergence " \
-          "ratio")                                                          \
-          range(0, max_uintx-1)                                             \
-          constraint(CMSPrecleanNumeratorConstraintFunc,AfterErgo)          \
-                                                                            \
-  product(bool, CMSPrecleanRefLists1, true,                                 \
-          "Preclean ref lists during (initial) preclean phase")             \
-                                                                            \
-  product(bool, CMSPrecleanRefLists2, false,                                \
-          "Preclean ref lists during abortable preclean phase")             \
-                                                                            \
-  product(bool, CMSPrecleanSurvivors1, false,                               \
-          "Preclean survivors during (initial) preclean phase")             \
-                                                                            \
-  product(bool, CMSPrecleanSurvivors2, true,                                \
-          "Preclean survivors during abortable preclean phase")             \
-                                                                            \
-  product(uintx, CMSPrecleanThreshold, 1000,                                \
-          "Do not iterate again if number of dirty cards is less than this")\
-          range(100, max_uintx)                                             \
-                                                                            \
-  product(bool, CMSCleanOnEnter, true,                                      \
-          "Clean-on-enter optimization for reducing number of dirty cards") \
-                                                                            \
-  product(uintx, CMSRemarkVerifyVariant, 1,                                 \
-          "Choose variant (1,2) of verification following remark")          \
-          range(1, 2)                                                       \
-                                                                            \
-  product(size_t, CMSScheduleRemarkEdenSizeThreshold, 2*M,                  \
-          "If Eden size is below this, do not try to schedule remark")      \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(uintx, CMSScheduleRemarkEdenPenetration, 50,                      \
-          "The Eden occupancy percentage (0-100) at which "                 \
-          "to try and schedule remark pause")                               \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, CMSScheduleRemarkSamplingRatio, 5,                         \
-          "Start sampling eden top at least before young gen "              \
-          "occupancy reaches 1/<ratio> of the size at which "               \
-          "we plan to schedule remark")                                     \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, CMSSamplingGrain, 16*K,                                    \
-          "The minimum distance between eden samples for CMS (see above)")  \
-          range(ObjectAlignmentInBytes, max_uintx)                          \
-          constraint(CMSSamplingGrainConstraintFunc,AfterMemoryInit)        \
-                                                                            \
-  product(bool, CMSScavengeBeforeRemark, false,                             \
-          "Attempt scavenge before the CMS remark step")                    \
-                                                                            \
-  product(uintx, CMSWorkQueueDrainThreshold, 10,                            \
-          "Don't drain below this size per parallel worker/thief")          \
-          range(1, max_juint)                                               \
-          constraint(CMSWorkQueueDrainThresholdConstraintFunc,AfterErgo)    \
-                                                                            \
-  manageable(intx, CMSWaitDuration, 2000,                                   \
-          "Time in milliseconds that CMS thread waits for young GC")        \
-          range(min_jint, max_jint)                                         \
-                                                                            \
-  develop(uintx, CMSCheckInterval, 1000,                                    \
-          "Interval in milliseconds that CMS thread checks if it "          \
-          "should start a collection cycle")                                \
-                                                                            \
-  product(bool, CMSYield, true,                                             \
-          "Yield between steps of CMS")                                     \
-                                                                            \
-  product(size_t, CMSBitMapYieldQuantum, 10*M,                              \
-          "Bitmap operations should process at most this many bits "        \
-          "between yields")                                                 \
-          range(1, max_uintx)                                               \
-          constraint(CMSBitMapYieldQuantumConstraintFunc,AfterMemoryInit)   \
-                                                                            \
-  product(bool, CMSPrintChunksInDump, false,                                \
-          "If logging for the \"gc\" and \"promotion\" tags is enabled on"  \
-          "trace level include more detailed information about the"         \
-          "free chunks")                \
-                                                                            \
-  product(bool, CMSPrintObjectsInDump, false,                               \
-          "If logging for the \"gc\" and \"promotion\" tags is enabled on"  \
-          "trace level include more detailed information about the"         \
-          "allocated objects")                                              \
-                                                                            \
-  diagnostic(bool, FLSVerifyAllHeapReferences, false,                       \
-          "Verify that all references across the FLS boundary "             \
-          "are to valid objects")                                           \
-                                                                            \
-  diagnostic(bool, FLSVerifyLists, false,                                   \
-          "Do lots of (expensive) FreeListSpace verification")              \
-                                                                            \
-  diagnostic(bool, FLSVerifyIndexTable, false,                              \
-          "Do lots of (expensive) FLS index table verification")            \
-                                                                            \
   develop(bool, FLSVerifyDictionary, false,                                 \
           "Do lots of (expensive) FLS dictionary verification")             \
                                                                             \
-  develop(bool, VerifyBlockOffsetArray, false,                              \
-          "Do (expensive) block offset array verification")                 \
-                                                                            \
-  diagnostic(bool, BlockOffsetArrayUseUnallocatedBlock, false,              \
-          "Maintain _unallocated_block in BlockOffsetArray "                \
-          "(currently applicable only to CMS collector)")                   \
-                                                                            \
-  product(intx, RefDiscoveryPolicy, 0,                                      \
-          "Select type of reference discovery policy: "                     \
-          "reference-based(0) or referent-based(1)")                        \
-          range(ReferenceProcessor::DiscoveryPolicyMin,                     \
-                ReferenceProcessor::DiscoveryPolicyMax)                     \
-                                                                            \
-  product(bool, ParallelRefProcEnabled, false,                              \
-          "Enable parallel reference processing whenever possible")         \
-                                                                            \
-  product(bool, ParallelRefProcBalancingEnabled, true,                      \
-          "Enable balancing of reference processing queues")                \
-                                                                            \
-  product(uintx, CMSTriggerRatio, 80,                                       \
-          "Percentage of MinHeapFreeRatio in CMS generation that is "       \
-          "allocated before a CMS collection cycle commences")              \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, CMSBootstrapOccupancy, 50,                                 \
-          "Percentage CMS generation occupancy at which to "                \
-          "initiate CMS collection for bootstrapping collection stats")     \
-          range(0, 100)                                                     \
-                                                                            \
-  product(intx, CMSInitiatingOccupancyFraction, -1,                         \
-          "Percentage CMS generation occupancy to start a CMS collection "  \
-          "cycle. A negative value means that CMSTriggerRatio is used")     \
-          range(min_intx, 100)                                              \
-                                                                            \
-  product(uintx, InitiatingHeapOccupancyPercent, 45,                        \
-          "The percent occupancy (IHOP) of the current old generation "     \
-          "capacity above which a concurrent mark cycle will be initiated " \
-          "Its value may change over time if adaptive IHOP is enabled, "    \
-          "otherwise the value remains constant. "                          \
-          "In the latter case a value of 0 will result as frequent as "     \
-          "possible concurrent marking cycles. A value of 100 disables "    \
-          "concurrent marking. "                                            \
-          "Fragmentation waste in the old generation is not considered "    \
-          "free space in this calculation. (G1 collector only)")            \
-          range(0, 100)                                                     \
-                                                                            \
-  manageable(intx, CMSTriggerInterval, -1,                                  \
-          "Commence a CMS collection cycle (at least) every so many "       \
-          "milliseconds (0 permanently, -1 disabled)")                      \
-          range(-1, max_intx)                                               \
-                                                                            \
-  product(bool, UseCMSInitiatingOccupancyOnly, false,                       \
-          "Only use occupancy as a criterion for starting a CMS collection")\
-                                                                            \
-  product(uintx, CMSIsTooFullPercentage, 98,                                \
-          "An absolute ceiling above which CMS will always consider the "   \
-          "unloading of classes when class unloading is enabled")           \
-          range(0, 100)                                                     \
-                                                                            \
-  develop(bool, CMSTestInFreeList, false,                                   \
-          "Check if the coalesced range is already in the "                 \
-          "free lists as claimed")                                          \
-                                                                            \
-  notproduct(bool, CMSVerifyReturnedBytes, false,                           \
-          "Check that all the garbage collected was returned to the "       \
-          "free lists")                                                     \
-                                                                            \
-  notproduct(bool, ScavengeALot, false,                                     \
-          "Force scavenge at every Nth exit from the runtime system "       \
-          "(N=ScavengeALotInterval)")                                       \
-                                                                            \
-  develop(bool, FullGCALot, false,                                          \
-          "Force full gc at every Nth exit from the runtime system "        \
-          "(N=FullGCALotInterval)")                                         \
-                                                                            \
-  notproduct(bool, GCALotAtAllSafepoints, false,                            \
-          "Enforce ScavengeALot/GCALot at all potential safepoints")        \
-                                                                            \
-  notproduct(bool, PromotionFailureALot, false,                             \
-          "Use promotion failure handling on every youngest generation "    \
-          "collection")                                                     \
-                                                                            \
-  develop(uintx, PromotionFailureALotCount, 1000,                           \
-          "Number of promotion failures occurring at PLAB "                 \
-          "refill attempts (ParNew) or promotion attempts "                 \
-          "(other young collectors)")                                       \
-                                                                            \
-  develop(uintx, PromotionFailureALotInterval, 5,                           \
-          "Total collections between promotion failures a lot")             \
-                                                                            \
-  experimental(uintx, WorkStealingSleepMillis, 1,                           \
-          "Sleep time when sleep is used for yields")                       \
-                                                                            \
-  experimental(uintx, WorkStealingYieldsBeforeSleep, 5000,                  \
-          "Number of yields before a sleep is done during work stealing")   \
-                                                                            \
-  experimental(uintx, WorkStealingHardSpins, 4096,                          \
-          "Number of iterations in a spin loop between checks on "          \
-          "time out of hard spin")                                          \
-                                                                            \
-  experimental(uintx, WorkStealingSpinToYieldRatio, 10,                     \
-          "Ratio of hard spins to calls to yield")                          \
-                                                                            \
-  develop(uintx, ObjArrayMarkingStride, 2048,                               \
-          "Number of object array elements to push onto the marking stack " \
-          "before pushing a continuation entry")                            \
-                                                                            \
-  develop(bool, MetadataAllocationFailALot, false,                          \
-          "Fail metadata allocations at intervals controlled by "           \
-          "MetadataAllocationFailALotInterval")                             \
-                                                                            \
-  develop(uintx, MetadataAllocationFailALotInterval, 1000,                  \
-          "Metadata allocation failure a lot interval")                     \
-                                                                            \
-  notproduct(bool, ExecuteInternalVMTests, false,                           \
-          "Enable execution of internal VM tests")                          \
-                                                                            \
-  notproduct(bool, VerboseInternalVMTests, false,                           \
-          "Turn on logging for internal VM tests.")                         \
-                                                                            \
-  product(bool, ExecutingUnitTests, false,                                  \
-          "Whether the JVM is running unit tests or not")                   \
-                                                                            \
-  product_pd(bool, UseTLAB, "Use thread-local object allocation")           \
-                                                                            \
-  product_pd(bool, ResizeTLAB,                                              \
-          "Dynamically resize TLAB size for threads")                       \
-                                                                            \
-  product(bool, ZeroTLAB, false,                                            \
-          "Zero out the newly created TLAB")                                \
-                                                                            \
-  product(bool, TLABStats, true,                                            \
-          "Provide more detailed and expensive TLAB statistics.")           \
-                                                                            \
-  product_pd(bool, NeverActAsServerClassMachine,                            \
-          "Never act like a server-class machine")                          \
-                                                                            \
-  product(bool, AlwaysActAsServerClassMachine, false,                       \
-          "Always act like a server-class machine")                         \
-                                                                            \
-  product_pd(uint64_t, MaxRAM,                                              \
-          "Real memory size (in bytes) used to set maximum heap size")      \
-          range(0, 0XFFFFFFFFFFFFFFFF)                                      \
-                                                                            \
-  product(bool, AggressiveHeap, false,                                      \
-          "Optimize heap options for long-running memory intensive apps")   \
-                                                                            \
-  product(size_t, ErgoHeapSizeLimit, 0,                                     \
-          "Maximum ergonomically set heap size (in bytes); zero means use " \
-          "MaxRAM * MaxRAMPercentage / 100")                                \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(uintx, MaxRAMFraction, 4,                                         \
-          "Maximum fraction (1/n) of real memory used for maximum heap "    \
-          "size. "                                                          \
-          "Deprecated, use MaxRAMPercentage instead")                       \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, MinRAMFraction, 2,                                         \
-          "Minimum fraction (1/n) of real memory used for maximum heap "    \
-          "size on systems with small physical memory size. "               \
-          "Deprecated, use MinRAMPercentage instead")                       \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, InitialRAMFraction, 64,                                    \
-          "Fraction (1/n) of real memory used for initial heap size. "      \
-          "Deprecated, use InitialRAMPercentage instead")                   \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(double, MaxRAMPercentage, 25.0,                                   \
-          "Maximum percentage of real memory used for maximum heap size")   \
-          range(0.0, 100.0)                                                 \
-                                                                            \
-  product(double, MinRAMPercentage, 50.0,                                   \
-          "Minimum percentage of real memory used for maximum heap"         \
-          "size on systems with small physical memory size")                \
-          range(0.0, 100.0)                                                 \
-                                                                            \
-  product(double, InitialRAMPercentage, 1.5625,                             \
-          "Percentage of real memory used for initial heap size")           \
-          range(0.0, 100.0)                                                 \
-                                                                            \
-  product(int, ActiveProcessorCount, -1,                                    \
-          "Specify the CPU count the VM should use and report as active")   \
-                                                                            \
-  develop(uintx, MaxVirtMemFraction, 2,                                     \
-          "Maximum fraction (1/n) of virtual memory used for ergonomically "\
-          "determining maximum heap size")                                  \
-                                                                            \
-  product(bool, UseAdaptiveSizePolicy, true,                                \
-          "Use adaptive generation sizing policies")                        \
-                                                                            \
-  product(bool, UsePSAdaptiveSurvivorSizePolicy, true,                      \
-          "Use adaptive survivor sizing policies")                          \
-                                                                            \
-  product(bool, UseAdaptiveGenerationSizePolicyAtMinorCollection, true,     \
-          "Use adaptive young-old sizing policies at minor collections")    \
-                                                                            \
-  product(bool, UseAdaptiveGenerationSizePolicyAtMajorCollection, true,     \
-          "Use adaptive young-old sizing policies at major collections")    \
-                                                                            \
-  product(bool, UseAdaptiveSizePolicyWithSystemGC, false,                   \
-          "Include statistics from System.gc() for adaptive size policy")   \
-                                                                            \
-  product(bool, UseAdaptiveGCBoundary, false,                               \
-          "Allow young-old boundary to move")                               \
-                                                                            \
-  develop(intx, PSAdaptiveSizePolicyResizeVirtualSpaceAlot, -1,             \
-          "Resize the virtual spaces of the young or old generations")      \
-          range(-1, 1)                                                      \
-                                                                            \
-  product(uintx, AdaptiveSizeThroughPutPolicy, 0,                           \
-          "Policy for changing generation size for throughput goals")       \
-          range(0, 1)                                                       \
-                                                                            \
-  product(uintx, AdaptiveSizePolicyInitializingSteps, 20,                   \
-          "Number of steps where heuristics is used before data is used")   \
-          range(0, max_uintx)                                               \
-                                                                            \
-  develop(uintx, AdaptiveSizePolicyReadyThreshold, 5,                       \
-          "Number of collections before the adaptive sizing is started")    \
-                                                                            \
-  product(uintx, AdaptiveSizePolicyOutputInterval, 0,                       \
-          "Collection interval for printing information; zero means never") \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(bool, UseAdaptiveSizePolicyFootprintGoal, true,                   \
-          "Use adaptive minimum footprint as a goal")                       \
-                                                                            \
-  product(uintx, AdaptiveSizePolicyWeight, 10,                              \
-          "Weight given to exponential resizing, between 0 and 100")        \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, AdaptiveTimeWeight,       25,                              \
-          "Weight given to time in adaptive policy, between 0 and 100")     \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, PausePadding, 1,                                           \
-          "How much buffer to keep for pause time")                         \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, PromotedPadding, 3,                                        \
-          "How much buffer to keep for promotion failure")                  \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, SurvivorPadding, 3,                                        \
-          "How much buffer to keep for survivor overflow")                  \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, ThresholdTolerance, 10,                                    \
-          "Allowed collection cost difference between generations")         \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, AdaptiveSizePolicyCollectionCostMargin, 50,                \
-          "If collection costs are within margin, reduce both by full "     \
-          "delta")                                                          \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, YoungGenerationSizeIncrement, 20,                          \
-          "Adaptive size percentage change in young generation")            \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, YoungGenerationSizeSupplement, 80,                         \
-          "Supplement to YoungedGenerationSizeIncrement used at startup")   \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, YoungGenerationSizeSupplementDecay, 8,                     \
-          "Decay factor to YoungedGenerationSizeSupplement")                \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, TenuredGenerationSizeIncrement, 20,                        \
-          "Adaptive size percentage change in tenured generation")          \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, TenuredGenerationSizeSupplement, 80,                       \
-          "Supplement to TenuredGenerationSizeIncrement used at startup")   \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, TenuredGenerationSizeSupplementDecay, 2,                   \
-          "Decay factor to TenuredGenerationSizeIncrement")                 \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(uintx, MaxGCPauseMillis, max_uintx - 1,                           \
-          "Adaptive size policy maximum GC pause time goal in millisecond, "\
-          "or (G1 Only) the maximum GC time per MMU time slice")            \
-          range(1, max_uintx - 1)                                           \
-          constraint(MaxGCPauseMillisConstraintFunc,AfterErgo)              \
-                                                                            \
-  product(uintx, GCPauseIntervalMillis, 0,                                  \
-          "Time slice for MMU specification")                               \
-          constraint(GCPauseIntervalMillisConstraintFunc,AfterErgo)         \
-                                                                            \
-  product(uintx, MaxGCMinorPauseMillis, max_uintx,                          \
-          "Adaptive size policy maximum GC minor pause time goal "          \
-          "in millisecond")                                                 \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(uintx, GCTimeRatio, 99,                                           \
-          "Adaptive size policy application time to GC time ratio")         \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, AdaptiveSizeDecrementScaleFactor, 4,                       \
-          "Adaptive size scale down factor for shrinking")                  \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(bool, UseAdaptiveSizeDecayMajorGCCost, true,                      \
-          "Adaptive size decays the major cost for long major intervals")   \
-                                                                            \
-  product(uintx, AdaptiveSizeMajorGCDecayTimeScale, 10,                     \
-          "Time scale over which major costs decay")                        \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(uintx, MinSurvivorRatio, 3,                                       \
-          "Minimum ratio of young generation/survivor space size")          \
-          range(3, max_uintx)                                               \
-                                                                            \
-  product(uintx, InitialSurvivorRatio, 8,                                   \
-          "Initial ratio of young generation/survivor space size")          \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(size_t, BaseFootPrintEstimate, 256*M,                             \
-          "Estimate of footprint other than Java Heap")                     \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(bool, UseGCOverheadLimit, true,                                   \
-          "Use policy to limit of proportion of time spent in GC "          \
-          "before an OutOfMemory error is thrown")                          \
-                                                                            \
-  product(uintx, GCTimeLimit, 98,                                           \
-          "Limit of the proportion of time spent in GC before "             \
-          "an OutOfMemoryError is thrown (used with GCHeapFreeLimit)")      \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, GCHeapFreeLimit, 2,                                        \
-          "Minimum percentage of free space after a full GC before an "     \
-          "OutOfMemoryError is thrown (used with GCTimeLimit)")             \
-          range(0, 100)                                                     \
-                                                                            \
-  develop(uintx, AdaptiveSizePolicyGCTimeLimitThreshold, 5,                 \
-          "Number of consecutive collections before gc time limit fires")   \
-          range(1, max_uintx)                                               \
-                                                                            \
-  product(intx, PrefetchCopyIntervalInBytes, -1,                            \
-          "How far ahead to prefetch destination area (<= 0 means off)")    \
-          range(-1, max_jint)                                               \
-                                                                            \
-  product(intx, PrefetchScanIntervalInBytes, -1,                            \
-          "How far ahead to prefetch scan area (<= 0 means off)")           \
-          range(-1, max_jint)                                               \
-                                                                            \
-  product(intx, PrefetchFieldsAhead, -1,                                    \
-          "How many fields ahead to prefetch in oop scan (<= 0 means off)") \
-          range(-1, max_jint)                                               \
-                                                                            \
-  diagnostic(bool, VerifyDuringStartup, false,                              \
-          "Verify memory system before executing any Java code "            \
-          "during VM initialization")                                       \
-                                                                            \
-  diagnostic(bool, VerifyBeforeExit, trueInDebug,                           \
-          "Verify system before exiting")                                   \
-                                                                            \
-  diagnostic(bool, VerifyBeforeGC, false,                                   \
-          "Verify memory system before GC")                                 \
-                                                                            \
-  diagnostic(bool, VerifyAfterGC, false,                                    \
-          "Verify memory system after GC")                                  \
-                                                                            \
-  diagnostic(bool, VerifyDuringGC, false,                                   \
-          "Verify memory system during GC (between phases)")                \
-                                                                            \
-  diagnostic(ccstrlist, VerifyGCType, "",                                   \
-             "GC type(s) to verify when Verify*GC is enabled."              \
-             "Available types are collector specific.")                     \
-                                                                            \
-  diagnostic(ccstrlist, VerifySubSet, "",                                   \
-          "Memory sub-systems to verify when Verify*GC flag(s) "            \
-          "are enabled. One or more sub-systems can be specified "          \
-          "in a comma separated string. Sub-systems are: "                  \
-          "threads, heap, symbol_table, string_table, codecache, "          \
-          "dictionary, classloader_data_graph, metaspace, jni_handles, "    \
-          "codecache_oops")                                                 \
-                                                                            \
-  diagnostic(bool, GCParallelVerificationEnabled, true,                     \
-          "Enable parallel memory system verification")                     \
-                                                                            \
-  diagnostic(bool, DeferInitialCardMark, false,                             \
-          "When +ReduceInitialCardMarks, explicitly defer any that "        \
-          "may arise from new_pre_store_barrier")                           \
-                                                                            \
-  product(bool, UseCondCardMark, false,                                     \
-          "Check for already marked card before updating card table")       \
-                                                                            \
-  diagnostic(bool, VerifyRememberedSets, false,                             \
-          "Verify GC remembered sets")                                      \
-                                                                            \
-  diagnostic(bool, VerifyObjectStartArray, true,                            \
-          "Verify GC object start array if verify before/after")            \
-                                                                            \
-  product(bool, DisableExplicitGC, false,                                   \
-          "Ignore calls to System.gc()")                                    \
                                                                             \
   notproduct(bool, CheckMemoryInitialization, false,                        \
           "Check memory initialization")                                    \
                                                                             \
-  diagnostic(bool, BindCMSThreadToCPU, false,                               \
-          "Bind CMS Thread to CPU if possible")                             \
-                                                                            \
-  diagnostic(uintx, CPUForCMSThread, 0,                                     \
-          "When BindCMSThreadToCPU is true, the CPU to bind CMS thread to") \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(bool, BindGCTaskThreadsToCPUs, false,                             \
-          "Bind GCTaskThreads to CPUs if possible")                         \
-                                                                            \
-  product(bool, UseGCTaskAffinity, false,                                   \
-          "Use worker affinity when asking for GCTasks")                    \
-                                                                            \
   product(uintx, ProcessDistributionStride, 4,                              \
           "Stride through processors when distributing processes")          \
           range(0, max_juint)                                               \
                                                                             \
-  product(uintx, CMSCoordinatorYieldSleepCount, 10,                         \
-          "Number of times the coordinator GC thread will sleep while "     \
-          "yielding before giving up and resuming GC")                      \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(uintx, CMSYieldSleepCount, 0,                                     \
-          "Number of times a GC thread (minus the coordinator) "            \
-          "will sleep while yielding before giving up and resuming GC")     \
-          range(0, max_juint)                                               \
-                                                                            \
-  product(bool, PrintGC, false,                                             \
-          "Print message at garbage collection. "                           \
-          "Deprecated, use -Xlog:gc instead.")                              \
-                                                                            \
-  product(bool, PrintGCDetails, false,                                      \
-          "Print more details at garbage collection. "                      \
-          "Deprecated, use -Xlog:gc* instead.")                             \
-                                                                            \
-  develop(intx, ConcGCYieldTimeout, 0,                                      \
-          "If non-zero, assert that GC threads yield within this "          \
-          "number of milliseconds")                                         \
-          range(0, max_intx)                                                \
-                                                                            \
   develop(bool, TraceFinalizerRegistration, false,                          \
           "Trace registration of final references")                         \
                                                                             \
@@ -2336,18 +1418,6 @@
   manageable(bool, PrintClassHistogram, false,                              \
           "Print a histogram of class instances")                           \
                                                                             \
-  develop(bool, TraceGCTaskManager, false,                                  \
-          "Trace actions of the GC task manager")                           \
-                                                                            \
-  develop(bool, TraceGCTaskQueue, false,                                    \
-          "Trace actions of the GC task queues")                            \
-                                                                            \
-  develop(bool, TraceParallelOldGCMarkingPhase, false,                      \
-          "Trace marking phase in ParallelOldGC")                           \
-                                                                            \
-  develop(bool, TraceParallelOldGCDensePrefix, false,                       \
-          "Trace dense prefix computation for ParallelOldGC")               \
-                                                                            \
   develop(bool, IgnoreLibthreadGPFault, false,                              \
           "Suppress workaround for libthread GP fault")                     \
                                                                             \
@@ -2982,19 +2052,6 @@
           "(+ProfileIntervals)")                                            \
           range(0, max_intx)                                                \
                                                                             \
-  notproduct(intx, ScavengeALotInterval,     1,                             \
-          "Interval between which scavenge will occur with +ScavengeALot")  \
-                                                                            \
-  notproduct(intx, FullGCALotInterval,     1,                               \
-          "Interval between which full gc will occur with +FullGCALot")     \
-                                                                            \
-  notproduct(intx, FullGCALotStart,     0,                                  \
-          "For which invocation to start FullGCAlot")                       \
-                                                                            \
-  notproduct(intx, FullGCALotDummies,  32*K,                                \
-          "Dummy object allocated with +FullGCALot, forcing all objects "   \
-          "to move")                                                        \
-                                                                            \
   develop(intx, DontYieldALotInterval,    10,                               \
           "Interval between which yields will be dropped (milliseconds)")   \
                                                                             \
@@ -3064,88 +2121,6 @@
           "Size in K to allocate for the Profile Nodes of each thread")     \
           range(0, 1024)                                                    \
                                                                             \
-  /* gc parameters */                                                       \
-  product(size_t, InitialHeapSize, 0,                                       \
-          "Initial heap size (in bytes); zero means use ergonomics")        \
-          constraint(InitialHeapSizeConstraintFunc,AfterErgo)               \
-                                                                            \
-  product(size_t, MaxHeapSize, ScaleForWordSize(96*M),                      \
-          "Maximum heap size (in bytes)")                                   \
-          constraint(MaxHeapSizeConstraintFunc,AfterErgo)                   \
-                                                                            \
-  product(size_t, OldSize, ScaleForWordSize(4*M),                           \
-          "Initial tenured generation size (in bytes)")                     \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(size_t, NewSize, ScaleForWordSize(1*M),                           \
-          "Initial new generation size (in bytes)")                         \
-          constraint(NewSizeConstraintFunc,AfterErgo)                       \
-                                                                            \
-  product(size_t, MaxNewSize, max_uintx,                                    \
-          "Maximum new generation size (in bytes), max_uintx means set "    \
-          "ergonomically")                                                  \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product_pd(size_t, HeapBaseMinAddress,                                    \
-          "OS specific low limit for heap base address")                    \
-          constraint(HeapBaseMinAddressConstraintFunc,AfterErgo)            \
-                                                                            \
-  product(size_t, PretenureSizeThreshold, 0,                                \
-          "Maximum size in bytes of objects allocated in DefNew "           \
-          "generation; zero means no maximum")                              \
-          range(0, max_uintx)                                               \
-                                                                            \
-  product(size_t, MinTLABSize, 2*K,                                         \
-          "Minimum allowed TLAB size (in bytes)")                           \
-          range(1, max_uintx/2)                                             \
-          constraint(MinTLABSizeConstraintFunc,AfterMemoryInit)             \
-                                                                            \
-  product(size_t, TLABSize, 0,                                              \
-          "Starting TLAB size (in bytes); zero means set ergonomically")    \
-          constraint(TLABSizeConstraintFunc,AfterMemoryInit)                \
-                                                                            \
-  product(size_t, YoungPLABSize, 4096,                                      \
-          "Size of young gen promotion LAB's (in HeapWords)")               \
-          constraint(YoungPLABSizeConstraintFunc,AfterMemoryInit)           \
-                                                                            \
-  product(size_t, OldPLABSize, 1024,                                        \
-          "Size of old gen promotion LAB's (in HeapWords), or Number "      \
-          "of blocks to attempt to claim when refilling CMS LAB's")         \
-          constraint(OldPLABSizeConstraintFunc,AfterMemoryInit)             \
-                                                                            \
-  product(uintx, TLABAllocationWeight, 35,                                  \
-          "Allocation averaging weight")                                    \
-          range(0, 100)                                                     \
-                                                                            \
-  /* Limit the lower bound of this flag to 1 as it is used  */              \
-  /* in a division expression.                              */              \
-  product(uintx, TLABWasteTargetPercent, 1,                                 \
-          "Percentage of Eden that can be wasted")                          \
-          range(1, 100)                                                     \
-                                                                            \
-  product(uintx, TLABRefillWasteFraction,    64,                            \
-          "Maximum TLAB waste at a refill (internal fragmentation)")        \
-          range(1, max_juint)                                               \
-                                                                            \
-  product(uintx, TLABWasteIncrement,    4,                                  \
-          "Increment allowed waste at slow allocation")                     \
-          range(0, max_jint)                                                \
-          constraint(TLABWasteIncrementConstraintFunc,AfterMemoryInit)      \
-                                                                            \
-  product(uintx, SurvivorRatio, 8,                                          \
-          "Ratio of eden/survivor space size")                              \
-          range(1, max_uintx-2)                                             \
-          constraint(SurvivorRatioConstraintFunc,AfterMemoryInit)           \
-                                                                            \
-  product(uintx, NewRatio, 2,                                               \
-          "Ratio of old/new generation sizes")                              \
-          range(0, max_uintx-1)                                             \
-                                                                            \
-  product_pd(size_t, NewSizeThreadIncrease,                                 \
-          "Additional size added to desired new generation size per "       \
-          "non-daemon thread (in bytes)")                                   \
-          range(0, max_uintx)                                               \
-                                                                            \
   product_pd(size_t, MetaspaceSize,                                         \
           "Initial threshold (in bytes) at which a garbage collection "     \
           "is done to reduce Metaspace usage")                              \
@@ -3208,63 +2183,6 @@
           "The maximum expansion of Metaspace without full GC (in bytes)")  \
           range(0, max_uintx)                                               \
                                                                             \
-  product(uintx, QueuedAllocationWarningCount, 0,                           \
-          "Number of times an allocation that queues behind a GC "          \
-          "will retry before printing a warning")                           \
-          range(0, max_uintx)                                               \
-                                                                            \
-  diagnostic(uintx, VerifyGCStartAt,   0,                                   \
-          "GC invoke count where +VerifyBefore/AfterGC kicks in")           \
-          range(0, max_uintx)                                               \
-                                                                            \
-  diagnostic(intx, VerifyGCLevel,     0,                                    \
-          "Generation level at which to start +VerifyBefore/AfterGC")       \
-          range(0, 1)                                                       \
-                                                                            \
-  product(uintx, MaxTenuringThreshold,    15,                               \
-          "Maximum value for tenuring threshold")                           \
-          range(0, markOopDesc::max_age + 1)                                \
-          constraint(MaxTenuringThresholdConstraintFunc,AfterErgo)          \
-                                                                            \
-  product(uintx, InitialTenuringThreshold,    7,                            \
-          "Initial value for tenuring threshold")                           \
-          range(0, markOopDesc::max_age + 1)                                \
-          constraint(InitialTenuringThresholdConstraintFunc,AfterErgo)      \
-                                                                            \
-  product(uintx, TargetSurvivorRatio,    50,                                \
-          "Desired percentage of survivor space used after scavenge")       \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uintx, MarkSweepDeadRatio,     5,                                 \
-          "Percentage (0-100) of the old gen allowed as dead wood. "        \
-          "Serial mark sweep treats this as both the minimum and maximum "  \
-          "value. "                                                         \
-          "CMS uses this value only if it falls back to mark sweep. "       \
-          "Par compact uses a variable scale based on the density of the "  \
-          "generation and treats this as the maximum value when the heap "  \
-          "is either completely full or completely empty.  Par compact "    \
-          "also has a smaller default value; see arguments.cpp.")           \
-          range(0, 100)                                                     \
-                                                                            \
-  product(uint, MarkSweepAlwaysCompactCount,     4,                         \
-          "How often should we fully compact the heap (ignoring the dead "  \
-          "space parameters)")                                              \
-          range(1, max_juint)                                               \
-                                                                            \
-  develop(uintx, GCExpandToAllocateDelayMillis, 0,                          \
-          "Delay between expansion and allocation (in milliseconds)")       \
-                                                                            \
-  develop(uintx, GCWorkerDelayMillis, 0,                                    \
-          "Delay in scheduling GC workers (in milliseconds)")               \
-                                                                            \
-  product(bool, PSChunkLargeArrays, true,                                   \
-          "Process large arrays in chunks")                                 \
-                                                                            \
-  product(uintx, GCDrainStackTargetSize, 64,                                \
-          "Number of entries we will try to leave on the stack "            \
-          "during parallel gc")                                             \
-          range(0, max_juint)                                               \
-                                                                            \
   /* stack parameters */                                                    \
   product_pd(intx, StackYellowPages,                                        \
           "Number of yellow zone (recoverable overflows) pages of size "    \
@@ -4066,7 +2984,52 @@
           "On internal errors, include registers in error report.")         \
                                                                             \
 
-
+#define VM_FLAGS(develop,                                                   \
+                 develop_pd,                                                \
+                 product,                                                   \
+                 product_pd,                                                \
+                 diagnostic,                                                \
+                 diagnostic_pd,                                             \
+                 experimental,                                              \
+                 notproduct,                                                \
+                 manageable,                                                \
+                 product_rw,                                                \
+                 lp64_product,                                              \
+                 range,                                                     \
+                 constraint,                                                \
+                 writeable)                                                 \
+                                                                            \
+  RUNTIME_FLAGS(                                                            \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable)                                                              \
+                                                                            \
+  GC_FLAGS(                                                                 \
+    develop,                                                                \
+    develop_pd,                                                             \
+    product,                                                                \
+    product_pd,                                                             \
+    diagnostic,                                                             \
+    diagnostic_pd,                                                          \
+    experimental,                                                           \
+    notproduct,                                                             \
+    manageable,                                                             \
+    product_rw,                                                             \
+    lp64_product,                                                           \
+    range,                                                                  \
+    constraint,                                                             \
+    writeable)                                                              \
 
 /*
  *  Macros for factoring of globals
@@ -4126,20 +3089,20 @@
 
 #define IGNORE_WRITEABLE(type)
 
-RUNTIME_FLAGS(DECLARE_DEVELOPER_FLAG, \
-              DECLARE_PD_DEVELOPER_FLAG, \
-              DECLARE_PRODUCT_FLAG, \
-              DECLARE_PD_PRODUCT_FLAG, \
-              DECLARE_DIAGNOSTIC_FLAG, \
-              DECLARE_PD_DIAGNOSTIC_FLAG, \
-              DECLARE_EXPERIMENTAL_FLAG, \
-              DECLARE_NOTPRODUCT_FLAG, \
-              DECLARE_MANAGEABLE_FLAG, \
-              DECLARE_PRODUCT_RW_FLAG, \
-              DECLARE_LP64_PRODUCT_FLAG, \
-              IGNORE_RANGE, \
-              IGNORE_CONSTRAINT, \
-              IGNORE_WRITEABLE)
+VM_FLAGS(DECLARE_DEVELOPER_FLAG, \
+         DECLARE_PD_DEVELOPER_FLAG, \
+         DECLARE_PRODUCT_FLAG, \
+         DECLARE_PD_PRODUCT_FLAG, \
+         DECLARE_DIAGNOSTIC_FLAG, \
+         DECLARE_PD_DIAGNOSTIC_FLAG, \
+         DECLARE_EXPERIMENTAL_FLAG, \
+         DECLARE_NOTPRODUCT_FLAG, \
+         DECLARE_MANAGEABLE_FLAG, \
+         DECLARE_PRODUCT_RW_FLAG, \
+         DECLARE_LP64_PRODUCT_FLAG, \
+         IGNORE_RANGE, \
+         IGNORE_CONSTRAINT, \
+         IGNORE_WRITEABLE)
 
 RUNTIME_OS_FLAGS(DECLARE_DEVELOPER_FLAG, \
                  DECLARE_PD_DEVELOPER_FLAG, \
--- a/src/hotspot/share/runtime/globals_extension.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/globals_extension.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,9 +28,6 @@
 #include "runtime/globals.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1_globals.hpp"
-#endif
 #if INCLUDE_JVMCI
 #include "jvmci/jvmci_globals.hpp"
 #endif
@@ -96,21 +93,22 @@
 #define ARCH_NOTPRODUCT_FLAG_MEMBER(type, name, value, doc)      FLAG_MEMBER(name),
 
 typedef enum {
- RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
-               RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
-               RUNTIME_PRODUCT_FLAG_MEMBER, \
-               RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
-               RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
-               RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER, \
-               RUNTIME_EXPERIMENTAL_FLAG_MEMBER, \
-               RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
-               RUNTIME_MANAGEABLE_FLAG_MEMBER, \
-               RUNTIME_PRODUCT_RW_FLAG_MEMBER, \
-               RUNTIME_LP64_PRODUCT_FLAG_MEMBER, \
-               IGNORE_RANGE, \
-               IGNORE_CONSTRAINT, \
-               IGNORE_WRITEABLE)
- RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
+ VM_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
+          RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
+          RUNTIME_PRODUCT_FLAG_MEMBER, \
+          RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
+          RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
+          RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER, \
+          RUNTIME_EXPERIMENTAL_FLAG_MEMBER, \
+          RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
+          RUNTIME_MANAGEABLE_FLAG_MEMBER, \
+          RUNTIME_PRODUCT_RW_FLAG_MEMBER, \
+          RUNTIME_LP64_PRODUCT_FLAG_MEMBER, \
+          IGNORE_RANGE, \
+          IGNORE_CONSTRAINT, \
+          IGNORE_WRITEABLE)
+
+ RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER,    \
                   RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
                   RUNTIME_PRODUCT_FLAG_MEMBER, \
                   RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
@@ -120,21 +118,6 @@
                   IGNORE_RANGE, \
                   IGNORE_CONSTRAINT, \
                   IGNORE_WRITEABLE)
-#if INCLUDE_ALL_GCS
- G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, \
-          RUNTIME_PD_DEVELOP_FLAG_MEMBER, \
-          RUNTIME_PRODUCT_FLAG_MEMBER, \
-          RUNTIME_PD_PRODUCT_FLAG_MEMBER, \
-          RUNTIME_DIAGNOSTIC_FLAG_MEMBER, \
-          RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER, \
-          RUNTIME_EXPERIMENTAL_FLAG_MEMBER, \
-          RUNTIME_NOTPRODUCT_FLAG_MEMBER, \
-          RUNTIME_MANAGEABLE_FLAG_MEMBER, \
-          RUNTIME_PRODUCT_RW_FLAG_MEMBER, \
-          IGNORE_RANGE, \
-          IGNORE_CONSTRAINT, \
-          IGNORE_WRITEABLE)
-#endif // INCLUDE_ALL_GCS
 #if INCLUDE_JVMCI
  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER, \
              JVMCI_PD_DEVELOP_FLAG_MEMBER, \
@@ -239,20 +222,21 @@
 #define ARCH_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc)      FLAG_MEMBER_WITH_TYPE(name,type),
 
 typedef enum {
- RUNTIME_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE,
-               RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE,
-               IGNORE_RANGE,
-               IGNORE_CONSTRAINT,
-               IGNORE_WRITEABLE)
+  VM_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE,
+           RUNTIME_LP64_PRODUCT_FLAG_MEMBER_WITH_TYPE,
+           IGNORE_RANGE,
+           IGNORE_CONSTRAINT,
+           IGNORE_WRITEABLE)
+
  RUNTIME_OS_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
                   RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
@@ -263,21 +247,6 @@
                   IGNORE_RANGE,
                   IGNORE_CONSTRAINT,
                   IGNORE_WRITEABLE)
-#if INCLUDE_ALL_GCS
- G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_PRODUCT_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_PD_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_EXPERIMENTAL_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_MANAGEABLE_FLAG_MEMBER_WITH_TYPE,
-          RUNTIME_PRODUCT_RW_FLAG_MEMBER_WITH_TYPE,
-          IGNORE_RANGE,
-          IGNORE_CONSTRAINT,
-          IGNORE_WRITEABLE)
-#endif // INCLUDE_ALL_GCS
 #if INCLUDE_JVMCI
  JVMCI_FLAGS(JVMCI_DEVELOP_FLAG_MEMBER_WITH_TYPE,
              JVMCI_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE,
--- a/src/hotspot/share/runtime/init.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/init.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -58,14 +58,8 @@
 void os_init_globals();        // depends on VM_Version_init, before universe_init
 void stubRoutines_init1();
 jint universe_init();          // depends on codeCache_init and stubRoutines_init
-#if INCLUDE_ALL_GCS
 // depends on universe_init, must be before interpreter_init (currently only on SPARC)
-#ifndef ZERO
-void g1_barrier_stubs_init() NOT_SPARC({});
-#else
-void g1_barrier_stubs_init() {};
-#endif
-#endif
+void gc_barrier_stubs_init();
 void interpreter_init();       // before any methods loaded
 void invocationCounter_init(); // before any methods loaded
 void marksweep_init();
@@ -120,9 +114,7 @@
   if (status != JNI_OK)
     return status;
 
-#if INCLUDE_ALL_GCS
-  g1_barrier_stubs_init();   // depends on universe_init, must be before interpreter_init
-#endif
+  gc_barrier_stubs_init();   // depends on universe_init, must be before interpreter_init
   interpreter_init();        // before any methods loaded
   invocationCounter_init();  // before any methods loaded
   marksweep_init();
--- a/src/hotspot/share/runtime/interfaceSupport.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/interfaceSupport.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -25,7 +25,6 @@
 #include "precompiled.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "gc/shared/collectedHeap.inline.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/frame.inline.hpp"
--- a/src/hotspot/share/runtime/java.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/java.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -31,7 +31,6 @@
 #include "code/codeCache.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compilerOracle.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "interpreter/bytecodeHistogram.hpp"
 #if INCLUDE_JVMCI
 #include "jvmci/jvmciCompiler.hpp"
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -48,6 +48,8 @@
 Mutex*   JNIWeakAlloc_lock            = NULL;
 Mutex*   JNIWeakActive_lock           = NULL;
 Mutex*   JNIHandleBlockFreeList_lock  = NULL;
+Mutex*   VMWeakAlloc_lock             = NULL;
+Mutex*   VMWeakActive_lock            = NULL;
 Mutex*   ResolvedMethodTable_lock     = NULL;
 Mutex*   JmethodIdCreation_lock       = NULL;
 Mutex*   JfieldIdCreation_lock        = NULL;
@@ -260,6 +262,8 @@
   def(JNIGlobalActive_lock         , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
   def(JNIWeakAlloc_lock            , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
   def(JNIWeakActive_lock           , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
+  def(VMWeakAlloc_lock             , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_never);
+  def(VMWeakActive_lock            , PaddedMutex  , nonleaf-1,   true,  Monitor::_safepoint_check_never);
   def(JNICritical_lock             , PaddedMonitor, nonleaf,     true,  Monitor::_safepoint_check_always);     // used for JNI critical regions
   def(AdapterHandlerLibrary_lock   , PaddedMutex  , nonleaf,     true,  Monitor::_safepoint_check_always);
 
--- a/src/hotspot/share/runtime/mutexLocker.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -41,6 +41,8 @@
 extern Mutex*   JNIWeakAlloc_lock;               // JNI weak storage allocate list lock
 extern Mutex*   JNIWeakActive_lock;              // JNI weak storage active list lock
 extern Mutex*   JNIHandleBlockFreeList_lock;     // a lock on the JNI handle block free list
+extern Mutex*   VMWeakAlloc_lock;                // VM Weak Handles storage allocate list lock
+extern Mutex*   VMWeakActive_lock;               // VM Weak Handles storage active list lock
 extern Mutex*   ResolvedMethodTable_lock;        // a lock on the ResolvedMethodTable updates
 extern Mutex*   JmethodIdCreation_lock;          // a lock on creating JNI method identifiers
 extern Mutex*   JfieldIdCreation_lock;           // a lock on creating JNI static field identifiers
--- a/src/hotspot/share/runtime/sharedRuntime.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -36,6 +36,7 @@
 #include "compiler/abstractCompiler.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/disassembler.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "gc/shared/gcLocker.inline.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/interpreterRuntime.hpp"
@@ -75,6 +76,9 @@
 #ifdef COMPILER1
 #include "c1/c1_Runtime1.hpp"
 #endif
+#if INCLUDE_ALL_GCS
+#include "gc/g1/g1ThreadLocalData.hpp"
+#endif // INCLUDE_ALL_GCS
 
 // Shared stub locations
 RuntimeStub*        SharedRuntime::_wrong_method_blob;
@@ -214,12 +218,12 @@
   }
   assert(oopDesc::is_oop(orig, true /* ignore mark word */), "Error");
   // store the original value that was in the field reference
-  thread->satb_mark_queue().enqueue(orig);
+  G1ThreadLocalData::satb_mark_queue(thread).enqueue(orig);
 JRT_END
 
 // G1 write-barrier post: executed after a pointer store.
 JRT_LEAF(void, SharedRuntime::g1_wb_post(void* card_addr, JavaThread* thread))
-  thread->dirty_card_queue().enqueue(card_addr);
+  G1ThreadLocalData::dirty_card_queue(thread).enqueue(card_addr);
 JRT_END
 
 #endif // INCLUDE_ALL_GCS
@@ -3146,6 +3150,6 @@
   oop new_obj = thread->vm_result();
   if (new_obj == NULL) return;
 
-  BarrierSet *bs = Universe::heap()->barrier_set();
+  BarrierSet *bs = BarrierSet::barrier_set();
   bs->on_slowpath_allocation_exit(thread, new_obj);
 }
--- a/src/hotspot/share/runtime/thread.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/thread.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -33,6 +33,7 @@
 #include "code/scopeDesc.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/compileTask.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "gc/shared/gcId.hpp"
 #include "gc/shared/gcLocker.inline.hpp"
 #include "gc/shared/workgroup.hpp"
@@ -105,7 +106,9 @@
 #include "services/threadService.hpp"
 #include "trace/traceMacros.hpp"
 #include "trace/tracing.hpp"
+#include "trace/tracingExport.hpp"
 #include "utilities/align.hpp"
+#include "utilities/copy.hpp"
 #include "utilities/defaultStream.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/events.hpp"
@@ -310,6 +313,15 @@
            "bug in forced alignment of thread objects");
   }
 #endif // ASSERT
+
+  // Notify the barrier set that a thread is being created. Note that the
+  // main thread is created before a barrier set is available. The call to
+  // BarrierSet::on_thread_create() for the main thread is therefore deferred
+  // until it calls BarrierSet::set_barrier_set().
+  BarrierSet* const barrier_set = BarrierSet::barrier_set();
+  if (barrier_set != NULL) {
+    barrier_set->on_thread_create(this);
+  }
 }
 
 void Thread::initialize_thread_current() {
@@ -360,6 +372,13 @@
 Thread::~Thread() {
   EVENT_THREAD_DESTRUCT(this);
 
+  // Notify the barrier set that a thread is being destroyed. Note that a barrier
+  // set might not be available if we encountered errors during bootstrapping.
+  BarrierSet* const barrier_set = BarrierSet::barrier_set();
+  if (barrier_set != NULL) {
+    barrier_set->on_thread_destroy(this);
+  }
+
   // stack_base can be NULL if the thread is never started or exited before
   // record_stack_base_and_size called. Although, we would like to ensure
   // that all started threads do call record_stack_base_and_size(), there is
@@ -1588,18 +1607,8 @@
   pd_initialize();
 }
 
-#if INCLUDE_ALL_GCS
-SATBMarkQueueSet JavaThread::_satb_mark_queue_set;
-DirtyCardQueueSet JavaThread::_dirty_card_queue_set;
-#endif // INCLUDE_ALL_GCS
-
 JavaThread::JavaThread(bool is_attaching_via_jni) :
-                       Thread()
-#if INCLUDE_ALL_GCS
-                       , _satb_mark_queue(&_satb_mark_queue_set),
-                       _dirty_card_queue(&_dirty_card_queue_set)
-#endif // INCLUDE_ALL_GCS
-{
+                       Thread() {
   initialize();
   if (is_attaching_via_jni) {
     _jni_attach_state = _attaching_via_jni;
@@ -1661,12 +1670,7 @@
 static void sweeper_thread_entry(JavaThread* thread, TRAPS);
 
 JavaThread::JavaThread(ThreadFunction entry_point, size_t stack_sz) :
-                       Thread()
-#if INCLUDE_ALL_GCS
-                       , _satb_mark_queue(&_satb_mark_queue_set),
-                       _dirty_card_queue(&_dirty_card_queue_set)
-#endif // INCLUDE_ALL_GCS
-{
+                       Thread() {
   initialize();
   _jni_attach_state = _not_attaching_via_jni;
   set_entry_point(entry_point);
@@ -3432,17 +3436,14 @@
 // All JavaThreads
 #define ALL_JAVA_THREADS(X) DO_JAVA_THREADS(ThreadsSMRSupport::get_java_thread_list(), X)
 
-// All JavaThreads + all non-JavaThreads (i.e., every thread in the system)
-void Threads::threads_do(ThreadClosure* tc) {
-  assert_locked_or_safepoint(Threads_lock);
-  // ALL_JAVA_THREADS iterates through all JavaThreads
-  ALL_JAVA_THREADS(p) {
-    tc->do_thread(p);
-  }
+// All non-JavaThreads (i.e., every non-JavaThread in the system).
+void Threads::non_java_threads_do(ThreadClosure* tc) {
   // Someday we could have a table or list of all non-JavaThreads.
   // For now, just manually iterate through them.
   tc->do_thread(VMThread::vm_thread());
-  Universe::heap()->gc_threads_do(tc);
+  if (Universe::heap() != NULL) {
+    Universe::heap()->gc_threads_do(tc);
+  }
   WatcherThread *wt = WatcherThread::watcher_thread();
   // Strictly speaking, the following NULL check isn't sufficient to make sure
   // the data for WatcherThread is still valid upon being examined. However,
@@ -3455,9 +3456,26 @@
     tc->do_thread(wt);
   }
 
+#if INCLUDE_TRACE
+  Thread* sampler_thread = TracingExport::sampler_thread_acquire();
+  if (sampler_thread != NULL) {
+    tc->do_thread(sampler_thread);
+  }
+#endif
+
   // If CompilerThreads ever become non-JavaThreads, add them here
 }
 
+// All JavaThreads + all non-JavaThreads (i.e., every thread in the system).
+void Threads::threads_do(ThreadClosure* tc) {
+  assert_locked_or_safepoint(Threads_lock);
+  // ALL_JAVA_THREADS iterates through all JavaThreads.
+  ALL_JAVA_THREADS(p) {
+    tc->do_thread(p);
+  }
+  non_java_threads_do(tc);
+}
+
 void Threads::possibly_parallel_threads_do(bool is_par, ThreadClosure* tc) {
   int cp = Threads::thread_claim_parity();
   ALL_JAVA_THREADS(p) {
@@ -3891,6 +3909,13 @@
   // cache the system and platform class loaders
   SystemDictionary::compute_java_loaders(CHECK_JNI_ERR);
 
+#if INCLUDE_CDS
+  if (DumpSharedSpaces) {
+    // capture the module path info from the ModuleEntryTable
+    ClassLoader::initialize_module_path(THREAD);
+  }
+#endif
+
 #if INCLUDE_JVMCI
   if (force_JVMCI_intialization) {
     JVMCIRuntime::force_initialization(CHECK_JNI_ERR);
--- a/src/hotspot/share/runtime/thread.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/thread.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -26,6 +26,7 @@
 #define SHARE_VM_RUNTIME_THREAD_HPP
 
 #include "jni.h"
+#include "gc/shared/gcThreadLocalData.hpp"
 #include "gc/shared/threadLocalAllocBuffer.hpp"
 #include "memory/allocation.hpp"
 #include "oops/oop.hpp"
@@ -47,10 +48,6 @@
 #include "utilities/align.hpp"
 #include "utilities/exceptions.hpp"
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/dirtyCardQueue.hpp"
-#include "gc/g1/satbMarkQueue.hpp"
-#endif // INCLUDE_ALL_GCS
 #ifdef ZERO
 # include "stack_zero.hpp"
 #endif
@@ -112,6 +109,22 @@
   static THREAD_LOCAL_DECL Thread* _thr_current;
 #endif
 
+ private:
+  // Thread local data area available to the GC. The internal
+  // structure and contents of this data area is GC-specific.
+  // Only GC and GC barrier code should access this data area.
+  GCThreadLocalData _gc_data;
+
+ public:
+  static ByteSize gc_data_offset() {
+    return byte_offset_of(Thread, _gc_data);
+  }
+
+  template <typename T> T* gc_data() {
+    STATIC_ASSERT(sizeof(T) <= sizeof(_gc_data));
+    return reinterpret_cast<T*>(&_gc_data);
+  }
+
   // Exception handling
   // (Note: _pending_exception and friends are in ThreadShadow)
   //oop       _pending_exception;                // pending exception for current thread
@@ -1059,18 +1072,6 @@
   }   _jmp_ring[jump_ring_buffer_size];
 #endif // PRODUCT
 
-#if INCLUDE_ALL_GCS
-  // Support for G1 barriers
-
-  SATBMarkQueue _satb_mark_queue;        // Thread-local log for SATB barrier.
-  // Set of all such queues.
-  static SATBMarkQueueSet _satb_mark_queue_set;
-
-  DirtyCardQueue _dirty_card_queue;      // Thread-local log for dirty cards.
-  // Set of all such queues.
-  static DirtyCardQueueSet _dirty_card_queue_set;
-#endif // INCLUDE_ALL_GCS
-
   friend class VMThread;
   friend class ThreadWaitTransition;
   friend class VM_Exit;
@@ -1670,11 +1671,6 @@
     return byte_offset_of(JavaThread, _should_post_on_exceptions_flag);
   }
 
-#if INCLUDE_ALL_GCS
-  static ByteSize satb_mark_queue_offset()       { return byte_offset_of(JavaThread, _satb_mark_queue); }
-  static ByteSize dirty_card_queue_offset()      { return byte_offset_of(JavaThread, _dirty_card_queue); }
-#endif // INCLUDE_ALL_GCS
-
   // Returns the jni environment for this thread
   JNIEnv* jni_environment()                      { return &_jni_environment; }
 
@@ -1945,20 +1941,6 @@
     _stack_size_at_create = value;
   }
 
-#if INCLUDE_ALL_GCS
-  // SATB marking queue support
-  SATBMarkQueue& satb_mark_queue() { return _satb_mark_queue; }
-  static SATBMarkQueueSet& satb_mark_queue_set() {
-    return _satb_mark_queue_set;
-  }
-
-  // Dirty card queue support
-  DirtyCardQueue& dirty_card_queue() { return _dirty_card_queue; }
-  static DirtyCardQueueSet& dirty_card_queue_set() {
-    return _dirty_card_queue_set;
-  }
-#endif // INCLUDE_ALL_GCS
-
   // Machine dependent stuff
 #include OS_CPU_HEADER(thread)
 
@@ -2114,6 +2096,7 @@
   // thread to the thread list before allocating its thread object
   static void add(JavaThread* p, bool force_daemon = false);
   static void remove(JavaThread* p);
+  static void non_java_threads_do(ThreadClosure* tc);
   static void threads_do(ThreadClosure* tc);
   static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc);
 
--- a/src/hotspot/share/runtime/threadSMR.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/threadSMR.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -470,16 +470,6 @@
 
 ThreadsListHandle::ThreadsListHandle(Thread *self) : _list(ThreadsSMRSupport::acquire_stable_list(self, /* is_ThreadsListSetter */ false)), _self(self) {
   assert(self == Thread::current(), "sanity check");
-  // Threads::threads_do() is used by the Thread-SMR protocol to visit all
-  // Threads in the system which ensures the safety of the ThreadsList
-  // managed by this ThreadsListHandle, but JavaThreads that are not on
-  // the Threads list cannot be included in that visit. The JavaThread that
-  // calls Threads::destroy_vm() is exempt from this check because it has
-  // to logically exit as part of the shutdown procedure. This is safe
-  // because VM_Exit::_shutdown_thread is not set until after the VMThread
-  // has started the final safepoint which holds the Threads_lock for the
-  // remainder of the VM's life.
-  assert(!self->is_Java_thread() || self == VM_Exit::shutdown_thread() || (((JavaThread*)self)->on_thread_list() && !((JavaThread*)self)->is_terminated()), "JavaThread must be on the Threads list to use a ThreadsListHandle");
   if (EnableThreadSMRStatistics) {
     _timer.start();
   }
@@ -553,6 +543,76 @@
   }
 }
 
+// Closure to determine if the specified JavaThread is found by
+// threads_do().
+//
+class VerifyHazardPointerThreadClosure : public ThreadClosure {
+ private:
+  bool _found;
+  Thread *_self;
+
+ public:
+  VerifyHazardPointerThreadClosure(Thread *self) : _found(false), _self(self) {}
+
+  bool found() const { return _found; }
+
+  virtual void do_thread(Thread *thread) {
+    if (thread == _self) {
+      _found = true;
+    }
+  }
+};
+
+// Apply the closure to all threads in the system, with a snapshot of
+// all JavaThreads provided by the list parameter.
+void ThreadsSMRSupport::threads_do(ThreadClosure *tc, ThreadsList *list) {
+  list->threads_do(tc);
+  Threads::non_java_threads_do(tc);
+}
+
+// Apply the closure to all threads in the system.
+void ThreadsSMRSupport::threads_do(ThreadClosure *tc) {
+  threads_do(tc, _java_thread_list);
+}
+
+// Verify that the stable hazard pointer used to safely keep threads
+// alive is scanned by threads_do() which is a key piece of honoring
+// the Thread-SMR protocol.
+void ThreadsSMRSupport::verify_hazard_pointer_scanned(Thread *self, ThreadsList *threads) {
+#ifdef ASSERT
+  assert(threads != NULL, "threads must not be NULL");
+
+  // The closure will attempt to verify that the calling thread can
+  // be found by threads_do() on the specified ThreadsList. If it
+  // is successful, then the specified ThreadsList was acquired as
+  // a stable hazard pointer by the calling thread in a way that
+  // honored the Thread-SMR protocol.
+  //
+  // If the calling thread cannot be found by threads_do() and if
+  // it is not the shutdown thread, then the calling thread is not
+  // honoring the Thread-SMR ptotocol. This means that the specified
+  // ThreadsList is not a stable hazard pointer and can be freed
+  // by another thread from the to-be-deleted list at any time.
+  //
+  // Note: The shutdown thread has removed itself from the Threads
+  // list and is safe to have a waiver from this check because
+  // VM_Exit::_shutdown_thread is not set until after the VMThread
+  // has started the final safepoint which holds the Threads_lock
+  // for the remainder of the VM's life.
+  //
+  VerifyHazardPointerThreadClosure cl(self);
+  threads_do(&cl, threads);
+
+  // If the calling thread is not honoring the Thread-SMR protocol,
+  // then we will either crash in threads_do() above because 'threads'
+  // was freed by another thread or we will fail the assert() below.
+  // In either case, we won't get past this point with a badly placed
+  // ThreadsListHandle.
+
+  assert(cl.found() || self == VM_Exit::shutdown_thread(), "Acquired a ThreadsList snapshot from a thread not recognized by the Thread-SMR protocol.");
+#endif
+}
+
 void ThreadsListSetter::set() {
   assert(_target->get_threads_hazard_ptr() == NULL, "hazard ptr should not already be set");
   (void) ThreadsSMRSupport::acquire_stable_list(_target, /* is_ThreadsListSetter */ true);
@@ -626,6 +686,8 @@
   // are protected and hence they should not be deleted until everyone
   // agrees it is safe to do so.
 
+  verify_hazard_pointer_scanned(self, threads);
+
   return threads;
 }
 
@@ -662,6 +724,8 @@
   }
   log_debug(thread, smr)("tid=" UINTX_FORMAT ": ThreadsSMRSupport::acquire_stable_list: add NestedThreadsList node containing ThreadsList=" INTPTR_FORMAT, os::current_thread_id(), p2i(node->t_list()));
 
+  verify_hazard_pointer_scanned(self, node->t_list());
+
   return node->t_list();
 }
 
@@ -722,7 +786,7 @@
   // Gather a hash table of the current hazard ptrs:
   ThreadScanHashtable *scan_table = new ThreadScanHashtable(hash_table_size);
   ScanHazardPtrGatherThreadsListClosure scan_cl(scan_table);
-  Threads::threads_do(&scan_cl);
+  threads_do(&scan_cl);
 
   // Walk through the linked list of pending freeable ThreadsLists
   // and free the ones that are not referenced from hazard ptrs.
@@ -784,7 +848,7 @@
   // hazard ptrs.
   ThreadScanHashtable *scan_table = new ThreadScanHashtable(hash_table_size);
   ScanHazardPtrGatherProtectedThreadsClosure scan_cl(scan_table);
-  Threads::threads_do(&scan_cl);
+  threads_do(&scan_cl);
 
   bool thread_is_protected = false;
   if (scan_table->has_entry((void*)thread)) {
@@ -949,7 +1013,7 @@
         log_debug(thread, smr)("tid=" UINTX_FORMAT ": ThreadsSMRSupport::smr_delete: thread=" INTPTR_FORMAT " is not deleted.", os::current_thread_id(), p2i(thread));
         if (log_is_enabled(Debug, os, thread)) {
           ScanHazardPtrPrintMatchingThreadsClosure scan_cl(thread);
-          Threads::threads_do(&scan_cl);
+          threads_do(&scan_cl);
         }
       }
     } // We have to drop the Threads_lock to wait or delete the thread
--- a/src/hotspot/share/runtime/threadSMR.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/threadSMR.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,8 @@
 #include "memory/allocation.hpp"
 #include "runtime/timer.hpp"
 
+class ThreadClosure;
+
 // Thread Safe Memory Reclamation (Thread-SMR) support.
 //
 // ThreadsListHandles are used to safely perform operations on one or more
@@ -124,9 +126,12 @@
   static void release_stable_list_nested_path(Thread *self);
   static void release_stable_list_wake_up(char *log_str);
   static void set_delete_notify();
+  static void threads_do(ThreadClosure *tc);
+  static void threads_do(ThreadClosure *tc, ThreadsList *list);
   static void update_deleted_thread_time_max(uint new_value);
   static void update_java_thread_list_max(uint new_value);
   static void update_tlh_time_max(uint new_value);
+  static void verify_hazard_pointer_scanned(Thread *self, ThreadsList *threads);
   static ThreadsList* xchg_java_thread_list(ThreadsList* new_list);
 
  public:
--- a/src/hotspot/share/runtime/vmStructs.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -44,19 +44,7 @@
 #include "code/vmreg.hpp"
 #include "compiler/compileBroker.hpp"
 #include "compiler/oopMap.hpp"
-#include "gc/parallel/immutableSpace.hpp"
-#include "gc/parallel/mutableSpace.hpp"
-#include "gc/serial/defNewGeneration.hpp"
-#include "gc/serial/serialHeap.hpp"
-#include "gc/serial/tenuredGeneration.hpp"
-#include "gc/cms/cmsHeap.hpp"
-#include "gc/shared/cardTableRS.hpp"
-#include "gc/shared/collectedHeap.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
-#include "gc/shared/generation.hpp"
-#include "gc/shared/generationSpec.hpp"
-#include "gc/shared/oopStorage.hpp"
-#include "gc/shared/space.hpp"
+#include "gc/shared/vmStructs_gc.hpp"
 #include "interpreter/bytecodeInterpreter.hpp"
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
@@ -113,23 +101,6 @@
 #include OS_HEADER(vmStructs)
 #include OS_CPU_HEADER(vmStructs)
 
-#if INCLUDE_ALL_GCS
-#include "gc/cms/compactibleFreeListSpace.hpp"
-#include "gc/cms/concurrentMarkSweepGeneration.hpp"
-#include "gc/cms/concurrentMarkSweepThread.hpp"
-#include "gc/cms/parNewGeneration.hpp"
-#include "gc/cms/vmStructs_cms.hpp"
-#include "gc/cms/vmStructs_parNew.hpp"
-#include "gc/g1/vmStructs_g1.hpp"
-#include "gc/parallel/asPSOldGen.hpp"
-#include "gc/parallel/asPSYoungGen.hpp"
-#include "gc/parallel/parallelScavengeHeap.hpp"
-#include "gc/parallel/psOldGen.hpp"
-#include "gc/parallel/psVirtualspace.hpp"
-#include "gc/parallel/psYoungGen.hpp"
-#include "gc/parallel/vmStructs_parallelgc.hpp"
-#endif // INCLUDE_ALL_GCS
-
 #if INCLUDE_JVMCI
 # include "jvmci/vmStructs_jvmci.hpp"
 #endif
@@ -210,29 +181,38 @@
 // NOTE that there are platform-specific additions to this table in
 // vmStructs_<os>_<cpu>.hpp.
 
-#define VM_STRUCTS(nonstatic_field, \
-                   static_field, \
-                   static_ptr_volatile_field, \
-                   unchecked_nonstatic_field, \
-                   volatile_nonstatic_field, \
-                   nonproduct_nonstatic_field, \
-                   c1_nonstatic_field, \
-                   c2_nonstatic_field, \
-                   unchecked_c1_static_field, \
-                   unchecked_c2_static_field) \
+#define VM_STRUCTS(nonstatic_field,                                                                                                  \
+                   static_field,                                                                                                     \
+                   static_ptr_volatile_field,                                                                                        \
+                   unchecked_nonstatic_field,                                                                                        \
+                   volatile_nonstatic_field,                                                                                         \
+                   nonproduct_nonstatic_field,                                                                                       \
+                   c1_nonstatic_field,                                                                                               \
+                   c2_nonstatic_field,                                                                                               \
+                   unchecked_c1_static_field,                                                                                        \
+                   unchecked_c2_static_field)                                                                                        \
+                                                                                                                                     \
+  /*************/                                                                                                                    \
+  /* GC fields */                                                                                                                    \
+  /*************/                                                                                                                    \
+                                                                                                                                     \
+  VM_STRUCTS_GC(nonstatic_field,                                                                                                     \
+                volatile_nonstatic_field,                                                                                            \
+                static_field,                                                                                                        \
+                unchecked_nonstatic_field)                                                                                           \
                                                                                                                                      \
   /******************************************************************/                                                               \
-  /* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete) */                                                                 \
+  /* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete)   */                                                               \
   /******************************************************************/                                                               \
                                                                                                                                      \
   volatile_nonstatic_field(oopDesc,            _mark,                                         markOop)                               \
   volatile_nonstatic_field(oopDesc,            _metadata._klass,                              Klass*)                                \
   volatile_nonstatic_field(oopDesc,            _metadata._compressed_klass,                   narrowKlass)                           \
-  static_field(BarrierSet,                     _bs,                                           BarrierSet*)                           \
+  static_field(BarrierSet,                     _barrier_set,                                  BarrierSet*)                           \
   nonstatic_field(ArrayKlass,                  _dimension,                                    int)                                   \
   volatile_nonstatic_field(ArrayKlass,         _higher_dimension,                             Klass*)                                \
   volatile_nonstatic_field(ArrayKlass,         _lower_dimension,                              Klass*)                                \
-  nonstatic_field(CompiledICHolder,            _holder_metadata,                              Metadata*)                               \
+  nonstatic_field(CompiledICHolder,            _holder_metadata,                              Metadata*)                             \
   nonstatic_field(CompiledICHolder,            _holder_klass,                                 Klass*)                                \
   nonstatic_field(ConstantPool,                _tags,                                         Array<u1>*)                            \
   nonstatic_field(ConstantPool,                _cache,                                        ConstantPoolCache*)                    \
@@ -433,99 +413,9 @@
                                                                                                                                      \
      static_field(os,                          _polling_page,                                 address)                               \
                                                                                                                                      \
-  /**********************************************************************************/                                               \
-  /* Generation and Space hierarchies                                               */                                               \
-  /**********************************************************************************/                                               \
-                                                                                                                                     \
-  unchecked_nonstatic_field(AgeTable,          sizes,                                         sizeof(AgeTable::sizes))               \
-                                                                                                                                     \
-  nonstatic_field(BarrierSet,                  _fake_rtti,                                    BarrierSet::FakeRtti)                  \
-                                                                                                                                     \
-  nonstatic_field(BarrierSet::FakeRtti,        _concrete_tag,                                 BarrierSet::Name)                      \
-                                                                                                                                     \
-  nonstatic_field(BlockOffsetTable,            _bottom,                                       HeapWord*)                             \
-  nonstatic_field(BlockOffsetTable,            _end,                                          HeapWord*)                             \
-                                                                                                                                     \
-  nonstatic_field(BlockOffsetSharedArray,      _reserved,                                     MemRegion)                             \
-  nonstatic_field(BlockOffsetSharedArray,      _end,                                          HeapWord*)                             \
-  nonstatic_field(BlockOffsetSharedArray,      _vs,                                           VirtualSpace)                          \
-  nonstatic_field(BlockOffsetSharedArray,      _offset_array,                                 u_char*)                               \
-                                                                                                                                     \
-  nonstatic_field(BlockOffsetArray,            _array,                                        BlockOffsetSharedArray*)               \
-  nonstatic_field(BlockOffsetArray,            _sp,                                           Space*)                                \
-  nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_threshold,                        HeapWord*)                             \
-  nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_index,                            size_t)                                \
-                                                                                                                                     \
-  nonstatic_field(BlockOffsetArrayNonContigSpace, _unallocated_block,                         HeapWord*)                             \
-                                                                                                                                     \
-  nonstatic_field(CardGeneration,              _rs,                                           CardTableRS*)                          \
-  nonstatic_field(CardGeneration,              _bts,                                          BlockOffsetSharedArray*)               \
-  nonstatic_field(CardGeneration,              _shrink_factor,                                size_t)                                \
-  nonstatic_field(CardGeneration,              _capacity_at_prologue,                         size_t)                                \
-  nonstatic_field(CardGeneration,              _used_at_prologue,                             size_t)                                \
-                                                                                                                                     \
-  nonstatic_field(CardTable,                   _whole_heap,                                   const MemRegion)                       \
-  nonstatic_field(CardTable,                   _guard_index,                                  const size_t)                          \
-  nonstatic_field(CardTable,                   _last_valid_index,                             const size_t)                          \
-  nonstatic_field(CardTable,                   _page_size,                                    const size_t)                          \
-  nonstatic_field(CardTable,                   _byte_map_size,                                const size_t)                          \
-  nonstatic_field(CardTable,                   _byte_map,                                     jbyte*)                                \
-  nonstatic_field(CardTable,                   _cur_covered_regions,                          int)                                   \
-  nonstatic_field(CardTable,                   _covered,                                      MemRegion*)                            \
-  nonstatic_field(CardTable,                   _committed,                                    MemRegion*)                            \
-  nonstatic_field(CardTable,                   _guard_region,                                 MemRegion)                             \
-  nonstatic_field(CardTable,                   _byte_map_base,                                jbyte*)                                \
-  nonstatic_field(CardTableBarrierSet,         _defer_initial_card_mark,                      bool)                                  \
-  nonstatic_field(CardTableBarrierSet,         _card_table,                                   CardTable*)                            \
-                                                                                                                                     \
-  nonstatic_field(CollectedHeap,               _reserved,                                     MemRegion)                             \
-  nonstatic_field(CollectedHeap,               _barrier_set,                                  BarrierSet*)                           \
-  nonstatic_field(CollectedHeap,               _is_gc_active,                                 bool)                                  \
-  nonstatic_field(CollectedHeap,               _total_collections,                            unsigned int)                          \
-                                                                                                                                     \
-  nonstatic_field(CompactibleSpace,            _compaction_top,                               HeapWord*)                             \
-  nonstatic_field(CompactibleSpace,            _first_dead,                                   HeapWord*)                             \
-  nonstatic_field(CompactibleSpace,            _end_of_live,                                  HeapWord*)                             \
-                                                                                                                                     \
-  nonstatic_field(ContiguousSpace,             _top,                                          HeapWord*)                             \
-  nonstatic_field(ContiguousSpace,             _concurrent_iteration_safe_limit,              HeapWord*)                             \
-  nonstatic_field(ContiguousSpace,             _saved_mark_word,                              HeapWord*)                             \
-                                                                                                                                     \
-  nonstatic_field(DefNewGeneration,            _old_gen,                                      Generation*)                           \
-  nonstatic_field(DefNewGeneration,            _tenuring_threshold,                           uint)                                  \
-  nonstatic_field(DefNewGeneration,            _age_table,                                    AgeTable)                              \
-  nonstatic_field(DefNewGeneration,            _eden_space,                                   ContiguousSpace*)                      \
-  nonstatic_field(DefNewGeneration,            _from_space,                                   ContiguousSpace*)                      \
-  nonstatic_field(DefNewGeneration,            _to_space,                                     ContiguousSpace*)                      \
-                                                                                                                                     \
-  nonstatic_field(Generation,                  _reserved,                                     MemRegion)                             \
-  nonstatic_field(Generation,                  _virtual_space,                                VirtualSpace)                          \
-  nonstatic_field(Generation,                  _stat_record,                                  Generation::StatRecord)                \
-                                                                                                                                     \
-  nonstatic_field(Generation::StatRecord,      invocations,                                   int)                                   \
-  nonstatic_field(Generation::StatRecord,      accumulated_time,                              elapsedTimer)                          \
-                                                                                                                                     \
-  nonstatic_field(GenerationSpec,              _name,                                         Generation::Name)                      \
-  nonstatic_field(GenerationSpec,              _init_size,                                    size_t)                                \
-  nonstatic_field(GenerationSpec,              _max_size,                                     size_t)                                \
-                                                                                                                                     \
-  nonstatic_field(GenCollectedHeap,            _young_gen,                                    Generation*)                           \
-  nonstatic_field(GenCollectedHeap,            _old_gen,                                      Generation*)                           \
-  nonstatic_field(GenCollectedHeap,            _young_gen_spec,                               GenerationSpec*)                       \
-  nonstatic_field(GenCollectedHeap,            _old_gen_spec,                                 GenerationSpec*)                       \
-                                                                                                                                     \
-  nonstatic_field(HeapWord,                    i,                                             char*)                                 \
-                                                                                                                                     \
-  nonstatic_field(MemRegion,                   _start,                                        HeapWord*)                             \
-  nonstatic_field(MemRegion,                   _word_size,                                    size_t)                                \
-                                                                                                                                     \
-  nonstatic_field(OffsetTableContigSpace,      _offsets,                                      BlockOffsetArray)                      \
-                                                                                                                                     \
-  nonstatic_field(TenuredGeneration,           _min_heap_delta_bytes,                         size_t)                                \
-  nonstatic_field(TenuredGeneration,           _the_space,                                    ContiguousSpace*)                      \
-                                                                                                                                     \
-  nonstatic_field(Space,                       _bottom,                                       HeapWord*)                             \
-  nonstatic_field(Space,                       _end,                                          HeapWord*)                             \
+  /**********/                                                                                                                       \
+  /* Memory */                                                                                                                       \
+  /**********/                                                                                                                       \
                                                                                                                                      \
   nonstatic_field(ThreadLocalAllocBuffer,      _start,                                        HeapWord*)                             \
   nonstatic_field(ThreadLocalAllocBuffer,      _top,                                          HeapWord*)                             \
@@ -910,8 +800,6 @@
   nonstatic_field(JavaThread,                  _stack_size,                                   size_t)                                \
   nonstatic_field(JavaThread,                  _vframe_array_head,                            vframeArray*)                          \
   nonstatic_field(JavaThread,                  _vframe_array_last,                            vframeArray*)                          \
-  nonstatic_field(JavaThread,                  _satb_mark_queue,                              SATBMarkQueue)                         \
-  nonstatic_field(JavaThread,                  _dirty_card_queue,                             DirtyCardQueue)                        \
   volatile_nonstatic_field(JavaThread,         _terminated,                                   JavaThread::TerminatedTypes)           \
   nonstatic_field(Thread,                      _resource_area,                                ResourceArea*)                         \
   nonstatic_field(CompilerThread,              _env,                                          ciEnv*)                                \
@@ -1260,13 +1148,7 @@
   nonstatic_field(AccessFlags,                 _flags,                                        jint)                                  \
   nonstatic_field(elapsedTimer,                _counter,                                      jlong)                                 \
   nonstatic_field(elapsedTimer,                _active,                                       bool)                                  \
-  nonstatic_field(InvocationCounter,           _counter,                                      unsigned int)                          \
-  volatile_nonstatic_field(FreeChunk,          _size,                                         size_t)                                \
-  nonstatic_field(FreeChunk,                   _next,                                         FreeChunk*)                            \
-  nonstatic_field(FreeChunk,                   _prev,                                         FreeChunk*)                            \
-  nonstatic_field(AdaptiveFreeList<FreeChunk>, _size,                                         size_t)                                \
-  nonstatic_field(AdaptiveFreeList<FreeChunk>, _count,                                        ssize_t)
-
+  nonstatic_field(InvocationCounter,           _counter,                                      unsigned int)
 
 //--------------------------------------------------------------------------------
 // VM_TYPES
@@ -1453,73 +1335,6 @@
   declare_toplevel_type(ClassLoaderData)                                  \
   declare_toplevel_type(ClassLoaderDataGraph)                             \
                                                                           \
-  /******************************************/                            \
-  /* Generation and space hierarchies       */                            \
-  /* (needed for run-time type information) */                            \
-  /******************************************/                            \
-                                                                          \
-  declare_toplevel_type(CollectedHeap)                                    \
-           declare_type(GenCollectedHeap,             CollectedHeap)      \
-           declare_type(CMSHeap,                      GenCollectedHeap)   \
-           declare_type(SerialHeap,                   GenCollectedHeap)   \
-  declare_toplevel_type(Generation)                                       \
-           declare_type(DefNewGeneration,             Generation)         \
-           declare_type(CardGeneration,               Generation)         \
-           declare_type(TenuredGeneration,            CardGeneration)     \
-  declare_toplevel_type(Space)                                            \
-           declare_type(CompactibleSpace,             Space)              \
-           declare_type(ContiguousSpace,              CompactibleSpace)   \
-           declare_type(OffsetTableContigSpace,       ContiguousSpace)    \
-           declare_type(TenuredSpace,                 OffsetTableContigSpace) \
-  declare_toplevel_type(BarrierSet)                                       \
-           declare_type(ModRefBarrierSet,             BarrierSet)         \
-           declare_type(CardTableBarrierSet,          ModRefBarrierSet)   \
-  declare_toplevel_type(CardTable)                                        \
-           declare_type(CardTableRS, CardTable)                           \
-  declare_toplevel_type(BarrierSet::Name)                                 \
-  declare_toplevel_type(BlockOffsetSharedArray)                           \
-  declare_toplevel_type(BlockOffsetTable)                                 \
-           declare_type(BlockOffsetArray,             BlockOffsetTable)   \
-           declare_type(BlockOffsetArrayContigSpace,  BlockOffsetArray)   \
-           declare_type(BlockOffsetArrayNonContigSpace, BlockOffsetArray) \
-                                                                          \
-  /* Miscellaneous other GC types */                                      \
-                                                                          \
-  declare_toplevel_type(AgeTable)                                         \
-  declare_toplevel_type(Generation::StatRecord)                           \
-  declare_toplevel_type(GenerationSpec)                                   \
-  declare_toplevel_type(HeapWord)                                         \
-  declare_toplevel_type(MemRegion)                                        \
-  declare_toplevel_type(ThreadLocalAllocBuffer)                           \
-  declare_toplevel_type(VirtualSpace)                                     \
-  declare_toplevel_type(SATBMarkQueue)                                    \
-  declare_toplevel_type(DirtyCardQueue)                                   \
-                                                                          \
-  /* Pointers to Garbage Collection types */                              \
-                                                                          \
-  declare_toplevel_type(BarrierSet*)                                      \
-  declare_toplevel_type(BlockOffsetSharedArray*)                          \
-  declare_toplevel_type(CardTable*)                                       \
-  declare_toplevel_type(CardTable*const)                                  \
-  declare_toplevel_type(CardTableRS*)                                     \
-  declare_toplevel_type(CardTableBarrierSet*)                             \
-  declare_toplevel_type(CardTableBarrierSet**)                            \
-  declare_toplevel_type(CollectedHeap*)                                   \
-  declare_toplevel_type(ContiguousSpace*)                                 \
-  declare_toplevel_type(DefNewGeneration*)                                \
-  declare_toplevel_type(GenCollectedHeap*)                                \
-  declare_toplevel_type(Generation*)                                      \
-  declare_toplevel_type(GenerationSpec**)                                 \
-  declare_toplevel_type(HeapWord*)                                        \
-  declare_toplevel_type(HeapWord* volatile)                               \
-  declare_toplevel_type(MemRegion*)                                       \
-  declare_toplevel_type(OffsetTableContigSpace*)                          \
-  declare_toplevel_type(Space*)                                           \
-  declare_toplevel_type(TenuredGeneration*)                               \
-  declare_toplevel_type(ThreadLocalAllocBuffer*)                          \
-                                                                          \
-  declare_toplevel_type(BarrierSet::FakeRtti)                             \
-                                                                          \
   /************************/                                              \
   /* PerfMemory - jvmstat */                                              \
   /************************/                                              \
@@ -2183,15 +1998,13 @@
   declare_toplevel_type(Annotations*)                                     \
   declare_type(OopMapValue, StackObj)                                     \
                                                                           \
-  /***************/                                                       \
-  /* Miscellaneous types */                                               \
-  /***************/                                                       \
+  /************/                                                          \
+  /* GC types */                                                          \
+  /************/                                                          \
                                                                           \
-  /* freelist */                                                          \
-  declare_toplevel_type(FreeChunk*)                                       \
-  declare_toplevel_type(AdaptiveFreeList<FreeChunk>*)                     \
-  declare_toplevel_type(AdaptiveFreeList<FreeChunk>)
-
+  VM_TYPES_GC(declare_type,                                               \
+              declare_toplevel_type,                                      \
+              declare_integer_type)
 
 //--------------------------------------------------------------------------------
 // VM_INT_CONSTANTS
@@ -2202,11 +2015,19 @@
 // all #defined constants.
 
 #define VM_INT_CONSTANTS(declare_constant,                                \
+                         declare_constant_with_value,                     \
                          declare_preprocessor_constant,                   \
                          declare_c1_constant,                             \
                          declare_c2_constant,                             \
                          declare_c2_preprocessor_constant)                \
                                                                           \
+  /****************/                                                      \
+  /* GC constants */                                                      \
+  /****************/                                                      \
+                                                                          \
+  VM_INT_CONSTANTS_GC(declare_constant,                                   \
+                      declare_constant_with_value)                        \
+                                                                          \
   /******************/                                                    \
   /* Useful globals */                                                    \
   /******************/                                                    \
@@ -2230,51 +2051,6 @@
                                                                           \
   declare_constant(LogKlassAlignmentInBytes)                              \
                                                                           \
-  /********************************************/                          \
-  /* Generation and Space Hierarchy Constants */                          \
-  /********************************************/                          \
-                                                                          \
-  declare_constant(AgeTable::table_size)                                  \
-                                                                          \
-  declare_constant(BarrierSet::ModRef)                                    \
-  declare_constant(BarrierSet::CardTableBarrierSet)                           \
-  declare_constant(BarrierSet::G1BarrierSet)                              \
-                                                                          \
-  declare_constant(BOTConstants::LogN)                                    \
-  declare_constant(BOTConstants::LogN_words)                              \
-  declare_constant(BOTConstants::N_bytes)                                 \
-  declare_constant(BOTConstants::N_words)                                 \
-  declare_constant(BOTConstants::LogBase)                                 \
-  declare_constant(BOTConstants::Base)                                    \
-  declare_constant(BOTConstants::N_powers)                                \
-                                                                          \
-  declare_constant(CardTable::clean_card)                                 \
-  declare_constant(CardTable::last_card)                                  \
-  declare_constant(CardTable::dirty_card)                                 \
-  declare_constant(CardTable::Precise)                                    \
-  declare_constant(CardTable::ObjHeadPreciseArray)                        \
-  declare_constant(CardTable::card_shift)                                 \
-  declare_constant(CardTable::card_size)                                  \
-  declare_constant(CardTable::card_size_in_words)                         \
-                                                                          \
-  declare_constant(CardTableRS::youngergen_card)                          \
-                                                                          \
-  declare_constant(G1CardTable::g1_young_gen)                             \
-                                                                          \
-  declare_constant(CollectedHeap::Serial)                                 \
-  declare_constant(CollectedHeap::Parallel)                               \
-  declare_constant(CollectedHeap::CMS)                                    \
-  declare_constant(CollectedHeap::G1)                                     \
-                                                                          \
-  /* constants from Generation::Name enum */                              \
-                                                                          \
-  declare_constant(Generation::DefNew)                                    \
-  declare_constant(Generation::MarkSweepCompact)                          \
-  declare_constant(Generation::Other)                                     \
-                                                                          \
-  declare_constant(Generation::LogOfGenGrain)                             \
-  declare_constant(Generation::GenGrain)                                  \
-                                                                          \
   declare_constant(HeapWordSize)                                          \
   declare_constant(LogHeapWordSize)                                       \
                                                                           \
@@ -3012,19 +2788,6 @@
              GENERATE_C1_UNCHECKED_STATIC_VM_STRUCT_ENTRY,
              GENERATE_C2_UNCHECKED_STATIC_VM_STRUCT_ENTRY)
 
-#if INCLUDE_ALL_GCS
-  VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
-                        GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
-                        GENERATE_STATIC_VM_STRUCT_ENTRY)
-
-  VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
-                 GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
-                 GENERATE_STATIC_VM_STRUCT_ENTRY)
-
-  VM_STRUCTS_G1(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
-                GENERATE_STATIC_VM_STRUCT_ENTRY)
-#endif // INCLUDE_ALL_GCS
-
 #if INCLUDE_TRACE
   VM_STRUCTS_TRACE(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
                    GENERATE_STATIC_VM_STRUCT_ENTRY)
@@ -3075,20 +2838,6 @@
            GENERATE_C2_VM_TYPE_ENTRY,
            GENERATE_C2_TOPLEVEL_VM_TYPE_ENTRY)
 
-#if INCLUDE_ALL_GCS
-  VM_TYPES_PARALLELGC(GENERATE_VM_TYPE_ENTRY,
-                      GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
-
-  VM_TYPES_CMS(GENERATE_VM_TYPE_ENTRY,
-               GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
-
-  VM_TYPES_PARNEW(GENERATE_VM_TYPE_ENTRY)
-
-  VM_TYPES_G1(GENERATE_VM_TYPE_ENTRY,
-              GENERATE_TOPLEVEL_VM_TYPE_ENTRY,
-              GENERATE_INTEGER_VM_TYPE_ENTRY)
-#endif // INCLUDE_ALL_GCS
-
 #if INCLUDE_TRACE
   VM_TYPES_TRACE(GENERATE_VM_TYPE_ENTRY,
               GENERATE_TOPLEVEL_VM_TYPE_ENTRY)
@@ -3131,20 +2880,12 @@
 VMIntConstantEntry VMStructs::localHotSpotVMIntConstants[] = {
 
   VM_INT_CONSTANTS(GENERATE_VM_INT_CONSTANT_ENTRY,
+                   GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
                    GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C1_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C2_VM_INT_CONSTANT_ENTRY,
                    GENERATE_C2_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
 
-#if INCLUDE_ALL_GCS
-  VM_INT_CONSTANTS_CMS(GENERATE_VM_INT_CONSTANT_ENTRY)
-
-  VM_INT_CONSTANTS_PARNEW(GENERATE_VM_INT_CONSTANT_ENTRY)
-
-  VM_INT_CONSTANTS_G1(GENERATE_VM_INT_CONSTANT_ENTRY,
-                      GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY)
-#endif // INCLUDE_ALL_GCS
-
 #if INCLUDE_TRACE
   VM_INT_CONSTANTS_TRACE(GENERATE_VM_INT_CONSTANT_ENTRY)
 #endif
@@ -3222,20 +2963,6 @@
              CHECK_NO_OP,
              CHECK_NO_OP);
 
-#if INCLUDE_ALL_GCS
-  VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
-                        CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
-                        CHECK_STATIC_VM_STRUCT_ENTRY);
-
-  VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
-                 CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
-                 CHECK_STATIC_VM_STRUCT_ENTRY);
-
-  VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
-                CHECK_STATIC_VM_STRUCT_ENTRY);
-
-#endif // INCLUDE_ALL_GCS
-
 #if INCLUDE_TRACE
   VM_STRUCTS_TRACE(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
                    CHECK_STATIC_VM_STRUCT_ENTRY);
@@ -3268,21 +2995,6 @@
            CHECK_C2_VM_TYPE_ENTRY,
            CHECK_C2_TOPLEVEL_VM_TYPE_ENTRY);
 
-#if INCLUDE_ALL_GCS
-  VM_TYPES_PARALLELGC(CHECK_VM_TYPE_ENTRY,
-                      CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
-
-  VM_TYPES_CMS(CHECK_VM_TYPE_ENTRY,
-               CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
-
-  VM_TYPES_PARNEW(CHECK_VM_TYPE_ENTRY)
-
-  VM_TYPES_G1(CHECK_VM_TYPE_ENTRY,
-              CHECK_SINGLE_ARG_VM_TYPE_NO_OP,
-              CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
-
-#endif // INCLUDE_ALL_GCS
-
 #if INCLUDE_TRACE
   VM_TYPES_TRACE(CHECK_VM_TYPE_ENTRY,
               CHECK_SINGLE_ARG_VM_TYPE_NO_OP);
@@ -3343,16 +3055,6 @@
                         ENSURE_C2_FIELD_TYPE_PRESENT,
                         CHECK_NO_OP,
                         CHECK_NO_OP));
-#if INCLUDE_ALL_GCS
-  debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT,
-                                   ENSURE_FIELD_TYPE_PRESENT,
-                                   ENSURE_FIELD_TYPE_PRESENT));
-  debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT,
-                            ENSURE_FIELD_TYPE_PRESENT,
-                            ENSURE_FIELD_TYPE_PRESENT));
-  debug_only(VM_STRUCTS_G1(ENSURE_FIELD_TYPE_PRESENT,
-                           ENSURE_FIELD_TYPE_PRESENT));
-#endif // INCLUDE_ALL_GCS
 
 #if INCLUDE_TRACE
   debug_only(VM_STRUCTS_TRACE(ENSURE_FIELD_TYPE_PRESENT,
--- a/src/hotspot/share/services/attachListener.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/services/attachListener.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -334,7 +334,9 @@
 static void attach_listener_thread_entry(JavaThread* thread, TRAPS) {
   os::set_priority(thread, NearMaxPriority);
 
-  thread->record_stack_base_and_size();
+  assert(thread == Thread::current(), "Must be");
+  assert(thread->stack_base() != NULL && thread->stack_size() > 0,
+         "Should already be setup");
 
   if (AttachListener::pd_init() != 0) {
     return;
--- a/src/hotspot/share/services/diagnosticCommand.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/services/diagnosticCommand.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -137,9 +137,15 @@
   _dcmdparser.add_dcmd_argument(&_cmd);
 };
 
+
+static int compare_strings(const char** s1, const char** s2) {
+  return ::strcmp(*s1, *s2);
+}
+
 void HelpDCmd::execute(DCmdSource source, TRAPS) {
   if (_all.value()) {
     GrowableArray<const char*>* cmd_list = DCmdFactory::DCmd_list(source);
+    cmd_list->sort(compare_strings);
     for (int i = 0; i < cmd_list->length(); i++) {
       DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
                                                   strlen(cmd_list->at(i)));
@@ -180,6 +186,7 @@
   } else {
     output()->print_cr("The following commands are available:");
     GrowableArray<const char *>* cmd_list = DCmdFactory::DCmd_list(source);
+    cmd_list->sort(compare_strings);
     for (int i = 0; i < cmd_list->length(); i++) {
       DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i),
                                                   strlen(cmd_list->at(i)));
--- a/src/hotspot/share/services/heapDumper.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/services/heapDumper.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -28,7 +28,6 @@
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "gc/shared/gcLocker.hpp"
-#include "gc/shared/genCollectedHeap.hpp"
 #include "gc/shared/vmGCOperations.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/resourceArea.hpp"
@@ -52,9 +51,6 @@
 #include "services/threadService.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/ostream.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/parallel/parallelScavengeHeap.hpp"
-#endif // INCLUDE_ALL_GCS
 
 /*
  * HPROF binary format - description copied from:
--- a/src/hotspot/share/services/memTracker.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/services/memTracker.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -41,7 +41,7 @@
      release
   };
   Tracker(enum TrackerType type) : _type(type) { }
-  void record(address addr, size_t size);
+  void record(address addr, size_t size) { }
  private:
   enum TrackerType  _type;
 };
@@ -313,4 +313,3 @@
 #endif // INCLUDE_NMT
 
 #endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP
-
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/trace/tracingExport.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/orderAccess.inline.hpp"
+#include "trace/tracingExport.hpp"
+
+// Allow lock-free reads of _sampler_thread.
+Thread* volatile TracingExport::_sampler_thread = NULL;
+
+Thread* TracingExport::sampler_thread_acquire() {
+  return (Thread*)OrderAccess::load_acquire(&_sampler_thread);
+}
+
+void TracingExport::set_sampler_thread_with_lock(Thread* thread) {
+  // Grab Threads_lock to avoid conflicts with Thread-SMR scans.
+  MutexLocker ml(Threads_lock);
+  assert(thread == NULL || _sampler_thread == NULL, "_sampler_thread should not already be set.");
+  // To match with the lock-free load_acquire():
+  OrderAccess::release_store(&_sampler_thread, thread);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/trace/tracingExport.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_TRACE_TRACINGEXPORT_HPP
+#define SHARE_VM_TRACE_TRACINGEXPORT_HPP
+
+#include "runtime/thread.hpp"
+
+class TracingExport : AllStatic {
+ public:
+  static Thread* sampler_thread_acquire();
+  static void set_sampler_thread_with_lock(Thread* thread);
+
+ private:
+  static Thread* volatile _sampler_thread;
+};
+
+#endif // SHARE_VM_TRACE_TRACINGEXPORT_HPP
--- a/src/hotspot/share/utilities/macros.hpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/utilities/macros.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -109,11 +109,13 @@
 #define CDS_ONLY(x) x
 #define NOT_CDS(x)
 #define NOT_CDS_RETURN        /* next token must be ; */
+#define NOT_CDS_RETURN0       /* next token must be ; */
 #define NOT_CDS_RETURN_(code) /* next token must be ; */
 #else
 #define CDS_ONLY(x)
 #define NOT_CDS(x) x
-#define NOT_CDS_RETURN          {}
+#define NOT_CDS_RETURN        {}
+#define NOT_CDS_RETURN0       { return 0; }
 #define NOT_CDS_RETURN_(code) { return code; }
 #endif // INCLUDE_CDS
 
@@ -141,9 +143,11 @@
 #endif // INCLUDE_ALL_GCS
 
 #if INCLUDE_ALL_GCS
+#define ALL_GCS_ONLY(x) x
 #define NOT_ALL_GCS_RETURN        /* next token must be ; */
 #define NOT_ALL_GCS_RETURN_(code) /* next token must be ; */
 #else
+#define ALL_GCS_ONLY(x)
 #define NOT_ALL_GCS_RETURN        {}
 #define NOT_ALL_GCS_RETURN_(code) { return code; }
 #endif // INCLUDE_ALL_GCS
--- a/src/hotspot/share/utilities/nativeCallStack.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/utilities/nativeCallStack.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "runtime/os.hpp"
+#include "utilities/decoder.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/nativeCallStack.hpp"
 
@@ -37,15 +38,15 @@
     // to call os::get_native_stack. A tail call is used if _NMT_NOINLINE_ is not defined
     // (which means this is not a slowdebug build), and we are on 64-bit (except Windows).
     // This is not necessarily a rule, but what has been obvserved to date.
-#define TAIL_CALL (!defined(_NMT_NOINLINE_) && !defined(WINDOWS) && defined(_LP64))
-#if !TAIL_CALL
+#if (defined(_NMT_NOINLINE_) || defined(_WINDOWS) || !defined(_LP64))
+    // Not a tail call.
     toSkip++;
 #if (defined(_NMT_NOINLINE_) && defined(BSD) && defined(_LP64))
     // Mac OS X slowdebug builds have this odd behavior where NativeCallStack::NativeCallStack
     // appears as two frames, so we need to skip an extra frame.
     toSkip++;
-#endif
-#endif
+#endif // Special-case for BSD.
+#endif // Not a tail call.
     os::get_native_stack(_stack, NMT_TrackingStackDepth, toSkip);
   } else {
     for (int index = 0; index < NMT_TrackingStackDepth; index ++) {
@@ -102,6 +103,7 @@
   address pc;
   char    buf[1024];
   int     offset;
+  int     line_no;
   if (is_empty()) {
     for (int index = 0; index < indent; index ++) out->print(" ");
     out->print("[BOOTSTRAP]");
@@ -112,10 +114,15 @@
       // Print indent
       for (int index = 0; index < indent; index ++) out->print(" ");
       if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-        out->print_cr("[" PTR_FORMAT "] %s+0x%x", p2i(pc), buf, offset);
+        out->print("[" PTR_FORMAT "] %s+0x%x", p2i(pc), buf, offset);
       } else {
-        out->print_cr("[" PTR_FORMAT "]", p2i(pc));
+        out->print("[" PTR_FORMAT "]", p2i(pc));
       }
+
+      if (Decoder::get_source_info(pc, buf, sizeof(buf), &line_no)) {
+        out->print("  (%s:%d)", buf, line_no);
+      }
+      out->cr();
     }
   }
 }
--- a/src/hotspot/share/utilities/ostream.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/utilities/ostream.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1027,6 +1027,8 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#elif defined(_WINDOWS)
+#include <winsock2.h>
 #endif
 
 // Network access
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/utilities/spinYield.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "utilities/ostream.hpp"
+#include "utilities/spinYield.hpp"
+#include "utilities/ticks.inline.hpp"
+
+SpinYield::SpinYield(uint spin_limit, uint yield_limit) :
+  _sleep_time(),
+  _spins(0),
+  _yields(0),
+  _spin_limit(os::is_MP() ? spin_limit : 0),
+  _yield_limit(yield_limit)
+{}
+
+void SpinYield::yield_or_sleep() {
+  if (_yields < _yield_limit) {
+    ++_yields;
+    os::naked_yield();
+  } else {
+    Ticks sleep_start = Ticks::now();
+    os::naked_short_sleep(1);
+    Ticks sleep_end = Ticks::now();
+    _sleep_time += (sleep_end - sleep_start);
+  }
+}
+
+static const char* print_separator(outputStream* s, const char* separator) {
+  s->print("%s", separator);
+  return ", ";
+}
+
+void SpinYield::report(outputStream* s) const {
+  const char* initial_separator = "";
+  const char* separator = initial_separator;
+  if (_spins > 0) {             // Report spins, if any.
+    separator = print_separator(s, separator);
+    s->print("spins = %u", _spins);
+  }
+  if (_yields > 0) {            // Report yields, if any.
+    separator = print_separator(s, separator);
+    s->print("yields = %u", _yields);
+  }
+  if (_sleep_time.value() != 0) { // Report sleep duration, if slept.
+    separator = print_separator(s, separator);
+    s->print("sleep = " JLONG_FORMAT " usecs",
+             TicksToTimeHelper::milliseconds(_sleep_time));
+  }
+  if (separator == initial_separator) {
+    s->print("no waiting");
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/utilities/spinYield.hpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_UTILITIES_SPINYIELD_HPP
+#define SHARE_UTILITIES_SPINYIELD_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/ticks.hpp"
+
+class outputStream;
+
+extern "C" int SpinPause();
+
+class SpinYield : public StackObj {
+  Tickspan _sleep_time;
+  uint _spins;
+  uint _yields;
+  uint _spin_limit;
+  uint _yield_limit;
+
+  void yield_or_sleep();
+
+public:
+  static const uint default_spin_limit = 4096;
+  static const uint default_yield_limit = 64;
+
+  // spin_limit is ignored (treated as zero) when !os::is_MP().
+  explicit SpinYield(uint spin_limit = default_spin_limit,
+                     uint yield_limit = default_yield_limit);
+
+  // Perform next round of delay.
+  void wait() {
+    // Simple policy: return immediately (spinning) configured number
+    // of times, then switch to yield/sleep.  Future work might
+    // provide other policies, such as (1) always spin if system is
+    // not saturated, or (2) sleeping if yielding is ineffective.
+    if (_spins < _spin_limit) {
+      ++_spins;
+      SpinPause();
+    } else {
+      yield_or_sleep();
+    }
+  }
+
+  // Write information about the wait duration to s.
+  void report(outputStream* s) const;
+};
+
+#endif // SHARE_UTILITIES_SPINYIELD_HPP
--- a/src/hotspot/share/utilities/vmError.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/hotspot/share/utilities/vmError.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1478,7 +1478,7 @@
       out.print_raw   ("/bin/sh -c ");
 #elif defined(SOLARIS)
       out.print_raw   ("/usr/bin/sh -c ");
-#elif defined(WINDOWS)
+#elif defined(_WINDOWS)
       out.print_raw   ("cmd /C ");
 #endif
       out.print_raw   ("\"");
--- a/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/aix/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -34,8 +34,6 @@
 import java.io.IOException;
 import java.io.File;
 
-// Based on linux/classes/sun/tools/attach/VirtualMachineImpl.java.
-
 /*
  * Aix implementation of HotSpotVirtualMachine
  */
@@ -140,7 +138,7 @@
      * Execute the given command in the target VM.
      */
     InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
-        assert args.length <= 3;            // includes null
+        assert args.length <= 3;                // includes null
 
         // did we detach?
         synchronized (this) {
@@ -261,7 +259,7 @@
         }
     }
 
-    // On Solaris/Linux/Aix a simple handshake is used to start the attach mechanism
+    // On Aix a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid<pid> file in the
     // target VM's working directory (or temp directory), and the SIGQUIT handler
     // checks for the file.
--- a/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/aix/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:25:13 2018 +0200
@@ -1,6 +1,6 @@
 /*
- * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2015 SAP SE. All rights reserved.
+ * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, SAP SE. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,27 +24,18 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
-#include "jvm.h"
 
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-
-/*
- * Based on 'LinuxVirtualMachine.c'. Non-relevant code has been removed and all
- * occurrences of the string "Linux" have been replaced by "Aix".
- */
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -67,15 +58,6 @@
     if (fd == -1) {
         JNU_ThrowIOExceptionWithLastError(env, "socket");
     }
-    /* added time out values */
-    else {
-        struct timeval tv;
-        tv.tv_sec = 2 * 60;
-        tv.tv_usec = 0;
-
-        setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv));
-        setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char*)&tv, sizeof(tv));
-    }
     return (jint)fd;
 }
 
@@ -125,23 +107,6 @@
     }
 }
 
-
-/*
- * Structure and callback function used to send a QUIT signal to all
- * children of a given process
- */
-typedef struct {
-    pid_t ppid;
-} SendQuitContext;
-
-static void SendQuitCallback(const pid_t pid, void* user_data) {
-    SendQuitContext* context = (SendQuitContext*)user_data;
-    pid_t parent = getParent(pid);
-    if (parent == context->ppid) {
-        kill(pid, SIGQUIT);
-    }
-}
-
 /*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    sendQuitTo
@@ -169,7 +134,7 @@
         struct stat64 sb;
         uid_t uid, gid;
         int res;
-        /* added missing initialization of the stat64 buffer */
+
         memset(&sb, 0, sizeof(struct stat64));
 
         /*
@@ -189,21 +154,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
@@ -229,11 +194,7 @@
   (JNIEnv *env, jclass cls, jint fd)
 {
     int res;
-    /* Fixed deadlock when this call of close by the client is not seen by the attach server
-     * which has accepted the (very short) connection already and is waiting for the request. But read don't get a byte,
-     * because the close is lost without shutdown.
-     */
-    shutdown(fd, 2);
+    shutdown(fd, SHUT_RDWR);
     RESTARTABLE(close(fd), res);
 }
 
--- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -105,7 +105,7 @@
             } finally {
                 f.delete();
             }
-      }
+        }
 
         // Check that the file owner/permission to avoid attaching to
         // bogus process
@@ -274,7 +274,7 @@
         return new File(root, ".java_pid" + ns_pid);
     }
 
-    // On Solaris/Linux a simple handshake is used to start the attach mechanism
+    // On Linux a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid<pid> file in the
     // target VM's working directory (or temp directory), and the SIGQUIT handler
     // checks for the file.
@@ -356,8 +356,6 @@
 
     //-- native methods
 
-    static native void sendQuitToChildrenOf(int pid) throws IOException;
-
     static native void sendQuitTo(int pid) throws IOException;
 
     static native void checkPermissions(String path) throws IOException;
--- a/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/linux/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,23 +23,18 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
-#include "jvm.h"
 
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/un.h>
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -55,85 +50,6 @@
 DEF_STATIC_JNI_OnLoad
 
 /*
- * Defines a callback that is invoked for each process
- */
-typedef void (*ProcessCallback)(const pid_t pid, void* user_data);
-
-/*
- * Invokes the callback function for each process
- */
-static void forEachProcess(ProcessCallback f, void* user_data) {
-    DIR* dir;
-    struct dirent* ptr;
-
-    /*
-     * To locate the children we scan /proc looking for files that have a
-     * position integer as a filename.
-     */
-    if ((dir = opendir("/proc")) == NULL) {
-        return;
-    }
-    while ((ptr = readdir(dir)) != NULL) {
-        pid_t pid;
-
-        /* skip current/parent directories */
-        if (strcmp(ptr->d_name, ".") == 0 || strcmp(ptr->d_name, "..") == 0) {
-            continue;
-        }
-
-        /* skip files that aren't numbers */
-        pid = (pid_t)atoi(ptr->d_name);
-        if ((int)pid <= 0) {
-            continue;
-        }
-
-        /* invoke the callback */
-        (*f)(pid, user_data);
-    }
-    closedir(dir);
-}
-
-
-/*
- * Returns the parent pid of a given pid, or -1 if not found
- */
-static pid_t getParent(pid_t pid) {
-    char state;
-    FILE* fp;
-    char stat[2048];
-    int statlen;
-    char fn[32];
-    int i, p;
-    char* s;
-
-    /*
-     * try to open /proc/%d/stat
-     */
-    sprintf(fn, "/proc/%d/stat", pid);
-    fp = fopen(fn, "r");
-    if (fp == NULL) {
-        return -1;
-    }
-
-    /*
-     * The format is: pid (command) state ppid ...
-     * As the command could be anything we must find the right most
-     * ")" and then skip the white spaces that follow it.
-     */
-    statlen = fread(stat, 1, 2047, fp);
-    stat[statlen] = '\0';
-    fclose(fp);
-    s = strrchr(stat, ')');
-    if (s == NULL) {
-        return -1;
-    }
-    do s++; while (isspace(*s));
-    i = sscanf(s, "%c %d", &state, &p);
-    return (pid_t)p;
-}
-
-
-/*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    socket
  * Signature: ()I
@@ -195,39 +111,6 @@
 }
 
 /*
- * Structure and callback function used to send a QUIT signal to all
- * children of a given process
- */
-typedef struct {
-    pid_t ppid;
-} SendQuitContext;
-
-static void SendQuitCallback(const pid_t pid, void* user_data) {
-    SendQuitContext* context = (SendQuitContext*)user_data;
-    pid_t parent = getParent(pid);
-    if (parent == context->ppid) {
-        kill(pid, SIGQUIT);
-    }
-}
-
-/*
- * Class:     sun_tools_attach_VirtualMachineImpl
- * Method:    sendQuitToChildrenOf
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_sendQuitToChildrenOf
-  (JNIEnv *env, jclass cls, jint pid)
-{
-    SendQuitContext context;
-    context.ppid = (pid_t)pid;
-
-    /*
-     * Iterate over all children of 'pid' and send a QUIT signal to each.
-     */
-    forEachProcess(SendQuitCallback, (void*)&context);
-}
-
-/*
  * Class:     sun_tools_attach_VirtualMachineImpl
  * Method:    sendQuitTo
  * Signature: (I)V
@@ -255,6 +138,8 @@
         uid_t uid, gid;
         int res;
 
+        memset(&sb, 0, sizeof(struct stat64));
+
         /*
          * Check that the path is owned by the effective uid/gid of this
          * process. Also check that group/other access is not allowed.
@@ -272,21 +157,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
@@ -312,6 +197,7 @@
   (JNIEnv *env, jclass cls, jint fd)
 {
     int res;
+    shutdown(fd, SHUT_RDWR);
     RESTARTABLE(close(fd), res);
 }
 
@@ -366,8 +252,8 @@
 
         RESTARTABLE(write(fd, buf, len), n);
         if (n > 0) {
-           off += n;
-           remaining -= n;
+            off += n;
+            remaining -= n;
         } else {
             JNU_ThrowIOExceptionWithLastError(env, "write");
             return;
--- a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -281,8 +281,7 @@
     }
 
     private File createAttachFile(int pid) throws IOException {
-        String fn = ".attach_pid" + pid;
-        File f = new File(tmpdir, fn);
+        File f = new File(tmpdir, ".attach_pid" + pid);
         createAttachFile0(f.getPath());
         return f;
     }
--- a/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,24 +23,20 @@
  * questions.
  */
 
-#include "jni.h"
 #include "jni_util.h"
-#include "jvm.h"
 
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/syslimits.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
 #include <unistd.h>
-#include <signal.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/syslimits.h>
-#include <sys/un.h>
-#include <fcntl.h>
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -144,6 +140,8 @@
         uid_t uid, gid;
         int res;
 
+        memset(&sb, 0, sizeof(struct stat));
+
         /*
          * Check that the path is owned by the effective uid/gid of this
          * process. Also check that group/other access is not allowed.
@@ -161,21 +159,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
@@ -201,6 +199,7 @@
   (JNIEnv *env, jclass cls, jint fd)
 {
     int res;
+    shutdown(fd, SHUT_RDWR);
     RESTARTABLE(close(fd), res);
 }
 
@@ -255,8 +254,8 @@
 
         RESTARTABLE(write(fd, buf, len), n);
         if (n > 0) {
-           off += n;
-           remaining -= n;
+            off += n;
+            remaining -= n;
         } else {
             JNU_ThrowIOExceptionWithLastError(env, "write");
             return;
--- a/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/solaris/classes/sun/tools/attach/VirtualMachineImpl.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -225,7 +225,7 @@
         return fd;
     }
 
-    // On Solaris/Linux a simple handshake is used to start the attach mechanism
+    // On Solaris a simple handshake is used to start the attach mechanism
     // if not already started. The client creates a .attach_pid<pid> file in the
     // target VM's working directory (or temporary directory), and the SIGQUIT
     // handler checks for the file.
--- a/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/solaris/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:25:13 2018 +0200
@@ -22,20 +22,19 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+#include "jni_util.h"
+
+#include <sys/stat.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <door.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
 #include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <limits.h>
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
+#include <unistd.h>
 
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
@@ -105,6 +104,8 @@
         uid_t uid, gid;
         int res;
 
+        memset(&sb, 0, sizeof(struct stat64));
+
         /*
          * Check that the path is owned by the effective uid/gid of this
          * process. Also check that group/other access is not allowed.
@@ -122,21 +123,21 @@
             char msg[100];
             jboolean isError = JNI_FALSE;
             if (sb.st_uid != uid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should be owned by the current user (which is %d) but is owned by %d", uid, sb.st_uid);
                 isError = JNI_TRUE;
             } else if (sb.st_gid != gid) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file's group should be the current group (which is %d) but the group is %d", gid, sb.st_gid);
                 isError = JNI_TRUE;
             } else if ((sb.st_mode & (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) != 0) {
-                jio_snprintf(msg, sizeof(msg)-1,
+                snprintf(msg, sizeof(msg),
                     "file should only be readable and writable by the owner but has 0%03o access", sb.st_mode & 0777);
                 isError = JNI_TRUE;
             }
             if (isError) {
                 char buf[256];
-                jio_snprintf(buf, sizeof(buf)-1, "well-known file %s is not secure: %s", p, msg);
+                snprintf(buf, sizeof(buf), "well-known file %s is not secure: %s", p, msg);
                 JNU_ThrowIOException(env, buf);
             }
         } else {
--- a/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.attach/windows/native/libattach/VirtualMachineImpl.c	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,16 +22,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
+#include "jni_util.h"
+
 #include <windows.h>
 #include <Sddl.h>
 #include <string.h>
 
-#include "jni.h"
-#include "jni_util.h"
-
 #include "sun_tools_attach_VirtualMachineImpl.h"
 
-
 /* kernel32 */
 typedef HINSTANCE (WINAPI* GetModuleHandleFunc) (LPCTSTR);
 typedef FARPROC (WINAPI* GetProcAddressFunc)(HMODULE, LPCSTR);
@@ -303,9 +302,7 @@
     LocalFree(sa.lpSecurityDescriptor);
 
     if (hPipe == INVALID_HANDLE_VALUE) {
-        char msg[256];
-        _snprintf(msg, sizeof(msg), "CreateNamedPipe failed: %d", GetLastError());
-        JNU_ThrowIOExceptionWithLastError(env, msg);
+        JNU_ThrowIOExceptionWithLastError(env, "CreateNamedPipe failed");
     }
     return (jlong)hPipe;
 }
@@ -318,7 +315,7 @@
 JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_closePipe
   (JNIEnv *env, jclass cls, jlong hPipe)
 {
-    CloseHandle( (HANDLE)hPipe );
+    CloseHandle((HANDLE)hPipe);
 }
 
 /*
@@ -430,7 +427,7 @@
             if ((*env)->ExceptionOccurred(env)) return;
         }
     }
-    for (i=argsLen; i<MAX_ARGS; i++) {
+    for (i = argsLen; i < MAX_ARGS; i++) {
         data.arg[i][0] = '\0';
     }
 
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Tue Apr 17 15:25:13 2018 +0200
@@ -380,9 +380,7 @@
     public final int javaThreadAnchorOffset = getFieldOffset("JavaThread::_anchor", Integer.class, "JavaFrameAnchor");
     public final int threadObjectOffset = getFieldOffset("JavaThread::_threadObj", Integer.class, "oop");
     public final int osThreadOffset = getFieldOffset("JavaThread::_osthread", Integer.class, "OSThread*");
-    public final int javaThreadDirtyCardQueueOffset = getFieldOffset("JavaThread::_dirty_card_queue", Integer.class, "DirtyCardQueue");
     public final int threadIsMethodHandleReturnOffset = getFieldOffset("JavaThread::_is_method_handle_return", Integer.class, "int");
-    public final int javaThreadSatbMarkQueueOffset = getFieldOffset("JavaThread::_satb_mark_queue", Integer.class);
     public final int threadObjectResultOffset = getFieldOffset("JavaThread::_vm_result", Integer.class, "oop");
     public final int jvmciCountersThreadOffset = getFieldOffset("JavaThread::_jvmci_counters", Integer.class, "jlong*");
     public final int javaThreadReservedStackActivationOffset = getFieldOffset("JavaThread::_reserved_stack_activation", Integer.class, "address", intNotPresentInJDK8);
@@ -455,13 +453,6 @@
     public final int frameInterpreterFrameSenderSpOffset = getConstant("frame::interpreter_frame_sender_sp_offset", Integer.class, intRequiredOnAMD64);
     public final int frameInterpreterFrameLastSpOffset = getConstant("frame::interpreter_frame_last_sp_offset", Integer.class, intRequiredOnAMD64);
 
-    private final int dirtyCardQueueBufferOffset = isJDK8 ? getFieldOffset("PtrQueue::_buf", Integer.class, "void**") : getConstant("dirtyCardQueueBufferOffset", Integer.class);
-    private final int dirtyCardQueueIndexOffset = isJDK8 ? getFieldOffset("PtrQueue::_index", Integer.class, "size_t") : getConstant("dirtyCardQueueIndexOffset", Integer.class);
-
-    private final int satbMarkQueueBufferOffset = getConstant("satbMarkQueueBufferOffset", Integer.class, intNotPresentInJDK8);
-    private final int satbMarkQueueIndexOffset = getConstant("satbMarkQueueIndexOffset", Integer.class, intNotPresentInJDK8);
-    private final int satbMarkQueueActiveOffset = isJDK8 ? getFieldOffset("PtrQueue::_active", Integer.class, "bool") : getConstant("satbMarkQueueActiveOffset", Integer.class, intNotPresentInJDK8);
-
     public final int osThreadInterruptedOffset = getFieldOffset("OSThread::_interrupted", Integer.class, "jint");
 
     public final long markOopDescHashShift = getConstant("markOopDesc::hash_shift", Long.class);
@@ -575,25 +566,11 @@
 
     // G1 Collector Related Values.
 
-    public int g1CardQueueIndexOffset() {
-        return javaThreadDirtyCardQueueOffset + dirtyCardQueueIndexOffset;
-    }
-
-    public int g1CardQueueBufferOffset() {
-        return javaThreadDirtyCardQueueOffset + dirtyCardQueueBufferOffset;
-    }
-
-    public int g1SATBQueueMarkingOffset() {
-        return javaThreadSatbMarkQueueOffset + satbMarkQueueActiveOffset;
-    }
-
-    public int g1SATBQueueIndexOffset() {
-        return javaThreadSatbMarkQueueOffset + (isJDK8 ? dirtyCardQueueIndexOffset : satbMarkQueueIndexOffset);
-    }
-
-    public int g1SATBQueueBufferOffset() {
-        return javaThreadSatbMarkQueueOffset + (isJDK8 ? dirtyCardQueueBufferOffset : satbMarkQueueBufferOffset);
-    }
+    public final int g1SATBQueueMarkingOffset = getConstant("G1ThreadLocalData::satb_mark_queue_active_offset", Integer.class);
+    public final int g1SATBQueueIndexOffset = getConstant("G1ThreadLocalData::satb_mark_queue_index_offset", Integer.class);
+    public final int g1SATBQueueBufferOffset = getConstant("G1ThreadLocalData::satb_mark_queue_buffer_offset", Integer.class);
+    public final int g1CardQueueIndexOffset = getConstant("G1ThreadLocalData::dirty_card_queue_index_offset", Integer.class);
+    public final int g1CardQueueBufferOffset = getConstant("G1ThreadLocalData::dirty_card_queue_buffer_offset", Integer.class);
 
     public final int klassOffset = getFieldValue("java_lang_Class::_klass_offset", Integer.class, "int");
     public final int arrayKlassOffset = getFieldValue("java_lang_Class::_array_klass_offset", Integer.class, "int");
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Tue Apr 17 15:25:13 2018 +0200
@@ -631,12 +631,12 @@
 
     @Fold
     public static int g1CardQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.g1CardQueueIndexOffset();
+        return config.g1CardQueueIndexOffset;
     }
 
     @Fold
     public static int g1CardQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.g1CardQueueBufferOffset();
+        return config.g1CardQueueBufferOffset;
     }
 
     @Fold
@@ -646,17 +646,17 @@
 
     @Fold
     public static int g1SATBQueueMarkingOffset(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.g1SATBQueueMarkingOffset();
+        return config.g1SATBQueueMarkingOffset;
     }
 
     @Fold
     public static int g1SATBQueueIndexOffset(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.g1SATBQueueIndexOffset();
+        return config.g1SATBQueueIndexOffset;
     }
 
     @Fold
     public static int g1SATBQueueBufferOffset(@InjectedParameter GraalHotSpotVMConfig config) {
-        return config.g1SATBQueueBufferOffset();
+        return config.g1SATBQueueBufferOffset;
     }
 
     public static final LocationIdentity KLASS_SUPER_CHECK_OFFSET_LOCATION = NamedLocationIdentity.immutable("Klass::_super_check_offset");
--- a/test/hotspot/gtest/gc/shared/test_oopStorage.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/gtest/gc/shared/test_oopStorage.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -856,9 +856,6 @@
   vstate.check();
 }
 
-// Parallel iteration not available unless INCLUDE_ALL_GCS
-#if INCLUDE_ALL_GCS
-
 class OopStorageTestParIteration : public OopStorageTestIteration {
 public:
   WorkGang* workers();
@@ -1017,8 +1014,6 @@
   vstate.check();
 }
 
-#endif // INCLUDE_ALL_GCS
-
 TEST_VM_F(OopStorageTestWithAllocation, delete_empty_blocks_safepoint) {
   TestAccess::BlockList& active_list = TestAccess::active_list(_storage);
 
@@ -1384,4 +1379,3 @@
   }
   EXPECT_EQ(NULL_BLOCK, active_block);
 }
-
--- a/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/gtest/gc/shared/test_preservedMarks.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,6 +23,7 @@
 
 #include "precompiled.hpp"
 #include "gc/shared/preservedMarks.inline.hpp"
+#include "oops/oop.inline.hpp"
 #include "unittest.hpp"
 
 class ScopedDisabledBiasedLocking {
@@ -38,14 +39,14 @@
   oopDesc _oop;
 
 public:
-  FakeOop() : _oop() { _oop.set_mark(originalMark()); }
+  FakeOop() : _oop() { _oop.set_mark_raw(originalMark()); }
 
   oop get_oop() { return &_oop; }
-  markOop mark() { return _oop.mark(); }
-  void set_mark(markOop m) { _oop.set_mark(m); }
+  markOop mark() { return _oop.mark_raw(); }
+  void set_mark(markOop m) { _oop.set_mark_raw(m); }
   void forward_to(oop obj) {
     markOop m = markOopDesc::encode_pointer_as_mark(obj);
-    _oop.set_mark(m);
+    _oop.set_mark_raw(m);
   }
 
   static markOop originalMark() { return markOop(markOopDesc::lock_mask_in_place); }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/gtest/utilities/test_spinYield.cpp	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "utilities/ostream.hpp"
+#include "utilities/spinYield.hpp"
+#include "unittest.hpp"
+
+// Some basic tests of SpinYield, using comparison of report output with
+// expected results to verify state.  This is all very hard-wired to the
+// current implementation of SpinYield, esp. the report function.
+
+static void check_report(const SpinYield* spinner, const char* expected) {
+  char buffer[100];
+  stringStream s(buffer, sizeof(buffer));
+  spinner->report(&s);
+  ASSERT_STREQ(expected, buffer);
+}
+
+TEST(SpinYield, no_waiting) {
+  SpinYield spinner;
+  check_report(&spinner, "no waiting");
+}
+
+TEST(SpinYield, one_wait) {
+  SpinYield spinner(100);
+  spinner.wait();
+  check_report(&spinner, os::is_MP() ? "spins = 1" : "yields = 1");
+}
+
+TEST(SpinYield, ten_waits) {
+  SpinYield spinner(100, 100);
+  for (unsigned i = 0; i < 10; ++i) {
+    spinner.wait();
+  }
+  check_report(&spinner, os::is_MP() ? "spins = 10" : "yields = 10");
+}
+
+TEST(SpinYield, two_yields) {
+  SpinYield spinner(0, 10);
+  spinner.wait();
+  spinner.wait();
+  check_report(&spinner, "yields = 2");
+}
+
+TEST(SpinYield, one_sleep) {
+  SpinYield spinner(0, 0);
+  spinner.wait();
+
+  char buffer[100];
+  stringStream s(buffer, sizeof(buffer));
+  spinner.report(&s);
+
+  const char* expected = "sleep = ";
+  ASSERT_TRUE(strncmp(expected, buffer, strlen(expected)) == 0);
+}
+
+TEST(SpinYield, one_spin_one_sleep) {
+  SpinYield spinner(1, 0);
+  spinner.wait();
+  spinner.wait();
+
+  char buffer[100];
+  stringStream s(buffer, sizeof(buffer));
+  spinner.report(&s);
+
+  const char* expected_MP = "spins = 1, sleep = ";
+  const char* expected_UP = "sleep = ";
+  const char* expected = os::is_MP() ? expected_MP : expected_UP;
+  ASSERT_TRUE(strncmp(expected, buffer, strlen(expected)) == 0);
+}
--- a/test/hotspot/jtreg/TEST.groups	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/TEST.groups	Tue Apr 17 15:25:13 2018 +0200
@@ -177,7 +177,7 @@
 
 tier1_runtime = \
   runtime/ \
- -runtime/6626217/Test6626217.sh \
+ -runtime/6626217/bug_21227.java \
  -runtime/7100935 \
  -runtime/7158988/FieldMonitor.java \
  -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
@@ -265,7 +265,8 @@
  -:tier1_runtime \
  -:tier1_serviceability \
  -:hotspot_tier2_runtime_platform_agnostic \
- -runtime/signal
+ -runtime/signal \
+ -runtime/NMT/MallocStressTest.java
 
 hotspot_tier2_runtime_platform_agnostic = \
   runtime/SelectionResolution \
--- a/test/hotspot/jtreg/runtime/6626217/Loader2.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/6626217/Loader2.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -36,7 +36,7 @@
     print("Fetching the implementation of "+name);
     int old = _recur;
     try {
-      FileInputStream fi = new FileInputStream(name+".impl2");
+      FileInputStream fi = new FileInputStream(name+".class");
       byte result[] = new byte[fi.available()];
       fi.read(result);
 
--- a/test/hotspot/jtreg/runtime/6626217/Test6626217.sh	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,75 +0,0 @@
-# 
-#  Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved.
-#  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 @(#)Test6626217.sh
-# @bug 6626217
-# @summary Loader-constraint table allows arrays instead of only the base-classes
-# @run shell Test6626217.sh
-#
-## some tests require path to find test source dir
-if [ "${TESTSRC}" = "" ]
-then
-  TESTSRC=${PWD}
-  echo "TESTSRC not set.  Using "${TESTSRC}" as default"
-fi
-echo "TESTSRC=${TESTSRC}"
-## Adding common setup Variables for running shell tests.
-. ${TESTSRC}/../../test_env.sh
-
-JAVA=${TESTJAVA}${FS}bin${FS}java
-JAVAC=${COMPILEJAVA}${FS}bin${FS}javac
-
-# Current directory is scratch directory, copy all the test source there
-# (for the subsequent moves to work).
-${CP} ${TESTSRC}${FS}* ${THIS_DIR}
-
-# A Clean Compile: this line will probably fail within jtreg as have a clean dir:
-${RM} -f *.class *.impl many_loader.java
-
-# Make sure that the compilation steps occurs in the future as not to allow fast systems
-# to copy and compile bug_21227.java so fast as to make the class and java have the same
-# time stamp, which later on would make the compilation step of many_loader.java fail
-sleep 2
-
-# Compile all the usual suspects, including the default 'many_loader'
-${CP} many_loader1.java.foo many_loader.java
-${JAVAC} ${TESTJAVACOPTS} -Xlint *.java
-
-# Rename the class files, so the custom loader (and not the system loader) will find it
-${MV} from_loader2.class from_loader2.impl2
-
-# Compile the next version of 'many_loader'
-${MV} many_loader.class many_loader.impl1
-${CP} many_loader2.java.foo many_loader.java
-${JAVAC} ${TESTJAVACOPTS} -Xlint many_loader.java
-
-# Rename the class file, so the custom loader (and not the system loader) will find it
-${MV} many_loader.class many_loader.impl2
-${MV} many_loader.impl1 many_loader.class
-${RM} many_loader.java
-
-${JAVA} ${TESTOPTS} -Xverify -Xint -cp . bug_21227 >test.out 2>&1
-grep "loader constraint" test.out
-exit $?
-
--- a/test/hotspot/jtreg/runtime/6626217/bug_21227.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/6626217/bug_21227.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,63 +22,85 @@
  *
  */
 
+/**
+ * @test
+ * @bug 6626217
+ * @summary Loader-constraint table allows arrays instead of only the base-classes
+ * @library /test/lib
+ * @compile bug_21227.java from_loader2.java
+ * @run driver ClassFileInstaller from_loader2
+ * @compile impl2/many_loader.java
+ * @run driver ClassFileInstaller many_loader
+ * @compile many_loader.java
+ * @run main/othervm -Xverify -Xint bug_21227
+ */
+
 import java.lang.reflect.*;
 import java.security.*;
 
 abstract public class bug_21227 {
 
-  // Jam anything you want in here, it will be cast to a You_Have_Been_P0wned
-  public static Object _p0wnee;
+    // Jam anything you want in here, it will be cast to a You_Have_Been_P0wned.
+    public static Object _p0wnee;
 
-  public static void main(String argv[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
-    System.out.println("Warmup");
+    public static void main(String argv[]) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
+        try {
+            System.out.println("Warmup");
 
-    // Make a Class 'many_loader' under the default loader
-    bug_21227 bug = new many_loader();
+            // Make a Class 'many_loader' under the default loader.
+            bug_21227 bug = new many_loader();
 
-    // Some classes under a new Loader, LOADER2, including another version of 'many_loader'
-    ClassLoader LOADER2 = new Loader2();
-    Class clazz2 = LOADER2.loadClass("from_loader2");
-    IFace iface = (IFace)clazz2.newInstance();
+            // Some classes under a new Loader, LOADER2, including another version of 'many_loader'.
+            ClassLoader LOADER2 = new Loader2();
+            Class clazz2 = LOADER2.loadClass("from_loader2");
+            IFace iface = (IFace)clazz2.newInstance();
 
-    // Set the victim, a String of length 6
-    String s = "victim";
-    _p0wnee = s;
+            // Set the victim, a String of length 6.
+            String s = "victim";
+            _p0wnee = s;
 
-    // Go cast '_p0wnee' to type You_Have_Been_P0wned
-    many_loader[] x2 = bug.make(iface);
+            // Go cast '_p0wnee' to type You_Have_Been_P0wned.
+            many_loader[] x2 = bug.make(iface);
 
-    many_loader b = x2[0];
+            many_loader b = x2[0];
 
-    // Make it clear that the runtime type many_loader (what we get from the
-    // array X2) varies from the static type of many_loader.
-    Class cl1 = b.getClass();
-    ClassLoader ld1 = cl1.getClassLoader();
-    Class cl2 = many_loader.class;
-    ClassLoader ld2 = cl2.getClassLoader();
-    System.out.println("bug.make()  "+ld1+":"+cl1);
-    System.out.println("many_loader "+ld2+":"+cl2);
+            // Make it clear that the runtime type many_loader (what we get from the
+            // array X2) varies from the static type of many_loader.
+            Class cl1 = b.getClass();
+            ClassLoader ld1 = cl1.getClassLoader();
+            Class cl2 = many_loader.class;
+            ClassLoader ld2 = cl2.getClassLoader();
+            System.out.println("bug.make()  "+ld1+":"+cl1);
+            System.out.println("many_loader "+ld2+":"+cl2);
+
+            // Read the victims guts out.
+            You_Have_Been_P0wned q = b._p0wnee;
+            System.out.println("q._a = 0x"+Integer.toHexString(q._a));
+            System.out.println("q._b = 0x"+Integer.toHexString(q._b));
+            System.out.println("q._c = 0x"+Integer.toHexString(q._c));
+            System.out.println("q._d = 0x"+Integer.toHexString(q._d));
 
-    // Read the victims guts out
-    You_Have_Been_P0wned q = b._p0wnee;
-    System.out.println("q._a = 0x"+Integer.toHexString(q._a));
-    System.out.println("q._b = 0x"+Integer.toHexString(q._b));
-    System.out.println("q._c = 0x"+Integer.toHexString(q._c));
-    System.out.println("q._d = 0x"+Integer.toHexString(q._d));
+            System.out.println("I will now crash the VM:");
+            // On 32-bit HotSpot Java6 this sets the victim String length shorter, then crashes the VM.
+            //q._c = 3;
+            q._a = -1;
 
-    System.out.println("I will now crash the VM:");
-    // On 32-bit HotSpot Java6 this sets the victim String length shorter, then crashes the VM
-    //q._c = 3;
-    q._a = -1;
-
-    System.out.println(s);
+            System.out.println(s);
+            throw new RuntimeException("Expected LinkageError was not thrown.");
+        } catch (LinkageError e) {
+            String errorMsg = e.getMessage();
+            if (!errorMsg.contains("loader constraint")) {
+                throw new RuntimeException("Error message of LinkageError does not contain \"loader constraint\":" +
+                                           errorMsg);
+            }
+            System.out.println("Passed with message: " + errorMsg);
+        }
+    }
 
-  }
-
-  // I need to compile (hence call in a loop) a function which returns a value
-  // loaded from classloader other than the system one.  The point of this
-  // call is to give me an abstract 'hook' into a function loaded with a
-  // foreign loader.
-  public abstract many_loader[] make( IFace iface ); // abstract factory
+    // I need to compile (hence call in a loop) a function which returns a value
+    // loaded from classloader other than the system one.  The point of this
+    // call is to give me an abstract 'hook' into a function loaded with a
+    // foreign loader.
+    public abstract many_loader[] make(IFace iface); // abstract factory
 }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/6626217/impl2/many_loader.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// A simple class to extend an abstract class and get loaded with different
+// loaders. This class is loaded via LOADER2. A similar named class will
+// be loaded via LOADER1.
+public class many_loader extends bug_21227 {
+    final Object _ref_to_be_p0wned;
+
+    many_loader() {
+        _ref_to_be_p0wned = bug_21227._p0wnee;
+        System.out.println("Gonna hack this thing: " + _ref_to_be_p0wned.toString() );
+    }
+
+    // I need to compile (hence call in a loop) a function which returns a value
+    // loaded from classloader other than the system one. The point of this
+    // call is to give me an abstract 'hook' into a function loaded with a
+    // foreign loader.
+    public many_loader[] make(IFace iface) {
+        throw new Error("do not call me");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/6626217/many_loader.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2010, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+// A simple class to extend an abstract class and get loaded with different
+// loaders. This class is loaded via LOADER1. A similar named class will
+// be loaded via LOADER2.
+public class many_loader extends bug_21227 {
+    public You_Have_Been_P0wned _p0wnee;
+
+    // I need to compile (hence call in a loop) a function which returns a value
+    // loaded from classloader other than the system one. The point of this
+    // call is to give me an abstract 'hook' into a function loaded with a
+    // foreign loader.
+
+    // The original 'make(boolean)' returns a bug_21227. The VM will inject a
+    // synthetic method to up-cast the returned 'from_loader1' into a
+    // 'bug_21227'.
+    public many_loader[] make(IFace iface) {
+        // This function needs to return a value known to be loaded from LOADER2.
+        // Since I need to use a yet different loader, I need to make an unknown
+        // foreign call. In this case I'll be using an interface to make the
+        // unknown call, with but a single implementor so the compiler can do the
+        // upcast statically.
+        return iface==null ? null : iface.gen();
+    }
+}
--- a/test/hotspot/jtreg/runtime/6626217/many_loader1.java.foo	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * 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 simple class to extend an abstract class and get loaded with different
-// loaders.  This class is loaded via LOADER1.  A similar named class will
-// be loaded via LOADER2.
-public class many_loader extends bug_21227 {
-  public You_Have_Been_P0wned _p0wnee;
-
-  // I need to compile (hence call in a loop) a function which returns a value
-  // loaded from classloader other than the system one.  The point of this
-  // call is to give me an abstract 'hook' into a function loaded with a
-  // foreign loader.
-
-  // The original 'make(boolean)' returns a bug_21227.  The VM will inject a
-  // synthetic method to up-cast the returned 'from_loader1' into a
-  // 'bug_21227'.
-  public many_loader[] make( IFace iface ) { 
-    // This function needs to return a value known to be loaded from LOADER2.
-    // Since I need to use a yet different loader, I need to make an unknown
-    // foreign call.  In this case I'll be using an interface to make the
-    // unknown call, with but a single implementor so the compiler can do the
-    // upcast statically.
-    return iface==null ? null : iface.gen(); 
-  }
-}
--- a/test/hotspot/jtreg/runtime/6626217/many_loader2.java.foo	Tue Apr 17 15:39:20 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,43 +0,0 @@
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- * 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 simple class to extend an abstract class and get loaded with different
-// loaders.  This class is loaded via LOADER2.  A similar named class will
-// be loaded via LOADER1.
-public class many_loader extends bug_21227 {
-  final Object _ref_to_be_p0wned;
-
-  many_loader() {
-    _ref_to_be_p0wned = bug_21227._p0wnee;
-    System.out.println("Gonna hack this thing: " + _ref_to_be_p0wned.toString() );
-  }
-
-  // I need to compile (hence call in a loop) a function which returns a value
-  // loaded from classloader other than the system one.  The point of this
-  // call is to give me an abstract 'hook' into a function loaded with a
-  // foreign loader.
-  public many_loader[] make( IFace iface ) { 
-    throw new Error("do not call me");
-  }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/ClassFile/PreviewVersion.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8198908
+ * @summary Check that preview minor version and --enable-preview are handled
+ *          correctly.
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib
+ * @run main PreviewVersion
+ */
+
+import java.io.File;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+import jdk.test.lib.ByteCodeLoader;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class PreviewVersion {
+
+    public static void main(String args[]) throws Throwable {
+        System.out.println("Regression test for bug 8198908");
+
+        byte klassbuf[] = InMemoryJavaCompiler.compile("PVTest",
+            "public class PVTest { " +
+                "public static void main(String argv[]) { " +
+                    "System.out.println(\"Hi!\"); } }");
+
+        // Set class's minor version to 65535.
+        klassbuf[4] = -1;
+        klassbuf[5] = -1;
+
+        // Run the test. This should fail because --enable-preview is not specified.
+        ClassFileInstaller.writeClassToDisk("PVTest", klassbuf, System.getProperty("test.classes"));
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-cp", "." + File.pathSeparator + System.getProperty("test.classes"), "PVTest");
+        OutputAnalyzer oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("Preview features are not enabled");
+        oa.shouldHaveExitValue(1);
+
+        // This should be successful because --enable-preview is specified.
+        pb = ProcessTools.createJavaProcessBuilder("--enable-preview",
+            "-cp", "." + File.pathSeparator + System.getProperty("test.classes"), "PVTest");
+        oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("Hi!");
+
+        // Test -Xlog:class+preview
+        pb = ProcessTools.createJavaProcessBuilder("--enable-preview", "-Xlog:class+preview",
+            "-cp", "." + File.pathSeparator + System.getProperty("test.classes"), "PVTest");
+        oa = new OutputAnalyzer(pb.start());
+        oa.shouldContain("[info][class,preview] Loading preview feature type PVTest");
+
+        // Subtract 1 from class's major version.  The class should fail to load
+        // because its major_version does not match the JVM current version.
+        int prev_major_version = Runtime.version().feature() - 1;
+        klassbuf[6] = (byte)((prev_major_version >> 8) & 0xff);
+        klassbuf[7] = (byte)(prev_major_version & 0xff);
+        try {
+            ByteCodeLoader.load("PVTest", klassbuf);
+            throw new RuntimeException("UnsupportedClassVersionError exception not thrown");
+        } catch (java.lang.UnsupportedClassVersionError e) {
+            if (!e.getMessage().contains("compiled with preview features that are unsupported")) {
+                throw new RuntimeException(
+                    "Wrong UnsupportedClassVersionError exception: " + e.getMessage());
+            }
+        }
+
+        // Set class's major version to 45.  The class should load because class
+        // version 45.65535 is valid.
+        klassbuf[6] = 0;
+        klassbuf[7] = 45;
+        try {
+            ByteCodeLoader.load("PVTest", klassbuf);
+        } catch (java.lang.UnsupportedClassVersionError e) {
+            throw new RuntimeException(
+                "Unexpected UnsupportedClassVersionError exception thrown: " + e.getMessage());
+        }
+
+        // Check that a class with a recent older major version and a non-zero
+        // minor version fails to load.
+        klassbuf[6] = 0;
+        klassbuf[7] = 53;
+        klassbuf[4] = 0;
+        klassbuf[5] = 2;
+        try {
+            ByteCodeLoader.load("PVTest", klassbuf);
+            throw new RuntimeException("UnsupportedClassVersionError exception not thrown");
+        } catch (java.lang.UnsupportedClassVersionError e) {
+            if (!e.getMessage().contains("was compiled with an invalid non-zero minor version")) {
+                throw new RuntimeException(
+                    "Wrong UnsupportedClassVersionError exception: " + e.getMessage());
+            }
+        }
+    }
+}
--- a/test/hotspot/jtreg/runtime/appcds/JarBuilder.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/JarBuilder.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -32,9 +32,11 @@
  */
 
 import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.compiler.CompilerUtils;
 import jdk.test.lib.process.OutputAnalyzer;
 import jdk.test.lib.process.ProcessTools;
 import java.io.File;
+import java.nio.file.Path;
 import java.util.ArrayList;
 import sun.tools.jar.Main;
 
@@ -145,6 +147,21 @@
         }
     }
 
+    public static void createModularJar(String jarPath,
+                                      String classesDir,
+                                      String mainClass) throws Exception {
+        ArrayList<String> argList = new ArrayList<String>();
+        argList.add("--create");
+        argList.add("--file=" + jarPath);
+        if (mainClass != null) {
+            argList.add("--main-class=" + mainClass);
+        }
+        argList.add("-C");
+        argList.add(classesDir);
+        argList.add(".");
+        createJar(argList);
+    }
+
     private static void createJar(ArrayList<String> args) {
         if (DEBUG) printIterable("createJar args: ", args);
 
@@ -190,6 +207,23 @@
         output.shouldHaveExitValue(0);
     }
 
+    public static void compileModule(Path src,
+                                     Path dest,
+                                     String modulePathArg // arg to --module-path
+                                     ) throws Exception {
+        boolean compiled = false;
+        if (modulePathArg == null) {
+            compiled = CompilerUtils.compile(src, dest);
+        } else {
+            compiled = CompilerUtils.compile(src, dest,
+                                           "--module-path", modulePathArg);
+        }
+        if (!compiled) {
+            throw new RuntimeException("module did not compile");
+        }
+    }
+
+
     public static void signJar() throws Exception {
         String keyTool = JDKToolFinder.getJDKTool("keytool");
         String jarSigner = JDKToolFinder.getJDKTool("jarsigner");
--- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Tue Apr 17 15:25:13 2018 +0200
@@ -200,13 +200,18 @@
         return new Result(opts, runWithArchive(opts));
     }
 
-
     public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception {
         AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
         opts.addSuffix(suffix);
         return runWithArchive(opts);
     }
 
+    public static Result runWithModules(String prefix[], String upgrademodulepath, String modulepath,
+                                            String mid, String... testClassArgs) throws Exception {
+        AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath,
+                                               mid, testClassArgs);
+        return new Result(opts, runWithArchive(opts));
+    }
 
     public static OutputAnalyzer execAuto(String... suffix) throws Exception {
         AppCDSOptions opts = (new AppCDSOptions());
@@ -220,10 +225,9 @@
         return runWithArchive(opts);
     }
 
-    public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath,
-                                            String mid, String... testClassArgs)
-        throws Exception {
 
+    private static AppCDSOptions makeModuleOptions(String prefix[], String upgrademodulepath, String modulepath,
+                                            String mid, String testClassArgs[]) {
         AppCDSOptions opts = (new AppCDSOptions());
 
         opts.addPrefix(prefix);
@@ -234,7 +238,14 @@
                            "-p", modulepath, "-m", mid);
         }
         opts.addSuffix(testClassArgs);
+        return opts;
+    }
 
+    public static OutputAnalyzer execModule(String prefix[], String upgrademodulepath, String modulepath,
+                                            String mid, String... testClassArgs)
+        throws Exception {
+        AppCDSOptions opts = makeModuleOptions(prefix, upgrademodulepath, modulepath,
+                                               mid, testClassArgs);
         return runWithArchive(opts);
     }
 
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/CheckUnsupportedDumpingOptions.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,20 +40,15 @@
 
 public class CheckUnsupportedDumpingOptions {
     private static final String[] jigsawOptions = {
-        "-m",
         "--limit-modules",
-        "--module-path",
         "--upgrade-module-path",
         "--patch-module"
     };
     private static final String[] optionValues = {
         "mymod",
-        "mymod",
-        "mydir",
         ".",
         "java.naming=javax.naming.spi.NamingManger"
     };
-    private static final int infoIdx = 1;
 
     public static void main(String[] args) throws Exception {
         String source = "package javax.naming.spi; "                +
@@ -71,31 +66,11 @@
         String appClasses[] = {"Hello"};
         for (int i = 0; i < jigsawOptions.length; i++) {
             OutputAnalyzer output;
-            if (i == 5) {
-                // --patch-module
-                output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables",
-                                         jigsawOptions[i] + optionValues[i] + appJar);
-            } else {
-                output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables",
-                                         jigsawOptions[i], optionValues[i]);
-            }
-            if (i < infoIdx) {
-                output.shouldContain("Cannot use the following option " +
-                    "when dumping the shared archive: " + jigsawOptions[i])
-                      .shouldHaveExitValue(1);
-            } else {
-                output.shouldContain("Info: the " + jigsawOptions[i] +
-                    " option is ignored when dumping the shared archive");
-                if (optionValues[i].equals("mymod")) {
-                      // java will throw FindException for a module
-                      // which cannot be found during init_phase2() of vm init
-                      output.shouldHaveExitValue(1)
-                            .shouldContain("java.lang.module.FindException: Module mymod not found");
-                } else {
-                      output.shouldHaveExitValue(0);
-                }
-            }
+            output = TestCommon.dump(appJar, appClasses, "-Xlog:cds,cds+hashtables",
+                                     jigsawOptions[i], optionValues[i]);
+            output.shouldContain("Cannot use the following option " +
+                "when dumping the shared archive: " + jigsawOptions[i])
+                  .shouldHaveExitValue(1);
         }
     }
 }
-
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/JigsawOptionsCombo.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -69,8 +69,7 @@
     private ArrayList<TestCase> testCaseTable = new ArrayList<TestCase>();
 
     public static String infoDuringDump(String option) {
-        return "Info: the " + option +
-            " option is ignored when dumping the shared archive";
+        return "Cannot use the following option when dumping the shared archive: " + option;
     }
 
     public void runTests() throws Exception {
@@ -78,7 +77,7 @@
         testCaseTable.add(new TestCase(
             "basic: Basic dump and execute, to verify the test plumbing works",
             "", "", 0,
-            "", "", 0) );
+            "", "", 0, true) );
 
         String bcpArg = "-Xbootclasspath/a:" +
         TestCommon.getTestJar("hello_more.jar");
@@ -86,51 +85,50 @@
         testCaseTable.add(new TestCase(
             "Xbootclasspath/a: is OK for both dump and run time",
             bcpArg, "", 0,
-            bcpArg, "", 0) );
+            bcpArg, "", 0, true) );
 
         testCaseTable.add(new TestCase(
             "module-path-01: --module-path is ignored for dump time",
-            "--module-path mods",
-            infoDuringDump("--module-path"), 0,
-            null, null, 0) );
+            "--module-path mods", "", 0,
+            null, null, 0, true) );
 
         testCaseTable.add(new TestCase(
             "module-path-02: --module-path is ok for run time",
             "", "", 0,
-            "--module-path mods", "", 0) );
+            "--module-path mods", "", 0, true) );
 
         testCaseTable.add(new TestCase(
             "add-modules-01: --add-modules is ok at dump time",
             "--add-modules java.management",
             "", 0,
-            null, null, 0) );
+            null, null, 0, true) );
 
         testCaseTable.add(new TestCase(
             "add-modules-02: --add-modules is ok at run time",
             "", "", 0,
-            "--add-modules java.management", "", 0) );
+            "--add-modules java.management", "", 0, true) );
 
         testCaseTable.add(new TestCase(
             "limit-modules-01: --limit-modules is ignored at dump time",
             "--limit-modules java.base",
-            infoDuringDump("--limit-modules"), 0,
-            null, null, 0) );
+            infoDuringDump("--limit-modules"), 1,
+            null, null, 0, true) );
 
         testCaseTable.add(new TestCase(
             "limit-modules-02: --limit-modules is ok at run time",
             "", "", 0,
-            "--limit-modules java.base", "", 0) );
+            "--limit-modules java.base", "", 0, false) );
 
         testCaseTable.add(new TestCase(
             "upgrade-module-path-01: --upgrade-module-path is ignored at dump time",
             "--upgrade-module-path mods",
-            infoDuringDump("--upgrade-module-path"), 0,
-            null, null, 0) );
+            infoDuringDump("--upgrade-module-path"), 1,
+            null, null, 0, true) );
 
         testCaseTable.add(new TestCase(
             "-upgrade-module-path-module-path-02: --upgrade-module-path is ok at run time",
             "", "", 0,
-            "--upgrade-module-path mods", "", 0) );
+            "--upgrade-module-path mods", "", 0, false) );
 
         for (TestCase tc : testCaseTable) tc.execute();
     }
@@ -145,6 +143,7 @@
         String runTimeArgs;
         String runTimeExpectedOutput;
         int    runTimeExpectedExitValue;
+        boolean sharingOn;
 
         private String appJar = TestCommon.getTestJar("hello.jar");
         private String appClasses[] = {"Hello"};
@@ -152,7 +151,8 @@
 
         public TestCase(String description,
             String dumpTimeArgs, String dumpTimeExpectedOutput, int dumpTimeExpectedExitValue,
-            String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue) {
+            String runTimeArgs, String runTimeExpectedOutput, int runTimeExpectedExitValue,
+            boolean sharingOn) {
 
             this.description = description;
             this.dumpTimeArgs = dumpTimeArgs;
@@ -161,6 +161,7 @@
             this.runTimeArgs = runTimeArgs;
             this.runTimeExpectedOutput = runTimeExpectedOutput;
             this.runTimeExpectedExitValue = runTimeExpectedExitValue;
+            this.sharingOn = sharingOn;
         }
 
 
@@ -183,7 +184,13 @@
                 OutputAnalyzer execOutput = TestCommon.exec(appJar, getRunOptions());
 
                 if (runTimeExpectedExitValue == 0) {
-                    TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World");
+                    if (sharingOn) {
+                        TestCommon.checkExec(execOutput, runTimeExpectedOutput, "Hello World");
+                    } else {
+                        execOutput.shouldHaveExitValue(0)
+                                  .shouldContain(runTimeExpectedOutput)
+                                  .shouldContain("Hello World");
+                    }
                 } else {
                     execOutput.shouldMatch(dumpTimeExpectedOutput);
                     execOutput.shouldHaveExitValue(dumpTimeExpectedExitValue);
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/AppClassInCP.java	Tue Apr 17 15:25:13 2018 +0200
@@ -86,7 +86,8 @@
                 "--patch-module=java.naming=" + moduleJar,
                 "-Xlog:class+load",
                 "PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello");
-        TestCommon.checkDump(output, "Loading classes to share");
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         String classPath = appJar + File.pathSeparator + classDir;
         System.out.println("classPath: " + classPath);
@@ -96,9 +97,6 @@
             "--patch-module=java.naming=" + moduleJar,
             "-Xlog:class+load",
             "PatchMain", "javax.naming.spi.NamingManager", "mypackage.Hello")
-          .assertNormalExit(
-            "I pass!",
-            "Hello!",
-            "Hello source: shared objects file");
+            .assertSilentlyDisabledCDS(0, "I pass!", "Hello!");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/CustomPackage.java	Tue Apr 17 15:25:13 2018 +0200
@@ -70,7 +70,8 @@
                 "-Xlog:class+load",
                 "-Xlog:class+path=info",
                 "PatchMain", "javax.naming.myspi.NamingManager");
-        TestCommon.checkDump(output, "Preload Warning: Cannot find javax/naming/myspi/NamingManager");
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         TestCommon.run(
             "-XX:+UnlockDiagnosticVMOptions",
@@ -78,6 +79,6 @@
             "-Xlog:class+load",
             "-Xlog:class+path=info",
             "PatchMain", "javax.naming.myspi.NamingManager")
-          .assertNormalExit("I pass!");
+            .assertSilentlyDisabledCDS(0, "I pass!");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/MismatchedPatchModule.java	Tue Apr 17 15:25:13 2018 +0200
@@ -62,41 +62,18 @@
         JarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
         moduleJar = TestCommon.getTestJar("javanaming.jar");
 
-        // Case 1: --patch-module specified for dump time and run time
+        // Case 1: --patch-module specified for dump time
         System.out.println("Case 1: --patch-module specified for dump time and run time");
         OutputAnalyzer output =
             TestCommon.dump(null,
                 TestCommon.list("javax/naming/spi/NamingManager"),
                 "--patch-module=java.naming=" + moduleJar,
                 "PatchMain", "javax.naming.spi.NamingManager");
-        TestCommon.checkDump(output, "Loading classes to share");
-
-        // javax.naming.spi.NamingManager is not patched at runtime
-        TestCommon.run(
-            "-XX:+UnlockDiagnosticVMOptions",
-            "--patch-module=java.naming2=" + moduleJar,
-            "-Xlog:class+path=info",
-            "PatchMain", "javax.naming.spi.NamingManager")
-          .assertNormalExit(o -> o.shouldNotContain("I pass!"));
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
-        // Case 2: --patch-module specified for dump time but not for run time
-        System.out.println("Case 2: --patch-module specified for dump time but not for run time");
-        output =
-            TestCommon.dump(null,
-                TestCommon.list("javax/naming/spi/NamingManager"),
-                "--patch-module=java.naming=" + moduleJar,
-                "PatchMain", "javax.naming.spi.NamingManager");
-        TestCommon.checkDump(output, "Loading classes to share");
-
-        // javax.naming.spi.NamingManager is not patched at runtime
-        TestCommon.run(
-            "-XX:+UnlockDiagnosticVMOptions",
-            "-Xlog:class+path=info",
-            "PatchMain", "javax.naming.spi.NamingManager")
-          .assertNormalExit(o -> o.shouldNotContain("I pass!"));
-
-        // Case 3: --patch-module specified for run time but not for dump time
-        System.out.println("Case 3: --patch-module specified for run time but not for dump time");
+        // Case 2: --patch-module specified for run time but not for dump time
+        System.out.println("Case 2: --patch-module specified for run time but not for dump time");
         output =
             TestCommon.dump(null,
                 TestCommon.list("javax/naming/spi/NamingManager"),
@@ -107,26 +84,9 @@
         TestCommon.run(
             "-XX:+UnlockDiagnosticVMOptions",
             "--patch-module=java.naming=" + moduleJar,
-            "-Xlog:class+path=info",
-            "PatchMain", "javax.naming.spi.NamingManager")
-          .assertNormalExit("I pass!");
-
-        // Case 4: mismatched --patch-module entry counts between dump time and run time
-        System.out.println("Case 4: mismatched --patch-module entry counts between dump time and run time");
-        output =
-            TestCommon.dump(null,
-                TestCommon.list("javax/naming/spi/NamingManager"),
-                "--patch-module=java.naming=" + moduleJar,
-                "PatchMain", "javax.naming.spi.NamingManager");
-        TestCommon.checkDump(output, "Loading classes to share");
-
-        // javax.naming.spi.NamingManager is patched at runtime
-        TestCommon.run(
-            "-XX:+UnlockDiagnosticVMOptions",
-            "--patch-module=java.naming=" + moduleJar,
             "--patch-module=java.naming2=" + moduleJar,
             "-Xlog:class+path=info",
             "PatchMain", "javax.naming.spi.NamingManager")
-          .assertNormalExit("I pass!");
+            .assertSilentlyDisabledCDS(0, "I pass!");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchDir.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -67,7 +67,7 @@
             "--patch-module=java.naming=" + moduleJar,
             "-Xlog:class+load",
             "PatchMain", "javax.naming.spi.NamingManager")
-            .shouldContain("Loading classes to share")
-            .shouldHaveExitValue(0);
+            .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module")
+            .shouldHaveExitValue(1);
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/PatchJavaBase.java	Tue Apr 17 15:25:13 2018 +0200
@@ -62,7 +62,8 @@
             TestCommon.dump(null, null,
                 "--patch-module=java.base=" + moduleJar,
                 "PatchMain", "java.lang.NewClass");
-        TestCommon.checkDump(output, "Loading classes to share");
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         TestCommon.run(
             "-XX:+UnlockDiagnosticVMOptions",
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/Simple.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -68,7 +68,8 @@
                 "-Xlog:class+load",
                 "-Xlog:class+path=info",
                 "PatchMain", "javax.naming.spi.NamingManager");
-        TestCommon.checkDump(output, "Loading classes to share");
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         TestCommon.run(
             "-XX:+UnlockDiagnosticVMOptions",
@@ -76,6 +77,6 @@
             "-Xlog:class+load",
             "-Xlog:class+path=info",
             "PatchMain", "javax.naming.spi.NamingManager")
-          .assertNormalExit("I pass!");
+            .assertSilentlyDisabledCDS(0, "I pass!");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/SubClassOfPatchedClass.java	Tue Apr 17 15:25:13 2018 +0200
@@ -88,7 +88,8 @@
                 "--patch-module=java.naming=" + moduleJar,
                 "-Xlog:class+load",
                 "PatchMain", "javax.naming.Reference", "mypackage.MyReference");
-        TestCommon.checkDump(output, "Loading classes to share");
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         String classPath = appJar + File.pathSeparator + classDir;
         System.out.println("classPath: " + classPath);
@@ -98,8 +99,6 @@
             "--patch-module=java.naming=" + moduleJar,
             "-Xlog:class+load",
             "PatchMain", "javax.naming.Reference", "mypackage.MyReference")
-          .assertNormalExit(
-            "I pass!",
-            "MyReference source: file:");
+            .assertSilentlyDisabledCDS(0, "MyReference source: file:", "I pass!");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/PatchModule/TwoJars.java	Tue Apr 17 15:25:13 2018 +0200
@@ -87,7 +87,8 @@
                 "-Xlog:class+load",
                 "-Xlog:class+path=info",
                 "PatchMain", "javax.naming.spi.NamingManager");
-        TestCommon.checkDump(output, "Loading classes to share");
+        output.shouldHaveExitValue(1)
+              .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         TestCommon.run(
             "-XX:+UnlockDiagnosticVMOptions",
@@ -95,6 +96,6 @@
             "-Xlog:class+load",
             "-Xlog:class+path=info",
             "PatchMain", "javax.naming.spi.NamingManager")
-          .assertNormalExit("I pass");
+            .assertSilentlyDisabledCDS(0, "I pass!");
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/BootAppendTests.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -145,29 +145,32 @@
     // Test #3: A class in excluded package defined in boot module
     //     - should be loaded from the -Xbootclasspath/a by the boot classloader
     public static void testBootAppendExcludedModuleClassWithoutAppCDS() throws Exception {
-        CDSOptions opts = (new CDSOptions())
-            .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
-                       "--limit-modules", "java.base")
-            .setArchiveName(testArchiveName)
-            .addSuffix(MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT");
-
-        CDSTestUtils.runWithArchiveAndCheck(opts);
+        TestCommon.run(
+            "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
+            "-Xlog:class+load=info",
+            "--limit-modules", "java.base",
+            MAIN_CLASS, "Test #3", BOOT_APPEND_MODULE_CLASS, "true", "BOOT")
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch(".class.load. sun.nio.cs.ext.MyClass source:.*bootAppend.jar");
+            });
     }
 
     // Test #4: A shared class in excluded package that's archived from
     //          -Xbootclasspath/a
-    //     - should be loaded from the archive by the bootstrap classloader
+    //     - should be loaded from the jar since AppCDS will be disabled with
+    //       the --limit-modules option
     public static void testBootAppendExcludedModuleClassWithAppCDS() throws Exception {
-        OutputAnalyzer output = TestCommon.exec(
-            appJar,
-            "-Xbootclasspath/a:" + bootAppendJar,
+        TestCommon.run(
+            "-cp", appJar, "-Xbootclasspath/a:" + bootAppendJar,
+            "-Xlog:class+load=info",
             "--limit-modules", "java.base",
-            "-XX:+TraceClassLoading",
             MAIN_CLASS,
-            "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT");
-        TestCommon.checkExec(output);
-        if (!TestCommon.isUnableToMap(output))
-            output.shouldContain("[class,load] sun.nio.cs.ext.MyClass source: shared objects file");
+            "Test #4", BOOT_APPEND_MODULE_CLASS, "true", "BOOT")
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch(".class.load. sun.nio.cs.ext.MyClass source:.*bootAppend.jar");
+            });
     }
 
 
@@ -229,28 +232,28 @@
     public static void testBootAppendAppExcludeModuleClassWithoutAppCDS()
         throws Exception {
 
-        CDSOptions opts = (new CDSOptions())
-            .addPrefix("-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
-                       "--limit-modules", "java.base")
-            .setArchiveName(testArchiveName)
-            .addSuffix(MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT");
-
-        CDSTestUtils.runWithArchiveAndCheck(opts);
+        TestCommon.run(
+            "-Xbootclasspath/a:" + bootAppendJar, "-cp", appJar,
+            "-Xlog:class+load=info",
+            "--limit-modules", "java.base",
+            MAIN_CLASS, "Test #9", APP_MODULE_CLASS, "true", "BOOT")
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+            });
     }
 
     // Test #10: A shared class in excluded package defined in jimage app module
     //    - should be loaded from the -Xbootclasspath/a with AppCDS
     public static void testBootAppendAppExcludeModuleClassAppCDS() throws Exception {
-        OutputAnalyzer output = TestCommon.exec(
-            appJar,
-            "-Xbootclasspath/a:" + bootAppendJar,
-            "-XX:+TraceClassLoading",
+        TestCommon.run(
+            "-cp", appJar, "-Xbootclasspath/a:" + bootAppendJar,
+            "-Xlog:class+load=info",
             "--limit-modules", "java.base",
-            MAIN_CLASS,
-            "Test #10", APP_MODULE_CLASS, "true", "BOOT");
-        TestCommon.checkExec(output);
-
-        if (!TestCommon.isUnableToMap(output))
-            output.shouldContain("[class,load] com.sun.tools.javac.Main2 source: shared objects file");
+            MAIN_CLASS, "Test #10", APP_MODULE_CLASS, "true", "BOOT")
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch(".class.load. com.sun.tools.javac.Main2 source:.*bootAppend.jar");
+            });
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/classpathtests/EmptyClassInBootClassPath.java	Tue Apr 17 15:25:13 2018 +0200
@@ -89,13 +89,15 @@
         argsList.add("useAppLoader");
         opts = new String[argsList.size()];
         opts = argsList.toArray(opts);
-        TestCommon.run(opts).assertNormalExit(EXPECTED_EXCEPTION);
+        TestCommon.run(opts)
+            .assertSilentlyDisabledCDS(0, EXPECTED_EXCEPTION);
 
         // case 4: load class in bootclasspath using boot loader with '--limit-modules java.base'
         argsList.remove(argsList.size() - 1);
         argsList.add("useBootLoader");
         opts = new String[argsList.size()];
         opts = argsList.toArray(opts);
-        TestCommon.run(opts).assertNormalExit(EXPECTED_EXCEPTION);
+        TestCommon.run(opts)
+            .assertSilentlyDisabledCDS(0, EXPECTED_EXCEPTION);
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsHelper.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -65,11 +65,22 @@
                 // Make sure we got the expected defining ClassLoader
                 testLoader(clazz, expectedLoaders[i]);
 
-                // Make sure the class is in the shared space
-                if (!wb.isSharedClass(clazz)) {
-                    throw new RuntimeException(clazz.getName() +
-                        ".class should be in the shared space. " +
-                         "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName());
+                // Make sure the class is not in the shared space
+                // because CDS is disabled with --limit-modules during run time.
+                if (excludeModIdx != -1) {
+                    if (wb.isSharedClass(clazz)) {
+                        throw new RuntimeException(clazz.getName() +
+                            ".class should not be in the shared space. " +
+                             "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName());
+                    }
+                } else {
+                    // class should be in the shared space if --limit-modules
+                    // isn't specified during run time
+                    if (!wb.isSharedClass(clazz)) {
+                        throw new RuntimeException(clazz.getName() +
+                            ".class should be in the shared space. " +
+                             "loader=" + clazz.getClassLoader() + " module=" + clazz.getModule().getName());
+                    }
                 }
             }
             clazz = null;
--- a/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/limitmods/LimitModsTests.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -150,14 +150,14 @@
                     }
                 }
             }
-            output = TestCommon.exec(
-                appJar + File.pathSeparator + helperJar,
+            TestCommon.run(
+                "-cp", appJar + File.pathSeparator + helperJar,
                 "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", bootClassPath,
                 "--limit-modules", limitMods,
                 "LimitModsHelper",
                 BOOT_ARCHIVE_CLASS, PLATFORM_ARCHIVE_CLASS, APP_ARCHIVE_CLASS,
-                Integer.toString(excludeModIdx)); // last 4 args passed to test
-            TestCommon.checkExec(output);
+                Integer.toString(excludeModIdx)) // last 4 args passed to test
+                .assertSilentlyDisabledCDS(0);
             limitMods = null;
         }
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddModules.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jlink
+ * @run main AddModules
+ * @summary sanity test the --add-modules option
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class AddModules {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String MAIN_MODULE1 = "com.greetings";
+    private static final String MAIN_MODULE2 = "com.hello";
+    private static final String SUB_MODULE = "org.astro";
+
+    // the module main class
+    private static final String MAIN_CLASS1 = "com.greetings.Main";
+    private static final String MAIN_CLASS2 = "com.hello.Main";
+    private static final String APP_CLASS = "org.astro.World";
+
+    private static Path moduleDir = null;
+    private static Path subJar = null;
+    private static Path mainJar1 = null;
+    private static Path mainJar2 = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(SUB_MODULE),
+                                 MODS_DIR.resolve(SUB_MODULE),
+                                 null);
+
+        // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE1),
+                                 MODS_DIR.resolve(MAIN_MODULE1),
+                                 MODS_DIR.toString());
+
+        JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE2),
+                                 MODS_DIR.resolve(MAIN_MODULE2),
+                                 MODS_DIR.toString());
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+        subJar = moduleDir.resolve(SUB_MODULE + ".jar");
+        String classes = MODS_DIR.resolve(SUB_MODULE).toString();
+        JarBuilder.createModularJar(subJar.toString(), classes, null);
+
+        mainJar1 = moduleDir.resolve(MAIN_MODULE1 + ".jar");
+        classes = MODS_DIR.resolve(MAIN_MODULE1).toString();
+        JarBuilder.createModularJar(mainJar1.toString(), classes, MAIN_CLASS1);
+
+        mainJar2 = moduleDir.resolve(MAIN_MODULE2 + ".jar");
+        classes = MODS_DIR.resolve(MAIN_MODULE2).toString();
+        JarBuilder.createModularJar(mainJar2.toString(), classes, MAIN_CLASS2);
+
+    }
+
+    public static void main(String... args) throws Exception {
+        // compile the modules and create the modular jar files
+        buildTestModule();
+        String appClasses[] = {MAIN_CLASS1, MAIN_CLASS2, APP_CLASS};
+        // create an archive with the classes in the modules built in the
+        // previous step
+        OutputAnalyzer output = TestCommon.createArchive(
+                                        null, appClasses,
+                                        "--module-path", moduleDir.toString(),
+                                        "--add-modules",
+                                        MAIN_MODULE1 + "," + MAIN_MODULE2);
+        TestCommon.checkDump(output);
+        String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace"};
+
+        // run the com.greetings module with the archive with the --module-path
+        // the same as the one during dump time.
+        // The classes should be loaded from the archive.
+        TestCommon.runWithModules(prefix,
+                                  null, // --upgrade-module-path
+                                  moduleDir.toString(), // --module-path
+                                  MAIN_MODULE1) // -m
+            .assertNormalExit(out -> {
+                out.shouldContain("[class,load] com.greetings.Main source: shared objects file")
+                   .shouldContain("[class,load] org.astro.World source: shared objects file");
+            });
+
+        // run the com.hello module with the archive with the --module-path
+        // the same as the one during dump time.
+        // The classes should be loaded from the archive.
+        TestCommon.runWithModules(prefix,
+                                  null, // --upgrade-module-path
+                                  moduleDir.toString(), // --module-path
+                                  MAIN_MODULE2) // -m
+            .assertNormalExit(out -> {
+                out.shouldContain("[class,load] com.hello.Main source: shared objects file")
+                   .shouldContain("[class,load] org.astro.World source: shared objects file");
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddOpens.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jlink
+ * @run main AddOpens
+ * @summary sanity test the --add-opens option
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class AddOpens {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String TEST_MODULE1 = "com.simple";
+
+    // the module main class
+    private static final String MAIN_CLASS = "com.simple.Main";
+
+    private static Path moduleDir = null;
+    private static Path moduleDir2 = null;
+    private static Path destJar = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.toString());
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+        moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+
+        Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar");
+        destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar");
+        String classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+        JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS);
+        Files.copy(srcJar, destJar);
+
+    }
+
+    public static void main(String... args) throws Exception {
+        // compile the modules and create the modular jar files
+        buildTestModule();
+        String appClasses[] = {MAIN_CLASS};
+        // create an archive with both -cp and --module-path in the command line.
+        // Only the class in the modular jar in the --module-path will be archived;
+        // the class in the modular jar in the -cp won't be archived.
+        OutputAnalyzer output = TestCommon.createArchive(
+                                        destJar.toString(), appClasses,
+                                        "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+                                        "--module-path", moduleDir.toString(),
+                                        "-m", TEST_MODULE1);
+        TestCommon.checkDump(output);
+
+        // run with the archive using the same command line as in dump time
+        // plus the "--add-opens java.base/java.lang=com.simple" option.
+        // The main class should be loaded from the archive.
+        // The setaccessible(true) on the ClassLoader.defineClass method should
+        // be successful.
+        TestCommon.run( "-Xlog:class+load=trace",
+                        "-cp", destJar.toString(),
+                        "--add-opens", "java.base/java.lang=" + TEST_MODULE1,
+                        "--module-path", moduleDir.toString(),
+                        "-m", TEST_MODULE1, "with_add_opens")
+            .assertNormalExit(
+                "[class,load] com.simple.Main source: shared objects file",
+                "method.setAccessible succeeded!");
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/AddReads.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jlink
+ * @run main AddReads
+ * @summary sanity test the --add-reads option
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.Asserts;
+
+public class AddReads {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String MAIN_MODULE = "com.norequires";
+    private static final String SUB_MODULE = "org.astro";
+
+    // the module main class
+    private static final String MAIN_CLASS = "com.norequires.Main";
+    private static final String APP_CLASS = "org.astro.World";
+
+    private static Path moduleDir = null;
+    private static Path subJar = null;
+    private static Path mainJar = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(SUB_MODULE),
+                                       MODS_DIR.resolve(SUB_MODULE),
+                                       null);
+
+        Asserts.assertTrue(CompilerUtils
+            .compile(SRC_DIR.resolve(MAIN_MODULE),
+                     MODS_DIR.resolve(MAIN_MODULE),
+                     "-cp", MODS_DIR.resolve(SUB_MODULE).toString(),
+                     "--add-reads", "com.norequires=ALL-UNNAMED"));
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+        subJar = moduleDir.resolve(SUB_MODULE + ".jar");
+        String classes = MODS_DIR.resolve(SUB_MODULE).toString();
+        JarBuilder.createModularJar(subJar.toString(), classes, null);
+
+        mainJar = moduleDir.resolve(MAIN_MODULE + ".jar");
+        classes = MODS_DIR.resolve(MAIN_MODULE).toString();
+        JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS);
+    }
+
+    public static void main(String... args) throws Exception {
+        // compile the modules and create the modular jar files
+        buildTestModule();
+        String appClasses[] = {MAIN_CLASS, APP_CLASS};
+        // create an archive with the classes in the modules built in the
+        // previous step
+        OutputAnalyzer output = TestCommon.createArchive(
+                                        null, appClasses,
+                                        "--module-path", moduleDir.toString(),
+                                        "--add-modules", SUB_MODULE,
+                                        "--add-reads", "com.norequires=org.astro",
+                                        "-m", MAIN_MODULE);
+        TestCommon.checkDump(output);
+        String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace",
+                           "--add-modules", SUB_MODULE,
+                           "--add-reads", "com.norequires=org.astro"};
+
+        // run the com.norequires module with the archive with the same args
+        // used during dump time.
+        // The classes should be loaded from the archive.
+        TestCommon.runWithModules(prefix,
+                                  null, // --upgrade-module-path
+                                  moduleDir.toString(), // --module-path
+                                  MAIN_MODULE) // -m
+            .assertNormalExit(out -> {
+                out.shouldContain("[class,load] com.norequires.Main source: shared objects file")
+                   .shouldContain("[class,load] org.astro.World source: shared objects file");
+            });
+
+        // create an archive with -cp pointing to the jar file containing the
+        // org.astro module and --module-path pointing to the main module
+        output = TestCommon.createArchive(
+                                        subJar.toString(), appClasses,
+                                        "--module-path", moduleDir.toString(),
+                                        "--add-modules", SUB_MODULE,
+                                        "--add-reads", "com.norequires=org.astro",
+                                        "-m", MAIN_MODULE);
+        TestCommon.checkDump(output);
+        // run the com.norequires module with the archive with the sub-module
+        // in the -cp and with -add-reads=com.norequires=ALL-UNNAMED
+        // The main class should be loaded from the archive.
+        // The org.astro.World should be loaded from the jar.
+        String prefix2[] = {"-cp", subJar.toString(), "-Xlog:class+load=trace",
+                           "--add-reads", "com.norequires=ALL-UNNAMED"};
+        TestCommon.runWithModules(prefix2,
+                                  null, // --upgrade-module-path
+                                  moduleDir.toString(), // --module-path
+                                  MAIN_MODULE) // -m
+            .assertNormalExit(out -> {
+                out.shouldContain("[class,load] com.norequires.Main source: shared objects file")
+                   .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+            });
+
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ExportModule.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jlink
+ * @run main ExportModule
+ * @summary Tests involve exporting a module from the module path to a jar in the -cp.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.compiler.CompilerUtils;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+import jdk.testlibrary.Asserts;
+
+public class ExportModule {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String TEST_MODULE1 = "com.greetings";
+    private static final String TEST_MODULE2 = "org.astro";
+
+    // unnamed module package name
+    private static final String PKG_NAME = "com.nomodule";
+
+    // the module main class
+    private static final String MAIN_CLASS = "com.greetings.Main";
+    private static final String APP_CLASS = "org.astro.World";
+
+    // unnamed module main class
+    private static final String UNNAMED_MAIN = "com.nomodule.Main";
+
+    private static Path moduleDir = null;
+    private static Path moduleDir2 = null;
+    private static Path appJar = null;
+    private static Path appJar2 = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE2),
+                                 MODS_DIR.resolve(TEST_MODULE2),
+                                 null);
+
+        // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.toString());
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+        Path jar = moduleDir.resolve(TEST_MODULE2 + ".jar");
+        String classes = MODS_DIR.resolve(TEST_MODULE2).toString();
+        JarBuilder.createModularJar(jar.toString(), classes, null);
+
+        moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+        appJar = moduleDir2.resolve(TEST_MODULE1 + ".jar");
+        classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+        JarBuilder.createModularJar(appJar.toString(), classes, MAIN_CLASS);
+
+        // build a non-modular jar containing the main class which
+        // requires the org.astro package
+        boolean compiled
+            = CompilerUtils.compile(SRC_DIR.resolve(PKG_NAME),
+                                    MODS_DIR.resolve(PKG_NAME),
+                                    "--module-path", MODS_DIR.toString(),
+                                    "--add-modules", TEST_MODULE2,
+                                    "--add-exports", "org.astro/org.astro=ALL-UNNAMED");
+        Asserts.assertTrue(compiled, "test package did not compile");
+
+        appJar2 = moduleDir2.resolve(PKG_NAME + ".jar");
+        classes = MODS_DIR.resolve(PKG_NAME).toString();
+        JarBuilder.createModularJar(appJar2.toString(), classes, null);
+    }
+
+    public static void main(String... args) throws Exception {
+        // compile the modules and create the modular jar files
+        buildTestModule();
+        String appClasses[] = {MAIN_CLASS, APP_CLASS};
+        // create an archive with the class in the org.astro module built in the
+        // previous step and the main class from the modular jar in the -cp
+        // note: the main class is in the modular jar in the -cp which requires
+        // the module in the --module-path
+        OutputAnalyzer output = TestCommon.createArchive(
+                                        appJar.toString(), appClasses,
+                                        "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+                                        "--module-path", moduleDir.toString(),
+                                        "--add-modules", TEST_MODULE2, MAIN_CLASS);
+        TestCommon.checkDump(output);
+
+        // run it using the archive
+        // both the main class and the class from the org.astro module should
+        // be loaded from the archive
+        TestCommon.run("-Xlog:class+load=trace",
+                              "-cp", appJar.toString(),
+                              "--module-path", moduleDir.toString(),
+                              "--add-modules", TEST_MODULE2, MAIN_CLASS)
+            .assertNormalExit(
+                "[class,load] org.astro.World source: shared objects file",
+                "[class,load] com.greetings.Main source: shared objects file");
+
+        String appClasses2[] = {UNNAMED_MAIN, APP_CLASS};
+        // create an archive with the main class from a non-modular jar in the
+        // -cp and the class from the org.astro module
+        // note: the org.astro package needs to be exported to "ALL-UNNAMED"
+        // module since the jar in the -cp is a non-modular jar and thus it is
+        // unnmaed.
+        output = TestCommon.createArchive(
+                                        appJar2.toString(), appClasses2,
+                                        "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+                                        "--module-path", moduleDir.toString(),
+                                        "--add-modules", TEST_MODULE2,
+                                        "--add-exports", "org.astro/org.astro=ALL-UNNAMED",
+                                        UNNAMED_MAIN);
+        TestCommon.checkDump(output);
+
+        // both the main class and the class from the org.astro module should
+        // be loaded from the archive
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", appJar2.toString(),
+                       "--module-path", moduleDir.toString(),
+                       "--add-modules", TEST_MODULE2,
+                       "--add-exports", "org.astro/org.astro=ALL-UNNAMED",
+                       UNNAMED_MAIN)
+            .assertNormalExit(
+                "[class,load] org.astro.World source: shared objects file",
+                "[class,load] com.nomodule.Main source: shared objects file");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/JvmtiAddPath.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary JvmtiEnv::AddToBootstrapClassLoaderSearch and JvmtiEnv::AddToSystemClassLoaderSearch should disable AppCDS
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @build sun.hotspot.WhiteBox
+ * @run driver ClassFileInstaller sun.hotspot.WhiteBox
+ * @compile ../../test-classes/JvmtiApp.java
+ * @run main JvmtiAddPath
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import jdk.test.lib.process.OutputAnalyzer;
+import sun.hotspot.WhiteBox;
+
+public class JvmtiAddPath {
+    static String use_whitebox_jar;
+    static String[] no_extra_matches = {};
+    static String[] check_appcds_enabled = {
+        "[class,load] ExtraClass source: shared object"
+    };
+    static String[] check_appcds_disabled = {
+        "[class,load] ExtraClass source: file:"
+    };
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String TEST_MODULE1 = "com.simple";
+
+    // the module main class
+    private static final String MAIN_CLASS = "com.simple.Main";
+
+    private static Path moduleDir = null;
+    private static Path mainJar = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.toString());
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+
+        mainJar = moduleDir.resolve(TEST_MODULE1 + ".jar");
+        String classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+        JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS);
+    }
+
+    static void run(String cp, String... args) throws Exception {
+        run(no_extra_matches, cp, args);
+    }
+
+    static void run(String[] extra_matches, String cp, String... args) throws Exception {
+        String[] opts = {"-cp", cp, "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", use_whitebox_jar};
+        opts = TestCommon.concat(opts, args);
+        TestCommon.run(opts).assertNormalExit(extra_matches);
+    }
+
+    public static void main(String[] args) throws Exception {
+        buildTestModule();
+        JarBuilder.build("jvmti_app", "JvmtiApp", "ExtraClass");
+        JarBuilder.build(true, "WhiteBox", "sun/hotspot/WhiteBox");
+
+        // In all the test cases below, appJar does not contain Hello.class. Instead, we
+        // append JAR file(s) that contain Hello.class to the boot classpath, the app
+        // classpath, or both, and verify that Hello.class is loaded by the expected ClassLoader.
+        String appJar = TestCommon.getTestJar("jvmti_app.jar");         // contains JvmtiApp.class
+        String addappJar = mainJar.toString();  // contains Main.class
+        String addbootJar = mainJar.toString(); // contains Main.class
+        String twoAppJars = appJar + File.pathSeparator + addappJar;
+        String modulePath = "--module-path=" + moduleDir.toString();
+        String wbJar = TestCommon.getTestJar("WhiteBox.jar");
+        use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
+
+        OutputAnalyzer output = TestCommon.createArchive(
+                                    appJar,
+                                    TestCommon.list("JvmtiApp", "ExtraClass", MAIN_CLASS),
+                                    use_whitebox_jar,
+                                    "-Xlog:class+load=trace",
+                                    modulePath);
+        TestCommon.checkDump(output);
+
+        System.out.println("Test case 1: not adding module path - Hello.class should not be found");
+        run(check_appcds_enabled, appJar,
+            "-Xlog:class+load", "JvmtiApp", "noadd", MAIN_CLASS); // appcds should be enabled
+
+        System.out.println("Test case 2: add to boot classpath only - should find Hello.class in boot loader");
+        run(check_appcds_disabled, appJar,
+            "-Xlog:class+load=trace",
+            modulePath,
+            "JvmtiApp", "bootonly", addbootJar, MAIN_CLASS); // appcds should be disabled
+
+        System.out.println("Test case 3: add to app classpath only - should find Hello.class in app loader");
+        run(appJar, modulePath,
+            "JvmtiApp", "apponly", addappJar, MAIN_CLASS);
+
+        System.out.println("Test case 4: add to boot and app paths - should find Hello.class in boot loader");
+        run(appJar, modulePath,
+            "JvmtiApp", "appandboot", addbootJar, addappJar, MAIN_CLASS);
+
+        System.out.println("Test case 5: add to app using -cp, but add to boot using JVMTI - should find Hello.class in boot loader");
+        run(appJar, modulePath,
+            "JvmtiApp", "bootonly", addappJar, MAIN_CLASS);
+
+        System.out.println("Test case 6: add to app using AppCDS, but add to boot using JVMTI - should find Hello.class in boot loader");
+        output = TestCommon.createArchive(
+                     appJar, TestCommon.list("JvmtiApp", "ExtraClass"),
+                     use_whitebox_jar,
+                     "-Xlog:class+load=trace",
+                     modulePath);
+        TestCommon.checkDump(output);
+        run(twoAppJars, modulePath,
+            "JvmtiApp", "bootonly", addappJar, MAIN_CLASS);
+
+        System.out.println("Test case 7: add to app using AppCDS, no JVMTI calls - should find Hello.class in app loader");
+        run(twoAppJars, modulePath,
+            "JvmtiApp", "noadd-appcds", MAIN_CLASS);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/MainModuleOnly.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jlink
+ * @run main MainModuleOnly
+ * @summary Test some scenarios with a main modular jar specified in the --module-path and -cp options in the command line.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class MainModuleOnly {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String TEST_MODULE1 = "com.simple";
+
+    // the module main class
+    private static final String MAIN_CLASS = "com.simple.Main";
+
+    private static Path moduleDir = null;
+    private static Path moduleDir2 = null;
+    private static Path destJar = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.resolve(TEST_MODULE1),
+                                 MODS_DIR.toString());
+
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+        moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+
+        Path srcJar = moduleDir.resolve(TEST_MODULE1 + ".jar");
+        destJar = moduleDir2.resolve(TEST_MODULE1 + ".jar");
+        String classes = MODS_DIR.resolve(TEST_MODULE1).toString();
+        JarBuilder.createModularJar(srcJar.toString(), classes, MAIN_CLASS);
+        Files.copy(srcJar, destJar);
+
+    }
+
+    public static void main(String... args) throws Exception {
+        // compile the modules and create the modular jar files
+        buildTestModule();
+        String appClasses[] = {MAIN_CLASS};
+        // create an archive with both -cp and --module-path in the command line.
+        // Only the class in the modular jar in the --module-path will be archived;
+        // the class in the modular jar in the -cp won't be archived.
+        OutputAnalyzer output = TestCommon.createArchive(
+                                        destJar.toString(), appClasses,
+                                        "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+                                        "--module-path", moduleDir.toString(),
+                                        "-m", TEST_MODULE1);
+        TestCommon.checkDump(output);
+
+        // run with the archive using the same command line as in dump time.
+        // The main class should be loaded from the archive.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--module-path", moduleDir.toString(),
+                       "-m", TEST_MODULE1)
+            .assertNormalExit("[class,load] com.simple.Main source: shared objects file");
+
+        // run with the archive with the main class name inserted before the -m.
+        // The main class name will be picked up before the module name. So the
+        // main class should be loaded from the jar in the -cp.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--module-path", moduleDir.toString(),
+                       MAIN_CLASS, "-m", TEST_MODULE1)
+            .assertNormalExit(out ->
+                out.shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar"));
+
+        // run with the archive with exploded module. Since during dump time, we
+        // only archive classes from the modular jar in the --module-path, the
+        // main class should be loaded from the exploded module directory.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--module-path", MODS_DIR.toString(),
+                       "-m", TEST_MODULE1 + "/" + MAIN_CLASS)
+            .assertNormalExit(out -> {
+                out.shouldMatch(".class.load. com.simple.Main source:.*com.simple")
+                   .shouldContain(MODS_DIR.toString());
+            });
+
+        // run with the archive with the --upgrade-module-path option.
+        // CDS will be disabled with this options and the main class will be
+        // loaded from the modular jar.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--upgrade-module-path", moduleDir.toString(),
+                       "--module-path", moduleDir.toString(),
+                       "-m", TEST_MODULE1)
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch("CDS is disabled when the.*option is specified")
+                   .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar");
+            });
+        // run with the archive with the --limit-modules option.
+        // CDS will be disabled with this options and the main class will be
+        // loaded from the modular jar.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--limit-modules", "java.base," + TEST_MODULE1,
+                       "--module-path", moduleDir.toString(),
+                       "-m", TEST_MODULE1)
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch("CDS is disabled when the.*option is specified")
+                   .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar");
+            });
+        // run with the archive with the --patch-module option.
+        // CDS will be disabled with this options and the main class will be
+        // loaded from the modular jar.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--patch-module", TEST_MODULE1 + "=" + MODS_DIR.toString(),
+                       "--module-path", moduleDir.toString(),
+                       "-m", TEST_MODULE1)
+            .assertSilentlyDisabledCDS(out -> {
+                out.shouldHaveExitValue(0)
+                   .shouldMatch("CDS is disabled when the.*option is specified")
+                   .shouldMatch(".class.load. com.simple.Main source:.*com.simple.jar");
+            });
+        // modify the timestamp of the jar file
+        (new File(destJar.toString())).setLastModified(System.currentTimeMillis() + 2000);
+        // run with the archive and the jar with modified timestamp.
+        // It should fail due to timestamp of the jar doesn't match the one
+        // used during dump time.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", destJar.toString(),
+                       "--module-path", moduleDir.toString(),
+                       "-m", TEST_MODULE1)
+            .assertAbnormalExit(
+                "A jar/jimage file is not the one used while building the shared archive file:");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/ModulePathAndCP.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/**
+ * @test
+ * @requires vm.cds
+ * @library /test/jdk/lib/testlibrary /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules jdk.compiler
+ *          jdk.jartool/sun.tools.jar
+ *          jdk.jlink
+ * @run main ModulePathAndCP
+ * @summary 2 sets of tests: one with only --module-path in the command line;
+ *          another with both -cp and --module-path in the command line.
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.testlibrary.ProcessTools;
+
+public class ModulePathAndCP {
+
+    private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+    private static final String TEST_SRC = System.getProperty("test.src");
+
+    private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
+    private static final Path MODS_DIR = Paths.get("mods");
+
+    // the module name of the test module
+    private static final String MAIN_MODULE = "com.greetings";
+    private static final String APP_MODULE = "org.astro";
+
+    // the module main class
+    private static final String MAIN_CLASS = "com.greetings.Main";
+    private static final String APP_CLASS = "org.astro.World";
+
+    private static Path moduleDir = null;
+    private static Path moduleDir2 = null;
+    private static Path subJar = null;
+    private static Path mainJar = null;
+    private static Path destJar = null;
+
+    public static void buildTestModule() throws Exception {
+
+        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(APP_MODULE),
+                                 MODS_DIR.resolve(APP_MODULE),
+                                 null);
+
+        // javac -d mods/$TESTMODULE --module-path MOD_DIR src/$TESTMODULE/**
+        JarBuilder.compileModule(SRC_DIR.resolve(MAIN_MODULE),
+                                 MODS_DIR.resolve(MAIN_MODULE),
+                                 MODS_DIR.toString());
+
+        moduleDir = Files.createTempDirectory(USER_DIR, "mlib");
+        moduleDir2 = Files.createTempDirectory(USER_DIR, "mlib2");
+        subJar = moduleDir.resolve(APP_MODULE + ".jar");
+        destJar = moduleDir2.resolve(APP_MODULE + ".jar");
+        String classes = MODS_DIR.resolve(APP_MODULE).toString();
+        JarBuilder.createModularJar(subJar.toString(), classes, null);
+        Files.copy(subJar, destJar);
+
+        mainJar = moduleDir.resolve(MAIN_MODULE + ".jar");
+        Path mainJar2 = moduleDir2.resolve(MAIN_MODULE + ".jar");
+        classes = MODS_DIR.resolve(MAIN_MODULE).toString();
+        JarBuilder.createModularJar(mainJar.toString(), classes, MAIN_CLASS);
+        Files.copy(mainJar, mainJar2);
+
+    }
+
+    public static void main(String... args) throws Exception {
+        // compile the modules and create the modular jar files
+        buildTestModule();
+        String appClasses[] = {MAIN_CLASS, APP_CLASS};
+        // create an archive with the classes in the modules built in the
+        // previous step
+        OutputAnalyzer output = TestCommon.createArchive(
+                                        null, appClasses,
+                                        "--module-path", moduleDir.toString(),
+                                        "-m", MAIN_MODULE);
+        TestCommon.checkDump(output);
+        String prefix[] = {"-cp", "\"\"", "-Xlog:class+load=trace"};
+
+        // run with the archive with the --module-path the same as the one during
+        // dump time. The classes should be loaded from the archive.
+        TestCommon.runWithModules(prefix,
+                                  null, // --upgrade-module-path
+                                  moduleDir.toString(), // --module-path
+                                  MAIN_MODULE) // -m
+            .assertNormalExit(out -> {
+                out.shouldContain("[class,load] com.greetings.Main source: shared objects file")
+                   .shouldContain("[class,load] org.astro.World source: shared objects file");
+            });
+
+        // run with the archive with the --module-path different from the one during
+        // dump time. The classes should be loaded from the jar files.
+        TestCommon.runWithModules(prefix,
+                                  null, // --upgrade-module-path
+                                  moduleDir2.toString(), // --module-path
+                                  MAIN_MODULE) // -m
+            .assertNormalExit(out -> {
+                out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar")
+                   .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+            });
+
+        // create an archive with modular jar files in both -cp and --module-path
+        String jars = subJar.toString() + System.getProperty("path.separator") +
+                      mainJar.toString();
+        output = TestCommon.createArchive( jars, appClasses,
+                                           "-Xlog:class+load=trace", "-XX:+PrintSystemDictionaryAtExit",
+                                           "--module-path", moduleDir.toString(),
+                                           "-m", MAIN_MODULE);
+        TestCommon.checkDump(output);
+
+        // run with archive with the main class name specified before
+        // the module name with the -m option. Since the -m option was specified
+        // during dump time, the classes in the jar files after the -cp won't be
+        // archived. Therefore, the classes won't be loaded from the archive but
+        // will be loaded from the jar files.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", jars,
+                       "--module-path", moduleDir.toString(),
+                       MAIN_CLASS, "-m", MAIN_MODULE)
+            .assertNormalExit(out -> {
+                out.shouldMatch(".class.load. com.greetings.Main source:.*com.greetings.jar")
+                   .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+            });
+
+        // similar to the above case but without the main class name. The classes
+        // should be loaded from the archive.
+        TestCommon.run("-Xlog:class+load=trace",
+                       "-cp", jars,
+                       "--module-path", moduleDir.toString(),
+                       "-m", MAIN_MODULE)
+            .assertNormalExit(
+              "[class,load] com.greetings.Main source: shared objects file",
+              "[class,load] org.astro.World source: shared objects file");
+
+        // create an archive with two modular jars in the --module-path
+        output = TestCommon.createArchive(
+                                        null, appClasses,
+                                        "--module-path", jars,
+                                        "-m", MAIN_MODULE);
+        TestCommon.checkDump(output);
+
+        // run with the above archive but with the modular jar containing the
+        // org.astro module in a different location.
+        // The org.astro.World class should be loaded from the jar.
+        // The Main class should still be loaded from the archive.
+        jars = destJar.toString() + System.getProperty("path.separator") +
+                      mainJar.toString();
+        TestCommon.runWithModules(prefix,
+                                  null, // --upgrade-module-path
+                                  jars, // --module-path
+                                  MAIN_MODULE) // -m
+            .assertNormalExit(out -> {
+                out.shouldContain("[class,load] com.greetings.Main source: shared objects file")
+                   .shouldMatch(".class.load. org.astro.World source:.*org.astro.jar");
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/com/greetings/Main.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.greetings;
+import org.astro.World;
+public class Main {
+    public static void main(String[] args) {
+        System.out.format("Greetings %s!\n", World.name());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.greetings/module-info.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+module com.greetings {
+    requires org.astro;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/com/hello/Main.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.hello;
+import org.astro.World;
+public class Main {
+    public static void main(String[] args) {
+        System.out.format("Hello %s!\n", World.name());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.hello/module-info.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+module com.hello {
+    requires org.astro;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.nomodule/com/nomodule/Main.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.nomodule;
+import org.astro.World;
+public class Main {
+    public static void main(String[] args) {
+        System.out.format("Greetings %s!\n", World.name());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/com/norequires/Main.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.norequires;
+import org.astro.World;
+public class Main {
+    public static void main(String[] args) {
+        System.out.format("Hello %s!\n", World.name());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.norequires/module-info.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+module com.norequires { }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/com/simple/Main.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package com.simple;
+
+import java.lang.reflect.Method;
+
+public class Main {
+    public static void main(String[] args) throws Exception {
+        System.out.println("Hello World!");
+        if (args.length > 0 && args[0].equals("with_add_opens")) {
+            Method method = ClassLoader.class.getDeclaredMethod("defineClass",
+                byte[].class, int.class, int.class);
+            method.setAccessible(true);
+            System.out.println("method.setAccessible succeeded!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/com.simple/module-info.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+module com.simple {
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/module-info.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+module org.astro {
+    exports org.astro;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/jigsaw/modulepath/src/org.astro/org/astro/World.java	Tue Apr 17 15:25:13 2018 +0200
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package org.astro;
+public class World {
+    public static String name() {
+        return "world";
+    }
+}
--- a/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/appcds/test-classes/JvmtiApp.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,9 +25,9 @@
 import sun.hotspot.WhiteBox;
 
 public class JvmtiApp {
-    static Class forname() {
+    static Class forname(String cn) {
         try {
-            return Class.forName("Hello");
+            return Class.forName(cn);
         } catch (Throwable t) {
             return null;
         }
@@ -40,9 +40,14 @@
 
     // See ../JvmtiAddPath.java for how the classpaths are configured.
     public static void main(String args[]) {
+        String cn = "Hello";
+        if (args.length >= 3) {
+            cn = args[args.length - 1];
+        }
+
         if (args[0].equals("noadd")) {
-            if (forname() != null) {
-                failed("Hello class was loaded unexpectedly");
+            if (forname(cn) != null) {
+                failed(cn + " class was loaded unexpectedly");
             }
             // We use -verbose:class to verify that Extra.class IS loaded by AppCDS if
             // the boot classpath HAS NOT been appended.
@@ -54,39 +59,41 @@
 
         if (args[0].equals("bootonly")) {
             wb.addToBootstrapClassLoaderSearch(args[1]);
-            Class cls = forname();
+            Class cls = forname(cn);
             if (cls == null) {
-                failed("Cannot find Hello class");
+                failed("Cannot find " + cn + " class");
             }
             if (cls.getClassLoader() != null) {
                 failed("Hello class not loaded by boot classloader");
             }
         } else if (args[0].equals("apponly")) {
             wb.addToSystemClassLoaderSearch(args[1]);
-            Class cls = forname();
+            Class cls = forname(cn);
             if (cls == null) {
-                failed("Cannot find Hello class");
+                failed("Cannot find " + cn + " class");
             }
             if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) {
-                failed("Hello class not loaded by app classloader");
+                failed(cn + " class not loaded by app classloader");
             }
         } else if (args[0].equals("noadd-appcds")) {
-            Class cls = forname();
+            cn = (args.length == 1) ? "Hello" : args[1];
+            Class cls = forname(cn);
             if (cls == null) {
-                failed("Cannot find Hello class");
+                failed("Cannot find " + cn + " class");
             }
             if (cls.getClassLoader() != JvmtiApp.class.getClassLoader()) {
-                failed("Hello class not loaded by app classloader");
+                failed(cn + " class not loaded by app classloader");
             }
         } else if (args[0].equals("appandboot")) {
             wb.addToBootstrapClassLoaderSearch(args[1]);
             wb.addToSystemClassLoaderSearch(args[2]);
-            Class cls = forname();
+            cn = (args.length == 3) ? "Hello" : args[3];
+            Class cls = forname(cn);
             if (cls == null) {
-                failed("Cannot find Hello class");
+                failed("Cannot find " + cn + " class");
             }
             if (cls.getClassLoader() != null) {
-                failed("Hello class not loaded by boot classloader");
+                failed(cn + " class not loaded by boot classloader");
             }
         } else {
             failed("unknown option " + args[0]);
@@ -102,4 +109,4 @@
 
 class ExtraClass {
     static void doit() {}
-}
\ No newline at end of file
+}
--- a/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/runtime/modules/PatchModule/PatchModuleCDS.java	Tue Apr 17 15:25:13 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,8 @@
             "-Xlog:class+path=info",
             "-version");
         new OutputAnalyzer(pb.start())
-            .shouldContain("ro  space:"); // Make sure archive got created.
+            // --patch-module is not supported during CDS dumping
+            .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         // Case 2: Test that directory in --patch-module is supported for CDS dumping
         // Create a class file in the module java.base.
@@ -73,7 +74,8 @@
             "-Xlog:class+path=info",
             "-version");
         new OutputAnalyzer(pb.start())
-            .shouldContain("ro  space:"); // Make sure archive got created.
+            // --patch-module is not supported during CDS dumping
+            .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         // Case 3a: Test CDS dumping with jar file in --patch-module
         BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
@@ -87,7 +89,8 @@
             "-Xlog:class+path=info",
             "PatchModuleMain", "javax.naming.spi.NamingManager");
         new OutputAnalyzer(pb.start())
-            .shouldContain("ro  space:"); // Make sure archive got created.
+            // --patch-module is not supported during CDS dumping
+            .shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
 
         // Case 3b: Test CDS run with jar file in --patch-module
         pb = ProcessTools.createJavaProcessBuilder(
--- a/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/libFieldAccessWatch.c	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/hotspot/jtreg/serviceability/jvmti/FieldAccessWatch/libFieldAccessWatch.c	Tue Apr 17 15:25:13 2018 +0200
@@ -35,7 +35,6 @@
 static jvmtiEnv *jvmti = NULL;
 
 // valid while a test is executed
-static JNIEnv *javaEnv = NULL;
 static jobject testResultObject = NULL;
 static jclass testResultClass = NULL;
 
@@ -46,7 +45,8 @@
 
 
 // logs the notification and updates currentTestResult
-static void handleNotification(jmethodID method,
+static void handleNotification(JNIEnv *jni_env,
+    jmethodID method,
     jfieldID field,
     jclass field_klass,
     int modified,
@@ -92,21 +92,21 @@
         csig, mname, mgensig, modified ? "modified" : "accessed", name, (int)location);
 
     // set TestResult
-    if (javaEnv != NULL && testResultObject != NULL && testResultClass != NULL) {
+    if (testResultObject != NULL && testResultClass != NULL) {
         jfieldID fieldID;
         // field names in TestResult are "<field_name>_access"/"<field_name>_modify"
         char *fieldName = (char *)malloc(strlen(name) + 16);
         strcpy(fieldName, name);
         strcat(fieldName, modified ? "_modify" : "_access");
 
-        fieldID = (*javaEnv)->GetFieldID(javaEnv, testResultClass, fieldName, "Z");
+        fieldID = (*jni_env)->GetFieldID(jni_env, testResultClass, fieldName, "Z");
         if (fieldID != NULL) {
-            (*javaEnv)->SetBooleanField(javaEnv, testResultObject, fieldID, JNI_TRUE);
+            (*jni_env)->SetBooleanField(jni_env, testResultObject, fieldID, JNI_TRUE);
         } else {
             // the field is not interesting for the test
         }
         // clear any possible exception
-        (*javaEnv)->ExceptionClear(javaEnv);
+        (*jni_env)->ExceptionClear(jni_env);
 
         free(fieldName);
     }
@@ -179,7 +179,7 @@
             jobject object,
             jfieldID field)
 {
-    handleNotification(method, field, field_klass, 0, location);
+    handleNotification(jni_env, method, field, field_klass, 0, location);
 }
 
 
@@ -195,7 +195,7 @@
             char signature_type,
             jvalue new_value)
 {
-    handleNotification(method, field, field_klass, 1, location);
+    handleNotification(jni_env, method, field, field_klass, 1, location);
 
     if (signature_type == 'L') {
         jobject newObject = new_value.l;
@@ -282,9 +282,8 @@
 JNIEXPORT jboolean JNICALL
 Java_FieldAccessWatch_startTest(JNIEnv *env, jclass thisClass, jobject testResults)
 {
-    javaEnv = env;
-    testResultObject = (*javaEnv)->NewGlobalRef(javaEnv, testResults);
-    testResultClass = (jclass)(*javaEnv)->NewGlobalRef(javaEnv, (*javaEnv)->GetObjectClass(javaEnv, testResultObject));
+    testResultObject = (*env)->NewGlobalRef(env, testResults);
+    testResultClass = (jclass)(*env)->NewGlobalRef(env, (*env)->GetObjectClass(env, testResultObject));
 
     return JNI_TRUE;
 }
--- a/test/jdk/ProblemList.txt	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/jdk/ProblemList.txt	Tue Apr 17 15:25:13 2018 +0200
@@ -504,6 +504,8 @@
 java/lang/management/MemoryMXBean/Pending.java                  8158837 generic-all
 java/lang/management/MemoryMXBean/PendingAllGC.sh               8158837 generic-all
 
+java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java    8081652 generic-all
+
 ############################################################################
 
 # jdk_io
--- a/test/lib/jdk/test/lib/cds/CDSTestUtils.java	Tue Apr 17 15:39:20 2018 +0200
+++ b/test/lib/jdk/test/lib/cds/CDSTestUtils.java	Tue Apr 17 15:25:13 2018 +0200
@@ -117,6 +117,7 @@
         private final boolean hasMappingFailure;
         private final boolean hasAbnormalExit;
         private final boolean hasNormalExit;
+        private final String CDS_DISABLED = "warning: CDS is disabled when the";
 
         public Result(CDSOptions opts, OutputAnalyzer out) throws Exception {
             options = opts;
@@ -126,7 +127,9 @@
             hasNormalExit     = (!hasMappingFailure) && (output.getExitValue() == 0);
 
             if (hasNormalExit) {
-                if ("on".equals(options.xShareMode) && output.getStderr().contains("java version")) {
+                if ("on".equals(options.xShareMode) &&
+                    output.getStderr().contains("java version") &&
+                    !output.getStderr().contains(CDS_DISABLED)) {
                     // "-showversion" is always passed in the command-line by the execXXX methods.
                     // During normal exit, we require that the VM to show that sharing was enabled.
                     output.shouldContain("sharing");
@@ -150,6 +153,26 @@
             return this;
         }
 
+        // When {--limit-modules, --patch-module, and/or --upgrade-module-path}
+        // are specified, CDS is silently disabled for both -Xshare:auto and -Xshare:on.
+        public Result assertSilentlyDisabledCDS(Checker checker) throws Exception {
+            if (hasMappingFailure) {
+                throw new RuntimeException("Unexpected mapping failure");
+            }
+            // this comes from a JVM warning message.
+            output.shouldContain(CDS_DISABLED);
+
+            checker.check(output);
+            return this;
+        }
+
+        public Result assertSilentlyDisabledCDS(int exitCode, String... matches) throws Exception {
+            return assertSilentlyDisabledCDS((out) -> {
+                out.shouldHaveExitValue(exitCode);
+                checkMatches(out, matches);
+                   });
+        }
+
         public Result ifNormalExit(Checker checker) throws Exception {
             if (hasNormalExit) {
                 checker.check(output);