changeset 49752:93d84f667d12

8201318: Introduce GCThreadLocalData to abstract GC-specific data belonging to a thread Reviewed-by: shade, rehn
author pliden
date Thu, 12 Apr 2018 08:25:56 +0200
parents c3a10df652c0
children 46f2dc7c4c39
files src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp src/hotspot/cpu/arm/c1_Runtime1_arm.cpp src/hotspot/cpu/arm/macroAssembler_arm.cpp src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp src/hotspot/cpu/s390/c1_Runtime1_s390.cpp src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp src/hotspot/cpu/x86/c1_Runtime1_x86.cpp src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp src/hotspot/share/c1/c1_LIRGenerator.cpp src/hotspot/share/gc/g1/dirtyCardQueue.cpp src/hotspot/share/gc/g1/g1BarrierSet.cpp src/hotspot/share/gc/g1/g1BarrierSet.hpp src/hotspot/share/gc/g1/g1CollectedHeap.cpp src/hotspot/share/gc/g1/g1ConcurrentMark.cpp src/hotspot/share/gc/g1/g1ThreadLocalData.hpp src/hotspot/share/gc/g1/satbMarkQueue.cpp src/hotspot/share/gc/g1/vmStructs_g1.hpp src/hotspot/share/gc/shared/barrierSet.cpp src/hotspot/share/gc/shared/barrierSet.hpp src/hotspot/share/gc/shared/collectedHeap.cpp src/hotspot/share/gc/shared/gcThreadLocalData.hpp src/hotspot/share/jvmci/jvmciCompilerToVM.hpp src/hotspot/share/jvmci/jvmciRuntime.cpp src/hotspot/share/jvmci/vmStructs_jvmci.cpp src/hotspot/share/opto/compile.cpp src/hotspot/share/opto/escape.cpp src/hotspot/share/opto/graphKit.cpp src/hotspot/share/opto/macro.cpp src/hotspot/share/runtime/sharedRuntime.cpp src/hotspot/share/runtime/thread.cpp src/hotspot/share/runtime/thread.hpp src/hotspot/share/runtime/vmStructs.cpp src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java
diffstat 38 files changed, 372 insertions(+), 299 deletions(-) [+]
line wrap: on
line diff
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Thu Apr 12 08:25:56 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
 
 
@@ -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;
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -27,9 +27,9 @@
 #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"
 
 #define __ masm->
@@ -95,13 +95,9 @@
   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()));
-
+  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) {
@@ -182,10 +178,8 @@
   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()));
+  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 = Universe::heap()->barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
--- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp	Thu Apr 12 08:25:56 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
@@ -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;
@@ -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/macroAssembler_arm.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp	Thu Apr 12 08:25:56 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"
 #include "gc/g1/heapRegion.hpp"
 #endif
 
@@ -2174,12 +2175,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");
@@ -2260,10 +2258,8 @@
                                            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()));
+  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 = Universe::heap()->barrier_set();
   CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
--- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp	Thu Apr 12 08:25:56 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
@@ -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);
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -28,9 +28,9 @@
 #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"
 
 #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);
@@ -120,10 +120,10 @@
 
   // Is marking active?
   if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    __ lwz(tmp1, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
+    __ 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(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_active()), R16_thread);
+    __ lbz(tmp1, in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()), R16_thread);
   }
   __ cmpdi(CCR0, tmp1, 0);
   __ beq(CCR0, filtered);
@@ -165,13 +165,13 @@
   // (The index field is typed as size_t.)
   const Register Rbuffer = tmp1, Rindex = tmp2;
 
-  __ ld(Rindex, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index()), R16_thread);
+  __ 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(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_buf()), R16_thread);
+  __ ld(Rbuffer, in_bytes(G1ThreadLocalData::satb_mark_queue_buffer_offset()), R16_thread);
 
   __ addi(Rindex, Rindex, -wordSize); // Decrement index.
-  __ std(Rindex, in_bytes(JavaThread::satb_mark_queue_offset() + SATBMarkQueue::byte_offset_of_index()), R16_thread);
+  __ std(Rindex, in_bytes(G1ThreadLocalData::satb_mark_queue_index_offset()), R16_thread);
 
   // Record the previous value.
   __ stdx(pre_val, Rbuffer, Rindex);
@@ -253,13 +253,13 @@
 
   const Register Rqueue_index = tmp2,
                  Rqueue_buf   = tmp3;
