# HG changeset patch # User rkennke # Date 1504710968 -7200 # Wed Sep 06 17:16:08 2017 +0200 # Node ID c003381db0ba743084f2a0afb2c32003f9a8e13f # Parent 85b0809151724ed1eb83a54944ca89a6be188d93 Factor out keep-alive barrier from usual pre-barrier implementations. diff --git a/src/cpu/x86/vm/macroAssembler_x86.cpp b/src/cpu/x86/vm/macroAssembler_x86.cpp --- a/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -5591,6 +5591,22 @@ bind(done); } +void MacroAssembler::keep_alive_barrier(Register val, + Register thread, + Register tmp) { + + if (UseG1GC || (UseShenandoahGC && ShenandoahKeepAliveBarrier)) { + // Generate the G1 pre-barrier code to log the value of + // the referent field in an SATB buffer. + g1_write_barrier_pre(noreg, + rax /* pre_val */, + thread /* thread */, + tmp, + true /* tosca_live */, + true /* expand_call */); + } +} + #ifndef _LP64 void MacroAssembler::shenandoah_write_barrier(Register dst) { Unimplemented(); diff --git a/src/cpu/x86/vm/macroAssembler_x86.hpp b/src/cpu/x86/vm/macroAssembler_x86.hpp --- a/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -315,6 +315,10 @@ Register tmp, Register tmp2); + void keep_alive_barrier(Register val, + Register thread, + Register tmp); + void shenandoah_write_barrier_post(Register store_addr, Register new_val, Register thread, diff --git a/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp b/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp --- a/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp +++ b/src/cpu/x86/vm/templateInterpreterGenerator_x86.cpp @@ -760,16 +760,11 @@ const Register thread = NOT_LP64(rcx) LP64_ONLY(r15_thread); NOT_LP64(__ get_thread(thread)); - if (!UseShenandoahGC || ShenandoahSATBBarrier) { - // Generate the G1 pre-barrier code to log the value of - // the referent field in an SATB buffer. - __ g1_write_barrier_pre(noreg /* obj */, - rax /* pre_val */, - thread /* thread */, - rbx /* tmp */, - true /* tosca_live */, - true /* expand_call */); - } + // Generate the G1 pre-barrier code to log the value of + // the referent field in an SATB buffer. + __ keep_alive_barrier(rax /* pre_val */, + thread /* thread */, + rbx /* tmp */); // _areturn NOT_LP64(__ pop(rsi)); // get sender sp diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -1261,11 +1261,7 @@ __ 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 */); + keep_alive_barrier(result); } // Example: clazz.isInstance(object) @@ -1489,6 +1485,36 @@ } } +void LIRGenerator::keep_alive_barrier(LIR_Opr val) { + switch (_bs->kind()) { +#if INCLUDE_ALL_GCS + case BarrierSet::G1SATBCTLogging: + pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, + val /* pre_val */, + false /* do_load */, + false /* patch */, + NULL /* info */); + break; + case BarrierSet::ShenandoahBarrierSet: + if (ShenandoahKeepAliveBarrier) { + pre_barrier(LIR_OprFact::illegalOpr /* addr_opr */, + val /* pre_val */, + false /* do_load */, + false /* patch */, + NULL /* info */); + } + break; +#endif // INCLUDE_ALL_GCS + case BarrierSet::CardTableForRS: + case BarrierSet::CardTableExtension: + break; + case BarrierSet::ModRef: + break; + default : + ShouldNotReachHere(); + } +} + void LIRGenerator::post_barrier(LIR_OprDesc* addr, LIR_OprDesc* new_val) { switch (_bs->kind()) { #if INCLUDE_ALL_GCS diff --git a/src/share/vm/c1/c1_LIRGenerator.hpp b/src/share/vm/c1/c1_LIRGenerator.hpp --- a/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/src/share/vm/c1/c1_LIRGenerator.hpp @@ -274,6 +274,8 @@ 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); + void keep_alive_barrier(LIR_Opr val); + LIR_Opr shenandoah_read_barrier(LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); LIR_Opr shenandoah_write_barrier(LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); LIR_Opr shenandoah_storeval_barrier(LIR_Opr obj, CodeEmitInfo* info, bool need_null_check); diff --git a/src/share/vm/ci/ciObjectFactory.cpp b/src/share/vm/ci/ciObjectFactory.cpp --- a/src/share/vm/ci/ciObjectFactory.cpp +++ b/src/share/vm/ci/ciObjectFactory.cpp @@ -427,7 +427,7 @@ oop metadata_holder = metadata_owner_klass->klass_holder(); if (metadata_holder != NULL) { - G1SATBCardTableModRefBS::enqueue(metadata_holder); + oopDesc::bs()->keep_alive_barrier(metadata_holder); } #endif diff --git a/src/share/vm/classfile/stringTable.cpp b/src/share/vm/classfile/stringTable.cpp --- a/src/share/vm/classfile/stringTable.cpp +++ b/src/share/vm/classfile/stringTable.cpp @@ -43,7 +43,6 @@ #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS #include "gc/g1/g1CollectedHeap.hpp" -#include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/g1/g1StringDedup.hpp" #endif @@ -198,8 +197,8 @@ // considered dead. The SATB part of G1 needs to get notified about this // potential resurrection, otherwise the marking might not find the object. #if INCLUDE_ALL_GCS - if (((UseShenandoahGC && ShenandoahSATBBarrier) || UseG1GC) && string != NULL) { - G1SATBCardTableModRefBS::enqueue(string); + if (string != NULL) { + oopDesc::bs()->keep_alive_barrier(string); } #endif } diff --git a/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp b/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp --- a/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp +++ b/src/share/vm/gc/g1/g1SATBCardTableModRefBS.cpp @@ -263,3 +263,7 @@ } } } + +void G1SATBCardTableModRefBS::keep_alive_barrier(oop obj) { + G1SATBCardTableModRefBS::enqueue(obj); +} diff --git a/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp b/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp --- a/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp +++ b/src/share/vm/gc/g1/g1SATBCardTableModRefBS.hpp @@ -103,6 +103,9 @@ virtual void write_ref_nmethod_pre(oop* dst, nmethod* nm); virtual void write_ref_nmethod_post(oop* dst, nmethod* nm); + virtual void keep_alive_barrier(oop obj); + + }; template<> diff --git a/src/share/vm/gc/shared/barrierSet.hpp b/src/share/vm/gc/shared/barrierSet.hpp --- a/src/share/vm/gc/shared/barrierSet.hpp +++ b/src/share/vm/gc/shared/barrierSet.hpp @@ -231,6 +231,10 @@ return src; } + virtual void keep_alive_barrier(oop obj) { + // Default impl does nothing. + } + virtual bool obj_equals(oop obj1, oop obj2); virtual bool obj_equals(narrowOop obj1, narrowOop obj2); diff --git a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.cpp @@ -399,6 +399,12 @@ return obj; } +void ShenandoahBarrierSet::keep_alive_barrier(oop obj) { + if (ShenandoahKeepAliveBarrier) { + G1SATBCardTableModRefBS::enqueue(obj); + } +} + #ifdef ASSERT void ShenandoahBarrierSet::verify_safe_oop(oop p) { ShenandoahHeap* heap = ShenandoahHeap::heap(); diff --git a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp --- a/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/share/vm/gc/shenandoah/shenandoahBarrierSet.hpp @@ -102,6 +102,8 @@ virtual oop storeval_barrier(oop obj); + virtual void keep_alive_barrier(oop obj); + bool obj_equals(oop obj1, oop obj2); bool obj_equals(narrowOop obj1, narrowOop obj2); diff --git a/src/share/vm/gc/shenandoah/shenandoah_globals.hpp b/src/share/vm/gc/shenandoah/shenandoah_globals.hpp --- a/src/share/vm/gc/shenandoah/shenandoah_globals.hpp +++ b/src/share/vm/gc/shenandoah/shenandoah_globals.hpp @@ -282,6 +282,9 @@ diagnostic(bool, ShenandoahSATBBarrier, true, \ "Turn on/off SATB barriers in Shenandoah") \ \ + diagnostic(bool, ShenandoahKeepAliveBarrier, true, \ + "Turn on/off SATB barriers in Shenandoah") \ + \ diagnostic(bool, ShenandoahWriteBarrier, true, \ "Turn on/off write barriers in Shenandoah") \ \ diff --git a/src/share/vm/oops/constantPool.cpp b/src/share/vm/oops/constantPool.cpp --- a/src/share/vm/oops/constantPool.cpp +++ b/src/share/vm/oops/constantPool.cpp @@ -48,9 +48,6 @@ #include "runtime/signature.hpp" #include "runtime/vframe.hpp" #include "utilities/copy.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, TRAPS) { Array* tags = MetadataFactory::new_array(loader_data, length, 0, CHECK_NULL); @@ -308,7 +305,7 @@ // initial GC marking and during concurrent marking as strong roots are only // scanned during initial marking (at the start of the GC marking). assert(UseG1GC, "Requires G1 GC"); - G1SATBCardTableModRefBS::enqueue(archived); + oopDesc::bs()->keep_alive_barrier(archived); // Create handle for the archived resolved reference array object Handle refs_handle(THREAD, (oop)archived); set_resolved_references(loader_data->add_handle(refs_handle)); diff --git a/src/share/vm/oops/klass.cpp b/src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp +++ b/src/share/vm/oops/klass.cpp @@ -43,9 +43,6 @@ #include "trace/traceMacros.hpp" #include "utilities/macros.hpp" #include "utilities/stack.inline.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS bool Klass::is_cloneable() const { return _access_flags.is_cloneable_fast() || @@ -450,11 +447,9 @@ // the beginning. This function is only used when we write oops into Klasses. void Klass::klass_update_barrier_set_pre(oop* p, oop v) { #if INCLUDE_ALL_GCS - if (UseG1GC || (UseShenandoahGC && ShenandoahSATBBarrier)) { - oop obj = *p; - if (obj != NULL) { - G1SATBCardTableModRefBS::enqueue(obj); - } + oop obj = oopDesc::load_heap_oop(p); + if (! oopDesc::is_null(obj)) { + oopDesc::bs()->keep_alive_barrier(obj); } #endif } diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp --- a/src/share/vm/opto/graphKit.cpp +++ b/src/share/vm/opto/graphKit.cpp @@ -1631,6 +1631,43 @@ } } +void GraphKit::keep_alive_barrier(Node* ctl, Node* obj) { + BarrierSet* bs = Universe::heap()->barrier_set(); + switch (bs->kind()) { + case BarrierSet::G1SATBCTLogging: + pre_barrier(false /* do_load */, + ctl, + NULL /* obj */, + NULL /* adr */, + max_juint /* alias_idx */, + NULL /* val */, + NULL /* val_type */, + obj /* pre_val */, + T_OBJECT); + break; + case BarrierSet::ShenandoahBarrierSet: + if (ShenandoahKeepAliveBarrier) { + pre_barrier(false /* do_load */, + ctl, + NULL /* obj */, + NULL /* adr */, + max_juint /* alias_idx */, + NULL /* val */, + NULL /* val_type */, + obj /* pre_val */, + T_OBJECT); + } + break; + case BarrierSet::CardTableForRS: + case BarrierSet::CardTableExtension: + case BarrierSet::ModRef: + break; + default : + ShouldNotReachHere(); + + } +} + Node* GraphKit::store_oop(Node* ctl, Node* obj, Node* adr, diff --git a/src/share/vm/opto/graphKit.hpp b/src/share/vm/opto/graphKit.hpp --- a/src/share/vm/opto/graphKit.hpp +++ b/src/share/vm/opto/graphKit.hpp @@ -634,6 +634,8 @@ void post_barrier(Node* ctl, Node* store, Node* obj, Node* adr, uint adr_idx, Node* val, BasicType bt, bool use_precise); + void keep_alive_barrier(Node* ctl, Node* pre_val); + // Return addressing for an array element. Node* array_element_address(Node* ary, Node* idx, BasicType elembt, // Optional constraint on the array size: diff --git a/src/share/vm/opto/library_call.cpp b/src/share/vm/opto/library_call.cpp --- a/src/share/vm/opto/library_call.cpp +++ b/src/share/vm/opto/library_call.cpp @@ -6233,11 +6233,7 @@ Node* result = make_load(no_ctrl, adr, object_type, T_OBJECT, MemNode::unordered); // Use the pre-barrier to record the value in the referent field - pre_barrier(false /* do_load */, - control(), - NULL /* obj */, NULL /* adr */, max_juint /* alias_idx */, NULL /* val */, NULL /* val_type */, - result /* pre_val */, - T_OBJECT); + keep_alive_barrier(control(), result); // Add memory barrier to prevent commoning reads from this field // across safepoint since GC can change its value. diff --git a/src/share/vm/prims/jni.cpp b/src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp +++ b/src/share/vm/prims/jni.cpp @@ -85,9 +85,6 @@ #include "utilities/internalVMTests.hpp" #include "utilities/macros.hpp" #include "utilities/vmError.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS #if INCLUDE_JVMCI #include "jvmci/jvmciCompiler.hpp" #include "jvmci/jvmciRuntime.hpp" @@ -2077,20 +2074,18 @@ // If G1 is enabled and we are accessing the value of the referent // field in a reference object then we need to register a non-null // referent with the SATB barrier. - if (UseG1GC || (UseShenandoahGC && ShenandoahWriteBarrier)) { - bool needs_barrier = false; - - if (ret != NULL && - offset == java_lang_ref_Reference::referent_offset && - InstanceKlass::cast(k)->reference_type() != REF_NONE) { - assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); - needs_barrier = true; - } - - if (needs_barrier) { - oop referent = JNIHandles::resolve(ret); - G1SATBCardTableModRefBS::enqueue(referent); - } + bool needs_barrier = false; + + if (ret != NULL && + offset == java_lang_ref_Reference::referent_offset && + InstanceKlass::cast(k)->reference_type() != REF_NONE) { + assert(InstanceKlass::cast(k)->is_subclass_of(SystemDictionary::Reference_klass()), "sanity"); + needs_barrier = true; + } + + if (needs_barrier) { + oop referent = JNIHandles::resolve(ret); + oopDesc::bs()->keep_alive_barrier(referent); } #endif // INCLUDE_ALL_GCS HOTSPOT_JNI_GETOBJECTFIELD_RETURN(ret); diff --git a/src/share/vm/prims/jvmtiTagMap.cpp b/src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp +++ b/src/share/vm/prims/jvmtiTagMap.cpp @@ -51,7 +51,6 @@ #include "services/serviceUtil.hpp" #include "utilities/macros.hpp" #if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" #include "gc/parallel/parallelScavengeHeap.hpp" #endif // INCLUDE_ALL_GCS @@ -1536,12 +1535,10 @@ oop o = entry->object(); assert(o != NULL && Universe::heap()->is_in_reserved(o), "sanity check"); #if INCLUDE_ALL_GCS - if (UseG1GC || UseShenandoahGC) { - // The reference in this tag map could be the only (implicitly weak) - // reference to that object. If we hand it out, we need to keep it live wrt - // SATB marking similar to other j.l.ref.Reference referents. - G1SATBCardTableModRefBS::enqueue(o); - } + // The reference in this tag map could be the only (implicitly weak) + // reference to that object. If we hand it out, we need to keep it live wrt + // SATB marking similar to other j.l.ref.Reference referents. + oopDesc::bs()->keep_alive_barrier(o); #endif jobject ref = JNIHandles::make_local(JavaThread::current(), o); _object_results->append(ref); diff --git a/src/share/vm/prims/resolvedMethodTable.cpp b/src/share/vm/prims/resolvedMethodTable.cpp --- a/src/share/vm/prims/resolvedMethodTable.cpp +++ b/src/share/vm/prims/resolvedMethodTable.cpp @@ -33,9 +33,6 @@ #include "runtime/mutexLocker.hpp" #include "utilities/hashtable.inline.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif ResolvedMethodTable::ResolvedMethodTable() @@ -76,8 +73,8 @@ // considered dead. The SATB part of G1 needs to get notified about this // potential resurrection, otherwise the marking might not find the object. #if INCLUDE_ALL_GCS - if ((UseG1GC || (UseShenandoahGC && ShenandoahSATBBarrier)) && mname != NULL) { - G1SATBCardTableModRefBS::enqueue(mname); + if (mname != NULL) { + oopDesc::bs()->keep_alive_barrier(mname); } #endif } diff --git a/src/share/vm/prims/unsafe.cpp b/src/share/vm/prims/unsafe.cpp --- a/src/share/vm/prims/unsafe.cpp +++ b/src/share/vm/prims/unsafe.cpp @@ -45,9 +45,6 @@ #include "utilities/copy.hpp" #include "utilities/dtrace.hpp" #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif // INCLUDE_ALL_GCS /** * Implementation of the jdk.internal.misc.Unsafe class @@ -297,8 +294,8 @@ static void ensure_satb_referent_alive(oop o, jlong offset, oop v) { #if INCLUDE_ALL_GCS - if ((UseG1GC || (UseShenandoahGC && ShenandoahSATBBarrier)) && v != NULL && is_java_lang_ref_Reference_access(o, offset)) { - G1SATBCardTableModRefBS::enqueue(v); + if (v != NULL && is_java_lang_ref_Reference_access(o, offset)) { + oopDesc::bs()->keep_alive_barrier(v); } #endif } diff --git a/src/share/vm/runtime/jniHandles.cpp b/src/share/vm/runtime/jniHandles.cpp --- a/src/share/vm/runtime/jniHandles.cpp +++ b/src/share/vm/runtime/jniHandles.cpp @@ -32,9 +32,6 @@ #include "runtime/mutexLocker.hpp" #include "runtime/thread.inline.hpp" #include "utilities/align.hpp" -#if INCLUDE_ALL_GCS -#include "gc/g1/g1SATBCardTableModRefBS.hpp" -#endif JNIHandleBlock* JNIHandles::_global_handles = NULL; JNIHandleBlock* JNIHandles::_weak_global_handles = NULL; @@ -117,10 +114,8 @@ oop result = jweak_ref(handle); result = guard_value(result); #if INCLUDE_ALL_GCS - if (result != NULL && (UseG1GC || (UseShenandoahGC && ShenandoahSATBBarrier))) { - G1SATBCardTableModRefBS::enqueue(result); - } -#endif // INCLUDE_ALL_GCS + oopDesc::bs()->keep_alive_barrier(result); +#endif return result; }