8201543: Modularize C1 GC barriers
authoreosterlund
Thu, 26 Apr 2018 20:42:43 +0200
changeset 49906 4bb58f644e4e
parent 49905 a09af8ef8e5c
child 49907 1ca3406a2101
8201543: Modularize C1 GC barriers Reviewed-by: pliden, rbackman, rkennke
make/hotspot/lib/JvmFeatures.gmk
src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp
src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp
src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp
src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp
src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp
src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp
src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp
src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp
src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp
src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp
src/hotspot/cpu/arm/c1_Runtime1_arm.cpp
src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp
src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.hpp
src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp
src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp
src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp
src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp
src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp
src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp
src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp
src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp
src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp
src/hotspot/cpu/s390/c1_Runtime1_s390.cpp
src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp
src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp
src/hotspot/cpu/sparc/c1_CodeStubs_sparc.cpp
src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp
src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.hpp
src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp
src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp
src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp
src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp
src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp
src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp
src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp
src/hotspot/cpu/x86/c1_Runtime1_x86.cpp
src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp
src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp
src/hotspot/share/c1/c1_CodeStubs.hpp
src/hotspot/share/c1/c1_Decorators.hpp
src/hotspot/share/c1/c1_LIRAssembler.hpp
src/hotspot/share/c1/c1_LIRGenerator.cpp
src/hotspot/share/c1/c1_LIRGenerator.hpp
src/hotspot/share/c1/c1_MacroAssembler.hpp
src/hotspot/share/c1/c1_Runtime1.cpp
src/hotspot/share/c1/c1_Runtime1.hpp
src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp
src/hotspot/share/gc/g1/c1/g1BarrierSetC1.hpp
src/hotspot/share/gc/g1/g1BarrierSet.cpp
src/hotspot/share/gc/shared/barrierSet.hpp
src/hotspot/share/gc/shared/c1/barrierSetC1.cpp
src/hotspot/share/gc/shared/c1/barrierSetC1.hpp
src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp
src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.hpp
src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp
src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.hpp
src/hotspot/share/gc/shared/cardTableBarrierSet.cpp
src/hotspot/share/gc/shared/cardTableBarrierSet.hpp
src/hotspot/share/gc/shared/modRefBarrierSet.hpp
src/hotspot/share/oops/accessBackend.hpp
src/hotspot/share/oops/accessDecorators.hpp
src/hotspot/share/utilities/macros.hpp
--- a/make/hotspot/lib/JvmFeatures.gmk	Thu Apr 26 12:48:35 2018 -0700
+++ b/make/hotspot/lib/JvmFeatures.gmk	Thu Apr 26 20:42:43 2018 +0200
@@ -32,7 +32,7 @@
 ifeq ($(call check-jvm-feature, compiler1), true)
   JVM_CFLAGS_FEATURES += -DCOMPILER1
 else
-  JVM_EXCLUDE_PATTERNS += c1_
+  JVM_EXCLUDE_PATTERNS += c1_ c1/
 endif
 
 ifeq ($(call check-jvm-feature, compiler2), true)
--- a/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_CodeStubs_aarch64.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -32,9 +32,6 @@
 #include "nativeInst_aarch64.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "vmreg_aarch64.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif
 
 
 #define __ ce->masm()->
@@ -350,42 +347,4 @@
   __ b(_continuation);
 }
 
-
-/////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
-  // At this point we know that marking is in progress.
-  // If do_load() is true then we have to emit the
-  // load of the previous value; otherwise it has already
-  // been loaded into _pre_val.
-
-  __ bind(_entry);
-  assert(pre_val()->is_register(), "Precondition.");
-
-  Register pre_val_reg = pre_val()->as_register();
-
-  if (do_load()) {
-    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
-  }
-  __ cbz(pre_val_reg, _continuation);
-  ce->store_parameter(pre_val()->as_register(), 0);
-  __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id)));
-  __ b(_continuation);
-}
-
-void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-  assert(addr()->is_register(), "Precondition.");
-  assert(new_val()->is_register(), "Precondition.");
-  Register new_val_reg = new_val()->as_register();
-  __ cbz(new_val_reg, _continuation);
-  ce->store_parameter(addr()->as_pointer_register(), 0);
-  __ far_call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id)));
-  __ b(_continuation);
-}
-
-#endif // INCLUDE_ALL_GCS
-/////////////////////////////////////////////////////////////////////////////
-
 #undef __
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1558,7 +1558,16 @@
 
 void LIR_Assembler::emit_compare_and_swap(LIR_OpCompareAndSwap* op) {
   assert(VM_Version::supports_cx8(), "wrong machine");
-  Register addr = as_reg(op->addr());
+  Register addr;
+  if (op->addr()->is_register()) {
+    addr = as_reg(op->addr());
+  } else {
+    assert(op->addr()->is_address(), "what else?");
+    LIR_Address* addr_ptr = op->addr()->as_address_ptr();
+    assert(addr_ptr->disp() == 0, "need 0 disp");
+    assert(addr_ptr->index() == LIR_OprDesc::illegalOpr(), "need 0 index");
+    addr = as_reg(addr_ptr->base());
+  }
   Register newval = as_reg(op->new_value());
   Register cmpval = as_reg(op->cmp_value());
   Label succeed, fail, around;
--- a/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_LIRGenerator_aarch64.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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.
  *
@@ -144,8 +144,22 @@
 
   // accumulate fixed displacements
   if (index->is_constant()) {
-    large_disp += (intx)(index->as_constant_ptr()->as_jint()) << shift;
-    index = LIR_OprFact::illegalOpr;
+    LIR_Const *constant = index->as_constant_ptr();
+    if (constant->type() == T_INT) {
+      large_disp += index->as_jint() << shift;
+    } else {
+      assert(constant->type() == T_LONG, "should be");
+      jlong c = index->as_jlong() << shift;
+      if ((jlong)((jint)c) == c) {
+        large_disp += c;
+        index = LIR_OprFact::illegalOpr;
+      } else {
+        LIR_Opr tmp = new_register(T_LONG);
+        __ move(index, tmp);
+        index = tmp;
+        // apply shift and displacement below
+      }
+    }
   }
 
   if (index->is_register()) {
@@ -183,9 +197,8 @@
   }
 }
 
-
 LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
-                                              BasicType type, bool needs_card_mark) {
+                                              BasicType type) {
   int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type);
   int elem_size = type2aelembytes(type);
   int shift = exact_log2(elem_size);
@@ -206,16 +219,7 @@
                             LIR_Address::scale(type),
                             offset_in_bytes, type);
   }
-  if (needs_card_mark) {
-    // This store will need a precise card mark, so go ahead and
-    // compute the full adddres instead of computing once for the
-    // store and again for the card mark.
-    LIR_Opr tmp = new_pointer_register();
-    __ leal(LIR_OprFact::address(addr), tmp);
-    return new LIR_Address(tmp, type);
-  } else {
-    return addr;
-  }
+  return addr;
 }
 
 LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) {
@@ -305,87 +309,17 @@
   __ store(item, new LIR_Address(FrameMap::sp_opr, in_bytes(offset_from_sp), type));
 }
 
+void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci) {
+    LIR_Opr tmp1 = new_register(objectType);
+    LIR_Opr tmp2 = new_register(objectType);
+    LIR_Opr tmp3 = new_register(objectType);
+    __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci);
+}
+
 //----------------------------------------------------------------------
 //             visitor functions
 //----------------------------------------------------------------------
 
-
-void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
-  assert(x->is_pinned(),"");
-  bool needs_range_check = x->compute_needs_range_check();
-  bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
-                                         !get_jobject_constant(x->value())->is_null_object() ||
-                                         x->should_profile());
-
-  LIRItem array(x->array(), this);
-  LIRItem index(x->index(), this);
-  LIRItem value(x->value(), this);
-  LIRItem length(this);
-
-  array.load_item();
-  index.load_nonconstant();
-
-  if (use_length && needs_range_check) {
-    length.set_instruction(x->length());
-    length.load_item();
-
-  }
-  if (needs_store_check || x->check_boolean()) {
-    value.load_item();
-  } else {
-    value.load_for_store(x->elt_type());
-  }
-
-  set_no_result(x);
-
-  // the CodeEmitInfo must be duplicated for each different
-  // LIR-instruction because spilling can occur anywhere between two
-  // instructions and so the debug information must be different
-  CodeEmitInfo* range_check_info = state_for(x);
-  CodeEmitInfo* null_check_info = NULL;
-  if (x->needs_null_check()) {
-    null_check_info = new CodeEmitInfo(range_check_info);
-  }
-
-  // emit array address setup early so it schedules better
-  // FIXME?  No harm in this on aarch64, and it might help
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);
-
-  if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
-      __ cmp(lir_cond_belowEqual, length.result(), index.result());
-      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
-    } else {
-      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
-      // range_check also does the null check
-      null_check_info = NULL;
-    }
-  }
-
-  if (GenerateArrayStoreCheck && needs_store_check) {
-    LIR_Opr tmp1 = new_register(objectType);
-    LIR_Opr tmp2 = new_register(objectType);
-    LIR_Opr tmp3 = new_register(objectType);
-
-    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
-    __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci());
-  }
-
-  if (obj_store) {
-    // Needs GC write barriers.
-    pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-    __ move(value.result(), array_addr, null_check_info);
-    // Seems to be a precise
-    post_barrier(LIR_OprFact::address(array_addr), value.result());
-  } else {
-    LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
-    __ move(result, array_addr, null_check_info);
-  }
-}
-
 void LIRGenerator::do_MonitorEnter(MonitorEnter* x) {
   assert(x->is_pinned(),"");
   LIRItem obj(x->obj(), this);
@@ -771,76 +705,42 @@
   }
 }
 
-void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
-  assert(x->number_of_arguments() == 4, "wrong type");
-  LIRItem obj   (x->argument_at(0), this);  // object
-  LIRItem offset(x->argument_at(1), this);  // offset of field
-  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
-  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp
-
-  assert(obj.type()->tag() == objectTag, "invalid type");
-
-  // In 64bit the type can be long, sparc doesn't have this assert
-  // assert(offset.type()->tag() == intTag, "invalid type");
-
-  assert(cmp.type()->tag() == type->tag(), "invalid type");
-  assert(val.type()->tag() == type->tag(), "invalid type");
-
-  // get address of field
-  obj.load_item();
-  offset.load_nonconstant();
-  val.load_item();
-  cmp.load_item();
+LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) {
+  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
+  new_value.load_item();
+  cmp_value.load_item();
+  LIR_Opr result = new_register(T_INT);
+  if (type == T_OBJECT || type == T_ARRAY) {
+    __ cas_obj(addr, cmp_value.result(), new_value.result(), new_register(T_INT), new_register(T_INT), result);
+  } else if (type == T_INT) {
+    __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill);
+  } else if (type == T_LONG) {
+    __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill);
+  } else {
+    ShouldNotReachHere();
+    Unimplemented();
+  }
+  __ logical_xor(FrameMap::r8_opr, LIR_OprFact::intConst(1), result);
+  return result;
+}
 
-  LIR_Address* a;
-  if(offset.result()->is_constant()) {
-    jlong c = offset.result()->as_jlong();
-    if ((jlong)((jint)c) == c) {
-      a = new LIR_Address(obj.result(),
-                          (jint)c,
-                          as_BasicType(type));
-    } else {
-      LIR_Opr tmp = new_register(T_LONG);
-      __ move(offset.result(), tmp);
-      a = new LIR_Address(obj.result(),
-                          tmp,
-                          as_BasicType(type));
-    }
-  } else {
-    a = new LIR_Address(obj.result(),
-                        offset.result(),
-                        0,
-                        as_BasicType(type));
-  }
-  LIR_Opr addr = new_pointer_register();
-  __ leal(LIR_OprFact::address(a), addr);
+LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
+  bool is_oop = type == T_OBJECT || type == T_ARRAY;
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type");
+  LIR_Opr tmp = new_register(T_INT);
+  __ xchg(addr, value.result(), result, tmp);
+  return result;
+}
 
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    // Do the pre-write barrier, if any.
-    pre_barrier(addr, LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-
-  LIR_Opr result = rlock_result(x);
-
-  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
-  if (type == objectType)
-    __ cas_obj(addr, cmp.result(), val.result(), new_register(T_INT), new_register(T_INT),
-               result);
-  else if (type == intType)
-    __ cas_int(addr, cmp.result(), val.result(), ill, ill);
-  else if (type == longType)
-    __ cas_long(addr, cmp.result(), val.result(), ill, ill);
-  else {
-    ShouldNotReachHere();
-  }
-
-  __ logical_xor(FrameMap::r8_opr, LIR_OprFact::intConst(1), result);
-
-  if (type == objectType) {   // Write-barrier needed for Object fields.
-    // Seems to be precise
-    post_barrier(addr, val.result());
-  }
+LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  assert(type == T_INT LP64_ONLY( || type == T_LONG ), "unexpected type");
+  LIR_Opr tmp = new_register(T_INT);
+  __ xadd(addr, value.result(), result, tmp);
+  return result;
 }
 
 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
@@ -1433,84 +1333,3 @@
 
   __ volatile_load_mem_reg(address, result, info);
 }
-
-void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset,
-                                     BasicType type, bool is_volatile) {
-  LIR_Address* addr = new LIR_Address(src, offset, type);
-  __ load(addr, dst);
-}
-
-
-void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data,
-                                     BasicType type, bool is_volatile) {
-  LIR_Address* addr = new LIR_Address(src, offset, type);
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-  if (is_obj) {
-    // Do the pre-write barrier, if any.
-    pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-    __ move(data, addr);
-    assert(src->is_register(), "must be register");
-    // Seems to be a precise address
-    post_barrier(LIR_OprFact::address(addr), data);
-  } else {
-    __ move(data, addr);
-  }
-}
-
-void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
-  BasicType type = x->basic_type();
-  LIRItem src(x->object(), this);
-  LIRItem off(x->offset(), this);
-  LIRItem value(x->value(), this);
-
-  src.load_item();
-  off.load_nonconstant();
-
-  // We can cope with a constant increment in an xadd
-  if (! (x->is_add()
-         && value.is_constant()
-         && can_inline_as_constant(x->value()))) {
-    value.load_item();
-  }
-
-  LIR_Opr dst = rlock_result(x, type);
-  LIR_Opr data = value.result();
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-  LIR_Opr offset = off.result();
-
-  if (data == dst) {
-    LIR_Opr tmp = new_register(data->type());
-    __ move(data, tmp);
-    data = tmp;
-  }
-
-  LIR_Address* addr;
-  if (offset->is_constant()) {
-    jlong l = offset->as_jlong();
-    assert((jlong)((jint)l) == l, "offset too large for constant");
-    jint c = (jint)l;
-    addr = new LIR_Address(src.result(), c, type);
-  } else {
-    addr = new LIR_Address(src.result(), offset, type);
-  }
-
-  LIR_Opr tmp = new_register(T_INT);
-  LIR_Opr ptr = LIR_OprFact::illegalOpr;
-
-  if (x->is_add()) {
-    __ xadd(LIR_OprFact::address(addr), data, dst, tmp);
-  } else {
-    if (is_obj) {
-      // Do the pre-write barrier, if any.
-      ptr = new_pointer_register();
-      __ add(src.result(), off.result(), ptr);
-      pre_barrier(ptr, LIR_OprFact::illegalOpr /* pre_val */,
-                  true /* do_load */, false /* patch */, NULL);
-    }
-    __ xchg(LIR_OprFact::address(addr), data, dst, tmp);
-    if (is_obj) {
-      post_barrier(ptr, data);
-    }
-  }
-}
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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.
  *
@@ -358,6 +358,16 @@
 void C1_MacroAssembler::verified_entry() {
 }
 
+void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) {
+  // rbp, + 0: link
+  //     + 1: return address
+  //     + 2: argument with offset 0
+  //     + 3: argument with offset 1
+  //     + 4: ...
+
+  ldr(reg, Address(rfp, (offset_in_words + 2) * BytesPerWord));
+}
+
 #ifndef PRODUCT
 
 void C1_MacroAssembler::verify_stack_oop(int stack_offset) {
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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.
  *
@@ -109,4 +109,6 @@
   // This platform only uses signal-based null checks. The Label is not needed.
   void null_check(Register r, Label *Lnull = NULL) { MacroAssembler::null_check(r); }
 
+  void load_parameter(int offset_in_words, Register reg);
+
 #endif // CPU_AARCH64_VM_C1_MACROASSEMBLER_AARCH64_HPP
--- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -43,11 +43,6 @@
 #include "runtime/vframe.hpp"
 #include "runtime/vframeArray.hpp"
 #include "vmreg_aarch64.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1ThreadLocalData.hpp"
-#endif
 
 
 // Implementation of StubAssembler
@@ -173,31 +168,32 @@
   ~StubFrame();
 };;
 
+void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
+  set_info(name, must_gc_arguments);
+  enter();
+}
+
+void StubAssembler::epilogue() {
+  leave();
+  ret(lr);
+}
 
 #define __ _sasm->
 
 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) {
   _sasm = sasm;
-  __ set_info(name, must_gc_arguments);
-  __ enter();
+  __ prologue(name, must_gc_arguments);
 }
 
 // load parameters that were stored with LIR_Assembler::store_parameter
 // Note: offsets for store_parameter and load_argument must match
 void StubFrame::load_argument(int offset_in_words, Register reg) {
-  // rbp, + 0: link
-  //     + 1: return address
-  //     + 2: argument with offset 0
-  //     + 3: argument with offset 1
-  //     + 4: ...
-
-  __ ldr(reg, Address(rfp, (offset_in_words + 2) * BytesPerWord));
+  __ load_parameter(offset_in_words, reg);
 }
 
 
 StubFrame::~StubFrame() {
-  __ leave();
-  __ ret(lr);
+  __ epilogue();
 }
 
 #undef __
@@ -1100,136 +1096,6 @@
       }
       break;
 
-#if INCLUDE_ALL_GCS
-
-    case g1_pre_barrier_slow_id:
-      {
-        StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);
-        // arg0 : previous value of memory
-
-        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);
-          __ should_not_reach_here();
-          break;
-        }
-
-        const Register pre_val = r0;
-        const Register thread = rthread;
-        const Register tmp = rscratch1;
-
-        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;
-
-        // Is marking still 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);
-
-        // Can we store original value in the thread's buffer?
-        __ ldr(tmp, queue_index);
-        __ cbz(tmp, runtime);
-
-        __ sub(tmp, tmp, wordSize);
-        __ str(tmp, queue_index);
-        __ ldr(rscratch2, buffer);
-        __ add(tmp, tmp, rscratch2);
-        f.load_argument(0, rscratch2);
-        __ str(rscratch2, Address(tmp, 0));
-        __ b(done);
-
-        __ bind(runtime);
-        __ push_call_clobbered_registers();
-        f.load_argument(0, pre_val);
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
-        __ pop_call_clobbered_registers();
-        __ bind(done);
-      }
-      break;
-    case g1_post_barrier_slow_id:
-      {
-        StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);
-
-        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);
-          __ should_not_reach_here();
-          break;
-        }
-
-        // arg0: store_address
-        Address store_addr(rfp, 2*BytesPerWord);
-
-        Label done;
-        Label runtime;
-
-        // At this point we know new_value is non-NULL and the new_value crosses regions.
-        // Must check to see if card is already dirty
-
-        const Register thread = rthread;
-
-        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.
-        const Register byte_map_base = lr;
-
-        assert_different_registers(card_offset, byte_map_base, rscratch1);
-
-        f.load_argument(0, card_offset);
-        __ lsr(card_offset, card_offset, CardTable::card_shift);
-        __ load_byte_map_base(byte_map_base);
-        __ ldrb(rscratch1, Address(byte_map_base, card_offset));
-        __ cmpw(rscratch1, (int)G1CardTable::g1_young_card_val());
-        __ br(Assembler::EQ, done);
-
-        assert((int)CardTable::dirty_card_val() == 0, "must be 0");
-
-        __ membar(Assembler::StoreLoad);
-        __ ldrb(rscratch1, Address(byte_map_base, card_offset));
-        __ cbzw(rscratch1, done);
-
-        // storing region crossing non-NULL, card is clean.
-        // dirty card and log.
-        __ strb(zr, Address(byte_map_base, card_offset));
-
-        // Convert card offset into an address in card_addr
-        Register card_addr = card_offset;
-        __ add(card_addr, byte_map_base, card_addr);
-
-        __ ldr(rscratch1, queue_index);
-        __ cbz(rscratch1, runtime);
-        __ sub(rscratch1, rscratch1, wordSize);
-        __ str(rscratch1, queue_index);
-
-        // Reuse LR to hold buffer_addr
-        const Register buffer_addr = lr;
-
-        __ ldr(buffer_addr, buffer);
-        __ str(card_addr, Address(buffer_addr, rscratch1));
-        __ b(done);
-
-        __ bind(runtime);
-        __ push_call_clobbered_registers();
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
-        __ pop_call_clobbered_registers();
-        __ bind(done);
-
-      }
-      break;
-#endif
-
     case predicate_failed_trap_id:
       {
         StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments);
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -24,6 +24,9 @@
 
 #include "precompiled.hpp"
 #include "asm/macroAssembler.inline.hpp"
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
 #include "gc/g1/g1BarrierSet.hpp"
 #include "gc/g1/g1BarrierSetAssembler.hpp"
 #include "gc/g1/g1CardTable.hpp"
@@ -307,4 +310,167 @@
 
 }
 
+#ifdef COMPILER1
+
 #undef __
+#define __ ce->masm()->
+
+void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  // At this point we know that marking is in progress.
+  // If do_load() is true then we have to emit the
+  // load of the previous value; otherwise it has already
+  // been loaded into _pre_val.
+
+  __ bind(*stub->entry());
+
+  assert(stub->pre_val()->is_register(), "Precondition.");
+
+  Register pre_val_reg = stub->pre_val()->as_register();
+
+  if (stub->do_load()) {
+    ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
+  }
+  __ cbz(pre_val_reg, *stub->continuation());
+  ce->store_parameter(stub->pre_val()->as_register(), 0);
+  __ far_call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin()));
+  __ b(*stub->continuation());
+}
+
+void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
+  assert(stub->addr()->is_register(), "Precondition.");
+  assert(stub->new_val()->is_register(), "Precondition.");
+  Register new_val_reg = stub->new_val()->as_register();
+  __ cbz(new_val_reg, *stub->continuation());
+  ce->store_parameter(stub->addr()->as_pointer_register(), 0);
+  __ far_call(RuntimeAddress(bs->post_barrier_c1_runtime_code_blob()->code_begin()));
+  __ b(*stub->continuation());
+}
+
+#undef __
+
+#define __ sasm->
+
+void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("g1_pre_barrier", false);
+
+  // arg0 : previous value of memory
+
+  BarrierSet* bs = BarrierSet::barrier_set();
+
+  const Register pre_val = r0;
+  const Register thread = rthread;
+  const Register tmp = rscratch1;
+
+  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;
+
+  // Is marking still 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);
+
+  // Can we store original value in the thread's buffer?
+  __ ldr(tmp, queue_index);
+  __ cbz(tmp, runtime);
+
+  __ sub(tmp, tmp, wordSize);
+  __ str(tmp, queue_index);
+  __ ldr(rscratch2, buffer);
+  __ add(tmp, tmp, rscratch2);
+  __ load_parameter(0, rscratch2);
+  __ str(rscratch2, Address(tmp, 0));
+  __ b(done);
+
+  __ bind(runtime);
+  __ push_call_clobbered_registers();
+  __ load_parameter(0, pre_val);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), pre_val, thread);
+  __ pop_call_clobbered_registers();
+  __ bind(done);
+
+  __ epilogue();
+}
+
+void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("g1_post_barrier", false);
+
+  // arg0: store_address
+  Address store_addr(rfp, 2*BytesPerWord);
+
+  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;
+
+  // At this point we know new_value is non-NULL and the new_value crosses regions.
+  // Must check to see if card is already dirty
+
+  const Register thread = rthread;
+
+  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.
+  const Register byte_map_base = lr;
+
+  assert_different_registers(card_offset, byte_map_base, rscratch1);
+
+  __ load_parameter(0, card_offset);
+  __ lsr(card_offset, card_offset, CardTable::card_shift);
+  __ load_byte_map_base(byte_map_base);
+  __ ldrb(rscratch1, Address(byte_map_base, card_offset));
+  __ cmpw(rscratch1, (int)G1CardTable::g1_young_card_val());
+  __ br(Assembler::EQ, done);
+
+  assert((int)CardTable::dirty_card_val() == 0, "must be 0");
+
+  __ membar(Assembler::StoreLoad);
+  __ ldrb(rscratch1, Address(byte_map_base, card_offset));
+  __ cbzw(rscratch1, done);
+
+  // storing region crossing non-NULL, card is clean.
+  // dirty card and log.
+  __ strb(zr, Address(byte_map_base, card_offset));
+
+  // Convert card offset into an address in card_addr
+  Register card_addr = card_offset;
+  __ add(card_addr, byte_map_base, card_addr);
+
+  __ ldr(rscratch1, queue_index);
+  __ cbz(rscratch1, runtime);
+  __ sub(rscratch1, rscratch1, wordSize);
+  __ str(rscratch1, queue_index);
+
+  // Reuse LR to hold buffer_addr
+  const Register buffer_addr = lr;
+
+  __ ldr(buffer_addr, buffer);
+  __ str(card_addr, Address(buffer_addr, rscratch1));
+  __ b(done);
+
+  __ bind(runtime);
+  __ push_call_clobbered_registers();
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
+  __ pop_call_clobbered_registers();
+  __ bind(done);
+  __ epilogue();
+}
+
+#undef __
+
+#endif // COMPILER1
--- a/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -27,6 +27,12 @@
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
+#include "utilities/macros.hpp"
+
+class LIR_Assembler;
+class StubAssembler;
+class G1PreBarrierStub;
+class G1PostBarrierStub;
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
@@ -54,6 +60,14 @@
                             Address dst, Register val, Register tmp1, Register tmp2);
 
 public:
+#ifdef COMPILER1
+  void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
+  void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
+
+  void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
+#endif
+
   void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                Register dst, Address src, Register tmp1, Register tmp_thread);
 };
--- a/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/arm/c1_CodeStubs_arm.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,9 +33,6 @@
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_arm.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif // INCLUDE_ALL_GCS
 
 #define __ ce->masm()->
 
@@ -466,45 +463,4 @@
   __ b(_continuation);
 }
 
-/////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
-  // At this point we know that marking is in progress.
-  // If do_load() is true then we have to emit the
-  // load of the previous value; otherwise it has already
-  // been loaded into _pre_val.
-
-  __ bind(_entry);
-  assert(pre_val()->is_register(), "Precondition.");
-
-  Register pre_val_reg = pre_val()->as_register();
-
-  if (do_load()) {
-    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
-  }
-
-  __ cbz(pre_val_reg, _continuation);
-  ce->verify_reserved_argument_area_size(1);
-  __ str(pre_val_reg, Address(SP));
-  __ call(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id), relocInfo::runtime_call_type);
-
-  __ b(_continuation);
-}
-
-void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-  assert(addr()->is_register(), "Precondition.");
-  assert(new_val()->is_register(), "Precondition.");
-  Register new_val_reg = new_val()->as_register();
-  __ cbz(new_val_reg, _continuation);
-  ce->verify_reserved_argument_area_size(1);
-  __ str(addr()->as_pointer_register(), Address(SP));
-  __ call(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id), relocInfo::runtime_call_type);
-  __ b(_continuation);
-}
-
-#endif // INCLUDE_ALL_GCS
-/////////////////////////////////////////////////////////////////////////////
-
 #undef __
--- a/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/arm/c1_LIRGenerator_arm.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -34,6 +34,7 @@
 #include "ci/ciObjArrayKlass.hpp"
 #include "ci/ciTypeArrayKlass.hpp"
 #include "ci/ciUtilities.hpp"
+#include "gc/shared/c1/barrierSetC1.hpp"
 #include "gc/shared/cardTable.hpp"
 #include "gc/shared/cardTableBarrierSet.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -542,88 +543,17 @@
   }
 }
 
+void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci) {
+  LIR_Opr tmp1 = FrameMap::R0_oop_opr;
+  LIR_Opr tmp2 = FrameMap::R1_oop_opr;
+  LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
+  __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci);
+}
+
 //----------------------------------------------------------------------
 //             visitor functions
 //----------------------------------------------------------------------
 
-
-void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
-  assert(x->is_pinned(),"");
-  bool needs_range_check = x->compute_needs_range_check();
-  bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
-                                         !get_jobject_constant(x->value())->is_null_object() ||
-                                         x->should_profile());
-
-  LIRItem array(x->array(), this);
-  LIRItem index(x->index(), this);
-  LIRItem value(x->value(), this);
-  LIRItem length(this);
-
-  array.load_item();
-  index.load_nonconstant();
-
-  if (use_length && needs_range_check) {
-    length.set_instruction(x->length());
-    length.load_item();
-  }
-  if (needs_store_check || x->check_boolean()) {
-    value.load_item();
-  } else {
-    value.load_for_store(x->elt_type());
-  }
-
-  set_no_result(x);
-
-  // the CodeEmitInfo must be duplicated for each different
-  // LIR-instruction because spilling can occur anywhere between two
-  // instructions and so the debug information must be different
-  CodeEmitInfo* range_check_info = state_for(x);
-  CodeEmitInfo* null_check_info = NULL;
-  if (x->needs_null_check()) {
-    null_check_info = new CodeEmitInfo(range_check_info);
-  }
-
-  // emit array address setup early so it schedules better
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);
-
-  if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
-      __ cmp(lir_cond_belowEqual, length.result(), index.result());
-      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
-    } else {
-      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
-      // range_check also does the null check
-      null_check_info = NULL;
-    }
-  }
-
-  if (GenerateArrayStoreCheck && needs_store_check) {
-    LIR_Opr tmp1 = FrameMap::R0_oop_opr;
-    LIR_Opr tmp2 = FrameMap::R1_oop_opr;
-    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
-    __ store_check(value.result(), array.result(), tmp1, tmp2,
-                   LIR_OprFact::illegalOpr, store_check_info,
-                   x->profiled_method(), x->profiled_bci());
-  }
-
-#if INCLUDE_ALL_GCS
-  if (obj_store) {
-    // Needs GC write barriers.
-    pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-#endif // INCLUDE_ALL_GCS
-
-  LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
-  __ move(result, array_addr, null_check_info);
-  if (obj_store) {
-    post_barrier(LIR_OprFact::address(array_addr), value.result());
-  }
-}
-
-
 void LIRGenerator::do_MonitorEnter(MonitorEnter* x) {
   assert(x->is_pinned(),"");
   LIRItem obj(x->obj(), this);
@@ -1060,56 +990,52 @@
 #endif // __SOFTFP__
 }
 
-
-void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
-  assert(x->number_of_arguments() == 4, "wrong type");
-  LIRItem obj   (x->argument_at(0), this);  // object
-  LIRItem offset(x->argument_at(1), this);  // offset of field
-  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
-  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp
-
-  LIR_Opr addr = new_pointer_register();
+LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) {
+  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
   LIR_Opr tmp1 = LIR_OprFact::illegalOpr;
   LIR_Opr tmp2 = LIR_OprFact::illegalOpr;
-
-  // get address of field
-  obj.load_item();
-  offset.load_item();
-  cmp.load_item();
-  val.load_item();
-
-  __ add(obj.result(), offset.result(), addr);
-  LIR_Opr result = rlock_result(x);
-
-  if (type == objectType) {
-#if INCLUDE_ALL_GCS
-    // Do the pre-write barrier, if any.
-    pre_barrier(addr, LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-#endif // INCLUDE_ALL_GCS
+  new_value.load_item();
+  cmp_value.load_item();
+  LIR_Opr result = new_register(T_INT);
+  if (type == T_OBJECT || type == T_ARRAY) {
 #ifdef AARCH64
     if (UseCompressedOops) {
       tmp1 = new_pointer_register();
       tmp2 = new_pointer_register();
     }
-#endif // AARCH64
-    __ cas_obj(addr, cmp.result(), val.result(), tmp1, tmp2, result);
-    post_barrier(addr, val.result());
-  }
-  else if (type == intType) {
-    __ cas_int(addr, cmp.result(), val.result(), tmp1, tmp1, result);
-  }
-  else if (type == longType) {
+#endif
+    __ cas_obj(addr, cmp_value.result(), new_value.result(), new_register(T_INT), new_register(T_INT), result);
+  } else if (type == T_INT) {
+    __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), tmp1, tmp1, result);
+  } else if (type == T_LONG) {
 #ifndef AARCH64
     tmp1 = new_register(T_LONG);
 #endif // !AARCH64
-    __ cas_long(addr, cmp.result(), val.result(), tmp1, tmp2, result);
-  }
-  else {
+    __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), tmp1, tmp2, result);
+  } else {
     ShouldNotReachHere();
   }
+  return result;
 }
 
+LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
+  bool is_oop = type == T_OBJECT || type == T_ARRAY;
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type");
+  LIR_Opr tmp = (UseCompressedOops && is_oop) ? new_pointer_register() : LIR_OprFact::illegalOpr;
+  __ xchg(addr_ptr, data, dst, tmp);
+  return result;
+}
+
+LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  assert(type == T_INT LP64_ONLY( || type == T_LONG), "unexpected type");
+  LIR_Opr tmp = new_register(type);
+  __ xadd(addr, value.result(), result, tmp);
+  return result;
+}
 
 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
   address runtime_func;