-  __ ld(Rqueue_index, in_bytes(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index()), R16_thread);
+  __ 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(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_buf()), R16_thread);
+  __ 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(JavaThread::dirty_card_queue_offset() + DirtyCardQueue::byte_offset_of_index()), R16_thread);
+  __ std(Rqueue_index, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()), R16_thread);
 
   __ stdx(Rcard_addr, Rqueue_buf, Rqueue_index); // store card
   __ b(filtered);
--- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp	Thu Apr 12 08:25:56 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
@@ -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);
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -29,9 +29,9 @@
 #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"
 
 #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 {
@@ -127,9 +126,9 @@
 
   const Register Robj = obj ? obj->base() : noreg,
                  Roff = obj ? obj->index() : noreg;
-  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());
+  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!!
@@ -324,8 +323,8 @@
   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());
+  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.
   }
--- a/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp	Thu Apr 12 08:25:56 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
@@ -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) {
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -27,11 +27,11 @@
 #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 +46,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);
@@ -120,13 +119,8 @@
     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());
+  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),
@@ -216,17 +210,10 @@
 
   // 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?
@@ -318,12 +305,8 @@
   // 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());
+  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/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Thu Apr 12 08:25:56 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
 
 
@@ -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;
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -27,11 +27,11 @@
 #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 +48,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);
@@ -160,13 +159,9 @@
     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()));
-
+  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) {
@@ -268,10 +263,8 @@
   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()));
+  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>(Universe::heap()->barrier_set());
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Thu Apr 12 08:25:56 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
@@ -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);
--- a/src/hotspot/share/gc/g1/dirtyCardQueue.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/dirtyCardQueue.cpp	Thu Apr 12 08:25:56 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/g1BarrierSet.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Thu Apr 12 08:25:56 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"
@@ -52,8 +53,7 @@
   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);
     _satb_mark_queue_set.shared_satb_queue()->enqueue(pre_val);
@@ -107,8 +107,7 @@
     *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);
@@ -131,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 {
@@ -157,6 +155,16 @@
   }
 }
 
+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
@@ -176,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 (_satb_mark_queue_set.is_active()) {
-    thread->satb_mark_queue().set_active(true);
+    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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp	Thu Apr 12 08:25:56 2018 +0200
@@ -74,6 +74,8 @@
   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);
 
--- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -54,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"
@@ -2465,7 +2466,7 @@
 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 = G1BarrierSet::dirty_card_queue_set();
--- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -36,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"
@@ -1692,7 +1693,7 @@
         // 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)) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp	Thu Apr 12 08:25:56 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/satbMarkQueue.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/satbMarkQueue.cpp	Thu Apr 12 08:25:56 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"
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/g1/vmStructs_g1.hpp	Thu Apr 12 08:25:56 2018 +0200
@@ -69,10 +69,7 @@
                                                                               \
   nonstatic_field(PtrQueue,            _active,         bool)                 \
   nonstatic_field(PtrQueue,            _buf,            void**)               \
-  nonstatic_field(PtrQueue,            _index,          size_t)               \
-                                                                              \
-  nonstatic_field(JavaThread,          _satb_mark_queue,  SATBMarkQueue)      \
-  nonstatic_field(JavaThread,          _dirty_card_queue, DirtyCardQueue)
+  nonstatic_field(PtrQueue,            _index,          size_t)
 
 #define VM_INT_CONSTANTS_G1GC(declare_constant, declare_constant_with_value)  \
   declare_constant(HeapRegionType::FreeTag)                                   \
--- a/src/hotspot/share/gc/shared/barrierSet.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/shared/barrierSet.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -25,9 +25,20 @@
 #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() {
--- a/src/hotspot/share/gc/shared/barrierSet.hpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp	Thu Apr 12 08:25:56 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/collectedHeap.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/gc/shared/collectedHeap.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -313,7 +313,7 @@
 
 void CollectedHeap::set_barrier_set(BarrierSet* barrier_set) {
   _barrier_set = barrier_set;
-  BarrierSet::set_bs(barrier_set);
+  BarrierSet::set_barrier_set(barrier_set);
 }
 
 #ifndef PRODUCT
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/gcThreadLocalData.hpp	Thu Apr 12 08:25:56 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
--- a/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.hpp	Thu Apr 12 08:25:56 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/jvmciRuntime.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Thu Apr 12 08:25:56 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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Apr 12 08:25:56 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*)                             \
-  ALL_GCS_ONLY(nonstatic_field(JavaThread,     _satb_mark_queue,                              SATBMarkQueue))                        \
-  ALL_GCS_ONLY(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)                          \
                                                                           \
