8267726: ZGC: array_copy_requires_gc_barriers too strict

Reviewed-by: thartmann, vlivanov
This commit is contained in:
Nils Eliasson 2021-06-02 09:02:37 +00:00
parent d47a77d2d5
commit bba3728e23
10 changed files with 21 additions and 12 deletions

@ -254,7 +254,7 @@ public:
Expansion
};
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const { return false; }
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const { return false; }
virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const;
// Support for GC barriers emitted during parsing

@ -176,7 +176,7 @@ void CardTableBarrierSetC2::eliminate_gc_barrier(PhaseMacroExpand* macro, Node*
}
}
bool CardTableBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
bool CardTableBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const {
bool is_oop = is_reference_type(type);
return is_oop && (!tightly_coupled_alloc || !use_ReduceInitialCardMarks());
}

@ -45,7 +45,7 @@ public:
virtual void clone(GraphKit* kit, Node* src, Node* dst, Node* size, bool is_array) const;
virtual bool is_gc_barrier_node(Node* node) const;
virtual void eliminate_gc_barrier(PhaseMacroExpand* macro, Node* node) const;
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const;
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const;
bool use_ReduceInitialCardMarks() const;
};

@ -763,7 +763,7 @@ bool ShenandoahBarrierSetC2::optimize_loops(PhaseIdealLoop* phase, LoopOptsMode
return false;
}
bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const {
bool ShenandoahBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const {
bool is_oop = is_reference_type(type);
if (!is_oop) {
return false;

@ -109,7 +109,7 @@ public:
virtual void clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const;
// These are general helper methods used by C2
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, ArrayCopyPhase phase) const;
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type, bool is_clone, bool is_clone_instance, ArrayCopyPhase phase) const;
// Support for GC barriers emitted during parsing
virtual bool is_gc_barrier_node(Node* node) const;

@ -224,7 +224,15 @@ Node* ZBarrierSetC2::atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node*
}
bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc, BasicType type,
bool is_clone, ArrayCopyPhase phase) const {
bool is_clone, bool is_clone_instance,
ArrayCopyPhase phase) const {
if (phase == ArrayCopyPhase::Parsing) {
return false;
}
if (phase == ArrayCopyPhase::Optimization) {
return is_clone_instance;
}
// else ArrayCopyPhase::Expansion
return type == T_OBJECT || type == T_ARRAY;
}

@ -83,6 +83,7 @@ public:
virtual bool array_copy_requires_gc_barriers(bool tightly_coupled_alloc,
BasicType type,
bool is_clone,
bool is_clone_instance,
ArrayCopyPhase phase) const;
virtual void clone_at_expansion(PhaseMacroExpand* phase,
ArrayCopyNode* ac) const;

@ -276,7 +276,7 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
}
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
if (bs->array_copy_requires_gc_barriers(is_alloc_tightly_coupled(), dest_elem, false, BarrierSetC2::Optimization)) {
if (bs->array_copy_requires_gc_barriers(is_alloc_tightly_coupled(), dest_elem, false, false, BarrierSetC2::Optimization)) {
// It's an object array copy but we can't emit the card marking
// that is needed
return false;
@ -319,7 +319,7 @@ bool ArrayCopyNode::prepare_array_copy(PhaseGVN *phase, bool can_reshape,
}
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
if (bs->array_copy_requires_gc_barriers(true, elem, true, BarrierSetC2::Optimization)) {
if (bs->array_copy_requires_gc_barriers(true, elem, true, is_clone_inst(), BarrierSetC2::Optimization)) {
return false;
}
@ -423,7 +423,7 @@ Node* ArrayCopyNode::array_copy_backward(PhaseGVN *phase,
MergeMemNode* mm = MergeMemNode::make(mem);
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
assert(copy_type != T_OBJECT || !bs->array_copy_requires_gc_barriers(false, T_OBJECT, false, BarrierSetC2::Optimization), "only tightly coupled allocations for object arrays");
assert(copy_type != T_OBJECT || !bs->array_copy_requires_gc_barriers(false, T_OBJECT, false, false, BarrierSetC2::Optimization), "only tightly coupled allocations for object arrays");
if (count > 0) {
for (int i = count-1; i >= 1; i--) {
@ -456,7 +456,7 @@ bool ArrayCopyNode::finish_transform(PhaseGVN *phase, bool can_reshape,
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
if (out_mem->outcnt() != 1 || !out_mem->raw_out(0)->is_MergeMem() ||
out_mem->raw_out(0)->outcnt() != 1 || !out_mem->raw_out(0)->raw_out(0)->is_MemBar()) {
assert(bs->array_copy_requires_gc_barriers(true, T_OBJECT, true, BarrierSetC2::Optimization), "can only happen with card marking");
assert(bs->array_copy_requires_gc_barriers(true, T_OBJECT, true, is_clone_inst(), BarrierSetC2::Optimization), "can only happen with card marking");
return false;
}

@ -4233,7 +4233,7 @@ bool LibraryCallKit::inline_native_clone(bool is_virtual) {
Node* alloc_obj = new_array(obj_klass, obj_length, 0, &obj_size, /*deoptimize_on_exception=*/true);
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
if (bs->array_copy_requires_gc_barriers(true, T_OBJECT, true, BarrierSetC2::Parsing)) {
if (bs->array_copy_requires_gc_barriers(true, T_OBJECT, true, false, BarrierSetC2::Parsing)) {
// If it is an oop array, it requires very special treatment,
// because gc barriers are required when accessing the array.
Node* is_obja = generate_objArray_guard(obj_klass, (RegionNode*)NULL);

@ -656,7 +656,7 @@ Node* PhaseMacroExpand::generate_arraycopy(ArrayCopyNode *ac, AllocateArrayNode*
// At this point we know we do not need type checks on oop stores.
BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2();
if (!bs->array_copy_requires_gc_barriers(alloc != NULL, copy_type, false, BarrierSetC2::Expansion)) {
if (!bs->array_copy_requires_gc_barriers(alloc != NULL, copy_type, false, false, BarrierSetC2::Expansion)) {
// If we do not need gc barriers, copy using the jint or jlong stub.
copy_type = LP64_ONLY(UseCompressedOops ? T_INT : T_LONG) NOT_LP64(T_INT);
assert(type2aelembytes(basic_elem_type) == type2aelembytes(copy_type),