@@ -1669,110 +1595,3 @@
   // TODO-AARCH64 implement with ldar instruction
   __ load(address, result, info, lir_patch_none);
 }
-
-void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset,
-                                     BasicType type, bool is_volatile) {
-#ifdef AARCH64
-  __ load(new LIR_Address(src, offset, type), dst);
-#else
-  assert(offset->is_single_cpu(), "must be");
-  if (is_volatile && dst->is_double_cpu()) {
-    LIR_Opr tmp = new_pointer_register();
-    __ add(src, offset, tmp);
-    __ volatile_load_mem_reg(new LIR_Address(tmp, (intx)0, type), dst, NULL);
-  } else if (type == T_FLOAT || type == T_DOUBLE) {
-    // fld doesn't have indexed addressing mode
-    LIR_Opr tmp = new_register(T_INT);
-    __ add(src, offset, tmp);
-    __ load(new LIR_Address(tmp, (intx)0, type), dst);
-  } else {
-    __ load(new LIR_Address(src, offset, type), dst);
-  }
-#endif // AARCH64
-}
-
-void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data,
-                                     BasicType type, bool is_volatile) {
-#ifdef AARCH64
-  LIR_Address* addr = new LIR_Address(src, offset, type);
-  if (type == T_ARRAY || type == T_OBJECT) {
-    pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-    __ move(data, addr);
-    assert(src->is_register(), "must be register");
-    post_barrier(LIR_OprFact::address(addr), data);
-  } else {
-    __ move(data, addr);
-  }
-#else
-  assert(offset->is_single_cpu(), "must be");
-  if (is_volatile && data->is_double_cpu()) {
-    LIR_Opr tmp = new_register(T_INT);
-    __ add(src, offset, tmp);
-    __ volatile_store_mem_reg(data, new LIR_Address(tmp, (intx)0, type), NULL);
-  } else if (type == T_FLOAT || type == T_DOUBLE) {
-    // fst doesn't have indexed addressing mode
-    LIR_Opr tmp = new_register(T_INT);
-    __ add(src, offset, tmp);
-    __ move(data, new LIR_Address(tmp, (intx)0, type));
-  } else {
-    LIR_Address* addr = new LIR_Address(src, offset, type);
-    bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-#if INCLUDE_ALL_GCS
-    if (is_obj) {
-      // Do the pre-write barrier, if any.
-      pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                  true /* do_load */, false /* patch */, NULL);
-    }
-#endif // INCLUDE_ALL_GCS
-    __ move(data, addr);
-    if (is_obj) {
-      assert(src->is_register(), "must be register");
-      post_barrier(LIR_OprFact::address(addr), data);
-    }
-  }
-#endif // AARCH64
-}
-
-void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
-  BasicType type = x->basic_type();
-  LIRItem src(x->object(), this);
-  LIRItem off(x->offset(), this);
-  LIRItem value(x->value(), this);
-
-  src.load_item();
-  if (x->is_add()) {
-    value.load_nonconstant();
-  } else {
-    value.load_item();
-  }
-  off.load_nonconstant();
-
-  LIR_Opr dst = rlock_result(x, type);
-  LIR_Opr data = value.result();
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-
-  assert (type == T_INT || type == T_LONG || (!x->is_add() && is_obj), "unexpected type");
-  LIR_Opr addr_ptr = new_pointer_register();
-
-  __ add(src.result(), off.result(), addr_ptr);
-
-  LIR_Address* addr = new LIR_Address(addr_ptr, (intx)0, type);
-
-  if (x->is_add()) {
-    LIR_Opr tmp = new_register(type);
-    __ xadd(addr_ptr, data, dst, tmp);
-  } else {
-    LIR_Opr tmp = (UseCompressedOops && is_obj) ? new_pointer_register() : LIR_OprFact::illegalOpr;
-    if (is_obj) {
-      // Do the pre-write barrier, if any.
-      pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                  true /* do_load */, false /* patch */, NULL);
-    }
-    __ xchg(addr_ptr, data, dst, tmp);
-    if (is_obj) {
-      // Seems to be a precise address
-      post_barrier(LIR_OprFact::address(addr), data);
-    }
-  }
-}
--- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -42,11 +42,6 @@
 #include "runtime/vframeArray.hpp"
 #include "utilities/align.hpp"
 #include "vmreg_arm.inline.hpp"
-#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
 // correct as long as it is not implicitly used in lower layers (the
@@ -356,6 +351,13 @@
   restore_live_registers(sasm, true, true, false, restore_fpu_registers);
 }
 
+void StubAssembler::save_live_registers() {
+  save_live_registers(this);
+}
+
+void StubAssembler::restore_live_registers_without_return() {
+  restore_live_registers_without_return(this);
+}
 
 void Runtime1::initialize_pd() {
 }
@@ -533,201 +535,6 @@
       }
       break;
 
-#if INCLUDE_ALL_GCS
-    case g1_pre_barrier_slow_id:
-      {
-        // Input:
-        // - pre_val pushed on the stack
-
-        __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
-
-        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);
-          __ should_not_reach_here();
-          break;
-        }
-
-        // save at least the registers that need saving if the runtime is called
-#ifdef AARCH64
-        __ raw_push(R0, R1);
-        __ raw_push(R2, R3);
-        const int nb_saved_regs = 4;
-#else // AARCH64
-        const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
-        const int nb_saved_regs = 6;
-        assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
-        __ push(saved_regs);
-#endif // AARCH64
-
-        const Register r_pre_val_0  = R0; // must be R0, to be ready for the runtime call
-        const Register r_index_1    = R1;
-        const Register r_buffer_2   = R2;
-
-        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;
-
-        // Is marking still active?
-        assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-        __ ldrb(R1, queue_active);
-        __ cbz(R1, done);
-
-        __ ldr(r_index_1, queue_index);
-        __ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
-        __ ldr(r_buffer_2, buffer);
-
-        __ subs(r_index_1, r_index_1, wordSize);
-        __ b(runtime, lt);
-
-        __ str(r_index_1, queue_index);
-        __ str(r_pre_val_0, Address(r_buffer_2, r_index_1));
-
-        __ bind(done);
-
-#ifdef AARCH64
-        __ raw_pop(R2, R3);
-        __ raw_pop(R0, R1);
-#else // AARCH64
-        __ pop(saved_regs);
-#endif // AARCH64
-
-        __ ret();
-
-        __ bind(runtime);
-
-        save_live_registers(sasm);
-
-        assert(r_pre_val_0 == c_rarg0, "pre_val should be in R0");
-        __ mov(c_rarg1, Rthread);
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), c_rarg0, c_rarg1);
-
-        restore_live_registers_without_return(sasm);
-
-        __ b(done);
-      }
-      break;
-    case g1_post_barrier_slow_id:
-      {
-        // Input:
-        // - store_addr, pushed on the stack
-
-        __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
-
-        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);
-          __ should_not_reach_here();
-          break;
-        }
-
-        Label done;
-        Label recheck;
-        Label runtime;
-
-        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);
-
-        // save at least the registers that need saving if the runtime is called
-#ifdef AARCH64
-        __ raw_push(R0, R1);
-        __ raw_push(R2, R3);
-        const int nb_saved_regs = 4;
-#else // AARCH64
-        const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
-        const int nb_saved_regs = 6;
-        assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
-        __ push(saved_regs);
-#endif // AARCH64
-
-        const Register r_card_addr_0 = R0; // must be R0 for the slow case
-        const Register r_obj_0 = R0;
-        const Register r_card_base_1 = R1;
-        const Register r_tmp2 = R2;
-        const Register r_index_2 = R2;
-        const Register r_buffer_3 = R3;
-        const Register tmp1 = Rtemp;
-
-        __ ldr(r_obj_0, Address(SP, nb_saved_regs*wordSize));
-        // Note: there is a comment in x86 code about not using
-        // ExternalAddress / lea, due to relocation not working
-        // properly for that address. Should be OK for arm, where we
-        // explicitly specify that 'cardtable' has a relocInfo::none
-        // type.
-        __ lea(r_card_base_1, cardtable);
-        __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift));
-
-        // first quick check without barrier
-        __ ldrb(r_tmp2, Address(r_card_addr_0));
-
-        __ cmp(r_tmp2, (int)G1CardTable::g1_young_card_val());
-        __ b(recheck, ne);
-
-        __ bind(done);
-
-#ifdef AARCH64
-        __ raw_pop(R2, R3);
-        __ raw_pop(R0, R1);
-#else // AARCH64
-        __ pop(saved_regs);
-#endif // AARCH64
-
-        __ ret();
-
-        __ bind(recheck);
-
-        __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp1);
-
-        // reload card state after the barrier that ensures the stored oop was visible
-        __ ldrb(r_tmp2, Address(r_card_addr_0));
-
-        assert(CardTable::dirty_card_val() == 0, "adjust this code");
-        __ cbz(r_tmp2, done);
-
-        // storing region crossing non-NULL, card is clean.
-        // dirty card and log.
-
-        assert(0 == (int)CardTable::dirty_card_val(), "adjust this code");
-        if ((ci_card_table_address_as<intptr_t>() & 0xff) == 0) {
-          // Card table is aligned so the lowest byte of the table address base is zero.
-          __ strb(r_card_base_1, Address(r_card_addr_0));
-        } else {
-          __ strb(__ zero_register(r_tmp2), Address(r_card_addr_0));
-        }
-
-        __ ldr(r_index_2, queue_index);
-        __ ldr(r_buffer_3, buffer);
-
-        __ subs(r_index_2, r_index_2, wordSize);
-        __ b(runtime, lt); // go to runtime if now negative
-
-        __ str(r_index_2, queue_index);
-
-        __ str(r_card_addr_0, Address(r_buffer_3, r_index_2));
-
-        __ b(done);
-
-        __ bind(runtime);
-
-        save_live_registers(sasm);
-
-        assert(r_card_addr_0 == c_rarg0, "card_addr should be in R0");
-        __ mov(c_rarg1, Rthread);
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), c_rarg0, c_rarg1);
-
-        restore_live_registers_without_return(sasm);
-
-        __ b(done);
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
     case new_instance_id:
     case fast_new_instance_id:
     case fast_new_instance_init_check_id:
--- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -32,6 +32,11 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/thread.hpp"
 #include "utilities/macros.hpp"
+#ifdef COMPILER1
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#endif
 
 #define __ masm->
 
@@ -120,3 +125,243 @@
 #endif // !R9_IS_SCRATCHED
 #endif // !AARCH64
 }
+
+#ifdef COMPILER1
+
+#undef __
+#define __ ce->masm()->
+
+void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  // At this point we know that marking is in progress.
+  // If do_load() is true then we have to emit the
+  // load of the previous value; otherwise it has already
+  // been loaded into _pre_val.
+
+  __ bind(*stub->entry());
+  assert(stub->pre_val()->is_register(), "Precondition.");
+
+  Register pre_val_reg = stub->pre_val()->as_register();
+
+  if (stub->do_load()) {
+    ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
+  }
+
+  __ cbz(pre_val_reg, *stub->continuation());
+  ce->verify_reserved_argument_area_size(1);
+  __ str(pre_val_reg, Address(SP));
+  __ call(bs->pre_barrier_c1_runtime_code_blob()->code_begin(), relocInfo::runtime_call_type);
+
+  __ b(*stub->continuation());
+}
+
+void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
+  assert(stub->addr()->is_register(), "Precondition.");
+  assert(stub->new_val()->is_register(), "Precondition.");
+  Register new_val_reg = stub->new_val()->as_register();
+  __ cbz(new_val_reg, *stub->continuation());
+  ce->verify_reserved_argument_area_size(1);
+  __ str(stub->addr()->as_pointer_register(), Address(SP));
+  __ call(bs->post_barrier_c1_runtime_code_blob()->code_begin(), relocInfo::runtime_call_type);
+  __ b(*stub->continuation());
+}
+
+#undef __
+#define __ sasm->
+
+void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
+  // Input:
+  // - pre_val pushed on the stack
+
+  __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
+
+  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);
+    __ should_not_reach_here();
+    break;
+  }
+
+  // save at least the registers that need saving if the runtime is called
+#ifdef AARCH64
+  __ raw_push(R0, R1);
+  __ raw_push(R2, R3);
+  const int nb_saved_regs = 4;
+#else // AARCH64
+  const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
+  const int nb_saved_regs = 6;
+  assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
+  __ push(saved_regs);
+#endif // AARCH64
+
+  const Register r_pre_val_0  = R0; // must be R0, to be ready for the runtime call
+  const Register r_index_1    = R1;
+  const Register r_buffer_2   = R2;
+
+  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;
+
+  // Is marking still active?
+  assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+  __ ldrb(R1, queue_active);
+  __ cbz(R1, done);
+
+  __ ldr(r_index_1, queue_index);
+  __ ldr(r_pre_val_0, Address(SP, nb_saved_regs*wordSize));
+  __ ldr(r_buffer_2, buffer);
+
+  __ subs(r_index_1, r_index_1, wordSize);
+  __ b(runtime, lt);
+
+  __ str(r_index_1, queue_index);
+  __ str(r_pre_val_0, Address(r_buffer_2, r_index_1));
+
+  __ bind(done);
+
+#ifdef AARCH64
+  __ raw_pop(R2, R3);
+  __ raw_pop(R0, R1);
+#else // AARCH64
+  __ pop(saved_regs);
+#endif // AARCH64
+
+  __ ret();
+
+  __ bind(runtime);
+
+  __ save_live_registers();
+
+  assert(r_pre_val_0 == c_rarg0, "pre_val should be in R0");
+  __ mov(c_rarg1, Rthread);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), c_rarg0, c_rarg1);
+
+  __ restore_live_registers_without_return();
+
+  __ b(done);
+}
+
+void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
+  // Input:
+  // - store_addr, pushed on the stack
+
+  __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
+
+  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);
+    __ should_not_reach_here();
+    break;
+  }
+
+  Label done;
+  Label recheck;
+  Label runtime;
+
+  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);
+
+  // save at least the registers that need saving if the runtime is called
+#ifdef AARCH64
+  __ raw_push(R0, R1);
+  __ raw_push(R2, R3);
+  const int nb_saved_regs = 4;
+#else // AARCH64
+  const RegisterSet saved_regs = RegisterSet(R0,R3) | RegisterSet(R12) | RegisterSet(LR);
+  const int nb_saved_regs = 6;
+  assert(nb_saved_regs == saved_regs.size(), "fix nb_saved_regs");
+  __ push(saved_regs);
+#endif // AARCH64
+
+  const Register r_card_addr_0 = R0; // must be R0 for the slow case
+  const Register r_obj_0 = R0;
+  const Register r_card_base_1 = R1;
+  const Register r_tmp2 = R2;
+  const Register r_index_2 = R2;
+  const Register r_buffer_3 = R3;
+  const Register tmp1 = Rtemp;
+
+  __ ldr(r_obj_0, Address(SP, nb_saved_regs*wordSize));
+  // Note: there is a comment in x86 code about not using
+  // ExternalAddress / lea, due to relocation not working
+  // properly for that address. Should be OK for arm, where we
+  // explicitly specify that 'cardtable' has a relocInfo::none
+  // type.
+  __ lea(r_card_base_1, cardtable);
+  __ add(r_card_addr_0, r_card_base_1, AsmOperand(r_obj_0, lsr, CardTable::card_shift));
+
+  // first quick check without barrier
+  __ ldrb(r_tmp2, Address(r_card_addr_0));
+
+  __ cmp(r_tmp2, (int)G1CardTable::g1_young_card_val());
+  __ b(recheck, ne);
+
+  __ bind(done);
+
+#ifdef AARCH64
+  __ raw_pop(R2, R3);
+  __ raw_pop(R0, R1);
+#else // AARCH64
+  __ pop(saved_regs);
+#endif // AARCH64
+
+  __ ret();
+
+  __ bind(recheck);
+
+  __ membar(MacroAssembler::Membar_mask_bits(MacroAssembler::StoreLoad), tmp1);
+
+  // reload card state after the barrier that ensures the stored oop was visible
+  __ ldrb(r_tmp2, Address(r_card_addr_0));
+
+  assert(CardTable::dirty_card_val() == 0, "adjust this code");
+  __ cbz(r_tmp2, done);
+
+  // storing region crossing non-NULL, card is clean.
+  // dirty card and log.
+
+  assert(0 == (int)CardTable::dirty_card_val(), "adjust this code");
+  if ((ci_card_table_address_as<intptr_t>() & 0xff) == 0) {
+    // Card table is aligned so the lowest byte of the table address base is zero.
+    __ strb(r_card_base_1, Address(r_card_addr_0));
+  } else {
+    __ strb(__ zero_register(r_tmp2), Address(r_card_addr_0));
+  }
+
+  __ ldr(r_index_2, queue_index);
+  __ ldr(r_buffer_3, buffer);
+
+  __ subs(r_index_2, r_index_2, wordSize);
+  __ b(runtime, lt); // go to runtime if now negative
+
+  __ str(r_index_2, queue_index);
+
+  __ str(r_card_addr_0, Address(r_buffer_3, r_index_2));
+
+  __ b(done);
+
+  __ bind(runtime);
+
+  __ save_live_registers();
+
+  assert(r_card_addr_0 == c_rarg0, "card_addr should be in R0");
+  __ mov(c_rarg1, Rthread);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), c_rarg0, c_rarg1);
+
+  __ restore_live_registers_without_return();
+
+  __ b(done);
+}
+
+#undef __
+
+#endif // COMPILER1
--- a/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/arm/gc/g1/g1BarrierSetAssembler_arm.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -27,6 +27,12 @@
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
+#include "utilities/macros.hpp"
+
+class LIR_Assembler;
+class StubAssembler;
+class G1PreBarrierStub;
+class G1PostBarrierStub;
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
@@ -34,6 +40,14 @@
                                        Register addr, Register count, int callee_saved_regs);
   void gen_write_ref_array_post_barrier(MacroAssembler* masm, DecoratorSet decorators,
                                         Register addr, Register count, Register tmp);
+
+#ifdef COMPILER1
+  void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
+  void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
+
+  void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
+#endif
 };
 
 #endif // CPU_ARM_GC_G1_G1BARRIERSETASSEMBLER_ARM_HPP
--- a/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/ppc/c1_CodeStubs_ppc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,9 +33,6 @@
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_ppc.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif // INCLUDE_ALL_GCS
 
 #define __ ce->masm()->
 
@@ -470,58 +467,4 @@
   __ b(_continuation);
 }
 
-
-///////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
-  // At this point we know that marking is in progress.
-  // If do_load() is true then we have to emit the
-  // load of the previous value; otherwise it has already
-  // been loaded into _pre_val.
-
-  __ bind(_entry);
-
-  assert(pre_val()->is_register(), "Precondition.");
-  Register pre_val_reg = pre_val()->as_register();
-
-  if (do_load()) {
-    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
-  }
-
-  __ cmpdi(CCR0, pre_val_reg, 0);
-  __ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CCR0, Assembler::equal), _continuation);
-
-  address stub = Runtime1::entry_for(Runtime1::Runtime1::g1_pre_barrier_slow_id);
-  //__ load_const_optimized(R0, stub);
-  __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub));
-  __ std(pre_val_reg, -8, R1_SP); // Pass pre_val on stack.
-  __ mtctr(R0);
-  __ bctrl();
-  __ b(_continuation);
-}
-
-void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-
-  assert(addr()->is_register(), "Precondition.");
-  assert(new_val()->is_register(), "Precondition.");
-  Register addr_reg = addr()->as_pointer_register();
-  Register new_val_reg = new_val()->as_register();
-
-  __ cmpdi(CCR0, new_val_reg, 0);
-  __ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CCR0, Assembler::equal), _continuation);
-
-  address stub = Runtime1::entry_for(Runtime1::Runtime1::g1_post_barrier_slow_id);
-  //__ load_const_optimized(R0, stub);
-  __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(stub));
-  __ mtctr(R0);
-  __ mr(R0, addr_reg); // Pass addr in R0.
-  __ bctrl();
-  __ b(_continuation);
-}
-
-#endif // INCLUDE_ALL_GCS
-///////////////////////////////////////////////////////////////////////////////////
-
 #undef __
--- a/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/ppc/c1_LIRAssembler_ppc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -2978,7 +2978,9 @@
 
 
 void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr dest, LIR_Opr tmp) {
-  const Register Rptr = src->as_pointer_register(),
+  const LIR_Address *addr = src->as_address_ptr();
+  assert(addr->disp() == 0 && addr->index()->is_illegal(), "use leal!");
+  const Register Rptr = addr->base()->as_pointer_register(),
                  Rtmp = tmp->as_register();
   Register Rco = noreg;
   if (UseCompressedOops && data->is_oop()) {
--- a/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/ppc/c1_LIRGenerator_ppc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -149,7 +149,12 @@
 
   // Accumulate fixed displacements.
   if (index->is_constant()) {
-    large_disp += (intx)(index->as_constant_ptr()->as_jint()) << shift;
+    LIR_Const *constant = index->as_constant_ptr();
+    if (constant->type() == T_LONG) {
+      large_disp += constant->as_jlong() << shift;
+    } else {
+      large_disp += (intx)(constant->as_jint()) << shift;
+    }
     index = LIR_OprFact::illegalOpr;
   }
 
@@ -190,7 +195,7 @@
 
 
 LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
-                                              BasicType type, bool needs_card_mark) {
+                                              BasicType type) {
   int elem_size = type2aelembytes(type);
   int shift = exact_log2(elem_size);
 
@@ -230,13 +235,7 @@
       __ add(index_opr, array_opr, base_opr);
     }
   }
-  if (needs_card_mark) {
-    LIR_Opr ptr = new_pointer_register();
-    __ add(base_opr, LIR_OprFact::intptrConst(offset), ptr);
-    return new LIR_Address(ptr, type);
-  } else {
-    return new LIR_Address(base_opr, offset, type);
-  }
+  return new LIR_Address(base_opr, offset, type);
 }
 
 
@@ -320,80 +319,12 @@
 //             visitor functions
 //----------------------------------------------------------------------
 
-void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
-  assert(x->is_pinned(),"");
-  bool needs_range_check = x->compute_needs_range_check();
-  bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
-                                         !get_jobject_constant(x->value())->is_null_object() ||
-                                         x->should_profile());
-
-  LIRItem array(x->array(), this);
-  LIRItem index(x->index(), this);
-  LIRItem value(x->value(), this);
-  LIRItem length(this);
-
-  array.load_item();
-  index.load_nonconstant();
-
-  if (use_length && needs_range_check) {
-    length.set_instruction(x->length());
-    length.load_item();
-  }
-  if (needs_store_check || x->check_boolean()) {
-    value.load_item();
-  } else {
-    value.load_for_store(x->elt_type());
-  }
-
-  set_no_result(x);
-
-  // The CodeEmitInfo must be duplicated for each different
-  // LIR-instruction because spilling can occur anywhere between two
-  // instructions and so the debug information must be different.
-  CodeEmitInfo* range_check_info = state_for(x);
-  CodeEmitInfo* null_check_info = NULL;
-  if (x->needs_null_check()) {
-    null_check_info = new CodeEmitInfo(range_check_info);
-  }
-
-  // Emit array address setup early so it schedules better.
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);
-
-  if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
-      __ cmp(lir_cond_belowEqual, length.result(), index.result());
-      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
-    } else {
-      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
-      // Range_check also does the null check.
-      null_check_info = NULL;
-    }
-  }
-
-  if (GenerateArrayStoreCheck && needs_store_check) {
-    // Following registers are used by slow_subtype_check:
-    LIR_Opr tmp1 = FrameMap::R4_opr; // super_klass
-    LIR_Opr tmp2 = FrameMap::R5_opr; // sub_klass
-    LIR_Opr tmp3 = FrameMap::R6_opr; // temp
-
-    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
-    __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3,
-                   store_check_info, x->profiled_method(), x->profiled_bci());
-  }
-
-  if (obj_store) {
-    // Needs GC write barriers.
-    pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-  LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
-  __ move(result, array_addr, null_check_info);
-  if (obj_store) {
-    // Precise card mark.
-    post_barrier(LIR_OprFact::address(array_addr), value.result());
-  }
+void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci) {
+  // Following registers are used by slow_subtype_check:
+  LIR_Opr tmp1 = FrameMap::R4_opr; // super_klass
+  LIR_Opr tmp2 = FrameMap::R5_opr; // sub_klass
+  LIR_Opr tmp3 = FrameMap::R6_opr; // temp
+  __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci);
 }
 
 
@@ -702,24 +633,68 @@
 }
 
 
-void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
-  assert(x->number_of_arguments() == 4, "wrong type");
-  LIRItem obj   (x->argument_at(0), this);  // object
-  LIRItem offset(x->argument_at(1), this);  // offset of field
-  LIRItem cmp   (x->argument_at(2), this);  // Value to compare with field.
-  LIRItem val   (x->argument_at(3), this);  // Replace field with val if matches cmp.
-
+LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) {
+  LIR_Opr result = new_register(T_INT);
   LIR_Opr t1 = LIR_OprFact::illegalOpr;
   LIR_Opr t2 = LIR_OprFact::illegalOpr;
-  LIR_Opr addr = new_pointer_register();
+  cmp_value.load_item();
+  new_value.load_item();
+
+  // Volatile load may be followed by Unsafe CAS.
+  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+    __ membar();
+  } else {
+    __ membar_release();
+  }
+
+  if (type == T_OBJECT || type == T_ARRAY) {
+    if (UseCompressedOops) {
+      t1 = new_register(T_OBJECT);
+      t2 = new_register(T_OBJECT);
+    }
+    __ cas_obj(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else if (type == T_INT) {
+    __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else if (type == T_LONG) {
+    __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else {
+    Unimplemented();
+  }
+  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
+           result, type);
+  return result;
+}
+
 
-  // Get address of field.
-  obj.load_item();
-  offset.load_item();
-  cmp.load_item();
-  val.load_item();
+LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
+  LIR_Opr result = new_register(type);
+  LIR_Opr tmp = FrameMap::R0_opr;
+
+  value.load_item();
+
+  // Volatile load may be followed by Unsafe CAS.
+  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+    __ membar();
+  } else {
+    __ membar_release();
+  }
+
+  __ xchg(addr, value.result(), result, tmp);
 
-  __ add(obj.result(), offset.result(), addr);
+  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+    __ membar_acquire();
+  } else {
+    __ membar();
+  }
+  return result;
+}
+
+
+LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
+  LIR_Opr result = new_register(type);
+  LIR_Opr tmp = FrameMap::R0_opr;
+
+  value.load_item();
 
   // Volatile load may be followed by Unsafe CAS.
   if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
@@ -728,33 +703,14 @@
     __ membar_release();
   }
 
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    // Only cmp value can get overwritten, no do_load required.
-    pre_barrier(LIR_OprFact::illegalOpr /* addr */, cmp.result() /* pre_val */,
-                false /* do_load */, false /* patch */, NULL);
-  }
+  __ xadd(addr, value.result(), result, tmp);
 
-  if (type == objectType) {
-    if (UseCompressedOops) {
-      t1 = new_register(T_OBJECT);
-      t2 = new_register(T_OBJECT);
-    }
-    __ cas_obj(addr, cmp.result(), val.result(), t1, t2);
-  } else if (type == intType) {
-    __ cas_int(addr, cmp.result(), val.result(), t1, t2);
-  } else if (type == longType) {
-    __ cas_long(addr, cmp.result(), val.result(), t1, t2);
+  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
+    __ membar_acquire();
   } else {
-    ShouldNotReachHere();
+    __ membar();
   }
-  // Benerate conditional move of boolean result.
-  LIR_Opr result = rlock_result(x);
-  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
-           result, as_BasicType(type));
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    // Precise card mark since could either be object or array.
-    post_barrier(addr, val.result());
-  }
+  return result;
 }
 
 
@@ -1255,110 +1211,6 @@
 }
 
 
-void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data,
-                                     BasicType type, bool is_volatile) {
-  LIR_Opr base_op = src;
-  LIR_Opr index_op = offset;
-
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-#ifndef _LP64
-  if (is_volatile && type == T_LONG) {
-    __ volatile_store_unsafe_reg(data, src, offset, type, NULL, lir_patch_none);
-  } else
-#endif
-  {
-    if (type == T_BOOLEAN) {
-      type = T_BYTE;
-    }
-    LIR_Address* addr;
-    if (type == T_ARRAY || type == T_OBJECT) {
-      LIR_Opr tmp = new_pointer_register();
-      __ add(base_op, index_op, tmp);
-      addr = new LIR_Address(tmp, type);
-    } else {
-      addr = new LIR_Address(base_op, index_op, type);
-    }
-
-    if (is_obj) {
-      pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-          true /* do_load */, false /* patch */, NULL);
-      // _bs->c1_write_barrier_pre(this, LIR_OprFact::address(addr));
-    }
-    __ move(data, addr);
-    if (is_obj) {
-      // This address is precise.
-      post_barrier(LIR_OprFact::address(addr), data);
-    }
-  }
-}
-
-
-void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset,
-                                     BasicType type, bool is_volatile) {
-#ifndef _LP64
-  if (is_volatile && type == T_LONG) {
-    __ volatile_load_unsafe_reg(src, offset, dst, type, NULL, lir_patch_none);
-  } else
-#endif
-    {
-    LIR_Address* addr = new LIR_Address(src, offset, type);
-    __ load(addr, dst);
-  }
-}
-
-
-void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
-  BasicType type = x->basic_type();
-  LIRItem src(x->object(), this);
-  LIRItem off(x->offset(), this);
-  LIRItem value(x->value(), this);
-
-  src.load_item();
-  value.load_item();
-  off.load_nonconstant();
-
-  LIR_Opr dst = rlock_result(x, type);
-  LIR_Opr data = value.result();
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-
-  LIR_Opr tmp = FrameMap::R0_opr;
-  LIR_Opr ptr = new_pointer_register();
-  __ add(src.result(), off.result(), ptr);
-
-  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
-    __ membar();
-  } else {
-    __ membar_release();
-  }
-
-  if (x->is_add()) {
-    __ xadd(ptr, data, dst, tmp);
-  } else {
-    const bool can_move_barrier = true; // TODO: port GraphKit::can_move_pre_barrier() from C2
-    if (!can_move_barrier && is_obj) {
-      // Do the pre-write barrier, if any.
-      pre_barrier(ptr, LIR_OprFact::illegalOpr /* pre_val */,
-                  true /* do_load */, false /* patch */, NULL);
-    }
-    __ xchg(ptr, data, dst, tmp);
-    if (is_obj) {
-      // Seems to be a precise address.
-      post_barrier(ptr, data);
-      if (can_move_barrier) {
-        pre_barrier(LIR_OprFact::illegalOpr, dst /* pre_val */,
-                    false /* do_load */, false /* patch */, NULL);
-      }
-    }
-  }
-
-  if (support_IRIW_for_not_multiple_copy_atomic_cpu) {
-    __ membar_acquire();
-  } else {
-    __ membar();
-  }
-}
-
-
 void LIRGenerator::do_update_CRC32(Intrinsic* x) {
   assert(UseCRC32Intrinsics, "or should not be here");
   LIR_Opr result = rlock_result(x);
--- a/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/ppc/c1_Runtime1_ppc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -42,11 +42,6 @@
 #include "utilities/align.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_ppc.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1ThreadLocalData.hpp"
-#endif
 
 // Implementation of StubAssembler
 
@@ -708,164 +703,6 @@
       }
       break;
 