-  ALL_GCS_ONLY(declare_constant_with_value("dirtyCardQueueBufferOffset", in_bytes(DirtyCardQueue::byte_offset_of_buf()))) \
-  ALL_GCS_ONLY(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)                       \
                                                                           \
-  ALL_GCS_ONLY(declare_constant_with_value("satbMarkQueueBufferOffset", in_bytes(SATBMarkQueue::byte_offset_of_buf()))) \
-  ALL_GCS_ONLY(declare_constant_with_value("satbMarkQueueIndexOffset", in_bytes(SATBMarkQueue::byte_offset_of_index()))) \
-  ALL_GCS_ONLY(declare_constant_with_value("satbMarkQueueActiveOffset", in_bytes(SATBMarkQueue::byte_offset_of_active()))) \
-                                                                          \
   declare_constant(vmIntrinsics::_invokeBasic)                            \
   declare_constant(vmIntrinsics::_linkToVirtual)                          \
   declare_constant(vmIntrinsics::_linkToStatic)                           \
@@ -654,7 +646,12 @@
   static_field(HeapRegion, LogOfHRGrainBytes, int)
 
 #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("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
 
--- a/src/hotspot/share/opto/compile.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/opto/compile.cpp	Thu Apr 12 08:25:56 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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/opto/escape.cpp	Thu Apr 12 08:25:56 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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/opto/graphKit.cpp	Thu Apr 12 08:25:56 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.
@@ -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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/opto/macro.cpp	Thu Apr 12 08:25:56 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/runtime/sharedRuntime.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/runtime/sharedRuntime.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -75,6 +75,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 +217,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
--- a/src/hotspot/share/runtime/thread.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/runtime/thread.cpp	Thu Apr 12 08:25:56 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"
@@ -115,7 +116,6 @@
 #include "utilities/vmError.hpp"
 #if INCLUDE_ALL_GCS
 #include "gc/cms/concurrentMarkSweepThread.hpp"
-#include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1ConcurrentMarkThread.inline.hpp"
 #include "gc/parallel/pcTasks.hpp"
 #endif // INCLUDE_ALL_GCS
@@ -312,6 +312,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() {
@@ -362,6 +371,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
@@ -1591,12 +1607,7 @@
 }
 
 JavaThread::JavaThread(bool is_attaching_via_jni) :
-                       Thread()
-#if INCLUDE_ALL_GCS
-                       , _satb_mark_queue(&G1BarrierSet::satb_mark_queue_set()),
-                       _dirty_card_queue(&G1BarrierSet::dirty_card_queue_set())
-#endif // INCLUDE_ALL_GCS
-{
+                       Thread() {
   initialize();
   if (is_attaching_via_jni) {
     _jni_attach_state = _attaching_via_jni;
@@ -1658,12 +1669,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(&G1BarrierSet::satb_mark_queue_set()),
-                       _dirty_card_queue(&G1BarrierSet::dirty_card_queue_set())
-#endif // INCLUDE_ALL_GCS
-{
+                       Thread() {
   initialize();
   _jni_attach_state = _not_attaching_via_jni;
   set_entry_point(entry_point);
--- a/src/hotspot/share/runtime/thread.hpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/runtime/thread.hpp	Thu Apr 12 08:25:56 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,14 +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.
-
-  DirtyCardQueue _dirty_card_queue;      // Thread-local log for dirty cards.
-#endif // INCLUDE_ALL_GCS
-
   friend class VMThread;
   friend class ThreadWaitTransition;
   friend class VM_Exit;
@@ -1666,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; }
 
@@ -1941,14 +1941,6 @@
     _stack_size_at_create = value;
   }
 
-#if INCLUDE_ALL_GCS
-  // SATB marking queue support
-  SATBMarkQueue& satb_mark_queue() { return _satb_mark_queue; }
-
-  // Dirty card queue support
-  DirtyCardQueue& dirty_card_queue() { return _dirty_card_queue; }
-#endif // INCLUDE_ALL_GCS
-
   // Machine dependent stuff
 #include OS_CPU_HEADER(thread)
 
--- a/src/hotspot/share/runtime/vmStructs.cpp	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/hotspot/share/runtime/vmStructs.cpp	Thu Apr 12 08:25:56 2018 +0200
@@ -208,7 +208,7 @@
   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*)                                \
--- a/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/GraalHotSpotVMConfig.java	Thu Apr 12 08:25:56 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	Thu Apr 12 08:25:30 2018 +0200
+++ b/src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.hotspot/src/org/graalvm/compiler/hotspot/replacements/HotSpotReplacementsUtil.java	Thu Apr 12 08:25:56 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");