-#if INCLUDE_ALL_GCS
-    case g1_pre_barrier_slow_id:
-      {
-        BarrierSet* bs = BarrierSet::barrier_set();
-        if (bs->kind() != BarrierSet::G1BarrierSet) {
-          goto unimplemented_entry;
-        }
-
-        __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
-
-        // Using stack slots: pre_val (pre-pushed), spill tmp, spill tmp2.
-        const int stack_slots = 3;
-        Register pre_val = R0; // previous value of memory
-        Register tmp  = R14;
-        Register tmp2 = R15;
-
-        Label refill, restart, marking_not_active;
-        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);
-        __ std(tmp2, -24, R1_SP);
-
-        // Is marking still active?
-        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-          __ lwz(tmp, satb_q_active_byte_offset, R16_thread);
-        } else {
-          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-          __ lbz(tmp, satb_q_active_byte_offset, R16_thread);
-        }
-        __ cmpdi(CCR0, tmp, 0);
-        __ beq(CCR0, marking_not_active);
-
-        __ bind(restart);
-        // Load the index into the SATB buffer. SATBMarkQueue::_index is a
-        // size_t so ld_ptr is appropriate.
-        __ ld(tmp, satb_q_index_byte_offset, R16_thread);
-
-        // index == 0?
-        __ cmpdi(CCR0, tmp, 0);
-        __ beq(CCR0, refill);
-
-        __ ld(tmp2, satb_q_buf_byte_offset, R16_thread);
-        __ ld(pre_val, -8, R1_SP); // Load from stack.
-        __ addi(tmp, tmp, -oopSize);
-
-        __ std(tmp, satb_q_index_byte_offset, R16_thread);
-        __ stdx(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card>
-
-        __ bind(marking_not_active);
-        // Restore temp registers and return-from-leaf.
-        __ ld(tmp2, -24, R1_SP);
-        __ ld(tmp, -16, R1_SP);
-        __ blr();
-
-        __ bind(refill);
-        const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_slots) * BytesPerWord;
-        __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
-        __ mflr(R0);
-        __ std(R0, _abi(lr), R1_SP);
-        __ push_frame_reg_args(nbytes_save, R0); // dummy frame for C call
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SATBMarkQueueSet::handle_zero_index_for_thread), R16_thread);
-        __ pop_frame();
-        __ ld(R0, _abi(lr), R1_SP);
-        __ mtlr(R0);
-        __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
-        __ b(restart);
-      }
-      break;
-
-  case g1_post_barrier_slow_id:
-    {
-        BarrierSet* bs = BarrierSet::barrier_set();
-        if (bs->kind() != BarrierSet::G1BarrierSet) {
-          goto unimplemented_entry;
-        }
-
-        __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
-
-        // Using stack slots: spill addr, spill tmp2
-        const int stack_slots = 2;
-        Register tmp = R0;
-        Register addr = R14;
-        Register tmp2 = R15;
-        jbyte* byte_map_base = ci_card_table_address();
-
-        Label restart, refill, ret;
-
-        // Spill
-        __ std(addr, -8, R1_SP);
-        __ std(tmp2, -16, R1_SP);
-
-        __ srdi(addr, R0, CardTable::card_shift); // Addr is passed in R0.
-        __ load_const_optimized(/*cardtable*/ tmp2, byte_map_base, tmp);
-        __ add(addr, tmp2, addr);
-        __ lbz(tmp, 0, addr); // tmp := [addr + cardtable]
-
-        // Return if young card.
-        __ cmpwi(CCR0, tmp, G1CardTable::g1_young_card_val());
-        __ beq(CCR0, ret);
-
-        // Return if sequential consistent value is already dirty.
-        __ membar(Assembler::StoreLoad);
-        __ lbz(tmp, 0, addr); // tmp := [addr + cardtable]
-
-        __ cmpwi(CCR0, tmp, G1CardTable::dirty_card_val());
-        __ beq(CCR0, ret);
-
-        // Not dirty.
-
-        // First, dirty it.
-        __ li(tmp, G1CardTable::dirty_card_val());
-        __ stb(tmp, 0, addr);
-
-        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);
-
-        // Get the index into the update buffer. DirtyCardQueue::_index is
-        // a size_t so ld_ptr is appropriate here.
-        __ ld(tmp2, dirty_card_q_index_byte_offset, R16_thread);
-
-        // index == 0?
-        __ cmpdi(CCR0, tmp2, 0);
-        __ beq(CCR0, refill);
-
-        __ ld(tmp, dirty_card_q_buf_byte_offset, R16_thread);
-        __ addi(tmp2, tmp2, -oopSize);
-
-        __ std(tmp2, dirty_card_q_index_byte_offset, R16_thread);
-        __ add(tmp2, tmp, tmp2);
-        __ std(addr, 0, tmp2); // [_buf + index] := <address_of_card>
-
-        // Restore temp registers and return-from-leaf.
-        __ bind(ret);
-        __ ld(tmp2, -16, R1_SP);
-        __ ld(addr, -8, R1_SP);
-        __ blr();
-
-        __ bind(refill);
-        const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_slots) * BytesPerWord;
-        __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
-        __ mflr(R0);
-        __ std(R0, _abi(lr), R1_SP);
-        __ push_frame_reg_args(nbytes_save, R0); // dummy frame for C call
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread), R16_thread);
-        __ pop_frame();
-        __ ld(R0, _abi(lr), R1_SP);
-        __ mtlr(R0);
-        __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
-        __ b(restart);
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-
     case predicate_failed_trap_id:
       {
         __ set_info("predicate_failed_trap", dont_gc_arguments);
@@ -889,7 +726,6 @@
       break;
 
   default:
-  unimplemented_entry:
       {
         __ set_info("unimplemented entry", dont_gc_arguments);
         __ mflr(R0);
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -26,12 +26,17 @@
 #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 "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
+#ifdef COMPILER1
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#endif
 
 #define __ masm->
 
@@ -339,4 +344,209 @@
   __ bind(done);
 }
 
+#ifdef COMPILER1
+
 #undef __
+#define __ ce->masm()->
+
+void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  // At this point we know that marking is in progress.
+  // If do_load() is true then we have to emit the
+  // load of the previous value; otherwise it has already
+  // been loaded into _pre_val.
+
+  __ bind(*stub->entry());
+
+  assert(stub->pre_val()->is_register(), "Precondition.");
+  Register pre_val_reg = stub->pre_val()->as_register();
+
+  if (stub->do_load()) {
+    ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
+  }
+
+  __ cmpdi(CCR0, pre_val_reg, 0);
+  __ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CCR0, Assembler::equal), *stub->continuation());
+
+  address c_code = bs->pre_barrier_c1_runtime_code_blob()->code_begin();
+  //__ load_const_optimized(R0, c_code);
+  __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(c_code));
+  __ std(pre_val_reg, -8, R1_SP); // Pass pre_val on stack.
+  __ mtctr(R0);
+  __ bctrl();
+  __ b(*stub->continuation());
+}
+
+void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
+
+  assert(stub->addr()->is_register(), "Precondition.");
+  assert(stub->new_val()->is_register(), "Precondition.");
+  Register addr_reg = stub->addr()->as_pointer_register();
+  Register new_val_reg = stub->new_val()->as_register();
+
+  __ cmpdi(CCR0, new_val_reg, 0);
+  __ bc_far_optimized(Assembler::bcondCRbiIs1, __ bi0(CCR0, Assembler::equal), *stub->continuation());
+
+  address c_code = bs->post_barrier_c1_runtime_code_blob()->code_begin();
+  //__ load_const_optimized(R0, c_code);
+  __ add_const_optimized(R0, R29_TOC, MacroAssembler::offset_to_global_toc(c_code));
+  __ mtctr(R0);
+  __ mr(R0, addr_reg); // Pass addr in R0.
+  __ bctrl();
+  __ b(*stub->continuation());
+}
+
+#undef __
+#define __ sasm->
+
+void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
+  BarrierSet* bs = BarrierSet::barrier_set();
+
+  __ set_info("g1_pre_barrier_slow_id", false);
+
+  // Using stack slots: pre_val (pre-pushed), spill tmp, spill tmp2.
+  const int stack_slots = 3;
+  Register pre_val = R0; // previous value of memory
+  Register tmp  = R14;
+  Register tmp2 = R15;
+
+  Label refill, restart, marking_not_active;
+  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);
+  __ std(tmp2, -24, R1_SP);
+
+  // Is marking still active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ lwz(tmp, satb_q_active_byte_offset, R16_thread);
+  } else {
+    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ lbz(tmp, satb_q_active_byte_offset, R16_thread);
+  }
+  __ cmpdi(CCR0, tmp, 0);
+  __ beq(CCR0, marking_not_active);
+
+  __ bind(restart);
+  // Load the index into the SATB buffer. SATBMarkQueue::_index is a
+  // size_t so ld_ptr is appropriate.
+  __ ld(tmp, satb_q_index_byte_offset, R16_thread);
+
+  // index == 0?
+  __ cmpdi(CCR0, tmp, 0);
+  __ beq(CCR0, refill);
+
+  __ ld(tmp2, satb_q_buf_byte_offset, R16_thread);
+  __ ld(pre_val, -8, R1_SP); // Load from stack.
+  __ addi(tmp, tmp, -oopSize);
+
+  __ std(tmp, satb_q_index_byte_offset, R16_thread);
+  __ stdx(pre_val, tmp2, tmp); // [_buf + index] := <address_of_card>
+
+  __ bind(marking_not_active);
+  // Restore temp registers and return-from-leaf.
+  __ ld(tmp2, -24, R1_SP);
+  __ ld(tmp, -16, R1_SP);
+  __ blr();
+
+  __ bind(refill);
+  const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_slots) * BytesPerWord;
+  __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
+  __ mflr(R0);
+  __ std(R0, _abi(lr), R1_SP);
+  __ push_frame_reg_args(nbytes_save, R0); // dummy frame for C call
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SATBMarkQueueSet::handle_zero_index_for_thread), R16_thread);
+  __ pop_frame();
+  __ ld(R0, _abi(lr), R1_SP);
+  __ mtlr(R0);
+  __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
+  __ b(restart);
+}
+
+void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
+  G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+
+  __ set_info("g1_post_barrier_slow_id", false);
+
+  // Using stack slots: spill addr, spill tmp2
+  const int stack_slots = 2;
+  Register tmp = R0;
+  Register addr = R14;
+  Register tmp2 = R15;
+  jbyte* byte_map_base = bs->card_table()->byte_map_base();
+
+  Label restart, refill, ret;
+
+  // Spill
+  __ std(addr, -8, R1_SP);
+  __ std(tmp2, -16, R1_SP);
+
+  __ srdi(addr, R0, CardTable::card_shift); // Addr is passed in R0.
+  __ load_const_optimized(/*cardtable*/ tmp2, byte_map_base, tmp);
+  __ add(addr, tmp2, addr);
+  __ lbz(tmp, 0, addr); // tmp := [addr + cardtable]
+
+  // Return if young card.
+  __ cmpwi(CCR0, tmp, G1CardTable::g1_young_card_val());
+  __ beq(CCR0, ret);
+
+  // Return if sequential consistent value is already dirty.
+  __ membar(Assembler::StoreLoad);
+  __ lbz(tmp, 0, addr); // tmp := [addr + cardtable]
+
+  __ cmpwi(CCR0, tmp, G1CardTable::dirty_card_val());
+  __ beq(CCR0, ret);
+
+  // Not dirty.
+
+  // First, dirty it.
+  __ li(tmp, G1CardTable::dirty_card_val());
+  __ stb(tmp, 0, addr);
+
+  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);
+
+  // Get the index into the update buffer. DirtyCardQueue::_index is
+  // a size_t so ld_ptr is appropriate here.
+  __ ld(tmp2, dirty_card_q_index_byte_offset, R16_thread);
+
+  // index == 0?
+  __ cmpdi(CCR0, tmp2, 0);
+  __ beq(CCR0, refill);
+
+  __ ld(tmp, dirty_card_q_buf_byte_offset, R16_thread);
+  __ addi(tmp2, tmp2, -oopSize);
+
+  __ std(tmp2, dirty_card_q_index_byte_offset, R16_thread);
+  __ add(tmp2, tmp, tmp2);
+  __ std(addr, 0, tmp2); // [_buf + index] := <address_of_card>
+
+  // Restore temp registers and return-from-leaf.
+  __ bind(ret);
+  __ ld(tmp2, -16, R1_SP);
+  __ ld(addr, -8, R1_SP);
+  __ blr();
+
+  __ bind(refill);
+  const int nbytes_save = (MacroAssembler::num_volatile_regs + stack_slots) * BytesPerWord;
+  __ save_volatile_gprs(R1_SP, -nbytes_save); // except R0
+  __ mflr(R0);
+  __ std(R0, _abi(lr), R1_SP);
+  __ push_frame_reg_args(nbytes_save, R0); // dummy frame for C call
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread), R16_thread);
+  __ pop_frame();
+  __ ld(R0, _abi(lr), R1_SP);
+  __ mtlr(R0);
+  __ restore_volatile_gprs(R1_SP, -nbytes_save); // except R0
+  __ b(restart);
+}
+
+#undef __
+
+#endif // COMPILER1
--- a/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/ppc/gc/g1/g1BarrierSetAssembler_ppc.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -28,6 +28,12 @@
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
+#include "utilities/macros.hpp"
+
+class LIR_Assembler;
+class StubAssembler;
+class G1PreBarrierStub;
+class G1PostBarrierStub;
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
@@ -45,6 +51,14 @@
                             Register tmp1, Register tmp2, Register tmp3, bool needs_frame);
 
 public:
+#ifdef COMPILER1
+  void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
+  void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
+
+  void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
+#endif
+
   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);
--- a/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/s390/c1_CodeStubs_s390.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -34,9 +34,6 @@
 #include "utilities/align.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_s390.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif // INCLUDE_ALL_GCS
 
 #define __ ce->masm()->
 #undef  CHECK_BAILOUT
@@ -453,46 +450,4 @@
   __ branch_optimized(Assembler::bcondAlways, _continuation);
 }
 
-
-///////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
-  // At this point we know that marking is in progress.
-  // If do_load() is true then we have to emit the
-  // load of the previous value; otherwise it has already
-  // been loaded into _pre_val.
-  __ bind(_entry);
-  ce->check_reserved_argument_area(16); // RT stub needs 2 spill slots.
-  assert(pre_val()->is_register(), "Precondition.");
-
-  Register pre_val_reg = pre_val()->as_register();
-
-  if (do_load()) {
-    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
-  }
-
-  __ z_ltgr(Z_R1_scratch, pre_val_reg); // Pass oop in Z_R1_scratch to Runtime1::g1_pre_barrier_slow_id.
-  __ branch_optimized(Assembler::bcondZero, _continuation);
-  ce->emit_call_c(Runtime1::entry_for (Runtime1::g1_pre_barrier_slow_id));
-  CHECK_BAILOUT();
-  __ branch_optimized(Assembler::bcondAlways, _continuation);
-}
-
-void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-  ce->check_reserved_argument_area(16); // RT stub needs 2 spill slots.
-  assert(addr()->is_register(), "Precondition.");
-  assert(new_val()->is_register(), "Precondition.");
-  Register new_val_reg = new_val()->as_register();
-  __ z_ltgr(new_val_reg, new_val_reg);
-  __ branch_optimized(Assembler::bcondZero, _continuation);
-  __ z_lgr(Z_R1_scratch, addr()->as_pointer_register());
-  ce->emit_call_c(Runtime1::entry_for (Runtime1::g1_post_barrier_slow_id));
-  CHECK_BAILOUT();
-  __ branch_optimized(Assembler::bcondAlways, _continuation);
-}
-
-#endif // INCLUDE_ALL_GCS
-
 #undef __
--- a/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/s390/c1_LIRAssembler_s390.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -572,82 +572,145 @@
 void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmitInfo* info, bool wide) {
   assert(src->is_constant(), "should not call otherwise");
   assert(dest->is_address(), "should not call otherwise");
-  // See special case in LIRGenerator::do_StoreIndexed.
-  // T_BYTE: Special case for card mark store.
-  assert(type == T_BYTE || !dest->as_address_ptr()->index()->is_valid(), "not supported");
+
   LIR_Const* c = src->as_constant_ptr();
   Address addr = as_Address(dest->as_address_ptr());
 
   int store_offset = -1;
-  unsigned int lmem = 0;
-  unsigned int lcon = 0;
-  int64_t cbits = 0;
-  switch (type) {
-    case T_INT:    // fall through
-    case T_FLOAT:
-      lmem = 4; lcon = 4; cbits = c->as_jint_bits();
-      break;
-
-    case T_ADDRESS:
-      lmem = 8; lcon = 4; cbits = c->as_jint_bits();
-      break;
-
-    case T_OBJECT:  // fall through
-    case T_ARRAY:
-      if (c->as_jobject() == NULL) {
-        if (UseCompressedOops && !wide) {
-          store_offset = __ store_const(addr, (int32_t)NULL_WORD, 4, 4);
+
+  if (dest->as_address_ptr()->index()->is_valid()) {
+    switch (type) {
+      case T_INT:    // fall through
+      case T_FLOAT:
+        __ load_const_optimized(Z_R0_scratch, c->as_jint_bits());
+        store_offset = __ offset();
+        if (Immediate::is_uimm12(addr.disp())) {
+          __ z_st(Z_R0_scratch, addr);
+        } else {
+          __ z_sty(Z_R0_scratch, addr);
+        }
+        break;
+
+      case T_ADDRESS:
+        __ load_const_optimized(Z_R1_scratch, c->as_jint_bits());
+        store_offset = __ reg2mem_opt(Z_R1_scratch, addr, true);
+        break;
+
+      case T_OBJECT:  // fall through
+      case T_ARRAY:
+        if (c->as_jobject() == NULL) {
+          if (UseCompressedOops && !wide) {
+            __ clear_reg(Z_R1_scratch, false);
+            store_offset = __ reg2mem_opt(Z_R1_scratch, addr, false);
+          } else {
+            __ clear_reg(Z_R1_scratch, true);
+            store_offset = __ reg2mem_opt(Z_R1_scratch, addr, true);
+          }
+        } else {
+          jobject2reg(c->as_jobject(), Z_R1_scratch);
+          if (UseCompressedOops && !wide) {
+            __ encode_heap_oop(Z_R1_scratch);
+            store_offset = __ reg2mem_opt(Z_R1_scratch, addr, false);
+          } else {
+            store_offset = __ reg2mem_opt(Z_R1_scratch, addr, true);
+          }
+        }
+        assert(store_offset >= 0, "check");
+        break;
+
+      case T_LONG:    // fall through
+      case T_DOUBLE:
+        __ load_const_optimized(Z_R1_scratch, (int64_t)(c->as_jlong_bits()));
+        store_offset = __ reg2mem_opt(Z_R1_scratch, addr, true);
+        break;
+
+      case T_BOOLEAN: // fall through
+      case T_BYTE:
+        __ load_const_optimized(Z_R0_scratch, (int8_t)(c->as_jint()));
+        store_offset = __ offset();
+        if (Immediate::is_uimm12(addr.disp())) {
+          __ z_stc(Z_R0_scratch, addr);
+        } else {
+          __ z_stcy(Z_R0_scratch, addr);
+        }
+        break;
+
+      case T_CHAR:    // fall through
+      case T_SHORT:
+        __ load_const_optimized(Z_R0_scratch, (int16_t)(c->as_jint()));
+        store_offset = __ offset();
+        if (Immediate::is_uimm12(addr.disp())) {
+          __ z_sth(Z_R0_scratch, addr);
         } else {
-          store_offset = __ store_const(addr, (int64_t)NULL_WORD, 8, 8);
+          __ z_sthy(Z_R0_scratch, addr);
         }
-      } else {
-        jobject2reg(c->as_jobject(), Z_R1_scratch);
-        if (UseCompressedOops && !wide) {
-          __ encode_heap_oop(Z_R1_scratch);
-          store_offset = __ reg2mem_opt(Z_R1_scratch, addr, false);
+        break;
+
+      default:
+        ShouldNotReachHere();
+    }
+
+  } else { // no index
+
+    unsigned int lmem = 0;
+    unsigned int lcon = 0;
+    int64_t cbits = 0;
+
+    switch (type) {
+      case T_INT:    // fall through
+      case T_FLOAT:
+        lmem = 4; lcon = 4; cbits = c->as_jint_bits();
+        break;
+
+      case T_ADDRESS:
+        lmem = 8; lcon = 4; cbits = c->as_jint_bits();
+        break;
+
+      case T_OBJECT:  // fall through
+      case T_ARRAY:
+        if (c->as_jobject() == NULL) {
+          if (UseCompressedOops && !wide) {
+            store_offset = __ store_const(addr, (int32_t)NULL_WORD, 4, 4);
+          } else {
+            store_offset = __ store_const(addr, (int64_t)NULL_WORD, 8, 8);
+          }
         } else {
-          store_offset = __ reg2mem_opt(Z_R1_scratch, addr, true);
+          jobject2reg(c->as_jobject(), Z_R1_scratch);
+          if (UseCompressedOops && !wide) {
+            __ encode_heap_oop(Z_R1_scratch);
+            store_offset = __ reg2mem_opt(Z_R1_scratch, addr, false);
+          } else {
+            store_offset = __ reg2mem_opt(Z_R1_scratch, addr, true);
+          }
         }
-      }
+        assert(store_offset >= 0, "check");
+        break;
+
+      case T_LONG:    // fall through
+      case T_DOUBLE:
+        lmem = 8; lcon = 8; cbits = (int64_t)(c->as_jlong_bits());
+        break;
+
+      case T_BOOLEAN: // fall through
+      case T_BYTE:
+        lmem = 1; lcon = 1; cbits = (int8_t)(c->as_jint());
+        break;
+
+      case T_CHAR:    // fall through
+      case T_SHORT:
+        lmem = 2; lcon = 2; cbits = (int16_t)(c->as_jint());
+        break;
+
+      default:
+        ShouldNotReachHere();
+    }
+
+    if (store_offset == -1) {
+      store_offset = __ store_const(addr, cbits, lmem, lcon);
       assert(store_offset >= 0, "check");
-      break;
-
-    case T_LONG:    // fall through
-    case T_DOUBLE:
-      lmem = 8; lcon = 8; cbits = (int64_t)(c->as_jlong_bits());
-      break;
-
-    case T_BOOLEAN: // fall through
-    case T_BYTE:
-      lmem = 1; lcon = 1; cbits = (int8_t)(c->as_jint());
-      break;
-
-    case T_CHAR:    // fall through
-    case T_SHORT:
-      lmem = 2; lcon = 2; cbits = (int16_t)(c->as_jint());
-      break;
-
-    default:
-      ShouldNotReachHere();
-  };
-
-  // Index register is normally not supported, but for
-  // LIRGenerator::CardTableBarrierSet_post_barrier we make an exception.
-  if (type == T_BYTE && dest->as_address_ptr()->index()->is_valid()) {
-    __ load_const_optimized(Z_R0_scratch, (int8_t)(c->as_jint()));
-    store_offset = __ offset();
-    if (Immediate::is_uimm12(addr.disp())) {
-      __ z_stc(Z_R0_scratch, addr);
-    } else {
-      __ z_stcy(Z_R0_scratch, addr);
     }
   }
 
-  if (store_offset == -1) {
-    store_offset = __ store_const(addr, cbits, lmem, lcon);
-    assert(store_offset >= 0, "check");
-  }
-
   if (info != NULL) {
     add_debug_info_for_null_check(store_offset, info);
   }
--- a/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/s390/c1_LIRGenerator_s390.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -140,7 +140,13 @@
                                             int shift, int disp, BasicType type) {
   assert(base->is_register(), "must be");
   if (index->is_constant()) {
-    intptr_t large_disp = ((intx)(index->as_constant_ptr()->as_jint()) << shift) + disp;
+    intx large_disp = disp;
+    LIR_Const *constant = index->as_constant_ptr();
+    if (constant->type() == T_LONG) {
+      large_disp += constant->as_jlong() << shift;
+    } else {
+      large_disp += (intx)(constant->as_jint()) << shift;
+    }
     if (Displacement::is_validDisp(large_disp)) {
       return new LIR_Address(base, large_disp, type);
     }
@@ -159,7 +165,7 @@
 }
 
 LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
-                                              BasicType type, bool needs_card_mark) {
+                                              BasicType type) {
   int elem_size = type2aelembytes(type);
   int shift = exact_log2(elem_size);
   int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type);
@@ -181,16 +187,7 @@
                            index_opr,
                            offset_in_bytes, type);
   }
-  if (needs_card_mark) {
-    // This store will need a precise card mark, so go ahead and
-    // compute the full adddres instead of computing once for the
-    // store and again for the card mark.
-    LIR_Opr tmp = new_pointer_register();
-    __ leal(LIR_OprFact::address(addr), tmp);
-    return new LIR_Address(tmp, type);
-  } else {
-    return addr;
-  }
+  return addr;
 }
 
 LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) {
@@ -252,86 +249,11 @@
 //             visitor functions
 //----------------------------------------------------------------------
 
-void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
-  assert(x->is_pinned(),"");
-  bool needs_range_check = x->compute_needs_range_check();
-  bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
-                                         !get_jobject_constant(x->value())->is_null_object() ||
-                                         x->should_profile());
-
-  LIRItem array(x->array(), this);
-  LIRItem index(x->index(), this);
-  LIRItem value(x->value(), this);
-  LIRItem length(this);
-
-  array.load_item();
-  index.load_nonconstant(20);
-
-  if (use_length && needs_range_check) {
-    length.set_instruction(x->length());
-    length.load_item();
-  }
-  if (needs_store_check || x->check_boolean()) {
-    value.load_item();
-  } else {
-    value.load_for_store(x->elt_type());
-  }
-
-  set_no_result(x);
-
-  // The CodeEmitInfo must be duplicated for each different
-  // LIR-instruction because spilling can occur anywhere between two
-  // instructions and so the debug information must be different.
-  CodeEmitInfo* range_check_info = state_for (x);
-  CodeEmitInfo* null_check_info = NULL;
-  if (x->needs_null_check()) {
-    null_check_info = new CodeEmitInfo(range_check_info);
-  }
-
-  // Emit array address setup early so it schedules better.
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);
-  if (value.result()->is_constant() && array_addr->index()->is_valid()) {
-    // Constants cannot be stored with index register on ZARCH_64 (see LIR_Assembler::const2mem()).
-    LIR_Opr tmp = new_pointer_register();
-    __ leal(LIR_OprFact::address(array_addr), tmp);
-    array_addr = new LIR_Address(tmp, x->elt_type());
-  }
-
-  if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
-      __ cmp(lir_cond_belowEqual, length.result(), index.result());
-      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
-    } else {
-      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
-      // Range_check also does the null check.
-      null_check_info = NULL;
-    }
-  }
-
-  if (GenerateArrayStoreCheck && needs_store_check) {
-    LIR_Opr tmp1 = new_register(objectType);
-    LIR_Opr tmp2 = new_register(objectType);
-    LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
-
-    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
-    __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci());
-  }
-
-  if (obj_store) {
-    // Needs GC write barriers.
-    pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-
-  LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
-  __ move(result, array_addr, null_check_info);
-
-  if (obj_store) {
-    // Precise card mark
-    post_barrier(LIR_OprFact::address(array_addr), value.result());
-  }
+void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci) {
+  LIR_Opr tmp1 = new_register(objectType);
+  LIR_Opr tmp2 = new_register(objectType);
+  LIR_Opr tmp3 = LIR_OprFact::illegalOpr;
+  __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci);
 }
 
 void LIRGenerator::do_MonitorEnter(MonitorEnter* x) {
@@ -665,59 +587,42 @@
   }
 }
 
-void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
-  assert(x->number_of_arguments() == 4, "wrong type");
-  LIRItem obj   (x->argument_at(0), this);  // object
-  LIRItem offset(x->argument_at(1), this);  // offset of field
-  LIRItem cmp   (x->argument_at(2), this);  // Value to compare with field.
-  LIRItem val   (x->argument_at(3), this);  // Replace field with val if matches cmp.
-
-  // Get address of field.
-  obj.load_item();
-  offset.load_nonconstant(20);
-  cmp.load_item();
-  val.load_item();
-
-  LIR_Opr addr = new_pointer_register();
-  LIR_Address* a;
-  if (offset.result()->is_constant()) {
-    assert(Immediate::is_simm20(offset.result()->as_jlong()), "should have been loaded into register");
-    a = new LIR_Address(obj.result(),
-                        offset.result()->as_jlong(),
-                        as_BasicType(type));
-  } else {
-    a = new LIR_Address(obj.result(),
-                        offset.result(),
-                        0,
-                        as_BasicType(type));
-  }
-  __ leal(LIR_OprFact::address(a), addr);
-
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    pre_barrier(addr, LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-
-  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
-  if (type == objectType) {
-    __ cas_obj(addr, cmp.result(), val.result(), new_register(T_OBJECT), new_register(T_OBJECT));
-  } else if (type == intType) {
-    __ cas_int(addr, cmp.result(), val.result(), ill, ill);
-  } else if (type == longType) {
-    __ cas_long(addr, cmp.result(), val.result(), ill, ill);
+LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) {
+  LIR_Opr t1 = LIR_OprFact::illegalOpr;
+  LIR_Opr t2 = LIR_OprFact::illegalOpr;
+  cmp_value.load_item();
+  new_value.load_item();
+  if (type == T_OBJECT) {
+    if (UseCompressedOops) {
+      t1 = new_register(T_OBJECT);
+      t2 = new_register(T_OBJECT);
+    }
+    __ cas_obj(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else if (type == T_INT) {
+    __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else if (type == T_LONG) {
+    __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
   } else {
     ShouldNotReachHere();
   }
   // Generate conditional move of boolean result.
-  LIR_Opr result = rlock_result(x);
+  LIR_Opr result = new_register(T_INT);
   __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
-           result, as_BasicType(type));
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    // Precise card mark since could either be object or array
-    post_barrier(addr, val.result());
-  }
+           result, type);
+  return result;
 }
 
+LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
+  Unimplemented(); // Currently not supported on this platform.
+  return LIR_OprFact::illegalOpr;
+}
+
+LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  __ xadd(addr, value.result(), result, LIR_OprFact::illegalOpr);
+  return result;
+}
 
 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
   switch (x->id()) {
@@ -1104,57 +1009,6 @@
   __ load(address, result, info);
 }
 
-
-void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data,
-                                     BasicType type, bool is_volatile) {
-  LIR_Address* addr = new LIR_Address(src, offset, type);
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-  if (is_obj) {
-    // Do the pre-write barrier, if any.
-    pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-    __ move(data, addr);
-    assert(src->is_register(), "must be register");
-    // Seems to be a precise address.
-    post_barrier(LIR_OprFact::address(addr), data);
-  } else {
-    __ move(data, addr);
-  }
-}
-
-
-void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset,
-                                     BasicType type, bool is_volatile) {
-  LIR_Address* addr = new LIR_Address(src, offset, type);
-  __ load(addr, dst);
-}
-
-void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
-  BasicType type = x->basic_type();
-  assert (x->is_add() && type != T_ARRAY && type != T_OBJECT, "not supported");
-  LIRItem src(x->object(), this);
-  LIRItem off(x->offset(), this);
-  LIRItem value(x->value(), this);
-
-  src.load_item();
-  value.load_item();
-  off.load_nonconstant(20);
-
-  LIR_Opr dst = rlock_result(x, type);
-  LIR_Opr data = value.result();
-  LIR_Opr offset = off.result();
-
-  LIR_Address* addr;
-  if (offset->is_constant()) {
-    assert(Immediate::is_simm20(offset->as_jlong()), "should have been loaded into register");
-    addr = new LIR_Address(src.result(), offset->as_jlong(), type);
-  } else {
-    addr = new LIR_Address(src.result(), offset, type);
-  }
-
-  __ xadd(LIR_OprFact::address(addr), data, dst, LIR_OprFact::illegalOpr);
-}
-
 void LIRGenerator::do_update_CRC32(Intrinsic* x) {
   assert(UseCRC32Intrinsics, "or should not be here");
   LIR_Opr result = rlock_result(x);
--- a/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/s390/c1_Runtime1_s390.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -42,11 +42,6 @@
 #include "utilities/macros.hpp"
 #include "vmreg_s390.inline.hpp"
 #include "registerSaver_s390.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1ThreadLocalData.hpp"
-#endif
 
 // Implementation of StubAssembler
 
@@ -190,15 +185,6 @@
   return RegisterSaver::save_live_registers(sasm, reg_set);
 }
 
-static OopMap* save_volatile_registers(StubAssembler* sasm, Register return_pc = Z_R14) {
-  __ block_comment("save_volatile_registers");
-  RegisterSaver::RegisterSet reg_set = RegisterSaver::all_volatile_registers;
-  int frame_size_in_slots =
-    RegisterSaver::live_reg_frame_size(reg_set) / VMRegImpl::stack_slot_size;
-  sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word);
-  return RegisterSaver::save_live_registers(sasm, reg_set, return_pc);
-}
-
 static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
   __ block_comment("restore_live_registers");
   RegisterSaver::RegisterSet reg_set =
@@ -214,12 +200,6 @@
   RegisterSaver::restore_live_registers(sasm, RegisterSaver::all_registers_except_r2);
 }
 
-static void restore_volatile_registers(StubAssembler* sasm) {
-  __ block_comment("restore_volatile_registers");
-  RegisterSaver::RegisterSet reg_set = RegisterSaver::all_volatile_registers;
-  RegisterSaver::restore_live_registers(sasm, reg_set);
-}
-
 void Runtime1::initialize_pd() {
   // Nothing to do.
 }
@@ -764,160 +744,6 @@
       break;
 #endif // TODO
 
-#if INCLUDE_ALL_GCS
-    case g1_pre_barrier_slow_id:
-      { // Z_R1_scratch: previous value of memory
-
-        BarrierSet* bs = BarrierSet::barrier_set();
-        if (bs->kind() != BarrierSet::G1BarrierSet) {
-          __ should_not_reach_here(FILE_AND_LINE);
-          break;
-        }
-
-        __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
-
-        Register pre_val = Z_R1_scratch;
-        Register tmp  = Z_R6; // Must be non-volatile because it is used to save pre_val.
-        Register tmp2 = Z_R7;
-
-        Label refill, restart, marking_not_active;
-        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);
-        __ z_stg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-
-        // Is marking still active?
-        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-          __ load_and_test_int(tmp, Address(Z_thread, satb_q_active_byte_offset));
-        } else {
-          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-          __ load_and_test_byte(tmp, Address(Z_thread, satb_q_active_byte_offset));
-        }
-        __ z_bre(marking_not_active); // Activity indicator is zero, so there is no marking going on currently.
-
-        __ bind(restart);
-        // Load the index into the SATB buffer. SATBMarkQueue::_index is a
-        // size_t so ld_ptr is appropriate.
-        __ z_ltg(tmp, satb_q_index_byte_offset, Z_R0, Z_thread);
-
-        // index == 0?
-        __ z_brz(refill);
-
-        __ z_lg(tmp2, satb_q_buf_byte_offset, Z_thread);
-        __ add2reg(tmp, -oopSize);
-
-        __ z_stg(pre_val, 0, tmp, tmp2); // [_buf + index] := <address_of_card>
-        __ z_stg(tmp, satb_q_index_byte_offset, Z_thread);
-
-        __ bind(marking_not_active);
-        // Restore tmp registers (see assertion in G1PreBarrierStub::emit_code()).
-        __ z_lg(tmp,  0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-        __ z_lg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-        __ z_br(Z_R14);
-
-        __ bind(refill);
-        save_volatile_registers(sasm);
-        __ z_lgr(tmp, pre_val); // save pre_val
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SATBMarkQueueSet::handle_zero_index_for_thread),
-                        Z_thread);
-        __ z_lgr(pre_val, tmp); // restore pre_val
-        restore_volatile_registers(sasm);
-        __ z_bru(restart);
-      }
-      break;
-
-    case g1_post_barrier_slow_id:
-      { // Z_R1_scratch: oop address, address of updated memory slot
-        BarrierSet* bs = BarrierSet::barrier_set();
-        if (bs->kind() != BarrierSet::G1BarrierSet) {
-          __ should_not_reach_here(FILE_AND_LINE);
-          break;
-        }
-
-        __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
-
-        Register addr_oop  = Z_R1_scratch;
-        Register addr_card = Z_R1_scratch;
-        Register r1        = Z_R6; // Must be saved/restored.
-        Register r2        = Z_R7; // Must be saved/restored.
-        Register cardtable = r1;   // Must be non-volatile, because it is used to save addr_card.
-        jbyte* byte_map_base = ci_card_table_address();
-
-        // Save registers used below (see assertion in G1PreBarrierStub::emit_code()).
-        __ z_stg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-
-        Label not_already_dirty, restart, refill, young_card;
-
-        // Calculate address of card corresponding to the updated oop slot.
-        AddressLiteral rs(byte_map_base);
-        __ z_srlg(addr_card, addr_oop, CardTable::card_shift);
-        addr_oop = noreg; // dead now
-        __ load_const_optimized(cardtable, rs); // cardtable := <card table base>
-        __ z_agr(addr_card, cardtable); // addr_card := addr_oop>>card_shift + cardtable
-
-        __ z_cli(0, addr_card, (int)G1CardTable::g1_young_card_val());
-        __ z_bre(young_card);
-
-        __ z_sync(); // Required to support concurrent cleaning.
-
-        __ z_cli(0, addr_card, (int)CardTable::dirty_card_val());
-        __ z_brne(not_already_dirty);
-
-        __ bind(young_card);
-        // We didn't take the branch, so we're already dirty: restore
-        // used registers and return.
-        __ z_lg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-        __ z_br(Z_R14);
-
-        // Not dirty.
-        __ bind(not_already_dirty);
-
-        // First, dirty it: [addr_card] := 0
-        __ z_mvi(0, addr_card, CardTable::dirty_card_val());
-
-        Register idx = cardtable; // Must be non-volatile, because it is used to save addr_card.
-        Register buf = r2;
-        cardtable = noreg; // now dead
-
-        // 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 = G1ThreadLocalData::dirty_card_queue_index_offset();
-        ByteSize dirty_card_q_buf_byte_offset = G1ThreadLocalData::dirty_card_queue_buffer_offset();
-
-        __ bind(restart);
-
-        // Get the index into the update buffer. DirtyCardQueue::_index is
-        // a size_t so z_ltg is appropriate here.
-        __ z_ltg(idx, Address(Z_thread, dirty_card_q_index_byte_offset));
-
-        // index == 0?
-        __ z_brz(refill);
-
-        __ z_lg(buf, Address(Z_thread, dirty_card_q_buf_byte_offset));
-        __ add2reg(idx, -oopSize);
-
-        __ z_stg(addr_card, 0, idx, buf); // [_buf + index] := <address_of_card>
-        __ z_stg(idx, Address(Z_thread, dirty_card_q_index_byte_offset));
-        // Restore killed registers and return.
-        __ z_lg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-        __ z_lg(r2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
-        __ z_br(Z_R14);
-
-        __ bind(refill);
-        save_volatile_registers(sasm);
-        __ z_lgr(idx, addr_card); // Save addr_card, tmp3 must be non-volatile.
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread),
-                                         Z_thread);
-        __ z_lgr(addr_card, idx);
-        restore_volatile_registers(sasm); // Restore addr_card.
-        __ z_bru(restart);
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
     case predicate_failed_trap_id:
       {
         __ set_info("predicate_failed_trap", dont_gc_arguments);
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,6 +33,11 @@
 #include "gc/g1/heapRegion.hpp"
 #include "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
+#ifdef COMPILER1
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#endif
 
 #define __ masm->
 
@@ -406,4 +411,209 @@
   __ bind(Ldone);
 }
 
+#ifdef COMPILER1
+
 #undef __
+#define __ ce->masm()->
+
+void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  // At this point we know that marking is in progress.
+  // If do_load() is true then we have to emit the
+  // load of the previous value; otherwise it has already
+  // been loaded into _pre_val.
+  __ bind(*stub->entry());
+  ce->check_reserved_argument_area(16); // RT stub needs 2 spill slots.
+  assert(stub->pre_val()->is_register(), "Precondition.");
+
+  Register pre_val_reg = stub->pre_val()->as_register();
+
+  if (stub->do_load()) {
+    ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
+  }
+
+  __ z_ltgr(Z_R1_scratch, pre_val_reg); // Pass oop in Z_R1_scratch to Runtime1::g1_pre_barrier_slow_id.
+  __ branch_optimized(Assembler::bcondZero, *stub->continuation());
+  ce->emit_call_c(bs->pre_barrier_c1_runtime_code_blob()->code_begin());
+  __ branch_optimized(Assembler::bcondAlways, *stub->continuation());
+}
+
+void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
+  ce->check_reserved_argument_area(16); // RT stub needs 2 spill slots.
+  assert(stub->addr()->is_register(), "Precondition.");
+  assert(stub->new_val()->is_register(), "Precondition.");
+  Register new_val_reg = stub->new_val()->as_register();
+  __ z_ltgr(new_val_reg, new_val_reg);
+  __ branch_optimized(Assembler::bcondZero, *stub->continuation());
+  __ z_lgr(Z_R1_scratch, stub->addr()->as_pointer_register());
+  ce->emit_call_c(bs->post_barrier_c1_runtime_code_blob()->code_begin());
+  __ branch_optimized(Assembler::bcondAlways, *stub->continuation());
+}
+
+#undef __
+
+#define __ sasm->
+
+static OopMap* save_volatile_registers(StubAssembler* sasm, Register return_pc = Z_R14) {
+  __ block_comment("save_volatile_registers");
+  RegisterSaver::RegisterSet reg_set = RegisterSaver::all_volatile_registers;
+  int frame_size_in_slots = RegisterSaver::live_reg_frame_size(reg_set) / VMRegImpl::stack_slot_size;
+  sasm->set_frame_size(frame_size_in_slots / VMRegImpl::slots_per_word);
+  return RegisterSaver::save_live_registers(sasm, reg_set, return_pc);
+}
+
+static void restore_volatile_registers(StubAssembler* sasm) {
+  __ block_comment("restore_volatile_registers");
+  RegisterSaver::RegisterSet reg_set = RegisterSaver::all_volatile_registers;
+  RegisterSaver::restore_live_registers(sasm, reg_set);
+}
+
+void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
+  // Z_R1_scratch: previous value of memory
+
+  BarrierSet* bs = BarrierSet::barrier_set();
+  __ set_info("g1_pre_barrier_slow_id", false);
+
+  Register pre_val = Z_R1_scratch;
+  Register tmp  = Z_R6; // Must be non-volatile because it is used to save pre_val.
+  Register tmp2 = Z_R7;
+
+  Label refill, restart, marking_not_active;
+  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);
+  __ z_stg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+
+  // Is marking still active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ load_and_test_int(tmp, Address(Z_thread, satb_q_active_byte_offset));
+  } else {
+    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ load_and_test_byte(tmp, Address(Z_thread, satb_q_active_byte_offset));
+  }
+  __ z_bre(marking_not_active); // Activity indicator is zero, so there is no marking going on currently.
+
+  __ bind(restart);
+  // Load the index into the SATB buffer. SATBMarkQueue::_index is a
+  // size_t so ld_ptr is appropriate.
+  __ z_ltg(tmp, satb_q_index_byte_offset, Z_R0, Z_thread);
+
+  // index == 0?
+  __ z_brz(refill);
+
+  __ z_lg(tmp2, satb_q_buf_byte_offset, Z_thread);
+  __ add2reg(tmp, -oopSize);
+
+  __ z_stg(pre_val, 0, tmp, tmp2); // [_buf + index] := <address_of_card>
+  __ z_stg(tmp, satb_q_index_byte_offset, Z_thread);
+
+  __ bind(marking_not_active);
+  // Restore tmp registers (see assertion in G1PreBarrierStub::emit_code()).
+  __ z_lg(tmp,  0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+  __ z_lg(tmp2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+  __ z_br(Z_R14);
+
+  __ bind(refill);
+  save_volatile_registers(sasm);
+  __ z_lgr(tmp, pre_val); // save pre_val
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SATBMarkQueueSet::handle_zero_index_for_thread),
+                  Z_thread);
+  __ z_lgr(pre_val, tmp); // restore pre_val
+  restore_volatile_registers(sasm);
+  __ z_bru(restart);
+}
+
+void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
+  // Z_R1_scratch: oop address, address of updated memory slot
+
+  BarrierSet* bs = BarrierSet::barrier_set();
+  __ set_info("g1_post_barrier_slow_id", false);
+
+  Register addr_oop  = Z_R1_scratch;
+  Register addr_card = Z_R1_scratch;
+  Register r1        = Z_R6; // Must be saved/restored.
+  Register r2        = Z_R7; // Must be saved/restored.
+  Register cardtable = r1;   // Must be non-volatile, because it is used to save addr_card.
+  CardTableBarrierSet* ctbs = barrier_set_cast<CardTableBarrierSet>(bs);
+  CardTable* ct = ctbs->card_table();
+  jbyte* byte_map_base = ct->byte_map_base();
+
+  // Save registers used below (see assertion in G1PreBarrierStub::emit_code()).
+  __ z_stg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+
+  Label not_already_dirty, restart, refill, young_card;
+
+  // Calculate address of card corresponding to the updated oop slot.
+  AddressLiteral rs(byte_map_base);
+  __ z_srlg(addr_card, addr_oop, CardTable::card_shift);
+  addr_oop = noreg; // dead now
+  __ load_const_optimized(cardtable, rs); // cardtable := <card table base>
+  __ z_agr(addr_card, cardtable); // addr_card := addr_oop>>card_shift + cardtable
+
+  __ z_cli(0, addr_card, (int)G1CardTable::g1_young_card_val());
+  __ z_bre(young_card);
+
+  __ z_sync(); // Required to support concurrent cleaning.
+
+  __ z_cli(0, addr_card, (int)CardTable::dirty_card_val());
+  __ z_brne(not_already_dirty);
+
+  __ bind(young_card);
+  // We didn't take the branch, so we're already dirty: restore
+  // used registers and return.
+  __ z_lg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+  __ z_br(Z_R14);
+
+  // Not dirty.
+  __ bind(not_already_dirty);
+
+  // First, dirty it: [addr_card] := 0
+  __ z_mvi(0, addr_card, CardTable::dirty_card_val());
+
+  Register idx = cardtable; // Must be non-volatile, because it is used to save addr_card.
+  Register buf = r2;
+  cardtable = noreg; // now dead
+
+  // 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 = G1ThreadLocalData::dirty_card_queue_index_offset();
+  ByteSize dirty_card_q_buf_byte_offset = G1ThreadLocalData::dirty_card_queue_buffer_offset();
+
+  __ bind(restart);
+
+  // Get the index into the update buffer. DirtyCardQueue::_index is
+  // a size_t so z_ltg is appropriate here.
+  __ z_ltg(idx, Address(Z_thread, dirty_card_q_index_byte_offset));
+
+  // index == 0?
+  __ z_brz(refill);
+
+  __ z_lg(buf, Address(Z_thread, dirty_card_q_buf_byte_offset));
+  __ add2reg(idx, -oopSize);
+
+  __ z_stg(addr_card, 0, idx, buf); // [_buf + index] := <address_of_card>
+  __ z_stg(idx, Address(Z_thread, dirty_card_q_index_byte_offset));
+  // Restore killed registers and return.
+  __ z_lg(r1, 0*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+  __ z_lg(r2, 1*BytesPerWord + FrameMap::first_available_sp_in_frame, Z_SP);
+  __ z_br(Z_R14);
+
+  __ bind(refill);
+  save_volatile_registers(sasm);
+  __ z_lgr(idx, addr_card); // Save addr_card, tmp3 must be non-volatile.
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, DirtyCardQueueSet::handle_zero_index_for_thread),
+                                   Z_thread);
+  __ z_lgr(addr_card, idx);
+  restore_volatile_registers(sasm); // Restore addr_card.
+  __ z_bru(restart);
+}
+
+#undef __
+
+#endif // COMPILER1
--- a/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/s390/gc/g1/g1BarrierSetAssembler_s390.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -28,6 +28,12 @@
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
+#include "utilities/macros.hpp"
+
+class LIR_Assembler;
+class StubAssembler;
+class G1PreBarrierStub;
+class G1PostBarrierStub;
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
  protected:
@@ -50,6 +56,14 @@
                             const Address& dst, Register val, Register tmp1, Register tmp2, Register tmp3);
 
  public:
+#ifdef COMPILER1
+  void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
+  void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
+
+  void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
+#endif
+
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        const Address& src, Register dst, Register tmp1, Register tmp2, Label *is_null = NULL);
 
--- a/src/hotspot/cpu/sparc/c1_CodeStubs_sparc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/sparc/c1_CodeStubs_sparc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -32,9 +32,6 @@
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_sparc.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif // INCLUDE_ALL_GCS
 
 #define __ ce->masm()->
 
@@ -454,63 +451,4 @@
   __ delayed()->nop();
 }
 
-
-///////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
-  // At this point we know that marking is in progress.
-  // If do_load() is true then we have to emit the
-  // load of the previous value; otherwise it has already
-  // been loaded into _pre_val.
-
-  __ bind(_entry);
-
-  assert(pre_val()->is_register(), "Precondition.");
-  Register pre_val_reg = pre_val()->as_register();
-
-  if (do_load()) {
-    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
-  }
-
-  if (__ is_in_wdisp16_range(_continuation)) {
-    __ br_null(pre_val_reg, /*annul*/false, Assembler::pt, _continuation);
-  } else {
-    __ cmp(pre_val_reg, G0);
-    __ brx(Assembler::equal, false, Assembler::pn, _continuation);
-  }
-  __ delayed()->nop();
-
-  __ call(Runtime1::entry_for(Runtime1::Runtime1::g1_pre_barrier_slow_id));
-  __ delayed()->mov(pre_val_reg, G4);
-  __ br(Assembler::always, false, Assembler::pt, _continuation);
-  __ delayed()->nop();
-
-}
-
-void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-
-  assert(addr()->is_register(), "Precondition.");
-  assert(new_val()->is_register(), "Precondition.");
-  Register addr_reg = addr()->as_pointer_register();
-  Register new_val_reg = new_val()->as_register();
-
-  if (__ is_in_wdisp16_range(_continuation)) {
-    __ br_null(new_val_reg, /*annul*/false, Assembler::pt, _continuation);
-  } else {
-    __ cmp(new_val_reg, G0);
-    __ brx(Assembler::equal, false, Assembler::pn, _continuation);
-  }
-  __ delayed()->nop();
-
-  __ call(Runtime1::entry_for(Runtime1::Runtime1::g1_post_barrier_slow_id));
-  __ delayed()->mov(addr_reg, G4);
-  __ br(Assembler::always, false, Assembler::pt, _continuation);
-  __ delayed()->nop();
-}
-
-#endif // INCLUDE_ALL_GCS
-///////////////////////////////////////////////////////////////////////////////////
-
 #undef __
--- a/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/sparc/c1_LIRGenerator_sparc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -193,7 +193,7 @@
 
 
 LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
-                                              BasicType type, bool needs_card_mark) {
+                                              BasicType type) {
   int elem_size = type2aelembytes(type);
   int shift = exact_log2(elem_size);
 
@@ -231,13 +231,8 @@
       __ add(index_opr, array_opr, base_opr);
     }
   }
-  if (needs_card_mark) {
-    LIR_Opr ptr = new_pointer_register();
-    __ add(base_opr, LIR_OprFact::intptrConst(offset), ptr);
-    return new LIR_Address(ptr, type);
-  } else {
-    return new LIR_Address(base_opr, offset, type);
-  }
+
+  return new LIR_Address(base_opr, offset, type);
 }
 
 LIR_Opr LIRGenerator::load_immediate(int x, BasicType type) {
@@ -311,86 +306,17 @@
   }
 }
 
+void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci) {
+  LIR_Opr tmp1 = FrameMap::G1_opr;
+  LIR_Opr tmp2 = FrameMap::G3_opr;
+  LIR_Opr tmp3 = FrameMap::G5_opr;
+  __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci);
+}
+
 //----------------------------------------------------------------------
 //             visitor functions
 //----------------------------------------------------------------------
 
-
-void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
-  assert(x->is_pinned(),"");
-  bool needs_range_check = x->compute_needs_range_check();
-  bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
-                                         !get_jobject_constant(x->value())->is_null_object() ||
-                                         x->should_profile());
-
-  LIRItem array(x->array(), this);
-  LIRItem index(x->index(), this);
-  LIRItem value(x->value(), this);
-  LIRItem length(this);
-
-  array.load_item();
-  index.load_nonconstant();
-
-  if (use_length && needs_range_check) {
-    length.set_instruction(x->length());
-    length.load_item();
-  }
-  if (needs_store_check || x->check_boolean()) {
-    value.load_item();
-  } else {
-    value.load_for_store(x->elt_type());
-  }
-
-  set_no_result(x);
-
-  // the CodeEmitInfo must be duplicated for each different
-  // LIR-instruction because spilling can occur anywhere between two
-  // instructions and so the debug information must be different
-  CodeEmitInfo* range_check_info = state_for(x);
-  CodeEmitInfo* null_check_info = NULL;
-  if (x->needs_null_check()) {
-    null_check_info = new CodeEmitInfo(range_check_info);
-  }
-
-  // emit array address setup early so it schedules better
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);
-
-  if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
-      __ cmp(lir_cond_belowEqual, length.result(), index.result());
-      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
-    } else {
-      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
-      // range_check also does the null check
-      null_check_info = NULL;
-    }
-  }
-
-  if (GenerateArrayStoreCheck && needs_store_check) {
-    LIR_Opr tmp1 = FrameMap::G1_opr;
-    LIR_Opr tmp2 = FrameMap::G3_opr;
-    LIR_Opr tmp3 = FrameMap::G5_opr;
-
-    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
-    __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci());
-  }
-
-  if (obj_store) {
-    // Needs GC write barriers.
-    pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-  LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
-  __ move(result, array_addr, null_check_info);
-  if (obj_store) {
-    // Precise card mark
-    post_barrier(LIR_OprFact::address(array_addr), value.result());
-  }
-}
-
-
 void LIRGenerator::do_MonitorEnter(MonitorEnter* x) {
   assert(x->is_pinned(),"");
   LIRItem obj(x->obj(), this);
@@ -635,51 +561,47 @@
   }
 }
 
-
-void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
-  assert(x->number_of_arguments() == 4, "wrong type");
-  LIRItem obj   (x->argument_at(0), this);  // object
-  LIRItem offset(x->argument_at(1), this);  // offset of field
-  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
-  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp
-
-  // Use temps to avoid kills
+LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) {
+  LIR_Opr result = new_register(T_INT);
   LIR_Opr t1 = FrameMap::G1_opr;
   LIR_Opr t2 = FrameMap::G3_opr;
-  LIR_Opr addr = new_pointer_register();
+  cmp_value.load_item();
+  new_value.load_item();
+  if (type == T_OBJECT || type == T_ARRAY) {
+    __ cas_obj(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else if (type == T_INT) {
+    __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else if (type == T_LONG) {
+    __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), t1, t2);
+  } else {
+    Unimplemented();
+  }
+  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
+           result, type);
+  return result;
+}
 
-  // get address of field
-  obj.load_item();
-  offset.load_item();
-  cmp.load_item();
-  val.load_item();
+LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
+  bool is_obj = type == T_OBJECT || type == T_ARRAY;
+  LIR_Opr result = new_register(type);
+  LIR_Opr tmp = LIR_OprFact::illegalOpr;
 
-  __ add(obj.result(), offset.result(), addr);
+  value.load_item();
 
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    pre_barrier(addr, LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
+  if (is_obj) {
+    tmp = FrameMap::G3_opr;
   }
 
-  if (type == objectType)
-    __ cas_obj(addr, cmp.result(), val.result(), t1, t2);
-  else if (type == intType)
-    __ cas_int(addr, cmp.result(), val.result(), t1, t2);
-  else if (type == longType)
-    __ cas_long(addr, cmp.result(), val.result(), t1, t2);
-  else {
-    ShouldNotReachHere();
-  }
-  // generate conditional move of boolean result
-  LIR_Opr result = rlock_result(x);
-  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
-           result, as_BasicType(type));
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    // Precise card mark since could either be object or array
-    post_barrier(addr, val.result());
-  }
+  // Because we want a 2-arg form of xchg
+  __ move(value.result(), result);
+  __ xchg(addr, result, result, tmp);
+  return result;
 }
 
+LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
+  Unimplemented();
+  return LIR_OprFact::illegalOpr;
+}
 
 void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
   switch (x->id()) {
@@ -1338,94 +1260,3 @@
                                        CodeEmitInfo* info) {
   __ load(address, result, info);
 }
-
-
-void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data,
-                                     BasicType type, bool is_volatile) {
-  LIR_Opr base_op = src;
-  LIR_Opr index_op = offset;
-
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-    {
-      if (type == T_BOOLEAN) {
-        type = T_BYTE;
-      }
-      LIR_Address* addr;
-      if (type == T_ARRAY || type == T_OBJECT) {
-        LIR_Opr tmp = new_pointer_register();
-        __ add(base_op, index_op, tmp);
-        addr = new LIR_Address(tmp, type);
-      } else {
-        addr = new LIR_Address(base_op, index_op, type);
-      }
-
-      if (is_obj) {
-        pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                    true /* do_load */, false /* patch */, NULL);
-        // _bs->c1_write_barrier_pre(this, LIR_OprFact::address(addr));
-      }
-      __ move(data, addr);
-      if (is_obj) {
-        // This address is precise
-        post_barrier(LIR_OprFact::address(addr), data);
-      }
-    }
-}
-
-
-void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset,
-                                     BasicType type, bool is_volatile) {
-    {
-    LIR_Address* addr = new LIR_Address(src, offset, type);
-    __ load(addr, dst);
-  }
-}
-
-void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
-  BasicType type = x->basic_type();
-  LIRItem src(x->object(), this);
-  LIRItem off(x->offset(), this);
-  LIRItem value(x->value(), this);
-
-  src.load_item();
-  value.load_item();
-  off.load_nonconstant();
-
-  LIR_Opr dst = rlock_result(x, type);
-  LIR_Opr data = value.result();
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-  LIR_Opr offset = off.result();
-
-  // Because we want a 2-arg form of xchg
-  __ move(data, dst);
-
-  assert (!x->is_add() && (type == T_INT || (is_obj && UseCompressedOops)), "unexpected type");
-  LIR_Address* addr;
-  if (offset->is_constant()) {
-
-    jlong l = offset->as_jlong();
-    assert((jlong)((jint)l) == l, "offset too large for constant");
-    jint c = (jint)l;
-    addr = new LIR_Address(src.result(), c, type);
-  } else {
-    addr = new LIR_Address(src.result(), offset, type);
-  }
-
-  LIR_Opr tmp = LIR_OprFact::illegalOpr;
-  LIR_Opr ptr = LIR_OprFact::illegalOpr;
-
-  if (is_obj) {
-    // Do the pre-write barrier, if any.
-    // barriers on sparc don't work with a base + index address
-    tmp = FrameMap::G3_opr;
-    ptr = new_pointer_register();
-    __ add(src.result(), off.result(), ptr);
-    pre_barrier(ptr, LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
-  __ xchg(LIR_OprFact::address(addr), dst, dst, tmp);
-  if (is_obj) {
-    // Seems to be a precise address
-    post_barrier(ptr, data);
-  }
-}
--- a/src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/sparc/c1_MacroAssembler_sparc.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -92,4 +92,7 @@
   // This platform only uses signal-based null checks. The Label is not needed.
   void null_check(Register r, Label *Lnull = NULL) { MacroAssembler::null_check(r); }
 
+  void save_live_registers_no_oop_map(bool save_fpu_registers);
+  void restore_live_registers(bool restore_fpu_registers);
+
 #endif // CPU_SPARC_VM_C1_MACROASSEMBLER_SPARC_HPP
--- a/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/sparc/c1_Runtime1_sparc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -40,11 +40,6 @@
 #include "utilities/macros.hpp"
 #include "utilities/align.hpp"
 #include "vmreg_sparc.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1ThreadLocalData.hpp"
-#endif
 
 // Implementation of StubAssembler
 
@@ -145,10 +140,16 @@
   return call_RT(oop_result1, metadata_result, entry, 3);
 }
 
+void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
+  set_info(name, must_gc_arguments);
+}
+
+void StubAssembler::epilogue() {
+  delayed()->restore();
+}
 
 // Implementation of Runtime1
 
-#define __ sasm->
 
 static int cpu_reg_save_offsets[FrameMap::nof_cpu_regs];
 static int fpu_reg_save_offsets[FrameMap::nof_fpu_regs];
@@ -156,7 +157,7 @@
 static int frame_size_in_bytes = -1;
 
 static OopMap* generate_oop_map(StubAssembler* sasm, bool save_fpu_registers) {
-  assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words),
+  assert(frame_size_in_bytes == sasm->total_frame_size_in_bytes(reg_save_size_in_words),
          "mismatch in calculation");
   sasm->set_frame_size(frame_size_in_bytes / BytesPerWord);
   int frame_size_in_slots = frame_size_in_bytes / sizeof(jint);
@@ -183,7 +184,9 @@
   return oop_map;
 }
 
-static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) {
+#define __ this->
+
+void C1_MacroAssembler::save_live_registers_no_oop_map(bool save_fpu_registers) {
   assert(frame_size_in_bytes == __ total_frame_size_in_bytes(reg_save_size_in_words),
          "mismatch in calculation");
   __ save_frame_c1(frame_size_in_bytes);
@@ -211,11 +214,9 @@
       __ stf(FloatRegisterImpl::S, r, SP, (sp_offset * BytesPerWord) + STACK_BIAS);
     }
   }
-
-  return generate_oop_map(sasm, save_fpu_registers);
 }
 
-static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
+void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) {
   for (int i = 0; i < FrameMap::nof_cpu_regs; i++) {
     Register r = as_Register(i);
     if (r == G1 || r == G3 || r == G4 || r == G5) {
@@ -231,6 +232,18 @@
   }
 }
 
+#undef __
+#define __ sasm->
+
+static OopMap* save_live_registers(StubAssembler* sasm, bool save_fpu_registers = true) {
+  sasm->save_live_registers_no_oop_map(save_fpu_registers);
+  return generate_oop_map(sasm, save_fpu_registers);
+}
+
+static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
+  sasm->restore_live_registers(restore_fpu_registers);
+}
+
 
 void Runtime1::initialize_pd() {
   // compute word offsets from SP at which live (non-windowed) registers are captured by stub routines
@@ -759,165 +772,6 @@
       }
       break;
 
-#if INCLUDE_ALL_GCS
-    case g1_pre_barrier_slow_id:
-      { // G4: previous value of memory
-        BarrierSet* bs = BarrierSet::barrier_set();
-        if (bs->kind() != BarrierSet::G1BarrierSet) {
-          __ save_frame(0);
-          __ set((int)id, O1);
-          __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0);
-          __ should_not_reach_here();
-          break;
-        }
-
-        __ set_info("g1_pre_barrier_slow_id", dont_gc_arguments);
-
-        Register pre_val = G4;
-        Register tmp  = G1_scratch;
-        Register tmp2 = G3_scratch;
-
-        Label refill, restart;
-        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) {
-          __ ld(G2_thread, satb_q_active_byte_offset, tmp);
-        } else {
-          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-          __ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
-        }
-        __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
-        __ retl();
-        __ delayed()->nop();
-
-        __ 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, tmp);
-
-        // index == 0?
-        __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill);
-
-        __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2);
-        __ sub(tmp, oopSize, tmp);
-
-        __ st_ptr(pre_val, tmp2, tmp);  // [_buf + index] := <address_of_card>
-        // Use return-from-leaf
-        __ retl();
-        __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset);
-
-        __ bind(refill);
-
-        save_live_registers(sasm);
-
-        __ call_VM_leaf(L7_thread_cache,
-                        CAST_FROM_FN_PTR(address,
-                                         SATBMarkQueueSet::handle_zero_index_for_thread),
-                                         G2_thread);
-
-        restore_live_registers(sasm);
-
-        __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
-        __ delayed()->restore();
-      }
-      break;
-
-    case g1_post_barrier_slow_id:
-      {
-        BarrierSet* bs = BarrierSet::barrier_set();
-        if (bs->kind() != BarrierSet::G1BarrierSet) {
-          __ save_frame(0);
-          __ set((int)id, O1);
-          __ call_RT(noreg, noreg, CAST_FROM_FN_PTR(address, unimplemented_entry), I0);
-          __ should_not_reach_here();
-          break;
-        }
-
-        __ set_info("g1_post_barrier_slow_id", dont_gc_arguments);
-
-        Register addr = G4;
-        Register cardtable = G5;
-        Register tmp  = G1_scratch;
-        Register tmp2 = G3_scratch;
-        jbyte* byte_map_base = ci_card_table_address();
-
-        Label not_already_dirty, restart, refill, young_card;
-
-        __ srlx(addr, CardTable::card_shift, addr);
-
-        AddressLiteral rs(byte_map_base);
-        __ set(rs, cardtable);         // cardtable := <card table base>
-        __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
-
-        __ cmp_and_br_short(tmp, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
-
-        __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
-        __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
-
-        assert(CardTable::dirty_card_val() == 0, "otherwise check this code");
-        __ cmp_and_br_short(tmp, 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 cardtable + tmp into a reg by itself
-        __ add(addr, cardtable, tmp2);
-
-        // First, dirty it.
-        __ stb(G0, tmp2, 0);  // [cardPtr] := 0  (i.e., dirty).
-
-        Register tmp3 = cardtable;
-        Register tmp4 = tmp;
-
-        // these registers are now dead
-        addr = cardtable = tmp = noreg;
-
-        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);
-
-        // Get 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, tmp3);
-
-        // index == 0?
-        __ cmp_and_brx_short(tmp3, G0, Assembler::equal,  Assembler::pn, refill);
-
-        __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4);
-        __ sub(tmp3, oopSize, tmp3);
-
-        __ st_ptr(tmp2, tmp4, tmp3);  // [_buf + index] := <address_of_card>
-        // Use return-from-leaf
-        __ retl();
-        __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset);
-
-        __ bind(refill);
-
-        save_live_registers(sasm);
-
-        __ call_VM_leaf(L7_thread_cache,
-                        CAST_FROM_FN_PTR(address,
-                                         DirtyCardQueueSet::handle_zero_index_for_thread),
-                                         G2_thread);
-
-        restore_live_registers(sasm);
-
-        __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
-        __ delayed()->restore();
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-
     case predicate_failed_trap_id:
       {
         __ set_info("predicate_failed_trap", dont_gc_arguments);
--- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -25,13 +25,18 @@
 #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 "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/macros.hpp"
+#ifdef COMPILER1
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#endif
 
 #define __ masm->
 
@@ -476,8 +481,6 @@
   }
 }
 
-#undef __
-
 void G1BarrierSetAssembler::barrier_stubs_init() {
   if (dirty_card_log_enqueue == 0) {
     G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
@@ -494,3 +497,211 @@
     assert(satb_log_enqueue_frameless != 0, "postcondition.");
   }
 }
+
+#ifdef COMPILER1
+
+#undef __
+#define __ ce->masm()->
+
+void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  // At this point we know that marking is in progress.
+  // If do_load() is true then we have to emit the
+  // load of the previous value; otherwise it has already
+  // been loaded into _pre_val.
+
+  __ bind(*stub->entry());
+
+  assert(stub->pre_val()->is_register(), "Precondition.");
+  Register pre_val_reg = stub->pre_val()->as_register();
+
+  if (stub->do_load()) {
+    ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
+  }
+
+  if (__ is_in_wdisp16_range(*stub->continuation())) {
+    __ br_null(pre_val_reg, /*annul*/false, Assembler::pt, *stub->continuation());
+  } else {
+    __ cmp(pre_val_reg, G0);
+    __ brx(Assembler::equal, false, Assembler::pn, *stub->continuation());
+  }
+  __ delayed()->nop();
+
+  __ call(bs->pre_barrier_c1_runtime_code_blob()->code_begin());
+  __ delayed()->mov(pre_val_reg, G4);
+  __ br(Assembler::always, false, Assembler::pt, *stub->continuation());
+  __ delayed()->nop();
+}
+
+void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
+
+  assert(stub->addr()->is_register(), "Precondition.");
+  assert(stub->new_val()->is_register(), "Precondition.");
+  Register addr_reg = stub->addr()->as_pointer_register();
+  Register new_val_reg = stub->new_val()->as_register();
+
+  if (__ is_in_wdisp16_range(*stub->continuation())) {
+    __ br_null(new_val_reg, /*annul*/false, Assembler::pt, *stub->continuation());
+  } else {
+    __ cmp(new_val_reg, G0);
+    __ brx(Assembler::equal, false, Assembler::pn, *stub->continuation());
+  }
+  __ delayed()->nop();
+
+  __ call(bs->post_barrier_c1_runtime_code_blob()->code_begin());
+  __ delayed()->mov(addr_reg, G4);
+  __ br(Assembler::always, false, Assembler::pt, *stub->continuation());
+  __ delayed()->nop();
+}
+
+#undef __
+#define __ sasm->
+
+void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("g1_pre_barrier", false);
+
+  // G4: previous value of memory
+
+  Register pre_val = G4;
+  Register tmp  = G1_scratch;
+  Register tmp2 = G3_scratch;
+
+  Label refill, restart;
+  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) {
+    __ ld(G2_thread, satb_q_active_byte_offset, tmp);
+  } else {
+    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ ldsb(G2_thread, satb_q_active_byte_offset, tmp);
+  }
+  __ cmp_and_br_short(tmp, G0, Assembler::notEqual, Assembler::pt, restart);
+  __ retl();
+  __ delayed()->nop();
+
+  __ 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, tmp);
+
+  // index == 0?
+  __ cmp_and_brx_short(tmp, G0, Assembler::equal, Assembler::pn, refill);
+
+  __ ld_ptr(G2_thread, satb_q_buf_byte_offset, tmp2);
+  __ sub(tmp, oopSize, tmp);
+
+  __ st_ptr(pre_val, tmp2, tmp);  // [_buf + index] := <address_of_card>
+  // Use return-from-leaf
+  __ retl();
+  __ delayed()->st_ptr(tmp, G2_thread, satb_q_index_byte_offset);
+
+  __ bind(refill);
+
+  __ save_live_registers_no_oop_map(true);
+
+  __ call_VM_leaf(L7_thread_cache,
+                  CAST_FROM_FN_PTR(address,
+                                   SATBMarkQueueSet::handle_zero_index_for_thread),
+                                   G2_thread);
+
+  __ restore_live_registers(true);
+
+  __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
+  __ epilogue();
+}
+
+void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("g1_post_barrier", false);
+
+  G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
+
+  Register addr = G4;
+  Register cardtable = G5;
+  Register tmp  = G1_scratch;
+  Register tmp2 = G3_scratch;
+  jbyte* byte_map_base = bs->card_table()->byte_map_base();
+
+  Label not_already_dirty, restart, refill, young_card;
+
+#ifdef _LP64
+  __ srlx(addr, CardTable::card_shift, addr);
+#else
+  __ srl(addr, CardTable::card_shift, addr);
+#endif
+
+  AddressLiteral rs((address)byte_map_base);
+  __ set(rs, cardtable);         // cardtable := <card table base>
+  __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
+
+  __ cmp_and_br_short(tmp, G1CardTable::g1_young_card_val(), Assembler::equal, Assembler::pt, young_card);
+
+  __ membar(Assembler::Membar_mask_bits(Assembler::StoreLoad));
+  __ ldub(addr, cardtable, tmp); // tmp := [addr + cardtable]
+
+  assert(G1CardTable::dirty_card_val() == 0, "otherwise check this code");
+  __ cmp_and_br_short(tmp, 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 cardtable + tmp into a reg by itself
+  __ add(addr, cardtable, tmp2);
+
+  // First, dirty it.
+  __ stb(G0, tmp2, 0);  // [cardPtr] := 0  (i.e., dirty).
+
+  Register tmp3 = cardtable;
+  Register tmp4 = tmp;
+
+  // these registers are now dead
+  addr = cardtable = tmp = noreg;
+
+  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);
+
+  // Get 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, tmp3);
+
+  // index == 0?
+  __ cmp_and_brx_short(tmp3, G0, Assembler::equal,  Assembler::pn, refill);
+
+  __ ld_ptr(G2_thread, dirty_card_q_buf_byte_offset, tmp4);
+  __ sub(tmp3, oopSize, tmp3);
+
+  __ st_ptr(tmp2, tmp4, tmp3);  // [_buf + index] := <address_of_card>
+  // Use return-from-leaf
+  __ retl();
+  __ delayed()->st_ptr(tmp3, G2_thread, dirty_card_q_index_byte_offset);
+
+  __ bind(refill);
+
+  __ save_live_registers_no_oop_map(true);
+
+  __ call_VM_leaf(L7_thread_cache,
+                  CAST_FROM_FN_PTR(address,
+                                   DirtyCardQueueSet::handle_zero_index_for_thread),
+                                   G2_thread);
+
+  __ restore_live_registers(true);
+
+  __ br(Assembler::always, /*annul*/false, Assembler::pt, restart);
+  __ epilogue();
+}
+
+#undef __
+
+#endif // COMPILER1
--- a/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/sparc/gc/g1/g1BarrierSetAssembler_sparc.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -27,6 +27,12 @@
 
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
+#include "utilities/macros.hpp"
+
+class LIR_Assembler;
+class StubAssembler;
+class G1PreBarrierStub;
+class G1PostBarrierStub;
 
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
 protected:
@@ -40,6 +46,14 @@
                             Register val, Address dst, Register tmp);
 
 public:
+#ifdef COMPILER1
+  void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
+  void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
+
+  void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
+#endif
+
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        Address src, Register dst, Register tmp);
   virtual void barrier_stubs_init();
--- a/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_CodeStubs_x86.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,9 +33,6 @@
 #include "utilities/align.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_x86.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#endif // INCLUDE_ALL_GCS
 
 
 #define __ ce->masm()->
@@ -521,45 +518,4 @@
   __ jmp(_continuation);
 }
 
-/////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
-  // At this point we know that marking is in progress.
-  // If do_load() is true then we have to emit the
-  // load of the previous value; otherwise it has already
-  // been loaded into _pre_val.
-
-  __ bind(_entry);
-  assert(pre_val()->is_register(), "Precondition.");
-
-  Register pre_val_reg = pre_val()->as_register();
-
-  if (do_load()) {
-    ce->mem2reg(addr(), pre_val(), T_OBJECT, patch_code(), info(), false /*wide*/, false /*unaligned*/);
-  }
-
-  __ cmpptr(pre_val_reg, (int32_t) NULL_WORD);
-  __ jcc(Assembler::equal, _continuation);
-  ce->store_parameter(pre_val()->as_register(), 0);
-  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_pre_barrier_slow_id)));
-  __ jmp(_continuation);
-
-}
-
-void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
-  __ bind(_entry);
-  assert(addr()->is_register(), "Precondition.");
-  assert(new_val()->is_register(), "Precondition.");
-  Register new_val_reg = new_val()->as_register();
-  __ cmpptr(new_val_reg, (int32_t) NULL_WORD);
-  __ jcc(Assembler::equal, _continuation);
-  ce->store_parameter(addr()->as_pointer_register(), 0);
-  __ call(RuntimeAddress(Runtime1::entry_for(Runtime1::g1_post_barrier_slow_id)));
-  __ jmp(_continuation);
-}
-
-#endif // INCLUDE_ALL_GCS
-/////////////////////////////////////////////////////////////////////////////
-
 #undef __
--- a/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_LIRGenerator_x86.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,6 +33,7 @@
 #include "ci/ciArray.hpp"
 #include "ci/ciObjArrayKlass.hpp"
 #include "ci/ciTypeArrayKlass.hpp"
+#include "gc/shared/c1/barrierSetC1.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "vmreg_x86.inline.hpp"
@@ -152,9 +153,27 @@
                                             int shift, int disp, BasicType type) {
   assert(base->is_register(), "must be");
   if (index->is_constant()) {
+    LIR_Const *constant = index->as_constant_ptr();
+#ifdef _LP64
+    jlong c;
+    if (constant->type() == T_INT) {
+      c = (jlong(index->as_jint()) << shift) + disp;
+    } else {
+      assert(constant->type() == T_LONG, "should be");
+      c = (index->as_jlong() << shift) + disp;
+    }
+    if ((jlong)((jint)c) == c) {
+      return new LIR_Address(base, (jint)c, type);
+    } else {
+      LIR_Opr tmp = new_register(T_LONG);
+      __ move(index, tmp);
+      return new LIR_Address(base, tmp, type);
+    }
+#else
     return new LIR_Address(base,
-                           ((intx)(index->as_constant_ptr()->as_jint()) << shift) + disp,
+                           ((intx)(constant->as_jint()) << shift) + disp,
                            type);
+#endif
   } else {
     return new LIR_Address(base, index, (LIR_Address::Scale)shift, disp, type);
   }
@@ -162,7 +181,7 @@
 
 
 LIR_Address* LIRGenerator::emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr,
-                                              BasicType type, bool needs_card_mark) {
+                                              BasicType type) {
   int offset_in_bytes = arrayOopDesc::base_offset_in_bytes(type);
 
   LIR_Address* addr;
@@ -183,16 +202,7 @@
                             LIR_Address::scale(type),
                             offset_in_bytes, type);
   }
-  if (needs_card_mark) {
-    // This store will need a precise card mark, so go ahead and
-    // compute the full adddres instead of computing once for the
-    // store and again for the card mark.
-    LIR_Opr tmp = new_pointer_register();
-    __ leal(LIR_OprFact::address(addr), tmp);
-    return new LIR_Address(tmp, type);
-  } else {
-    return addr;
-  }
+  return addr;
 }
 
 
@@ -253,87 +263,17 @@
   __ store(item, new LIR_Address(FrameMap::rsp_opr, in_bytes(offset_from_sp), type));
 }
 
+void LIRGenerator::array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci) {
+  LIR_Opr tmp1 = new_register(objectType);
+  LIR_Opr tmp2 = new_register(objectType);
+  LIR_Opr tmp3 = new_register(objectType);
+  __ store_check(value, array, tmp1, tmp2, tmp3, store_check_info, profiled_method, profiled_bci);
+}
+
 //----------------------------------------------------------------------
 //             visitor functions
 //----------------------------------------------------------------------
 
-
-void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
-  assert(x->is_pinned(),"");
-  bool needs_range_check = x->compute_needs_range_check();
-  bool use_length = x->length() != NULL;
-  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
-  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
-                                         !get_jobject_constant(x->value())->is_null_object() ||
-                                         x->should_profile());
-
-  LIRItem array(x->array(), this);
-  LIRItem index(x->index(), this);
-  LIRItem value(x->value(), this);
-  LIRItem length(this);
-
-  array.load_item();
-  index.load_nonconstant();
-
-  if (use_length && needs_range_check) {
-    length.set_instruction(x->length());
-    length.load_item();
-
-  }
-  if (needs_store_check || x->check_boolean()) {
-    value.load_item();
-  } else {
-    value.load_for_store(x->elt_type());
-  }
-
-  set_no_result(x);
-
-  // the CodeEmitInfo must be duplicated for each different
-  // LIR-instruction because spilling can occur anywhere between two
-  // instructions and so the debug information must be different
-  CodeEmitInfo* range_check_info = state_for(x);
-  CodeEmitInfo* null_check_info = NULL;
-  if (x->needs_null_check()) {
-    null_check_info = new CodeEmitInfo(range_check_info);
-  }
-
-  // emit array address setup early so it schedules better
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), obj_store);
-
-  if (GenerateRangeChecks && needs_range_check) {
-    if (use_length) {
-      __ cmp(lir_cond_belowEqual, length.result(), index.result());
-      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
-    } else {
-      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
-      // range_check also does the null check
-      null_check_info = NULL;
-    }
-  }
-
-  if (GenerateArrayStoreCheck && needs_store_check) {
-    LIR_Opr tmp1 = new_register(objectType);
-    LIR_Opr tmp2 = new_register(objectType);
-    LIR_Opr tmp3 = new_register(objectType);
-
-    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
-    __ store_check(value.result(), array.result(), tmp1, tmp2, tmp3, store_check_info, x->profiled_method(), x->profiled_bci());
-  }
-
-  if (obj_store) {
-    // Needs GC write barriers.
-    pre_barrier(LIR_OprFact::address(array_addr), LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-    __ move(value.result(), array_addr, null_check_info);
-    // Seems to be a precise
-    post_barrier(LIR_OprFact::address(array_addr), value.result());
-  } else {
-    LIR_Opr result = maybe_mask_boolean(x, array.result(), value.result(), null_check_info);
-    __ move(result, array_addr, null_check_info);
-  }
-}
-
-
 void LIRGenerator::do_MonitorEnter(MonitorEnter* x) {
   assert(x->is_pinned(),"");
   LIRItem obj(x->obj(), this);
@@ -715,93 +655,48 @@
   }
 }
 
-
-void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
-  assert(x->number_of_arguments() == 4, "wrong type");
-  LIRItem obj   (x->argument_at(0), this);  // object
-  LIRItem offset(x->argument_at(1), this);  // offset of field
-  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
-  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp
-
-  assert(obj.type()->tag() == objectTag, "invalid type");
-
-  // In 64bit the type can be long, sparc doesn't have this assert
-  // assert(offset.type()->tag() == intTag, "invalid type");
-
-  assert(cmp.type()->tag() == type->tag(), "invalid type");
-  assert(val.type()->tag() == type->tag(), "invalid type");
-
-  // get address of field
-  obj.load_item();
-  offset.load_nonconstant();
-
-  LIR_Opr addr = new_pointer_register();
-  LIR_Address* a;
-  if(offset.result()->is_constant()) {
-#ifdef _LP64
-    jlong c = offset.result()->as_jlong();
-    if ((jlong)((jint)c) == c) {
-      a = new LIR_Address(obj.result(),
-                          (jint)c,
-                          as_BasicType(type));
-    } else {
-      LIR_Opr tmp = new_register(T_LONG);
-      __ move(offset.result(), tmp);
-      a = new LIR_Address(obj.result(),
-                          tmp,
-                          as_BasicType(type));
-    }
-#else
-    a = new LIR_Address(obj.result(),
-                        offset.result()->as_jint(),
-                        as_BasicType(type));
-#endif
+LIR_Opr LIRGenerator::atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value) {
+  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
+  if (type == T_OBJECT || type == T_ARRAY) {
+    cmp_value.load_item_force(FrameMap::rax_oop_opr);
+    new_value.load_item();
+    __ cas_obj(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill);
+  } else if (type == T_INT) {
+    cmp_value.load_item_force(FrameMap::rax_opr);
+    new_value.load_item();
+    __ cas_int(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill);
+  } else if (type == T_LONG) {
+    cmp_value.load_item_force(FrameMap::long0_opr);
+    new_value.load_item_force(FrameMap::long1_opr);
+    __ cas_long(addr->as_address_ptr()->base(), cmp_value.result(), new_value.result(), ill, ill);
   } else {
-    a = new LIR_Address(obj.result(),
-                        offset.result(),
-                        0,
-                        as_BasicType(type));
+    Unimplemented();
   }
-  __ leal(LIR_OprFact::address(a), addr);
-
-  if (type == objectType) {  // Write-barrier needed for Object fields.
-    // Do the pre-write barrier, if any.
-    pre_barrier(addr, LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load */, false /* patch */, NULL);
-  }
+  LIR_Opr result = new_register(T_INT);
+  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
+           result, type);
+  return result;
+}
 
-  if (type == objectType) {
-    cmp.load_item_force(FrameMap::rax_oop_opr);
-    val.load_item();
-  } else if (type == intType) {
-    cmp.load_item_force(FrameMap::rax_opr);
-    val.load_item();
-  } else if (type == longType) {
-    cmp.load_item_force(FrameMap::long0_opr);
-    val.load_item_force(FrameMap::long1_opr);
-  } else {
-    ShouldNotReachHere();
-  }
+LIR_Opr LIRGenerator::atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& value) {
+  bool is_oop = type == T_OBJECT || type == T_ARRAY;
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  // Because we want a 2-arg form of xchg and xadd
+  __ move(value.result(), result);
+  assert(type == T_INT || is_oop LP64_ONLY( || type == T_LONG ), "unexpected type");
+  __ xchg(addr, result, result, LIR_OprFact::illegalOpr);
+  return result;
+}
 
-  LIR_Opr ill = LIR_OprFact::illegalOpr;  // for convenience
-  if (type == objectType)
-    __ cas_obj(addr, cmp.result(), val.result(), ill, ill);
-  else if (type == intType)
-    __ cas_int(addr, cmp.result(), val.result(), ill, ill);
-  else if (type == longType)
-    __ cas_long(addr, cmp.result(), val.result(), ill, ill);
-  else {
-    ShouldNotReachHere();
-  }
-
-  // generate conditional move of boolean result
-  LIR_Opr result = rlock_result(x);
-  __ cmove(lir_cond_equal, LIR_OprFact::intConst(1), LIR_OprFact::intConst(0),
-           result, as_BasicType(type));
-  if (type == objectType) {   // Write-barrier needed for Object fields.
-    // Seems to be precise
-    post_barrier(addr, val.result());
-  }
+LIR_Opr LIRGenerator::atomic_add(BasicType type, LIR_Opr addr, LIRItem& value) {
+  LIR_Opr result = new_register(type);
+  value.load_item();
+  // Because we want a 2-arg form of xchg and xadd
+  __ move(value.result(), result);
+  assert(type == T_INT LP64_ONLY( || type == T_LONG ), "unexpected type");
+  __ xadd(addr, result, result, LIR_OprFact::illegalOpr);
+  return result;
 }
 
 void LIRGenerator::do_FmaIntrinsic(Intrinsic* x) {
@@ -1570,8 +1465,6 @@
   }
 }
 
-
-
 void LIRGenerator::volatile_field_load(LIR_Address* address, LIR_Opr result,
                                        CodeEmitInfo* info) {
   if (address->type() == T_LONG) {
@@ -1593,100 +1486,3 @@
     __ load(address, result, info);
   }
 }
-
-void LIRGenerator::get_Object_unsafe(LIR_Opr dst, LIR_Opr src, LIR_Opr offset,
-                                     BasicType type, bool is_volatile) {
-  if (is_volatile && type == T_LONG) {
-    LIR_Address* addr = new LIR_Address(src, offset, T_DOUBLE);
-    LIR_Opr tmp = new_register(T_DOUBLE);
-    __ load(addr, tmp);
-    LIR_Opr spill = new_register(T_LONG);
-    set_vreg_flag(spill, must_start_in_memory);
-    __ move(tmp, spill);
-    __ move(spill, dst);
-  } else {
-    LIR_Address* addr = new LIR_Address(src, offset, type);
-    __ load(addr, dst);
-  }
-}
-
-
-void LIRGenerator::put_Object_unsafe(LIR_Opr src, LIR_Opr offset, LIR_Opr data,
-                                     BasicType type, bool is_volatile) {
-  if (is_volatile && type == T_LONG) {
-    LIR_Address* addr = new LIR_Address(src, offset, T_DOUBLE);
-    LIR_Opr tmp = new_register(T_DOUBLE);
-    LIR_Opr spill = new_register(T_DOUBLE);
-    set_vreg_flag(spill, must_start_in_memory);
-    __ move(data, spill);
-    __ move(spill, tmp);
-    __ move(tmp, addr);
-  } else {
-    LIR_Address* addr = new LIR_Address(src, offset, type);
-    bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-    if (is_obj) {
-      // Do the pre-write barrier, if any.
-      pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                  true /* do_load */, false /* patch */, NULL);
-      __ move(data, addr);
-      assert(src->is_register(), "must be register");
-      // Seems to be a precise address
-      post_barrier(LIR_OprFact::address(addr), data);
-    } else {
-      __ move(data, addr);
-    }
-  }
-}
-
-void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
-  BasicType type = x->basic_type();
-  LIRItem src(x->object(), this);
-  LIRItem off(x->offset(), this);
-  LIRItem value(x->value(), this);
-
-  src.load_item();
-  value.load_item();
-  off.load_nonconstant();
-
-  LIR_Opr dst = rlock_result(x, type);
-  LIR_Opr data = value.result();
-  bool is_obj = (type == T_ARRAY || type == T_OBJECT);
-  LIR_Opr offset = off.result();
-
-  assert (type == T_INT || (!x->is_add() && is_obj) LP64_ONLY( || type == T_LONG ), "unexpected type");
-  LIR_Address* addr;
-  if (offset->is_constant()) {
-#ifdef _LP64
-    jlong c = offset->as_jlong();
-    if ((jlong)((jint)c) == c) {
-      addr = new LIR_Address(src.result(), (jint)c, type);
-    } else {
-      LIR_Opr tmp = new_register(T_LONG);
-      __ move(offset, tmp);
-      addr = new LIR_Address(src.result(), tmp, type);
-    }
-#else
-    addr = new LIR_Address(src.result(), offset->as_jint(), type);
-#endif
-  } else {
-    addr = new LIR_Address(src.result(), offset, type);
-  }
-
-  // Because we want a 2-arg form of xchg and xadd
-  __ move(data, dst);
-
-  if (x->is_add()) {
-    __ xadd(LIR_OprFact::address(addr), dst, dst, LIR_OprFact::illegalOpr);
-  } else {
-    if (is_obj) {
-      // Do the pre-write barrier, if any.
-      pre_barrier(LIR_OprFact::address(addr), LIR_OprFact::illegalOpr /* pre_val */,
-                  true /* do_load */, false /* patch */, NULL);
-    }
-    __ xchg(LIR_OprFact::address(addr), dst, dst, LIR_OprFact::illegalOpr);
-    if (is_obj) {
-      // Seems to be a precise address
-      post_barrier(LIR_OprFact::address(addr), data);
-    }
-  }
-}
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -356,6 +356,15 @@
   verify_FPU(0, "method_entry");
 }
 
+void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) {
+  // rbp, + 0: link
+  //     + 1: return address
+  //     + 2: argument with offset 0
+  //     + 3: argument with offset 1
+  //     + 4: ...
+
+  movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord));
+}
 
 #ifndef PRODUCT
 
--- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -121,4 +121,9 @@
   // This platform only uses signal-based null checks. The Label is not needed.
   void null_check(Register r, Label *Lnull = NULL) { MacroAssembler::null_check(r); }
 
+  void load_parameter(int offset_in_words, Register reg);
+
+  void save_live_registers_no_oop_map(int num_rt_args, bool save_fpu_registers);
+  void restore_live_registers(bool restore_fpu_registers);
+
 #endif // CPU_X86_VM_C1_MACROASSEMBLER_X86_HPP
--- a/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/c1_Runtime1_x86.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -41,12 +41,6 @@
 #include "runtime/vframeArray.hpp"
 #include "utilities/macros.hpp"
 #include "vmreg_x86.inline.hpp"
-#if INCLUDE_ALL_GCS
-#include "gc/g1/g1BarrierSet.hpp"
-#include "gc/g1/g1CardTable.hpp"
-#include "gc/g1/g1ThreadLocalData.hpp"
-#endif
-
 
 // Implementation of StubAssembler
 
@@ -212,31 +206,32 @@
   ~StubFrame();
 };
 
+void StubAssembler::prologue(const char* name, bool must_gc_arguments) {
+  set_info(name, must_gc_arguments);
+  enter();
+}
+
+void StubAssembler::epilogue() {
+  leave();
+  ret(0);
+}
 
 #define __ _sasm->
 
 StubFrame::StubFrame(StubAssembler* sasm, const char* name, bool must_gc_arguments) {
   _sasm = sasm;
-  __ set_info(name, must_gc_arguments);
-  __ enter();
+  __ prologue(name, must_gc_arguments);
 }
 
 // load parameters that were stored with LIR_Assembler::store_parameter
 // Note: offsets for store_parameter and load_argument must match
 void StubFrame::load_argument(int offset_in_words, Register reg) {
-  // rbp, + 0: link
-  //     + 1: return address
-  //     + 2: argument with offset 0
-  //     + 3: argument with offset 1
-  //     + 4: ...
-
-  __ movptr(reg, Address(rbp, (offset_in_words + 2) * BytesPerWord));
+  __ load_parameter(offset_in_words, reg);
 }
 
 
 StubFrame::~StubFrame() {
-  __ leave();
-  __ ret(0);
+  __ epilogue();
 }
 
 #undef __
@@ -244,8 +239,6 @@
 
 // Implementation of Runtime1
 
-#define __ sasm->
-
 const int float_regs_as_doubles_size_in_slots = pd_nof_fpu_regs_frame_map * 2;
 const int xmm_regs_as_doubles_size_in_slots = FrameMap::nof_xmm_regs * 2;
 
@@ -310,8 +303,6 @@
   reg_save_frame_size   // As noted: neglects any parameters to runtime                     // 504
 };
 
-
-
 // Save off registers which might be killed by calls into the runtime.
 // Tries to smart of about FP registers.  In particular we separate
 // saving and describing the FPU registers for deoptimization since we
@@ -418,8 +409,9 @@
   return map;
 }
 
-static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
-                                   bool save_fpu_registers = true) {
+#define __ this->
+
+void C1_MacroAssembler::save_live_registers_no_oop_map(int num_rt_args, bool save_fpu_registers) {
   __ block_comment("save_live_registers");
 
   __ pusha();         // integer registers
@@ -493,12 +485,12 @@
 
   // FPU stack must be empty now
   __ verify_FPU(0, "save_live_registers");
-
-  return generate_oop_map(sasm, num_rt_args, save_fpu_registers);
 }
 
+#undef __
+#define __ sasm->
 
-static void restore_fpu(StubAssembler* sasm, bool restore_fpu_registers = true) {
+static void restore_fpu(C1_MacroAssembler* sasm, bool restore_fpu_registers) {
   if (restore_fpu_registers) {
     if (UseSSE >= 2) {
       // restore XMM registers
@@ -549,14 +541,28 @@
   __ addptr(rsp, extra_space_offset * VMRegImpl::stack_slot_size);
 }
 
+#undef __
+#define __ this->
 
-static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
+void C1_MacroAssembler::restore_live_registers(bool restore_fpu_registers) {
   __ block_comment("restore_live_registers");
 
-  restore_fpu(sasm, restore_fpu_registers);
+  restore_fpu(this, restore_fpu_registers);
   __ popa();
 }
 
+#undef __
+#define __ sasm->
+
+static OopMap* save_live_registers(StubAssembler* sasm, int num_rt_args,
+                                   bool save_fpu_registers = true) {
+  sasm->save_live_registers_no_oop_map(num_rt_args, save_fpu_registers);
+  return generate_oop_map(sasm, num_rt_args, save_fpu_registers);
+}
+
+static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registers = true) {
+  sasm->restore_live_registers(restore_fpu_registers);
+}
 
 static void restore_live_registers_except_rax(StubAssembler* sasm, bool restore_fpu_registers = true) {
   __ block_comment("restore_live_registers_except_rax");
@@ -1557,159 +1563,6 @@
       }
       break;
 
-#if INCLUDE_ALL_GCS
-    case g1_pre_barrier_slow_id:
-      {
-        StubFrame f(sasm, "g1_pre_barrier", dont_gc_arguments);
-        // arg0 : previous value of memory
-
-        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);
-          __ should_not_reach_here();
-          break;
-        }
-        __ push(rax);
-        __ push(rdx);
-
-        const Register pre_val = rax;
-        const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
-        const Register tmp = rdx;
-
-        NOT_LP64(__ get_thread(thread);)
-
-        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;
-
-        // Is marking still active?
-        if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-          __ cmpl(queue_active, 0);
-        } else {
-          assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
-          __ cmpb(queue_active, 0);
-        }
-        __ jcc(Assembler::equal, done);
-
-        // Can we store original value in the thread's buffer?
-
-        __ movptr(tmp, queue_index);
-        __ testptr(tmp, tmp);
-        __ jcc(Assembler::zero, runtime);
-        __ subptr(tmp, wordSize);
-        __ movptr(queue_index, tmp);
-        __ addptr(tmp, buffer);
-
-        // prev_val (rax)
-        f.load_argument(0, pre_val);
-        __ movptr(Address(tmp, 0), pre_val);
-        __ jmp(done);
-
-        __ bind(runtime);
-
-        save_live_registers(sasm, 3);
-
-        // load the pre-value
-        f.load_argument(0, rcx);
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread);
-
-        restore_live_registers(sasm);
-
-        __ bind(done);
-
-        __ pop(rdx);
-        __ pop(rax);
-      }
-      break;
-
-    case g1_post_barrier_slow_id:
-      {
-        StubFrame f(sasm, "g1_post_barrier", dont_gc_arguments);
-
-        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);
-          __ should_not_reach_here();
-          break;
-        }
-
-        // arg0: store_address
-        Address store_addr(rbp, 2*BytesPerWord);
-
-        Label done;
-        Label enqueued;
-        Label runtime;
-
-        // At this point we know new_value is non-NULL and the new_value crosses regions.
-        // Must check to see if card is already dirty
-
-        const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
-
-        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);
-
-        const Register cardtable = rax;
-        const Register card_addr = rcx;
-
-        f.load_argument(0, card_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, ci_card_table_address_as<intptr_t>());
-        __ addptr(card_addr, cardtable);
-
-        NOT_LP64(__ get_thread(thread);)
-
-        __ 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 region crossing non-NULL, card is clean.
-        // dirty card and log.
-
-        __ movb(Address(card_addr, 0), (int)CardTable::dirty_card_val());
-
-        const Register tmp = rdx;
-        __ push(rdx);
-
-        __ movptr(tmp, queue_index);
-        __ testptr(tmp, tmp);
-        __ jcc(Assembler::zero, runtime);
-        __ subptr(tmp, wordSize);
-        __ movptr(queue_index, tmp);
-        __ addptr(tmp, buffer);
-        __ movptr(Address(tmp, 0), card_addr);
-        __ jmp(enqueued);
-
-        __ bind(runtime);
-
-        save_live_registers(sasm, 3);
-
-        __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
-
-        restore_live_registers(sasm);
-
-        __ bind(enqueued);
-        __ pop(rdx);
-
-        __ bind(done);
-        __ pop(rcx);
-        __ pop(rax);
-      }
-      break;
-#endif // INCLUDE_ALL_GCS
-
     case predicate_failed_trap_id:
       {
         StubFrame f(sasm, "predicate_failed_trap", dont_gc_arguments);
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -32,6 +32,11 @@
 #include "interpreter/interp_masm.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "utilities/macros.hpp"
+#ifdef COMPILER1
+#include "c1/c1_LIRAssembler.hpp"
+#include "c1/c1_MacroAssembler.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#endif
 
 #define __ masm->
 
@@ -399,3 +404,193 @@
   }
   NOT_LP64(imasm->restore_bcp());
 }
+
+#ifdef COMPILER1
+
+#undef __
+#define __ ce->masm()->
+
+void G1BarrierSetAssembler::gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  // At this point we know that marking is in progress.
+  // If do_load() is true then we have to emit the
+  // load of the previous value; otherwise it has already
+  // been loaded into _pre_val.
+
+  __ bind(*stub->entry());
+  assert(stub->pre_val()->is_register(), "Precondition.");
+
+  Register pre_val_reg = stub->pre_val()->as_register();
+
+  if (stub->do_load()) {
+    ce->mem2reg(stub->addr(), stub->pre_val(), T_OBJECT, stub->patch_code(), stub->info(), false /*wide*/, false /*unaligned*/);
+  }
+
+  __ cmpptr(pre_val_reg, (int32_t)NULL_WORD);
+  __ jcc(Assembler::equal, *stub->continuation());
+  ce->store_parameter(stub->pre_val()->as_register(), 0);
+  __ call(RuntimeAddress(bs->pre_barrier_c1_runtime_code_blob()->code_begin()));
+  __ jmp(*stub->continuation());
+
+}
+
+void G1BarrierSetAssembler::gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub) {
+  G1BarrierSetC1* bs = (G1BarrierSetC1*)BarrierSet::barrier_set()->barrier_set_c1();
+  __ bind(*stub->entry());
+  assert(stub->addr()->is_register(), "Precondition.");
+  assert(stub->new_val()->is_register(), "Precondition.");
+  Register new_val_reg = stub->new_val()->as_register();
+  __ cmpptr(new_val_reg, (int32_t) NULL_WORD);
+  __ jcc(Assembler::equal, *stub->continuation());
+  ce->store_parameter(stub->addr()->as_pointer_register(), 0);
+  __ call(RuntimeAddress(bs->post_barrier_c1_runtime_code_blob()->code_begin()));
+  __ jmp(*stub->continuation());
+}
+
+#undef __
+
+#define __ sasm->
+
+void G1BarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("g1_pre_barrier", false);
+  // arg0 : previous value of memory
+
+  __ push(rax);
+  __ push(rdx);
+
+  const Register pre_val = rax;
+  const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+  const Register tmp = rdx;
+
+  NOT_LP64(__ get_thread(thread);)
+
+  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;
+
+  // Is marking still active?
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    __ cmpl(queue_active, 0);
+  } else {
+    assert(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1, "Assumption");
+    __ cmpb(queue_active, 0);
+  }
+  __ jcc(Assembler::equal, done);
+
+  // Can we store original value in the thread's buffer?
+
+  __ movptr(tmp, queue_index);
+  __ testptr(tmp, tmp);
+  __ jcc(Assembler::zero, runtime);
+  __ subptr(tmp, wordSize);
+  __ movptr(queue_index, tmp);
+  __ addptr(tmp, buffer);
+
+  // prev_val (rax)
+  __ load_parameter(0, pre_val);
+  __ movptr(Address(tmp, 0), pre_val);
+  __ jmp(done);
+
+  __ bind(runtime);
+
+  __ save_live_registers_no_oop_map(3, true);
+
+  // load the pre-value
+  __ load_parameter(0, rcx);
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_pre), rcx, thread);
+
+  __ restore_live_registers(true);
+
+  __ bind(done);
+
+  __ pop(rdx);
+  __ pop(rax);
+
+  __ epilogue();
+}
+
+void G1BarrierSetAssembler::generate_c1_post_barrier_runtime_stub(StubAssembler* sasm) {
+  __ prologue("g1_post_barrier", false);
+
+  // arg0: store_address
+  Address store_addr(rbp, 2*BytesPerWord);
+
+  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 enqueued;
+  Label runtime;
+
+  // At this point we know new_value is non-NULL and the new_value crosses regions.
+  // Must check to see if card is already dirty
+
+  const Register thread = NOT_LP64(rax) LP64_ONLY(r15_thread);
+
+  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);
+
+  const Register cardtable = rax;
+  const Register card_addr = rcx;
+
+  __ load_parameter(0, card_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);
+
+  NOT_LP64(__ get_thread(thread);)
+
+  __ 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 region crossing non-NULL, card is clean.
+  // dirty card and log.
+
+  __ movb(Address(card_addr, 0), (int)CardTable::dirty_card_val());
+
+  const Register tmp = rdx;
+  __ push(rdx);
+
+  __ movptr(tmp, queue_index);
+  __ testptr(tmp, tmp);
+  __ jcc(Assembler::zero, runtime);
+  __ subptr(tmp, wordSize);
+  __ movptr(queue_index, tmp);
+  __ addptr(tmp, buffer);
+  __ movptr(Address(tmp, 0), card_addr);
+  __ jmp(enqueued);
+
+  __ bind(runtime);
+
+  __ save_live_registers_no_oop_map(3, true);
+
+  __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::g1_wb_post), card_addr, thread);
+
+  __ restore_live_registers(true);
+
+  __ bind(enqueued);
+  __ pop(rdx);
+
+  __ bind(done);
+  __ pop(rcx);
+  __ pop(rax);
+
+  __ epilogue();
+}
+
+#undef __
+
+#endif // COMPILER1
--- a/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/cpu/x86/gc/g1/g1BarrierSetAssembler_x86.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -28,6 +28,11 @@
 #include "asm/macroAssembler.hpp"
 #include "gc/shared/modRefBarrierSetAssembler.hpp"
 
+class LIR_Assembler;
+class StubAssembler;
+class G1PreBarrierStub;
+class G1PostBarrierStub;
+
 class G1BarrierSetAssembler: public ModRefBarrierSetAssembler {
  protected:
   virtual void gen_write_ref_array_pre_barrier(MacroAssembler* masm, DecoratorSet decorators, Register addr, Register count);
@@ -52,6 +57,12 @@
                             Address dst, Register val, Register tmp1, Register tmp2);
 
  public:
+  void gen_pre_barrier_stub(LIR_Assembler* ce, G1PreBarrierStub* stub);
+  void gen_post_barrier_stub(LIR_Assembler* ce, G1PostBarrierStub* stub);
+
+  void generate_c1_pre_barrier_runtime_stub(StubAssembler* sasm);
+  void generate_c1_post_barrier_runtime_stub(StubAssembler* sasm);
+
   virtual void load_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
                        Register dst, Address src, Register tmp1, Register tmp_thread);
 };
--- a/src/hotspot/share/c1/c1_CodeStubs.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_CodeStubs.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -533,92 +533,4 @@
 #endif // PRODUCT
 };
 
-//////////////////////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-// Code stubs for Garbage-First barriers.
-class G1PreBarrierStub: public CodeStub {
- private:
-  bool _do_load;
-  LIR_Opr _addr;
-  LIR_Opr _pre_val;
-  LIR_PatchCode _patch_code;
-  CodeEmitInfo* _info;
-
- public:
-  // Version that _does_ generate a load of the previous value from addr.
-  // addr (the address of the field to be read) must be a LIR_Address
-  // pre_val (a temporary register) must be a register;
-  G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) :
-    _addr(addr), _pre_val(pre_val), _do_load(true),
-    _patch_code(patch_code), _info(info)
-  {
-    assert(_pre_val->is_register(), "should be temporary register");
-    assert(_addr->is_address(), "should be the address of the field");
-  }
-
-  // Version that _does not_ generate load of the previous value; the
-  // previous value is assumed to have already been loaded into pre_val.
-  G1PreBarrierStub(LIR_Opr pre_val) :
-    _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false),
-    _patch_code(lir_patch_none), _info(NULL)
-  {
-    assert(_pre_val->is_register(), "should be a register");
-  }
-
-  LIR_Opr addr() const { return _addr; }
-  LIR_Opr pre_val() const { return _pre_val; }
-  LIR_PatchCode patch_code() const { return _patch_code; }
-  CodeEmitInfo* info() const { return _info; }
-  bool do_load() const { return _do_load; }
-
-  virtual void emit_code(LIR_Assembler* e);
-  virtual void visit(LIR_OpVisitState* visitor) {
-    if (_do_load) {
-      // don't pass in the code emit info since it's processed in the fast
-      // path
-      if (_info != NULL)
-        visitor->do_slow_case(_info);
-      else
-        visitor->do_slow_case();
-
-      visitor->do_input(_addr);
-      visitor->do_temp(_pre_val);
-    } else {
-      visitor->do_slow_case();
-      visitor->do_input(_pre_val);
-    }
-  }
-#ifndef PRODUCT
-  virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); }
-#endif // PRODUCT
-};
-
-class G1PostBarrierStub: public CodeStub {
- private:
-  LIR_Opr _addr;
-  LIR_Opr _new_val;
-
- public:
-  // addr (the address of the object head) and new_val must be registers.
-  G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }
-
-  LIR_Opr addr() const { return _addr; }
-  LIR_Opr new_val() const { return _new_val; }
-
-  virtual void emit_code(LIR_Assembler* e);
-  virtual void visit(LIR_OpVisitState* visitor) {
-    // don't pass in the code emit info since it's processed in the fast path
-    visitor->do_slow_case();
-    visitor->do_input(_addr);
-    visitor->do_input(_new_val);
-  }
-#ifndef PRODUCT
-  virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); }
-#endif // PRODUCT
-};
-
-#endif // INCLUDE_ALL_GCS
-//////////////////////////////////////////////////////////////////////////////////////////
-
 #endif // SHARE_VM_C1_C1_CODESTUBS_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/c1/c1_Decorators.hpp	Thu Apr 26 20:42:43 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.
+ *
+ */
+
+#ifndef SHARE_VM_C1_C1_DECORATORS_HPP
+#define SHARE_VM_C1_C1_DECORATORS_HPP
+
+#include "oops/accessDecorators.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+// Use the C1_NEEDS_PATCHING decorator for situations when the access is using
+// an offset that is not yet known and will require patching
+const DecoratorSet C1_NEEDS_PATCHING = DECORATOR_LAST << 1;
+// Use the C1_MASK_BOOLEAN decorator for boolean accesses where the value
+// needs to be masked.
+const DecoratorSet C1_MASK_BOOLEAN   = DECORATOR_LAST << 2;
+// The C1_WRITE_ACCESS decorator is used to mark writing accesses.
+const DecoratorSet C1_WRITE_ACCESS   = DECORATOR_LAST << 3;
+// The C1_READ_ACCESS decorator is used to mark reading accesses.
+const DecoratorSet C1_READ_ACCESS    = DECORATOR_LAST << 4;
+
+#endif // SHARE_VM_C1_C1_DECORATORS_HPP
--- a/src/hotspot/share/c1/c1_LIRAssembler.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_LIRAssembler.hpp	Thu Apr 26 20:42:43 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
@@ -260,6 +260,8 @@
 
 #include CPU_HEADER(c1_LIRAssembler)
 
+ public:
+
   static int call_stub_size() {
     if (UseAOT) {
       return _call_stub_size + _call_aot_stub_size;
--- a/src/hotspot/share/c1/c1_LIRGenerator.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -34,19 +34,14 @@
 #include "ci/ciInstance.hpp"
 #include "ci/ciObjArray.hpp"
 #include "ci/ciUtilities.hpp"
-#include "gc/shared/cardTable.hpp"
-#include "gc/shared/cardTableBarrierSet.hpp"
-#include "gc/shared/collectedHeap.hpp"
+#include "gc/shared/barrierSet.hpp"
+#include "gc/shared/c1/barrierSetC1.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/vm_version.hpp"
 #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
 #include "trace/traceMacros.hpp"
 #endif
@@ -313,11 +308,6 @@
 //--------------------------------------------------------------
 
 
-void LIRGenerator::init() {
-  _bs = BarrierSet::barrier_set();
-}
-
-
 void LIRGenerator::block_do_prolog(BlockBegin* block) {
 #ifndef PRODUCT
   if (PrintIRWithLIR) {
@@ -1245,19 +1235,9 @@
     info = state_for(x);
   }
 
-  LIR_Address* referent_field_adr =
-    new LIR_Address(reference.result(), referent_offset, T_OBJECT);
-
-  LIR_Opr result = rlock_result(x);
-
-  __ load(referent_field_adr, result, info);
-
-  // Register the value in the referent field with the pre-barrier
-  pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */,
-              result /* pre_val */,
-              false  /* do_load */,
-              false  /* patch */,
-              NULL   /* info */);
+  LIR_Opr result = rlock_result(x, T_OBJECT);
+  access_load_at(IN_HEAP | ON_WEAK_OOP_REF, T_OBJECT,
+                 reference, LIR_OprFact::intConst(referent_offset), result);
 }
 
 // Example: clazz.isInstance(object)
@@ -1454,222 +1434,27 @@
   return result;
 }
 
-// Various barriers
-
-void LIRGenerator::pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val,
-                               bool do_load, bool patch, CodeEmitInfo* info) {
-  // Do the pre-write barrier, if any.
-  switch (_bs->kind()) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      G1BarrierSet_pre_barrier(addr_opr, pre_val, do_load, patch, info);
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-      // No pre barriers
-      break;
-    default      :
-      ShouldNotReachHere();
-
-  }
-}
-
-void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
-  switch (_bs->kind()) {
-#if INCLUDE_ALL_GCS
-    case BarrierSet::G1BarrierSet:
-      G1BarrierSet_post_barrier(addr,  new_val);
-      break;
-#endif // INCLUDE_ALL_GCS
-    case BarrierSet::CardTableBarrierSet:
-      CardTableBarrierSet_post_barrier(addr,  new_val);
-      break;
-    default      :
-      ShouldNotReachHere();
-    }
-}
-
-////////////////////////////////////////////////////////////////////////
-#if INCLUDE_ALL_GCS
-
-void LIRGenerator::G1BarrierSet_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val,
-                                            bool do_load, bool patch, CodeEmitInfo* info) {
-  // First we test whether marking is in progress.
-  BasicType flag_type;
-  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
-    flag_type = T_INT;
-  } else {
-    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
-              "Assumption");
-    // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
-    // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
-    flag_type = T_BOOLEAN;
-  }
-  LIR_Opr thrd = getThreadPointer();
-  LIR_Address* mark_active_flag_addr =
-    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);
-  __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
-
-  LIR_PatchCode pre_val_patch_code = lir_patch_none;
-
-  CodeStub* slow;
-
-  if (do_load) {
-    assert(pre_val == LIR_OprFact::illegalOpr, "sanity");
-    assert(addr_opr != LIR_OprFact::illegalOpr, "sanity");
-
-    if (patch)
-      pre_val_patch_code = lir_patch_normal;
-
-    pre_val = new_register(T_OBJECT);
-
-    if (!addr_opr->is_address()) {
-      assert(addr_opr->is_register(), "must be");
-      addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
-    }
-    slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info);
-  } else {
-    assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
-    assert(pre_val->is_register(), "must be");
-    assert(pre_val->type() == T_OBJECT, "must be an object");
-    assert(info == NULL, "sanity");
-
-    slow = new G1PreBarrierStub(pre_val);
-  }
-
-  __ branch(lir_cond_notEqual, T_INT, slow);
-  __ branch_destination(slow->continuation());
+//------------------------field access--------------------------------------
+
+void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
+  assert(x->number_of_arguments() == 4, "wrong type");
+  LIRItem obj   (x->argument_at(0), this);  // object
+  LIRItem offset(x->argument_at(1), this);  // offset of field
+  LIRItem cmp   (x->argument_at(2), this);  // value to compare with field
+  LIRItem val   (x->argument_at(3), this);  // replace field with val if matches cmp
+  assert(obj.type()->tag() == objectTag, "invalid type");
+
+  // In 64bit the type can be long, sparc doesn't have this assert
+  // assert(offset.type()->tag() == intTag, "invalid type");
+
+  assert(cmp.type()->tag() == type->tag(), "invalid type");
+  assert(val.type()->tag() == type->tag(), "invalid type");
+
+  LIR_Opr result = access_atomic_cmpxchg_at(IN_HEAP, as_BasicType(type),
+                                            obj, offset, cmp, val);
+  set_result(x, result);
 }
 
-void LIRGenerator::G1BarrierSet_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
-  // If the "new_val" is a constant NULL, no barrier is necessary.
-  if (new_val->is_constant() &&
-      new_val->as_constant_ptr()->as_jobject() == NULL) return;
-
-  if (!new_val->is_register()) {
-    LIR_Opr new_val_reg = new_register(T_OBJECT);
-    if (new_val->is_constant()) {
-      __ move(new_val, new_val_reg);
-    } else {
-      __ leal(new_val, new_val_reg);
-    }
-    new_val = new_val_reg;
-  }
-  assert(new_val->is_register(), "must be a register at this point");
-
-  if (addr->is_address()) {
-    LIR_Address* address = addr->as_address_ptr();
-    LIR_Opr ptr = new_pointer_register();
-    if (!address->index()->is_valid() && address->disp() == 0) {
-      __ move(address->base(), ptr);
-    } else {
-      assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
-      __ leal(addr, ptr);
-    }
-    addr = ptr;
-  }
-  assert(addr->is_register(), "must be a register at this point");
-
-  LIR_Opr xor_res = new_pointer_register();
-  LIR_Opr xor_shift_res = new_pointer_register();
-  if (TwoOperandLIRForm ) {
-    __ move(addr, xor_res);
-    __ logical_xor(xor_res, new_val, xor_res);
-    __ move(xor_res, xor_shift_res);
-    __ unsigned_shift_right(xor_shift_res,
-                            LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
-                            xor_shift_res,
-                            LIR_OprDesc::illegalOpr());
-  } else {
-    __ logical_xor(addr, new_val, xor_res);
-    __ unsigned_shift_right(xor_res,
-                            LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
-                            xor_shift_res,
-                            LIR_OprDesc::illegalOpr());
-  }
-
-  if (!new_val->is_register()) {
-    LIR_Opr new_val_reg = new_register(T_OBJECT);
-    __ leal(new_val, new_val_reg);
-    new_val = new_val_reg;
-  }
-  assert(new_val->is_register(), "must be a register at this point");
-
-  __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD));
-
-  CodeStub* slow = new G1PostBarrierStub(addr, new_val);
-  __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow);
-  __ branch_destination(slow->continuation());
-}
-
-#endif // INCLUDE_ALL_GCS
-////////////////////////////////////////////////////////////////////////
-
-void LIRGenerator::CardTableBarrierSet_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) {
-  LIR_Const* card_table_base = new LIR_Const(ci_card_table_address());
-  if (addr->is_address()) {
-    LIR_Address* address = addr->as_address_ptr();
-    // ptr cannot be an object because we use this barrier for array card marks
-    // and addr can point in the middle of an array.
-    LIR_Opr ptr = new_pointer_register();
-    if (!address->index()->is_valid() && address->disp() == 0) {
-      __ move(address->base(), ptr);
-    } else {
-      assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
-      __ leal(addr, ptr);
-    }
-    addr = ptr;
-  }
-  assert(addr->is_register(), "must be a register at this point");
-
-#ifdef CARDTABLEBARRIERSET_POST_BARRIER_HELPER
-  CardTableBarrierSet_post_barrier_helper(addr, card_table_base);
-#else
-  LIR_Opr tmp = new_pointer_register();
-  if (TwoOperandLIRForm) {
-    __ move(addr, tmp);
-    __ unsigned_shift_right(tmp, CardTable::card_shift, tmp);
-  } else {
-    __ unsigned_shift_right(addr, CardTable::card_shift, tmp);
-  }
-
-  LIR_Address* card_addr;
-  if (can_inline_as_constant(card_table_base)) {
-    card_addr = new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE);
-  } else {
-    card_addr = new LIR_Address(tmp, load_constant(card_table_base), T_BYTE);
-  }
-
-  LIR_Opr dirty = LIR_OprFact::intConst(CardTable::dirty_card_val());
-  if (UseCondCardMark) {
-    LIR_Opr cur_value = new_register(T_INT);
-    if (UseConcMarkSweepGC) {
-      __ membar_storeload();
-    }
-    __ move(card_addr, cur_value);
-
-    LabelObj* L_already_dirty = new LabelObj();
-    __ cmp(lir_cond_equal, cur_value, dirty);
-    __ branch(lir_cond_equal, T_BYTE, L_already_dirty->label());
-    __ 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
-}
-
-
-//------------------------field access--------------------------------------
-
 // Comment copied form templateTable_i486.cpp
 // ----------------------------------------------------------------------------
 // Volatile variables demand their effects be made known to all CPU's in
@@ -1702,7 +1487,6 @@
   bool needs_patching = x->needs_patching();
   bool is_volatile = x->field()->is_volatile();
   BasicType field_type = x->field_type();
-  bool is_oop = (field_type == T_ARRAY || field_type == T_OBJECT);
 
   CodeEmitInfo* info = NULL;
   if (needs_patching) {
@@ -1717,7 +1501,6 @@
     }
   }
 
-
   LIRItem object(x->obj(), this);
   LIRItem value(x->value(),  this);
 
@@ -1755,48 +1538,147 @@
     __ null_check(object.result(), new CodeEmitInfo(info), /* deoptimize */ needs_patching);
   }
 
-  LIR_Address* address;
+  DecoratorSet decorators = IN_HEAP;
+  if (is_volatile) {
+    decorators |= MO_SEQ_CST;
+  }
   if (needs_patching) {
-    // we need to patch the offset in the instruction so don't allow
-    // generate_address to try to be smart about emitting the -1.
-    // Otherwise the patching code won't know how to find the
-    // instruction to patch.
-    address = new LIR_Address(object.result(), PATCHED_ADDR, field_type);
+    decorators |= C1_NEEDS_PATCHING;
+  }
+
+  access_store_at(decorators, field_type, object, LIR_OprFact::intConst(x->offset()),
+                  value.result(), info != NULL ? new CodeEmitInfo(info) : NULL, info);
+}
+
+void LIRGenerator::do_StoreIndexed(StoreIndexed* x) {
+  assert(x->is_pinned(),"");
+  bool needs_range_check = x->compute_needs_range_check();
+  bool use_length = x->length() != NULL;
+  bool obj_store = x->elt_type() == T_ARRAY || x->elt_type() == T_OBJECT;
+  bool needs_store_check = obj_store && (x->value()->as_Constant() == NULL ||
+                                         !get_jobject_constant(x->value())->is_null_object() ||
+                                         x->should_profile());
+
+  LIRItem array(x->array(), this);
+  LIRItem index(x->index(), this);
+  LIRItem value(x->value(), this);
+  LIRItem length(this);
+
+  array.load_item();
+  index.load_nonconstant();
+
+  if (use_length && needs_range_check) {
+    length.set_instruction(x->length());
+    length.load_item();
+
+  }
+  if (needs_store_check || x->check_boolean()) {
+    value.load_item();
   } else {
-    address = generate_address(object.result(), x->offset(), field_type);
-  }
-
-  if (is_volatile && os::is_MP()) {
-    __ membar_release();
+    value.load_for_store(x->elt_type());
   }
 
-  if (is_oop) {
-    // Do the pre-write barrier, if any.
-    pre_barrier(LIR_OprFact::address(address),
-                LIR_OprFact::illegalOpr /* pre_val */,
-                true /* do_load*/,
-                needs_patching,
-                (info ? new CodeEmitInfo(info) : NULL));
+  set_no_result(x);
+
+  // the CodeEmitInfo must be duplicated for each different
+  // LIR-instruction because spilling can occur anywhere between two
+  // instructions and so the debug information must be different
+  CodeEmitInfo* range_check_info = state_for(x);
+  CodeEmitInfo* null_check_info = NULL;
+  if (x->needs_null_check()) {
+    null_check_info = new CodeEmitInfo(range_check_info);
+  }
+
+  if (GenerateRangeChecks && needs_range_check) {
+    if (use_length) {
+      __ cmp(lir_cond_belowEqual, length.result(), index.result());
+      __ branch(lir_cond_belowEqual, T_INT, new RangeCheckStub(range_check_info, index.result()));
+    } else {
+      array_range_check(array.result(), index.result(), null_check_info, range_check_info);
+      // range_check also does the null check
+      null_check_info = NULL;
+    }
   }
 
-  bool needs_atomic_access = is_volatile || AlwaysAtomicAccesses;
-  if (needs_atomic_access && !needs_patching) {
-    volatile_field_store(value.result(), address, info);
-  } else {
-    LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
-    __ store(value.result(), address, info, patch_code);
+  if (GenerateArrayStoreCheck && needs_store_check) {
+    CodeEmitInfo* store_check_info = new CodeEmitInfo(range_check_info);
+    array_store_check(value.result(), array.result(), store_check_info, x->profiled_method(), x->profiled_bci());
+  }
+
+  DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+  if (x->check_boolean()) {
+    decorators |= C1_MASK_BOOLEAN;
   }
 
-  if (is_oop) {
-    // Store to object so mark the card of the header
-    post_barrier(object.result(), value.result());
-  }
-
-  if (!support_IRIW_for_not_multiple_copy_atomic_cpu && is_volatile && os::is_MP()) {
-    __ membar();
+  access_store_at(decorators, x->elt_type(), array, index.result(), value.result(),
+                  NULL, null_check_info);
+}
+
+void LIRGenerator::access_load_at(DecoratorSet decorators, BasicType type,
+                                  LIRItem& base, LIR_Opr offset, LIR_Opr result,
+                                  CodeEmitInfo* patch_info, CodeEmitInfo* load_emit_info) {
+  decorators |= C1_READ_ACCESS;
+  LIRAccess access(this, decorators, base, offset, type, patch_info, load_emit_info);
+  if (access.is_raw()) {
+    _barrier_set->BarrierSetC1::load_at(access, result);
+  } else {
+    _barrier_set->load_at(access, result);
   }
 }
 
+void LIRGenerator::access_store_at(DecoratorSet decorators, BasicType type,
+                                   LIRItem& base, LIR_Opr offset, LIR_Opr value,
+                                   CodeEmitInfo* patch_info, CodeEmitInfo* store_emit_info) {
+  decorators |= C1_WRITE_ACCESS;
+  LIRAccess access(this, decorators, base, offset, type, patch_info, store_emit_info);
+  if (access.is_raw()) {
+    _barrier_set->BarrierSetC1::store_at(access, value);
+  } else {
+    _barrier_set->store_at(access, value);
+  }
+}
+
+LIR_Opr LIRGenerator::access_atomic_cmpxchg_at(DecoratorSet decorators, BasicType type,
+                                               LIRItem& base, LIRItem& offset, LIRItem& cmp_value, LIRItem& new_value) {
+  // Atomic operations are SEQ_CST by default
+  decorators |= C1_READ_ACCESS;
+  decorators |= C1_WRITE_ACCESS;
+  decorators |= ((decorators & MO_DECORATOR_MASK) != 0) ? MO_SEQ_CST : 0;
+  LIRAccess access(this, decorators, base, offset, type);
+  if (access.is_raw()) {
+    return _barrier_set->BarrierSetC1::atomic_cmpxchg_at(access, cmp_value, new_value);
+  } else {
+    return _barrier_set->atomic_cmpxchg_at(access, cmp_value, new_value);
+  }
+}
+
+LIR_Opr LIRGenerator::access_atomic_xchg_at(DecoratorSet decorators, BasicType type,
+                                            LIRItem& base, LIRItem& offset, LIRItem& value) {
+  // Atomic operations are SEQ_CST by default
+  decorators |= C1_READ_ACCESS;
+  decorators |= C1_WRITE_ACCESS;
+  decorators |= ((decorators & MO_DECORATOR_MASK) != 0) ? MO_SEQ_CST : 0;
+  LIRAccess access(this, decorators, base, offset, type);
+  if (access.is_raw()) {
+    return _barrier_set->BarrierSetC1::atomic_xchg_at(access, value);
+  } else {
+    return _barrier_set->atomic_xchg_at(access, value);
+  }
+}
+
+LIR_Opr LIRGenerator::access_atomic_add_at(DecoratorSet decorators, BasicType type,
+                                           LIRItem& base, LIRItem& offset, LIRItem& value) {
+  // Atomic operations are SEQ_CST by default
+  decorators |= C1_READ_ACCESS;
+  decorators |= C1_WRITE_ACCESS;
+  decorators |= ((decorators & MO_DECORATOR_MASK) != 0) ? MO_SEQ_CST : 0;
+  LIRAccess access(this, decorators, base, offset, type);
+  if (access.is_raw()) {
+    return _barrier_set->BarrierSetC1::atomic_add_at(access, value);
+  } else {
+    return _barrier_set->atomic_add_at(access, value);
+  }
+}
 
 void LIRGenerator::do_LoadField(LoadField* x) {
   bool needs_patching = x->needs_patching();
@@ -1843,33 +1725,18 @@
     __ null_check(obj, new CodeEmitInfo(info), /* deoptimize */ needs_patching);
   }
 
-  LIR_Opr reg = rlock_result(x, field_type);
-  LIR_Address* address;
-  if (needs_patching) {
-    // we need to patch the offset in the instruction so don't allow
-    // generate_address to try to be smart about emitting the -1.
-    // Otherwise the patching code won't know how to find the
-    // instruction to patch.
-    address = new LIR_Address(object.result(), PATCHED_ADDR, field_type);
-  } else {
-    address = generate_address(object.result(), x->offset(), field_type);
+  DecoratorSet decorators = IN_HEAP;
+  if (is_volatile) {
+    decorators |= MO_SEQ_CST;
   }
-
-  if (support_IRIW_for_not_multiple_copy_atomic_cpu && is_volatile && os::is_MP()) {
-    __ membar();
+  if (needs_patching) {
+    decorators |= C1_NEEDS_PATCHING;
   }
 
-  bool needs_atomic_access = is_volatile || AlwaysAtomicAccesses;
-  if (needs_atomic_access && !needs_patching) {
-    volatile_field_load(address, reg, info);
-  } else {
-    LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
-    __ load(address, reg, info, patch_code);
-  }
-
-  if (is_volatile && os::is_MP()) {
-    __ membar_acquire();
-  }
+  LIR_Opr result = rlock_result(x, field_type);
+  access_load_at(decorators, field_type,
+                 object, LIR_OprFact::intConst(x->offset()), result,
+                 info ? new CodeEmitInfo(info) : NULL, info);
 }
 
 
@@ -1968,9 +1835,6 @@
     }
   }
 
-  // emit array address setup early so it schedules better
-  LIR_Address* array_addr = emit_array_address(array.result(), index.result(), x->elt_type(), false);
-
   if (GenerateRangeChecks && needs_range_check) {
     if (StressLoopInvariantCodeMotion && range_check_info->deoptimize_on_exception()) {
       __ branch(lir_cond_always, T_ILLEGAL, new RangeCheckStub(range_check_info, index.result()));
@@ -1986,7 +1850,12 @@
     }
   }
 
-  __ move(array_addr, rlock_result(x, x->elt_type()), null_check_info);
+  DecoratorSet decorators = IN_HEAP | IN_HEAP_ARRAY;
+
+  LIR_Opr result = rlock_result(x, x->elt_type());
+  access_load_at(decorators, x->elt_type(),
+                 array, index.result(), result,
+                 NULL, null_check_info);
 }
 
 
@@ -2272,157 +2141,21 @@
   off.load_item();
   src.load_item();
 
-  LIR_Opr value = rlock_result(x, x->basic_type());
-
-  if (support_IRIW_for_not_multiple_copy_atomic_cpu && x->is_volatile() && os::is_MP()) {
-    __ membar();
+  DecoratorSet decorators = IN_HEAP;
+
+  if (x->is_volatile()) {
+    decorators |= MO_SEQ_CST;
+  }
+  if (type == T_BOOLEAN) {
+    decorators |= C1_MASK_BOOLEAN;
   }
-
-  get_Object_unsafe(value, src.result(), off.result(), type, x->is_volatile());
-
-#if INCLUDE_ALL_GCS
-  // We might be reading the value of the referent field of a
-  // Reference object in order to attach it back to the live
-  // object graph. If G1 is enabled then we need to record
-  // the value that is being returned in an SATB log buffer.
-  //
-  // We need to generate code similar to the following...
-  //
-  // if (offset == java_lang_ref_Reference::referent_offset) {
-  //   if (src != NULL) {
-  //     if (klass(src)->reference_type() != REF_NONE) {
-  //       pre_barrier(..., value, ...);
-  //     }
-  //   }
-  // }
-
-  if (UseG1GC && type == T_OBJECT) {
-    bool gen_pre_barrier = true;     // Assume we need to generate pre_barrier.
-    bool gen_offset_check = true;    // Assume we need to generate the offset guard.
-    bool gen_source_check = true;    // Assume we need to check the src object for null.
-    bool gen_type_check = true;      // Assume we need to check the reference_type.
-
-    if (off.is_constant()) {
-      jlong off_con = (off.type()->is_int() ?
-                        (jlong) off.get_jint_constant() :
-                        off.get_jlong_constant());
-
-
-      if (off_con != (jlong) java_lang_ref_Reference::referent_offset) {
-        // The constant offset is something other than referent_offset.
-        // We can skip generating/checking the remaining guards and
-        // skip generation of the code stub.
-        gen_pre_barrier = false;
-      } else {
-        // The constant offset is the same as referent_offset -
-        // we do not need to generate a runtime offset check.
-        gen_offset_check = false;
-      }
-    }
-
-    // We don't need to generate stub if the source object is an array
-    if (gen_pre_barrier && src.type()->is_array()) {
-      gen_pre_barrier = false;
-    }
-
-    if (gen_pre_barrier) {
-      // We still need to continue with the checks.
-      if (src.is_constant()) {
-        ciObject* src_con = src.get_jobject_constant();
-        guarantee(src_con != NULL, "no source constant");
-
-        if (src_con->is_null_object()) {
-          // The constant src object is null - We can skip
-          // generating the code stub.
-          gen_pre_barrier = false;
-        } else {
-          // Non-null constant source object. We still have to generate
-          // the slow stub - but we don't need to generate the runtime
-          // null object check.
-          gen_source_check = false;
-        }
-      }
-    }
-    if (gen_pre_barrier && !PatchALot) {
-      // Can the klass of object be statically determined to be
-      // a sub-class of Reference?
-      ciType* type = src.value()->declared_type();
-      if ((type != NULL) && type->is_loaded()) {
-        if (type->is_subtype_of(compilation()->env()->Reference_klass())) {
-          gen_type_check = false;
-        } else if (type->is_klass() &&
-                   !compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) {
-          // Not Reference and not Object klass.
-          gen_pre_barrier = false;
-        }
-      }
-    }
-
-    if (gen_pre_barrier) {
-      LabelObj* Lcont = new LabelObj();
-
-      // We can have generate one runtime check here. Let's start with
-      // the offset check.
-      if (gen_offset_check) {
-        // if (offset != referent_offset) -> continue
-        // If offset is an int then we can do the comparison with the
-        // referent_offset constant; otherwise we need to move
-        // referent_offset into a temporary register and generate
-        // a reg-reg compare.
-
-        LIR_Opr referent_off;
-
-        if (off.type()->is_int()) {
-          referent_off = LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset);
-        } else {
-          assert(off.type()->is_long(), "what else?");
-          referent_off = new_register(T_LONG);
-          __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off);
-        }
-        __ cmp(lir_cond_notEqual, off.result(), referent_off);
-        __ branch(lir_cond_notEqual, as_BasicType(off.type()), Lcont->label());
-      }
-      if (gen_source_check) {
-        // offset is a const and equals referent offset
-        // if (source == null) -> continue
-        __ cmp(lir_cond_equal, src.result(), LIR_OprFact::oopConst(NULL));
-        __ branch(lir_cond_equal, T_OBJECT, Lcont->label());
-      }
-      LIR_Opr src_klass = new_register(T_OBJECT);
-      if (gen_type_check) {
-        // We have determined that offset == referent_offset && src != null.
-        // if (src->_klass->_reference_type == REF_NONE) -> continue
-        __ move(new LIR_Address(src.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
-        LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
-        LIR_Opr reference_type = new_register(T_INT);
-        __ move(reference_type_addr, reference_type);
-        __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE));
-        __ branch(lir_cond_equal, T_INT, Lcont->label());
-      }
-      {
-        // We have determined that src->_klass->_reference_type != REF_NONE
-        // so register the value in the referent field with the pre-barrier.
-        pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */,
-                    value  /* pre_val */,
-                    false  /* do_load */,
-                    false  /* patch */,
-                    NULL   /* info */);
-      }
-      __ branch_destination(Lcont->label());
-    }
+  if (type == T_ARRAY || type == T_OBJECT) {
+    decorators |= ON_UNKNOWN_OOP_REF;
   }
-#endif // INCLUDE_ALL_GCS
-
-  if (x->is_volatile() && os::is_MP()) __ membar_acquire();
-
-  /* Normalize boolean value returned by unsafe operation, i.e., value  != 0 ? value = true : value false. */
-  if (type == T_BOOLEAN) {
-    LabelObj* equalZeroLabel = new LabelObj();
-    __ cmp(lir_cond_equal, value, 0);
-    __ branch(lir_cond_equal, T_BOOLEAN, equalZeroLabel->label());
-    __ move(LIR_OprFact::intConst(1), value);
-    __ branch_destination(equalZeroLabel->label());
-  }
+
+  LIR_Opr result = rlock_result(x, type);
+  access_load_at(decorators, type,
+                 src, off.result(), result);
 }
 
 
@@ -2442,11 +2175,36 @@
 
   set_no_result(x);
 
-  if (x->is_volatile() && os::is_MP()) __ membar_release();
-  put_Object_unsafe(src.result(), off.result(), data.result(), type, x->is_volatile());
-  if (!support_IRIW_for_not_multiple_copy_atomic_cpu && x->is_volatile() && os::is_MP()) __ membar();
+  DecoratorSet decorators = IN_HEAP;
+  if (type == T_ARRAY || type == T_OBJECT) {
+    decorators |= ON_UNKNOWN_OOP_REF;
+  }
+  if (x->is_volatile()) {
+    decorators |= MO_SEQ_CST;
+  }
+  access_store_at(decorators, type, src, off.result(), data.result());
 }
 
+void LIRGenerator::do_UnsafeGetAndSetObject(UnsafeGetAndSetObject* x) {
+  BasicType type = x->basic_type();
+  LIRItem src(x->object(), this);
+  LIRItem off(x->offset(), this);
+  LIRItem value(x->value(), this);
+
+  DecoratorSet decorators = IN_HEAP | MO_SEQ_CST;
+
+  if (type == T_ARRAY || type == T_OBJECT) {
+    decorators |= ON_UNKNOWN_OOP_REF;
+  }
+
+  LIR_Opr result;
+  if (x->is_add()) {
+    result = access_atomic_add_at(decorators, type, src, off, value);
+  } else {
+    result = access_atomic_xchg_at(decorators, type, src, off, value);
+  }
+  set_result(x, result);
+}
 
 void LIRGenerator::do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux) {
   int lng = x->length();
@@ -3826,25 +3584,30 @@
   }
 }
 
+LIR_Opr LIRGenerator::mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) {
+  LIR_Opr value_fixed = rlock_byte(T_BYTE);
+  if (TwoOperandLIRForm) {
+    __ move(value, value_fixed);
+    __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed);
+  } else {
+    __ logical_and(value, LIR_OprFact::intConst(1), value_fixed);
+  }
+  LIR_Opr klass = new_register(T_METADATA);
+  __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info);
+  null_check_info = NULL;
+  LIR_Opr layout = new_register(T_INT);
+  __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);
+  int diffbit = Klass::layout_helper_boolean_diffbit();
+  __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout);
+  __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0));
+  __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE);
+  value = value_fixed;
+  return value;
+}
+
 LIR_Opr LIRGenerator::maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info) {
   if (x->check_boolean()) {
-    LIR_Opr value_fixed = rlock_byte(T_BYTE);
-    if (TwoOperandLIRForm) {
-      __ move(value, value_fixed);
-      __ logical_and(value_fixed, LIR_OprFact::intConst(1), value_fixed);
-    } else {
-      __ logical_and(value, LIR_OprFact::intConst(1), value_fixed);
-    }
-    LIR_Opr klass = new_register(T_METADATA);
-    __ move(new LIR_Address(array, oopDesc::klass_offset_in_bytes(), T_ADDRESS), klass, null_check_info);
-    null_check_info = NULL;
-    LIR_Opr layout = new_register(T_INT);
-    __ move(new LIR_Address(klass, in_bytes(Klass::layout_helper_offset()), T_INT), layout);
-    int diffbit = Klass::layout_helper_boolean_diffbit();
-    __ logical_and(layout, LIR_OprFact::intConst(diffbit), layout);
-    __ cmp(lir_cond_notEqual, layout, LIR_OprFact::intConst(0));
-    __ cmove(lir_cond_notEqual, value_fixed, value, value_fixed, T_BYTE);
-    value = value_fixed;
+    value = mask_boolean(array, value, null_check_info);
   }
   return value;
 }
--- a/src/hotspot/share/c1/c1_LIRGenerator.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -25,12 +25,16 @@
 #ifndef SHARE_VM_C1_C1_LIRGENERATOR_HPP
 #define SHARE_VM_C1_C1_LIRGENERATOR_HPP
 
+#include "c1/c1_Decorators.hpp"
 #include "c1/c1_Instruction.hpp"
 #include "c1/c1_LIR.hpp"
 #include "ci/ciMethodData.hpp"
+#include "gc/shared/barrierSet.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/sizes.hpp"
 
+class BarrierSetC1;
+
 // The classes responsible for code emission and register allocation
 
 
@@ -165,7 +169,6 @@
   Values        _instruction_for_operand;
   BitMap2D      _vreg_flags; // flags which can be set on a per-vreg basis
   LIR_List*     _lir;
-  BarrierSet*   _bs;
 
   LIRGenerator* gen() {
     return this;
@@ -173,6 +176,7 @@
 
   void print_if_not_loaded(const NewInstance* new_instance) PRODUCT_RETURN;
 
+ public:
 #ifdef ASSERT
   LIR_List* lir(const char * file, int line) const {
     _lir->set_file_and_line(file, line);
@@ -183,6 +187,7 @@
     return _lir;
   }
 
+ private:
   // a simple cache of constants used within a block
   GrowableArray<LIR_Const*>       _constants;
   LIR_OprList                     _reg_for_constants;
@@ -190,6 +195,7 @@
 
   friend class PhiResolver;
 
+ public:
   // unified bailout support
   void bailout(const char* msg) const            { compilation()->bailout(msg); }
   bool bailed_out() const                        { return compilation()->bailed_out(); }
@@ -233,14 +239,15 @@
   void  move_to_phi(PhiResolver* resolver, Value cur_val, Value sux_val);
   void  move_to_phi(ValueStack* cur_state);
 
-  // code emission
-  void do_ArithmeticOp_Long   (ArithmeticOp*    x);
-  void do_ArithmeticOp_Int    (ArithmeticOp*    x);
-  void do_ArithmeticOp_FPU    (ArithmeticOp*    x);
-
   // platform dependent
   LIR_Opr getThreadPointer();
 
+ private:
+  // code emission
+  void do_ArithmeticOp_Long(ArithmeticOp* x);
+  void do_ArithmeticOp_Int (ArithmeticOp* x);
+  void do_ArithmeticOp_FPU (ArithmeticOp* x);
+
   void do_RegisterFinalizer(Intrinsic* x);
   void do_isInstance(Intrinsic* x);
   void do_isPrimitive(Intrinsic* x);
@@ -258,6 +265,7 @@
   void do_update_CRC32C(Intrinsic* x);
   void do_vectorizedMismatch(Intrinsic* x);
 
+ public:
   LIR_Opr call_runtime(BasicTypeArray* signature, LIRItemList* args, address entry, ValueType* result_type, CodeEmitInfo* info);
   LIR_Opr call_runtime(BasicTypeArray* signature, LIR_OprList* args, address entry, ValueType* result_type, CodeEmitInfo* info);
 
@@ -265,27 +273,37 @@
   LIR_Opr call_runtime(Value arg1, address entry, ValueType* result_type, CodeEmitInfo* info);
   LIR_Opr call_runtime(Value arg1, Value arg2, address entry, ValueType* result_type, CodeEmitInfo* info);
 
-  // GC Barriers
+  // Access API
+
+ private:
+  BarrierSetC1 *_barrier_set;
+
+ public:
+  void access_store_at(DecoratorSet decorators, BasicType type,
+                       LIRItem& base, LIR_Opr offset, LIR_Opr value,
+                       CodeEmitInfo* patch_info = NULL, CodeEmitInfo* store_emit_info = NULL);
+
+  void access_load_at(DecoratorSet decorators, BasicType type,
+                      LIRItem& base, LIR_Opr offset, LIR_Opr result,
+                      CodeEmitInfo* patch_info = NULL, CodeEmitInfo* load_emit_info = NULL);
 
-  // generic interface
+  LIR_Opr access_atomic_cmpxchg_at(DecoratorSet decorators, BasicType type,
+                                   LIRItem& base, LIRItem& offset, LIRItem& cmp_value, LIRItem& new_value);
+
+  LIR_Opr access_atomic_xchg_at(DecoratorSet decorators, BasicType type,
+                                LIRItem& base, LIRItem& offset, LIRItem& value);
 
-  void pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val, bool do_load, bool patch, CodeEmitInfo* info);
-  void post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val);
+  LIR_Opr access_atomic_add_at(DecoratorSet decorators, BasicType type,
+                               LIRItem& base, LIRItem& offset, LIRItem& value);
+
+  // These need to guarantee JMM volatile semantics are preserved on each platform
+  // and requires one implementation per architecture.
+  LIR_Opr atomic_cmpxchg(BasicType type, LIR_Opr addr, LIRItem& cmp_value, LIRItem& new_value);
+  LIR_Opr atomic_xchg(BasicType type, LIR_Opr addr, LIRItem& new_value);
+  LIR_Opr atomic_add(BasicType type, LIR_Opr addr, LIRItem& new_value);
 
   // specific implementations
-  // pre barriers
-
-  void G1BarrierSet_pre_barrier(LIR_Opr addr_opr, LIR_Opr pre_val,
-                                bool do_load, bool patch, CodeEmitInfo* info);
-
-  // post barriers
-
-  void G1BarrierSet_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val);
-  void CardTableBarrierSet_post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val);
-#ifdef CARDTABLEBARRIERSET_POST_BARRIER_HELPER
-  void CardTableBarrierSet_post_barrier_helper(LIR_OprDesc* addr, LIR_Const* card_table_base);
-#endif
-
+  void array_store_check(LIR_Opr value, LIR_Opr array, CodeEmitInfo* store_check_info, ciMethod* profiled_method, int profiled_bci);
 
   static LIR_Opr result_register_for(ValueType* type, bool callee = false);
 
@@ -354,7 +372,7 @@
   LIR_Address* generate_address(LIR_Opr base, int disp, BasicType type) {
     return generate_address(base, LIR_OprFact::illegalOpr, 0, disp, type);
   }
-  LIR_Address* emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr, BasicType type, bool needs_card_mark);
+  LIR_Address* emit_array_address(LIR_Opr array_opr, LIR_Opr index_opr, BasicType type);
 
   // the helper for generate_address
   void add_large_constant(LIR_Opr src, int c, LIR_Opr dest);
@@ -433,8 +451,6 @@
   void do_soft_float_compare(If *x);
 #endif // __SOFTFP__
 
-  void init();
-
   SwitchRangeArray* create_lookup_ranges(TableSwitch* x);
   SwitchRangeArray* create_lookup_ranges(LookupSwitch* x);
   void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux);
@@ -452,6 +468,7 @@
   void profile_arguments(ProfileCall* x);
   void profile_parameters(Base* x);
   void profile_parameters_at_call(ProfileCall* x);
+  LIR_Opr mask_boolean(LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info);
   LIR_Opr maybe_mask_boolean(StoreIndexed* x, LIR_Opr array, LIR_Opr value, CodeEmitInfo*& null_check_info);
 
  public:
@@ -478,8 +495,8 @@
     : _compilation(compilation)
     , _method(method)
     , _virtual_register_number(LIR_OprDesc::vreg_base)
-    , _vreg_flags(num_vreg_flags) {
-    init();
+    , _vreg_flags(num_vreg_flags)
+    , _barrier_set(BarrierSet::barrier_set()->barrier_set_c1()) {
   }
 
   // for virtual registers, maps them back to Phi's or Local's
--- a/src/hotspot/share/c1/c1_MacroAssembler.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_MacroAssembler.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -74,6 +74,9 @@
   void set_frame_size(int size);
   void set_num_rt_args(int args);
 
+  void save_live_registers();
+  void restore_live_registers_without_return();
+
   // accessors
   const char* name() const                       { return _name; }
   bool  must_gc_arguments() const                { return _must_gc_arguments; }
@@ -86,6 +89,9 @@
   int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1);
   int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2);
   int call_RT(Register oop_result1, Register metadata_result, address entry, Register arg1, Register arg2, Register arg3);
+
+  void prologue(const char* name, bool must_gc_arguments);
+  void epilogue();
 };
 
 #endif // SHARE_VM_C1_C1_MACROASSEMBLER_HPP
--- a/src/hotspot/share/c1/c1_Runtime1.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_Runtime1.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -39,6 +39,7 @@
 #include "code/vtableStubs.hpp"
 #include "compiler/disassembler.hpp"
 #include "gc/shared/barrierSet.hpp"
+#include "gc/shared/c1/barrierSetC1.hpp"
 #include "gc/shared/collectedHeap.hpp"
 #include "interpreter/bytecode.hpp"
 #include "interpreter/interpreter.hpp"
@@ -178,9 +179,17 @@
   }
 }
 
+class StubIDStubAssemblerCodeGenClosure: public StubAssemblerCodeGenClosure {
+ private:
+  Runtime1::StubID _id;
+ public:
+  StubIDStubAssemblerCodeGenClosure(Runtime1::StubID id) : _id(id) {}
+  virtual OopMapSet* generate_code(StubAssembler* sasm) {
+    return Runtime1::generate_code_for(_id, sasm);
+  }
+};
 
-void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
-  assert(0 <= id && id < number_of_ids, "illegal stub id");
+CodeBlob* Runtime1::generate_blob(BufferBlob* buffer_blob, int stub_id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure* cl) {
   ResourceMark rm;
   // create code buffer for code storage
   CodeBuffer code(buffer_blob);
@@ -192,33 +201,12 @@
   Compilation::setup_code_buffer(&code, 0);
 
   // create assembler for code generation
-  StubAssembler* sasm = new StubAssembler(&code, name_for(id), id);
+  StubAssembler* sasm = new StubAssembler(&code, name, stub_id);
   // generate code for runtime stub
-  oop_maps = generate_code_for(id, sasm);
+  oop_maps = cl->generate_code(sasm);
   assert(oop_maps == NULL || sasm->frame_size() != no_frame_size,
          "if stub has an oop map it must have a valid frame size");
-
-#ifdef ASSERT
-  // Make sure that stubs that need oopmaps have them
-  switch (id) {
-    // These stubs don't need to have an oopmap
-  case dtrace_object_alloc_id:
-  case g1_pre_barrier_slow_id:
-  case g1_post_barrier_slow_id:
-  case slow_subtype_check_id:
-  case fpu2long_stub_id:
-  case unwind_exception_id:
-  case counter_overflow_id:
-#if defined(SPARC) || defined(PPC32)
-  case handle_exception_nofpu_id:  // Unused on sparc
-#endif
-    break;
-
-    // All other stubs should have oopmaps
-  default:
-    assert(oop_maps != NULL, "must have an oopmap");
-  }
-#endif
+  assert(!expect_oop_map || oop_maps != NULL, "must have an oopmap");
 
   // align so printing shows nop's instead of random code at the end (SimpleStubs are aligned)
   sasm->align(BytesPerWord);
@@ -228,18 +216,43 @@
   frame_size = sasm->frame_size();
   must_gc_arguments = sasm->must_gc_arguments();
   // create blob - distinguish a few special cases
-  CodeBlob* blob = RuntimeStub::new_runtime_stub(name_for(id),
+  CodeBlob* blob = RuntimeStub::new_runtime_stub(name,
                                                  &code,
                                                  CodeOffsets::frame_never_safe,
                                                  frame_size,
                                                  oop_maps,
                                                  must_gc_arguments);
+  assert(blob != NULL, "blob must exist");
+  return blob;
+}
+
+void Runtime1::generate_blob_for(BufferBlob* buffer_blob, StubID id) {
+  assert(0 <= id && id < number_of_ids, "illegal stub id");
+  bool expect_oop_map = true;
+#ifdef ASSERT
+  // Make sure that stubs that need oopmaps have them
+  switch (id) {
+    // These stubs don't need to have an oopmap
+  case dtrace_object_alloc_id:
+  case slow_subtype_check_id:
+  case fpu2long_stub_id:
+  case unwind_exception_id:
+  case counter_overflow_id:
+#if defined(SPARC) || defined(PPC32)
+  case handle_exception_nofpu_id:  // Unused on sparc
+#endif
+    expect_oop_map = false;
+    break;
+  default:
+    break;
+  }
+#endif
+  StubIDStubAssemblerCodeGenClosure cl(id);
+  CodeBlob* blob = generate_blob(buffer_blob, id, name_for(id), expect_oop_map, &cl);
   // install blob
-  assert(blob != NULL, "blob must exist");
   _blobs[id] = blob;
 }
 
-
 void Runtime1::initialize(BufferBlob* blob) {
   // platform-dependent initialization
   initialize_pd();
@@ -257,9 +270,10 @@
     }
   }
 #endif
+  BarrierSetC1* bs = BarrierSet::barrier_set()->barrier_set_c1();
+  bs->generate_c1_runtime_stubs(blob);
 }
 
-
 CodeBlob* Runtime1::blob_for(StubID id) {
   assert(0 <= id && id < number_of_ids, "illegal stub id");
   return _blobs[id];
--- a/src/hotspot/share/c1/c1_Runtime1.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/c1/c1_Runtime1.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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,8 +68,6 @@
   stub(load_klass_patching)          \
   stub(load_mirror_patching)         \
   stub(load_appendix_patching)       \
-  stub(g1_pre_barrier_slow)          \
-  stub(g1_post_barrier_slow)         \
   stub(fpu2long_stub)                \
   stub(counter_overflow)             \
   stub(predicate_failed_trap)        \
@@ -80,6 +78,11 @@
 #define STUB_NAME(x)             #x " Runtime1 stub",
 #define LAST_STUB_NAME(x)        #x " Runtime1 stub"
 
+class StubAssemblerCodeGenClosure: public Closure {
+ public:
+  virtual OopMapSet* generate_code(StubAssembler* sasm) = 0;
+};
+
 class Runtime1: public AllStatic {
   friend class VMStructs;
   friend class ArrayCopyStub;
@@ -121,8 +124,11 @@
   static const char* _blob_names[];
 
   // stub generation
+ public:
+  static CodeBlob*  generate_blob(BufferBlob* buffer_blob, int stub_id, const char* name, bool expect_oop_map, StubAssemblerCodeGenClosure *cl);
   static void       generate_blob_for(BufferBlob* blob, StubID id);
   static OopMapSet* generate_code_for(StubID id, StubAssembler* sasm);
+ private:
   static OopMapSet* generate_exception_throw(StubAssembler* sasm, address target, bool has_argument);
   static OopMapSet* generate_handle_exception(StubID id, StubAssembler* sasm);
   static void       generate_unwind_exception(StubAssembler *sasm);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,230 @@
+/*
+ * 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 "c1/c1_LIRGenerator.hpp"
+#include "c1/c1_CodeStubs.hpp"
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#include "gc/g1/g1BarrierSet.hpp"
+#include "gc/g1/g1BarrierSetAssembler.hpp"
+#include "gc/g1/g1ThreadLocalData.hpp"
+#include "gc/g1/heapRegion.hpp"
+#include "utilities/macros.hpp"
+
+#ifdef ASSERT
+#define __ gen->lir(__FILE__, __LINE__)->
+#else
+#define __ gen->lir()->
+#endif
+
+void G1PreBarrierStub::emit_code(LIR_Assembler* ce) {
+  G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->gen_pre_barrier_stub(ce, this);
+}
+
+void G1PostBarrierStub::emit_code(LIR_Assembler* ce) {
+  G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
+  bs->gen_post_barrier_stub(ce, this);
+}
+
+void G1BarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr,
+                                 LIR_Opr pre_val, CodeEmitInfo* info) {
+  LIRGenerator* gen = access.gen();
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  bool in_conc_root = (decorators & IN_CONCURRENT_ROOT) != 0;
+  if (!in_heap && !in_conc_root) {
+    return;
+  }
+
+  // First we test whether marking is in progress.
+  BasicType flag_type;
+  bool patch = (decorators & C1_NEEDS_PATCHING) != 0;
+  bool do_load = pre_val == LIR_OprFact::illegalOpr;
+  if (in_bytes(SATBMarkQueue::byte_width_of_active()) == 4) {
+    flag_type = T_INT;
+  } else {
+    guarantee(in_bytes(SATBMarkQueue::byte_width_of_active()) == 1,
+              "Assumption");
+    // Use unsigned type T_BOOLEAN here rather than signed T_BYTE since some platforms, eg. ARM,
+    // need to use unsigned instructions to use the large offset to load the satb_mark_queue.
+    flag_type = T_BOOLEAN;
+  }
+  LIR_Opr thrd = gen->getThreadPointer();
+  LIR_Address* mark_active_flag_addr =
+    new LIR_Address(thrd,
+                    in_bytes(G1ThreadLocalData::satb_mark_queue_active_offset()),
+                    flag_type);
+  // Read the marking-in-progress flag.
+  LIR_Opr flag_val = gen->new_register(T_INT);
+  __ load(mark_active_flag_addr, flag_val);
+  __ cmp(lir_cond_notEqual, flag_val, LIR_OprFact::intConst(0));
+
+  LIR_PatchCode pre_val_patch_code = lir_patch_none;
+
+  CodeStub* slow;
+
+  if (do_load) {
+    assert(pre_val == LIR_OprFact::illegalOpr, "sanity");
+    assert(addr_opr != LIR_OprFact::illegalOpr, "sanity");
+
+    if (patch)
+      pre_val_patch_code = lir_patch_normal;
+
+    pre_val = gen->new_register(T_OBJECT);
+
+    if (!addr_opr->is_address()) {
+      assert(addr_opr->is_register(), "must be");
+      addr_opr = LIR_OprFact::address(new LIR_Address(addr_opr, T_OBJECT));
+    }
+    slow = new G1PreBarrierStub(addr_opr, pre_val, pre_val_patch_code, info);
+  } else {
+    assert(addr_opr == LIR_OprFact::illegalOpr, "sanity");
+    assert(pre_val->is_register(), "must be");
+    assert(pre_val->type() == T_OBJECT, "must be an object");
+    assert(info == NULL, "sanity");
+
+    slow = new G1PreBarrierStub(pre_val);
+  }
+
+  __ branch(lir_cond_notEqual, T_INT, slow);
+  __ branch_destination(slow->continuation());
+}
+
+void G1BarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprDesc* new_val) {
+  LIRGenerator* gen = access.gen();
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  if (!in_heap) {
+    return;
+  }
+
+  // If the "new_val" is a constant NULL, no barrier is necessary.
+  if (new_val->is_constant() &&
+      new_val->as_constant_ptr()->as_jobject() == NULL) return;
+
+  if (!new_val->is_register()) {
+    LIR_Opr new_val_reg = gen->new_register(T_OBJECT);
+    if (new_val->is_constant()) {
+      __ move(new_val, new_val_reg);
+    } else {
+      __ leal(new_val, new_val_reg);
+    }
+    new_val = new_val_reg;
+  }
+  assert(new_val->is_register(), "must be a register at this point");
+
+  if (addr->is_address()) {
+    LIR_Address* address = addr->as_address_ptr();
+    LIR_Opr ptr = gen->new_pointer_register();
+    if (!address->index()->is_valid() && address->disp() == 0) {
+      __ move(address->base(), ptr);
+    } else {
+      assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
+      __ leal(addr, ptr);
+    }
+    addr = ptr;
+  }
+  assert(addr->is_register(), "must be a register at this point");
+
+  LIR_Opr xor_res = gen->new_pointer_register();
+  LIR_Opr xor_shift_res = gen->new_pointer_register();
+  if (TwoOperandLIRForm) {
+    __ move(addr, xor_res);
+    __ logical_xor(xor_res, new_val, xor_res);
+    __ move(xor_res, xor_shift_res);
+    __ unsigned_shift_right(xor_shift_res,
+                            LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
+                            xor_shift_res,
+                            LIR_OprDesc::illegalOpr());
+  } else {
+    __ logical_xor(addr, new_val, xor_res);
+    __ unsigned_shift_right(xor_res,
+                            LIR_OprFact::intConst(HeapRegion::LogOfHRGrainBytes),
+                            xor_shift_res,
+                            LIR_OprDesc::illegalOpr());
+  }
+
+  if (!new_val->is_register()) {
+    LIR_Opr new_val_reg = gen->new_register(T_OBJECT);
+    __ leal(new_val, new_val_reg);
+    new_val = new_val_reg;
+  }
+  assert(new_val->is_register(), "must be a register at this point");
+
+  __ cmp(lir_cond_notEqual, xor_shift_res, LIR_OprFact::intptrConst(NULL_WORD));
+
+  CodeStub* slow = new G1PostBarrierStub(addr, new_val);
+  __ branch(lir_cond_notEqual, LP64_ONLY(T_LONG) NOT_LP64(T_INT), slow);
+  __ branch_destination(slow->continuation());
+}
+
+void G1BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
+  DecoratorSet decorators = access.decorators();
+  bool is_weak = (decorators & ON_WEAK_OOP_REF) != 0;
+  bool is_phantom = (decorators & ON_PHANTOM_OOP_REF) != 0;
+  bool is_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+  LIRGenerator *gen = access.gen();
+
+  BarrierSetC1::load_at_resolved(access, result);
+
+  if (access.is_oop() && (is_weak || is_phantom || is_anonymous)) {
+    // Register the value in the referent field with the pre-barrier
+    LabelObj *Lcont_anonymous;
+    if (is_anonymous) {
+      Lcont_anonymous = new LabelObj();
+      generate_referent_check(access, Lcont_anonymous);
+    }
+    pre_barrier(access, LIR_OprFact::illegalOpr /* addr_opr */,
+                result /* pre_val */, access.patch_emit_info() /* info */);
+    if (is_anonymous) {
+      __ branch_destination(Lcont_anonymous->label());
+    }
+  }
+}
+
+class C1G1PreBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
+  virtual OopMapSet* generate_code(StubAssembler* sasm) {
+    G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
+    bs->generate_c1_pre_barrier_runtime_stub(sasm);
+    return NULL;
+  }
+};
+
+class C1G1PostBarrierCodeGenClosure : public StubAssemblerCodeGenClosure {
+  virtual OopMapSet* generate_code(StubAssembler* sasm) {
+    G1BarrierSetAssembler* bs = (G1BarrierSetAssembler*)BarrierSet::barrier_set()->barrier_set_assembler();
+    bs->generate_c1_post_barrier_runtime_stub(sasm);
+    return NULL;
+  }
+};
+
+void G1BarrierSetC1::generate_c1_runtime_stubs(BufferBlob* buffer_blob) {
+  C1G1PreBarrierCodeGenClosure pre_code_gen_cl;
+  C1G1PostBarrierCodeGenClosure post_code_gen_cl;
+  _pre_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "g1_pre_barrier_slow",
+                                                              false, &pre_code_gen_cl);
+  _post_barrier_c1_runtime_code_blob = Runtime1::generate_blob(buffer_blob, -1, "g1_post_barrier_slow",
+                                                               false, &post_code_gen_cl);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/g1/c1/g1BarrierSetC1.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,138 @@
+/*
+ * 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_C1_G1BARRIERSETC1_HPP
+#define SHARE_GC_G1_C1_G1BARRIERSETC1_HPP
+
+#include "c1/c1_CodeStubs.hpp"
+#include "gc/shared/c1/modRefBarrierSetC1.hpp"
+
+class G1PreBarrierStub: public CodeStub {
+  friend class G1BarrierSetC1;
+ private:
+  bool _do_load;
+  LIR_Opr _addr;
+  LIR_Opr _pre_val;
+  LIR_PatchCode _patch_code;
+  CodeEmitInfo* _info;
+
+ public:
+  // Version that _does_ generate a load of the previous value from addr.
+  // addr (the address of the field to be read) must be a LIR_Address
+  // pre_val (a temporary register) must be a register;
+  G1PreBarrierStub(LIR_Opr addr, LIR_Opr pre_val, LIR_PatchCode patch_code, CodeEmitInfo* info) :
+    _addr(addr), _pre_val(pre_val), _do_load(true),
+    _patch_code(patch_code), _info(info)
+  {
+    assert(_pre_val->is_register(), "should be temporary register");
+    assert(_addr->is_address(), "should be the address of the field");
+  }
+
+  // Version that _does not_ generate load of the previous value; the
+  // previous value is assumed to have already been loaded into pre_val.
+  G1PreBarrierStub(LIR_Opr pre_val) :
+    _addr(LIR_OprFact::illegalOpr), _pre_val(pre_val), _do_load(false),
+    _patch_code(lir_patch_none), _info(NULL)
+  {
+    assert(_pre_val->is_register(), "should be a register");
+  }
+
+  LIR_Opr addr() const { return _addr; }
+  LIR_Opr pre_val() const { return _pre_val; }
+  LIR_PatchCode patch_code() const { return _patch_code; }
+  CodeEmitInfo* info() const { return _info; }
+  bool do_load() const { return _do_load; }
+
+  virtual void emit_code(LIR_Assembler* e);
+  virtual void visit(LIR_OpVisitState* visitor) {
+    if (_do_load) {
+      // don't pass in the code emit info since it's processed in the fast
+      // path
+      if (_info != NULL)
+        visitor->do_slow_case(_info);
+      else
+        visitor->do_slow_case();
+
+      visitor->do_input(_addr);
+      visitor->do_temp(_pre_val);
+    } else {
+      visitor->do_slow_case();
+      visitor->do_input(_pre_val);
+    }
+  }
+#ifndef PRODUCT
+  virtual void print_name(outputStream* out) const { out->print("G1PreBarrierStub"); }
+#endif // PRODUCT
+};
+
+class G1PostBarrierStub: public CodeStub {
+  friend class G1BarrierSetC1;
+ private:
+  LIR_Opr _addr;
+  LIR_Opr _new_val;
+
+ public:
+  // addr (the address of the object head) and new_val must be registers.
+  G1PostBarrierStub(LIR_Opr addr, LIR_Opr new_val): _addr(addr), _new_val(new_val) { }
+
+  LIR_Opr addr() const { return _addr; }
+  LIR_Opr new_val() const { return _new_val; }
+
+  virtual void emit_code(LIR_Assembler* e);
+  virtual void visit(LIR_OpVisitState* visitor) {
+    // don't pass in the code emit info since it's processed in the fast path
+    visitor->do_slow_case();
+    visitor->do_input(_addr);
+    visitor->do_input(_new_val);
+  }
+#ifndef PRODUCT
+  virtual void print_name(outputStream* out) const { out->print("G1PostBarrierStub"); }
+#endif // PRODUCT
+};
+
+class CodeBlob;
+
+class G1BarrierSetC1 : public ModRefBarrierSetC1 {
+ protected:
+  CodeBlob* _pre_barrier_c1_runtime_code_blob;
+  CodeBlob* _post_barrier_c1_runtime_code_blob;
+
+  virtual void pre_barrier(LIRAccess& access, LIR_Opr addr_opr,
+                           LIR_Opr pre_val, CodeEmitInfo* info);
+  virtual void post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprDesc* new_val);
+
+  virtual void load_at_resolved(LIRAccess& access, LIR_Opr result);
+
+ public:
+  G1BarrierSetC1()
+    : _pre_barrier_c1_runtime_code_blob(NULL),
+      _post_barrier_c1_runtime_code_blob(NULL) {}
+
+  CodeBlob* pre_barrier_c1_runtime_code_blob() { return _pre_barrier_c1_runtime_code_blob; }
+  CodeBlob* post_barrier_c1_runtime_code_blob() { return _post_barrier_c1_runtime_code_blob; }
+
+  virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob);
+};
+
+#endif // SHARE_GC_G1_C1_G1BARRIERSETC1_HPP
--- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -37,12 +37,18 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/macros.hpp"
+#ifdef COMPILER1
+#include "gc/g1/c1/g1BarrierSetC1.hpp"
+#endif
+
+class G1BarrierSetC1;
 
 SATBMarkQueueSet G1BarrierSet::_satb_mark_queue_set;
 DirtyCardQueueSet G1BarrierSet::_dirty_card_queue_set;
 
 G1BarrierSet::G1BarrierSet(G1CardTable* card_table) :
   CardTableBarrierSet(make_barrier_set_assembler<G1BarrierSetAssembler>(),
+                      make_barrier_set_c1<G1BarrierSetC1>(),
                       card_table,
                       BarrierSet::FakeRtti(BarrierSet::G1BarrierSet)) {}
 
--- a/src/hotspot/share/gc/shared/barrierSet.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/gc/shared/barrierSet.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,8 +33,9 @@
 #include "utilities/fakeRttiSupport.hpp"
 #include "utilities/macros.hpp"
 
+class BarrierSetAssembler;
+class BarrierSetC1;
 class JavaThread;
-class BarrierSetAssembler;
 
 // This class provides the interface between a barrier implementation and
 // the rest of the system.
@@ -68,6 +69,7 @@
 private:
   FakeRtti _fake_rtti;
   BarrierSetAssembler* _barrier_set_assembler;
+  BarrierSetC1* _barrier_set_c1;
 
 public:
   // Metafunction mapping a class derived from BarrierSet to the
@@ -88,9 +90,12 @@
   // End of fake RTTI support.
 
 protected:
-  BarrierSet(BarrierSetAssembler* barrier_set_assembler, const FakeRtti& fake_rtti) :
+  BarrierSet(BarrierSetAssembler* barrier_set_assembler,
+             BarrierSetC1* barrier_set_c1,
+             const FakeRtti& fake_rtti) :
     _fake_rtti(fake_rtti),
-    _barrier_set_assembler(barrier_set_assembler) { }
+    _barrier_set_assembler(barrier_set_assembler),
+    _barrier_set_c1(barrier_set_c1) {}
   ~BarrierSet() { }
 
   template <class BarrierSetAssemblerT>
@@ -98,6 +103,11 @@
     return NOT_ZERO(new BarrierSetAssemblerT()) ZERO_ONLY(NULL);
   }
 
+  template <class BarrierSetC1T>
+  BarrierSetC1* make_barrier_set_c1() {
+    return COMPILER1_PRESENT(new BarrierSetC1T()) NOT_COMPILER1(NULL);
+  }
+
 public:
   // Support for optimizing compilers to call the barrier set on slow path allocations
   // that did not enter a TLAB. Used for e.g. ReduceInitialCardMarks.
@@ -123,6 +133,11 @@
     return _barrier_set_assembler;
   }
 
+  BarrierSetC1* barrier_set_c1() {
+    assert(_barrier_set_c1 != NULL, "should be set");
+    return _barrier_set_c1;
+  }
+
   // The AccessBarrier of a BarrierSet subclass is called by the Access API
   // (cf. oops/access.hpp) to perform decorated accesses. GC implementations
   // may override these default access operations by declaring an
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,326 @@
+/*
+ * 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 "c1/c1_Defs.hpp"
+#include "c1/c1_LIRGenerator.hpp"
+#include "gc/shared/c1/barrierSetC1.hpp"
+#include "utilities/macros.hpp"
+
+#ifndef PATCHED_ADDR
+#define PATCHED_ADDR  (max_jint)
+#endif
+
+#ifdef ASSERT
+#define __ gen->lir(__FILE__, __LINE__)->
+#else
+#define __ gen->lir()->
+#endif
+
+LIR_Opr BarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
+  DecoratorSet decorators = access.decorators();
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
+
+  LIRItem& base = access.base().item();
+  LIR_Opr offset = access.offset().opr();
+  LIRGenerator *gen = access.gen();
+
+  LIR_Opr addr_opr;
+  if (on_array) {
+    addr_opr = LIR_OprFact::address(gen->emit_array_address(base.result(), offset, access.type()));
+  } else if (needs_patching) {
+    // we need to patch the offset in the instruction so don't allow
+    // generate_address to try to be smart about emitting the -1.
+    // Otherwise the patching code won't know how to find the
+    // instruction to patch.
+    addr_opr = LIR_OprFact::address(new LIR_Address(base.result(), PATCHED_ADDR, access.type()));
+  } else {
+    addr_opr = LIR_OprFact::address(gen->generate_address(base.result(), offset, 0, 0, access.type()));
+  }
+
+  if (resolve_in_register) {
+    LIR_Opr resolved_addr = gen->new_pointer_register();
+    __ leal(addr_opr, resolved_addr);
+    resolved_addr = LIR_OprFact::address(new LIR_Address(resolved_addr, access.type()));
+    return resolved_addr;
+  } else {
+    return addr_opr;
+  }
+}
+
+void BarrierSetC1::store_at(LIRAccess& access, LIR_Opr value) {
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  assert(in_heap, "not supported yet");
+
+  LIR_Opr resolved = resolve_address(access, false);
+  access.set_resolved_addr(resolved);
+  store_at_resolved(access, value);
+}
+
+void BarrierSetC1::load_at(LIRAccess& access, LIR_Opr result) {
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  assert(in_heap, "not supported yet");
+
+  LIR_Opr resolved = resolve_address(access, false);
+  access.set_resolved_addr(resolved);
+  load_at_resolved(access, result);
+}
+
+LIR_Opr BarrierSetC1::atomic_cmpxchg_at(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) {
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  assert(in_heap, "not supported yet");
+
+  access.load_address();
+
+  LIR_Opr resolved = resolve_address(access, true);
+  access.set_resolved_addr(resolved);
+  return atomic_cmpxchg_at_resolved(access, cmp_value, new_value);
+}
+
+LIR_Opr BarrierSetC1::atomic_xchg_at(LIRAccess& access, LIRItem& value) {
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  assert(in_heap, "not supported yet");
+
+  access.load_address();
+
+  LIR_Opr resolved = resolve_address(access, true);
+  access.set_resolved_addr(resolved);
+  return atomic_xchg_at_resolved(access, value);
+}
+
+LIR_Opr BarrierSetC1::atomic_add_at(LIRAccess& access, LIRItem& value) {
+  DecoratorSet decorators = access.decorators();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  assert(in_heap, "not supported yet");
+
+  access.load_address();
+
+  LIR_Opr resolved = resolve_address(access, true);
+  access.set_resolved_addr(resolved);
+  return atomic_add_at_resolved(access, value);
+}
+
+void BarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
+  DecoratorSet decorators = access.decorators();
+  bool is_volatile = (((decorators & MO_SEQ_CST) != 0) || AlwaysAtomicAccesses) && os::is_MP();
+  bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
+  bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0;
+  LIRGenerator* gen = access.gen();
+
+  if (mask_boolean) {
+    value = gen->mask_boolean(access.base().opr(), value, access.access_emit_info());
+  }
+
+  if (is_volatile && os::is_MP()) {
+    __ membar_release();
+  }
+
+  LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
+  if (is_volatile && !needs_patching) {
+    gen->volatile_field_store(value, access.resolved_addr()->as_address_ptr(), access.access_emit_info());
+  } else {
+    __ store(value, access.resolved_addr()->as_address_ptr(), access.access_emit_info(), patch_code);
+  }
+
+  if (is_volatile && !support_IRIW_for_not_multiple_copy_atomic_cpu) {
+    __ membar();
+  }
+}
+
+void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) {
+  LIRGenerator *gen = access.gen();
+  DecoratorSet decorators = access.decorators();
+  bool is_volatile = (((decorators & MO_SEQ_CST) != 0) || AlwaysAtomicAccesses) && os::is_MP();
+  bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
+  bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0;
+
+  if (support_IRIW_for_not_multiple_copy_atomic_cpu && is_volatile) {
+    __ membar();
+  }
+
+  LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none;
+  if (is_volatile && !needs_patching) {
+    gen->volatile_field_load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info());
+  } else {
+    __ load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info(), patch_code);
+  }
+
+  if (is_volatile && os::is_MP()) {
+    __ membar_acquire();
+  }
+
+  /* Normalize boolean value returned by unsafe operation, i.e., value  != 0 ? value = true : value false. */
+  if (mask_boolean) {
+    LabelObj* equalZeroLabel = new LabelObj();
+    __ cmp(lir_cond_equal, result, 0);
+    __ branch(lir_cond_equal, T_BOOLEAN, equalZeroLabel->label());
+    __ move(LIR_OprFact::intConst(1), result);
+    __ branch_destination(equalZeroLabel->label());
+  }
+}
+
+LIR_Opr BarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) {
+  LIRGenerator *gen = access.gen();
+  return gen->atomic_cmpxchg(access.type(), access.resolved_addr(), cmp_value, new_value);
+}
+
+LIR_Opr BarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value) {
+  LIRGenerator *gen = access.gen();
+  return gen->atomic_xchg(access.type(), access.resolved_addr(), value);
+}
+
+LIR_Opr BarrierSetC1::atomic_add_at_resolved(LIRAccess& access, LIRItem& value) {
+  LIRGenerator *gen = access.gen();
+  return gen->atomic_add(access.type(), access.resolved_addr(), value);
+}
+
+void BarrierSetC1::generate_referent_check(LIRAccess& access, LabelObj* cont) {
+  // We might be reading the value of the referent field of a
+  // Reference object in order to attach it back to the live
+  // object graph. If G1 is enabled then we need to record
+  // the value that is being returned in an SATB log buffer.
+  //
+  // We need to generate code similar to the following...
+  //
+  // if (offset == java_lang_ref_Reference::referent_offset) {
+  //   if (src != NULL) {
+  //     if (klass(src)->reference_type() != REF_NONE) {
+  //       pre_barrier(..., value, ...);
+  //     }
+  //   }
+  // }
+
+  bool gen_pre_barrier = true;     // Assume we need to generate pre_barrier.
+  bool gen_offset_check = true;    // Assume we need to generate the offset guard.
+  bool gen_source_check = true;    // Assume we need to check the src object for null.
+  bool gen_type_check = true;      // Assume we need to check the reference_type.
+
+  LIRGenerator *gen = access.gen();
+
+  LIRItem& base = access.base().item();
+  LIR_Opr offset = access.offset().opr();
+
+  if (offset->is_constant()) {
+    LIR_Const* constant = offset->as_constant_ptr();
+    jlong off_con = (constant->type() == T_INT ?
+                     (jlong)constant->as_jint() :
+                     constant->as_jlong());
+
+
+    if (off_con != (jlong) java_lang_ref_Reference::referent_offset) {
+      // The constant offset is something other than referent_offset.
+      // We can skip generating/checking the remaining guards and
+      // skip generation of the code stub.
+      gen_pre_barrier = false;
+    } else {
+      // The constant offset is the same as referent_offset -
+      // we do not need to generate a runtime offset check.
+      gen_offset_check = false;
+    }
+  }
+
+  // We don't need to generate stub if the source object is an array
+  if (gen_pre_barrier && base.type()->is_array()) {
+    gen_pre_barrier = false;
+  }
+
+  if (gen_pre_barrier) {
+    // We still need to continue with the checks.
+    if (base.is_constant()) {
+      ciObject* src_con = base.get_jobject_constant();
+      guarantee(src_con != NULL, "no source constant");
+
+      if (src_con->is_null_object()) {
+        // The constant src object is null - We can skip
+        // generating the code stub.
+        gen_pre_barrier = false;
+      } else {
+        // Non-null constant source object. We still have to generate
+        // the slow stub - but we don't need to generate the runtime
+        // null object check.
+        gen_source_check = false;
+      }
+    }
+  }
+  if (gen_pre_barrier && !PatchALot) {
+    // Can the klass of object be statically determined to be
+    // a sub-class of Reference?
+    ciType* type = base.value()->declared_type();
+    if ((type != NULL) && type->is_loaded()) {
+      if (type->is_subtype_of(gen->compilation()->env()->Reference_klass())) {
+        gen_type_check = false;
+      } else if (type->is_klass() &&
+                 !gen->compilation()->env()->Object_klass()->is_subtype_of(type->as_klass())) {
+        // Not Reference and not Object klass.
+        gen_pre_barrier = false;
+      }
+    }
+  }
+
+  if (gen_pre_barrier) {
+    // We can have generate one runtime check here. Let's start with
+    // the offset check.
+    if (gen_offset_check) {
+      // if (offset != referent_offset) -> continue
+      // If offset is an int then we can do the comparison with the
+      // referent_offset constant; otherwise we need to move
+      // referent_offset into a temporary register and generate
+      // a reg-reg compare.
+
+      LIR_Opr referent_off;
+
+      if (offset->type() == T_INT) {
+        referent_off = LIR_OprFact::intConst(java_lang_ref_Reference::referent_offset);
+      } else {
+        assert(offset->type() == T_LONG, "what else?");
+        referent_off = gen->new_register(T_LONG);
+        __ move(LIR_OprFact::longConst(java_lang_ref_Reference::referent_offset), referent_off);
+      }
+      __ cmp(lir_cond_notEqual, offset, referent_off);
+      __ branch(lir_cond_notEqual, offset->type(), cont->label());
+    }
+    if (gen_source_check) {
+      // offset is a const and equals referent offset
+      // if (source == null) -> continue
+      __ cmp(lir_cond_equal, base.result(), LIR_OprFact::oopConst(NULL));
+      __ branch(lir_cond_equal, T_OBJECT, cont->label());
+    }
+    LIR_Opr src_klass = gen->new_register(T_OBJECT);
+    if (gen_type_check) {
+      // We have determined that offset == referent_offset && src != null.
+      // if (src->_klass->_reference_type == REF_NONE) -> continue
+      __ move(new LIR_Address(base.result(), oopDesc::klass_offset_in_bytes(), T_ADDRESS), src_klass);
+      LIR_Address* reference_type_addr = new LIR_Address(src_klass, in_bytes(InstanceKlass::reference_type_offset()), T_BYTE);
+      LIR_Opr reference_type = gen->new_register(T_INT);
+      __ move(reference_type_addr, reference_type);
+      __ cmp(lir_cond_equal, reference_type, LIR_OprFact::intConst(REF_NONE));
+      __ branch(lir_cond_equal, T_INT, cont->label());
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,139 @@
+/*
+ * 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_C1_BARRIERSETC1_HPP
+#define SHARE_GC_SHARED_C1_BARRIERSETC1_HPP
+
+#include "c1/c1_Decorators.hpp"
+#include "c1/c1_LIRGenerator.hpp"
+#include "c1/c1_Instruction.hpp"
+#include "c1/c1_LIR.hpp"
+#include "memory/allocation.hpp"
+
+class LIRGenerator;
+class LIRItem;
+
+// The LIRAddressOpr comprises either a LIRItem or a LIR_Opr to describe elements
+// of an access in the C1 Access API. Both of them allow asking for the opr() which
+// will correspond to either _item.result() or _opr if there is no _item.
+class LIRAddressOpr: public StackObj {
+  LIRItem* _item;
+  LIR_Opr  _opr;
+public:
+  LIRAddressOpr(LIRItem& item) : _item(&item), _opr(NULL) {}
+  LIRAddressOpr(LIR_Opr opr) : _item(NULL), _opr(opr) {}
+  LIRAddressOpr(const LIRAddressOpr& other) : _item(other._item), _opr(other._opr) {}
+
+  LIRItem& item() const {
+    assert(_item != NULL, "sanity");
+    return *_item;
+  }
+
+  LIR_Opr opr() const {
+    if (_item == NULL) {
+      return _opr;
+    } else {
+      return _item->result();
+    }
+  }
+};
+
+// The LIRAccess class wraps shared context parameters required for performing
+// the right access in C1. This includes the address of the offset and the decorators.
+class LIRAccess: public StackObj {
+  LIRGenerator* _gen;
+  DecoratorSet  _decorators;
+  LIRAddressOpr _base;
+  LIRAddressOpr _offset;
+  BasicType     _type;
+  LIR_Opr       _resolved_addr;
+  CodeEmitInfo* _patch_emit_info;
+  CodeEmitInfo* _access_emit_info;
+
+public:
+  LIRAccess(LIRGenerator* gen, DecoratorSet decorators,
+            LIRAddressOpr base, LIRAddressOpr offset, BasicType type,
+            CodeEmitInfo* patch_emit_info = NULL, CodeEmitInfo* access_emit_info = NULL) :
+    _gen(gen),
+    _decorators(AccessInternal::decorator_fixup(decorators)),
+    _base(base),
+    _offset(offset),
+    _type(type),
+    _resolved_addr(NULL),
+    _patch_emit_info(patch_emit_info),
+    _access_emit_info(access_emit_info) {}
+
+  void load_base()   { _base.item().load_item(); }
+  void load_offset() { _offset.item().load_nonconstant(); }
+
+  void load_address() {
+    load_base();
+    load_offset();
+  }
+
+  LIRGenerator* gen() const            { return _gen; }
+  CodeEmitInfo*& patch_emit_info()     { return _patch_emit_info; }
+  CodeEmitInfo*& access_emit_info()    { return _access_emit_info; }
+  LIRAddressOpr& base()                { return _base; }
+  LIRAddressOpr& offset()              { return _offset; }
+  BasicType type() const               { return _type; }
+  LIR_Opr resolved_addr() const        { return _resolved_addr; }
+  void set_resolved_addr(LIR_Opr addr) { _resolved_addr = addr; }
+  bool is_oop() const                  { return _type == T_ARRAY || _type == T_OBJECT; }
+  DecoratorSet decorators() const      { return _decorators; }
+  bool is_raw() const                  { return (_decorators & AS_RAW) != 0; }
+};
+
+// The BarrierSetC1 class is the main entry point for the GC backend of the Access API in C1.
+// It is called by the LIRGenerator::access_* functions, which is the main entry poing for
+// access calls in C1.
+
+class BarrierSetC1: public CHeapObj<mtGC> {
+protected:
+  virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register);
+
+  virtual void generate_referent_check(LIRAccess& access, LabelObj* cont);
+
+  // Accesses with resolved address
+  virtual void store_at_resolved(LIRAccess& access, LIR_Opr value);
+  virtual void load_at_resolved(LIRAccess& access, LIR_Opr result);
+
+  virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
+
+  virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value);
+  virtual LIR_Opr atomic_add_at_resolved(LIRAccess& access, LIRItem& value);
+
+public:
+  virtual void store_at(LIRAccess& access, LIR_Opr value);
+  virtual void load_at(LIRAccess& access, LIR_Opr result);
+
+  virtual LIR_Opr atomic_cmpxchg_at(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
+
+  virtual LIR_Opr atomic_xchg_at(LIRAccess& access, LIRItem& value);
+  virtual LIR_Opr atomic_add_at(LIRAccess& access, LIRItem& value);
+
+  virtual void generate_c1_runtime_stubs(BufferBlob* buffer_blob) {}
+};
+
+#endif // SHARE_GC_SHARED_C1_BARRIERSETC1_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,102 @@
+/*
+ * 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/c1/cardTableBarrierSetC1.hpp"
+#include "gc/shared/cardTableBarrierSet.hpp"
+#include "utilities/macros.hpp"
+
+#ifdef ASSERT
+#define __ gen->lir(__FILE__, __LINE__)->
+#else
+#define __ gen->lir()->
+#endif
+
+void CardTableBarrierSetC1::post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprDesc* new_val) {
+  DecoratorSet decorators = access.decorators();
+  LIRGenerator* gen = access.gen();
+  bool in_heap = (decorators & IN_HEAP) != 0;
+  if (!in_heap) {
+    return;
+  }
+
+  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");
+  LIR_Const* card_table_base = new LIR_Const(ct->byte_map_base());
+  if (addr->is_address()) {
+    LIR_Address* address = addr->as_address_ptr();
+    // ptr cannot be an object because we use this barrier for array card marks
+    // and addr can point in the middle of an array.
+    LIR_Opr ptr = gen->new_pointer_register();
+    if (!address->index()->is_valid() && address->disp() == 0) {
+      __ move(address->base(), ptr);
+    } else {
+      assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
+      __ leal(addr, ptr);
+    }
+    addr = ptr;
+  }
+  assert(addr->is_register(), "must be a register at this point");
+
+#ifdef CARDTABLEBARRIERSET_POST_BARRIER_HELPER
+  gen->CardTableBarrierSet_post_barrier_helper(addr, card_table_base);
+#else
+  LIR_Opr tmp = gen->new_pointer_register();
+  if (TwoOperandLIRForm) {
+    __ move(addr, tmp);
+    __ unsigned_shift_right(tmp, CardTable::card_shift, tmp);
+  } else {
+    __ unsigned_shift_right(addr, CardTable::card_shift, tmp);
+  }
+
+  LIR_Address* card_addr;
+  if (gen->can_inline_as_constant(card_table_base)) {
+    card_addr = new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE);
+  } else {
+    card_addr = new LIR_Address(tmp, gen->load_constant(card_table_base), T_BYTE);
+  }
+
+  LIR_Opr dirty = LIR_OprFact::intConst(CardTable::dirty_card_val());
+  if (UseCondCardMark) {
+    LIR_Opr cur_value = gen->new_register(T_INT);
+    if (ct->scanned_concurrently()) {
+      __ membar_storeload();
+    }
+    __ move(card_addr, cur_value);
+
+    LabelObj* L_already_dirty = new LabelObj();
+    __ cmp(lir_cond_equal, cur_value, dirty);
+    __ branch(lir_cond_equal, T_BYTE, L_already_dirty->label());
+    __ move(dirty, card_addr);
+    __ branch_destination(L_already_dirty->label());
+  } else {
+    if (ct->scanned_concurrently()) {
+      __ membar_storestore();
+    }
+    __ move(dirty, card_addr);
+  }
+#endif
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/c1/cardTableBarrierSetC1.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,35 @@
+/*
+ * 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_C1_CARDTABLEBARRIERSETC1_HPP
+#define SHARE_GC_SHARED_C1_CARDTABLEBARRIERSETC1_HPP
+
+#include "gc/shared/c1/modRefBarrierSetC1.hpp"
+
+class CardTableBarrierSetC1 : public ModRefBarrierSetC1 {
+protected:
+  virtual void post_barrier(LIRAccess& access, LIR_OprDesc* addr, LIR_OprDesc* new_val);
+};
+
+#endif // SHARE_GC_SHARED_C1_CARDTABLEBARRIERSETC1_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,92 @@
+/*
+ * 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/c1/modRefBarrierSetC1.hpp"
+#include "utilities/macros.hpp"
+
+#ifdef ASSERT
+#define __ gen->lir(__FILE__, __LINE__)->
+#else
+#define __ gen->lir()->
+#endif
+
+void ModRefBarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) {
+  DecoratorSet decorators = access.decorators();
+  bool on_array = (decorators & IN_HEAP_ARRAY) != 0;
+  bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+
+  if (access.is_oop()) {
+    pre_barrier(access, access.resolved_addr(),
+                LIR_OprFact::illegalOpr /* pre_val */, access.patch_emit_info());
+  }
+
+  BarrierSetC1::store_at_resolved(access, value);
+
+  if (access.is_oop()) {
+    bool precise = on_array || on_anonymous;
+    LIR_Opr post_addr = precise ? access.resolved_addr() : access.base().opr();
+    post_barrier(access, post_addr, value);
+  }
+}
+
+LIR_Opr ModRefBarrierSetC1::atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value) {
+  if (access.is_oop()) {
+    pre_barrier(access, access.resolved_addr(),
+                LIR_OprFact::illegalOpr /* pre_val */, NULL);
+  }
+
+  LIR_Opr result = BarrierSetC1::atomic_cmpxchg_at_resolved(access, cmp_value, new_value);
+
+  if (access.is_oop()) {
+    post_barrier(access, access.resolved_addr(), new_value.result());
+  }
+
+  return result;
+}
+
+LIR_Opr ModRefBarrierSetC1::atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value) {
+  if (access.is_oop()) {
+    pre_barrier(access, access.resolved_addr(),
+                LIR_OprFact::illegalOpr /* pre_val */, NULL);
+  }
+
+  LIR_Opr result = BarrierSetC1::atomic_xchg_at_resolved(access, value);
+
+  if (access.is_oop()) {
+    post_barrier(access, access.resolved_addr(), value.result());
+  }
+
+  return result;
+}
+
+// This overrides the default to resolve the address into a register,
+// assuming it will be used by a write barrier anyway.
+LIR_Opr ModRefBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
+  DecoratorSet decorators = access.decorators();
+  bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0;
+  bool is_write = (decorators & C1_WRITE_ACCESS) != 0;
+  resolve_in_register |= !needs_patching && is_write && access.is_oop();
+  return BarrierSetC1::resolve_address(access, resolve_in_register);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/hotspot/share/gc/shared/c1/modRefBarrierSetC1.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -0,0 +1,50 @@
+/*
+ * 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_C1_MODREFBARRIERSETC1_HPP
+#define SHARE_GC_SHARED_C1_MODREFBARRIERSETC1_HPP
+
+#include "gc/shared/c1/barrierSetC1.hpp"
+
+// The ModRefBarrierSetC1 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 ModRefBarrierSetC1 : public BarrierSetC1 {
+protected:
+  virtual void pre_barrier(LIRAccess& access, LIR_Opr addr_opr,
+                           LIR_Opr pre_val, CodeEmitInfo* info) {}
+  virtual void post_barrier(LIRAccess& access, LIR_OprDesc* addr,
+                            LIR_OprDesc* new_val) {}
+
+  virtual LIR_Opr resolve_address(LIRAccess& access, bool resolve_in_register);
+
+  virtual void store_at_resolved(LIRAccess& access, LIR_Opr value);
+
+  virtual LIR_Opr atomic_cmpxchg_at_resolved(LIRAccess& access, LIRItem& cmp_value, LIRItem& new_value);
+
+  virtual LIR_Opr atomic_xchg_at_resolved(LIRAccess& access, LIRItem& value);
+};
+
+#endif // SHARE_GC_SHARED_C1_MODREFBARRIERSETC1_HPP
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp	Thu Apr 26 20:42:43 2018 +0200
@@ -34,15 +34,22 @@
 #include "services/memTracker.hpp"
 #include "utilities/align.hpp"
 #include "utilities/macros.hpp"
+#ifdef COMPILER1
+#include "gc/shared/c1/cardTableBarrierSetC1.hpp"
+#endif
+
+class CardTableBarrierSetC1;
 
 // This kind of "BarrierSet" allows a "CollectedHeap" to detect and
 // enumerate ref fields that have been modified (since the last
 // enumeration.)
 
 CardTableBarrierSet::CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler,
+                                         BarrierSetC1* barrier_set_c1,
                                          CardTable* card_table,
                                          const BarrierSet::FakeRtti& fake_rtti) :
   ModRefBarrierSet(barrier_set_assembler,
+                   barrier_set_c1,
                    fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)),
   _defer_initial_card_mark(false),
   _card_table(card_table)
@@ -50,6 +57,7 @@
 
 CardTableBarrierSet::CardTableBarrierSet(CardTable* card_table) :
   ModRefBarrierSet(make_barrier_set_assembler<CardTableBarrierSetAssembler>(),
+                   make_barrier_set_c1<CardTableBarrierSetC1>(),
                    BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)),
   _defer_initial_card_mark(false),
   _card_table(card_table)
--- a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -53,6 +53,7 @@
   CardTable* _card_table;
 
   CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler,
+                      BarrierSetC1* barrier_set_c1,
                       CardTable* card_table,
                       const BarrierSet::FakeRtti& fake_rtti);
 
--- a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -33,8 +33,10 @@
 class ModRefBarrierSet: public BarrierSet {
 protected:
   ModRefBarrierSet(BarrierSetAssembler* barrier_set_assembler,
+                   BarrierSetC1* barrier_set_c1,
                    const BarrierSet::FakeRtti& fake_rtti)
     : BarrierSet(barrier_set_assembler,
+                 barrier_set_c1,
                  fake_rtti.add_tag(BarrierSet::ModRef)) { }
   ~ModRefBarrierSet() { }
 
--- a/src/hotspot/share/oops/accessBackend.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/oops/accessBackend.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -980,31 +980,6 @@
     }
   };
 
-  // This class adds implied decorators that follow according to decorator rules.
-  // For example adding default reference strength and default memory ordering
-  // semantics.
-  template <DecoratorSet input_decorators>
-  struct DecoratorFixup: AllStatic {
-    // If no reference strength has been picked, then strong will be picked
-    static const DecoratorSet ref_strength_default = input_decorators |
-      (((ON_DECORATOR_MASK & input_decorators) == 0 && (INTERNAL_VALUE_IS_OOP & input_decorators) != 0) ?
-       ON_STRONG_OOP_REF : INTERNAL_EMPTY);
-    // If no memory ordering has been picked, unordered will be picked
-    static const DecoratorSet memory_ordering_default = ref_strength_default |
-      ((MO_DECORATOR_MASK & ref_strength_default) == 0 ? MO_UNORDERED : INTERNAL_EMPTY);
-    // If no barrier strength has been picked, normal will be used
-    static const DecoratorSet barrier_strength_default = memory_ordering_default |
-      ((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
-    // Heap array accesses imply it is a heap access
-    static const DecoratorSet heap_array_is_in_heap = barrier_strength_default |
-      ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
-    static const DecoratorSet conc_root_is_root = heap_array_is_in_heap |
-      ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY);
-    static const DecoratorSet archive_root_is_root = conc_root_is_root |
-      ((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY);
-    static const DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS;
-  };
-
   // Step 2: Reduce types.
   // Enforce that for non-oop types, T and P have to be strictly the same.
   // P is the type of the address and T is the type of the values.
--- a/src/hotspot/share/oops/accessDecorators.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/oops/accessDecorators.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -25,6 +25,11 @@
 #ifndef SHARE_OOPS_ACCESSDECORATORS_HPP
 #define SHARE_OOPS_ACCESSDECORATORS_HPP
 
+#include "gc/shared/barrierSetConfig.hpp"
+#include "memory/allocation.hpp"
+#include "metaprogramming/integralConstant.hpp"
+#include "utilities/globalDefinitions.hpp"
+
 // A decorator is an attribute or property that affects the way a memory access is performed in some way.
 // There are different groups of decorators. Some have to do with memory ordering, others to do with,
 // e.g. strength of references, strength of GC barriers, or whether compression should be applied or not.
@@ -216,4 +221,58 @@
                                                     ARRAYCOPY_DISJOINT | ARRAYCOPY_ARRAYOF |
                                                     ARRAYCOPY_ATOMIC | ARRAYCOPY_ALIGNED;
 
+// Keep track of the last decorator.
+const DecoratorSet DECORATOR_LAST = UCONST64(1) << 30;
+
+namespace AccessInternal {
+  // This class adds implied decorators that follow according to decorator rules.
+  // For example adding default reference strength and default memory ordering
+  // semantics.
+  template <DecoratorSet input_decorators>
+  struct DecoratorFixup: AllStatic {
+    // If no reference strength has been picked, then strong will be picked
+    static const DecoratorSet ref_strength_default = input_decorators |
+      (((ON_DECORATOR_MASK & input_decorators) == 0 && (INTERNAL_VALUE_IS_OOP & input_decorators) != 0) ?
+       ON_STRONG_OOP_REF : INTERNAL_EMPTY);
+    // If no memory ordering has been picked, unordered will be picked
+    static const DecoratorSet memory_ordering_default = ref_strength_default |
+      ((MO_DECORATOR_MASK & ref_strength_default) == 0 ? MO_UNORDERED : INTERNAL_EMPTY);
+    // If no barrier strength has been picked, normal will be used
+    static const DecoratorSet barrier_strength_default = memory_ordering_default |
+      ((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
+    // Heap array accesses imply it is a heap access
+    static const DecoratorSet heap_array_is_in_heap = barrier_strength_default |
+      ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
+    static const DecoratorSet conc_root_is_root = heap_array_is_in_heap |
+      ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY);
+    static const DecoratorSet archive_root_is_root = conc_root_is_root |
+      ((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY);
+    static const DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS;
+  };
+
+  // This function implements the above DecoratorFixup rules, but without meta
+  // programming for code generation that does not use templates.
+  inline DecoratorSet decorator_fixup(DecoratorSet input_decorators) {
+    // If no reference strength has been picked, then strong will be picked
+    DecoratorSet ref_strength_default = input_decorators |
+      (((ON_DECORATOR_MASK & input_decorators) == 0 && (INTERNAL_VALUE_IS_OOP & input_decorators) != 0) ?
+       ON_STRONG_OOP_REF : INTERNAL_EMPTY);
+    // If no memory ordering has been picked, unordered will be picked
+    DecoratorSet memory_ordering_default = ref_strength_default |
+      ((MO_DECORATOR_MASK & ref_strength_default) == 0 ? MO_UNORDERED : INTERNAL_EMPTY);
+    // If no barrier strength has been picked, normal will be used
+    DecoratorSet barrier_strength_default = memory_ordering_default |
+      ((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
+    // Heap array accesses imply it is a heap access
+    DecoratorSet heap_array_is_in_heap = barrier_strength_default |
+      ((IN_HEAP_ARRAY & barrier_strength_default) != 0 ? IN_HEAP : INTERNAL_EMPTY);
+    DecoratorSet conc_root_is_root = heap_array_is_in_heap |
+      ((IN_CONCURRENT_ROOT & heap_array_is_in_heap) != 0 ? IN_ROOT : INTERNAL_EMPTY);
+    DecoratorSet archive_root_is_root = conc_root_is_root |
+      ((IN_ARCHIVE_ROOT & conc_root_is_root) != 0 ? IN_ROOT : INTERNAL_EMPTY);
+    DecoratorSet value = archive_root_is_root | BT_BUILDTIME_DECORATORS;
+    return value;
+  }
+}
+
 #endif // SHARE_OOPS_ACCESSDECORATORS_HPP
--- a/src/hotspot/share/utilities/macros.hpp	Thu Apr 26 12:48:35 2018 -0700
+++ b/src/hotspot/share/utilities/macros.hpp	Thu Apr 26 20:42:43 2018 +0200
@@ -206,8 +206,10 @@
   #define TIERED
 #endif
 #define COMPILER1_PRESENT(code) code
+#define NOT_COMPILER1(code)
 #else // COMPILER1
 #define COMPILER1_PRESENT(code)
+#define NOT_COMPILER1(code) code
 #endif // COMPILER1
 
 // COMPILER2 variant