Skip to content

Commit ffa4bad

Browse files
committed
8332527: ZGC: generalize object cloning logic
Reviewed-by: aboldtch, thartmann
1 parent a3a367e commit ffa4bad

File tree

3 files changed

+56
-42
lines changed

3 files changed

+56
-42
lines changed

src/hotspot/share/gc/shared/c2/barrierSetC2.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -814,8 +814,58 @@ Node* BarrierSetC2::obj_allocate(PhaseMacroExpand* macro, Node* mem, Node* toobi
814814
return old_tlab_top;
815815
}
816816

817+
static const TypeFunc* clone_type() {
818+
// Create input type (domain)
819+
int argcnt = NOT_LP64(3) LP64_ONLY(4);
820+
const Type** const domain_fields = TypeTuple::fields(argcnt);
821+
int argp = TypeFunc::Parms;
822+
domain_fields[argp++] = TypeInstPtr::NOTNULL; // src
823+
domain_fields[argp++] = TypeInstPtr::NOTNULL; // dst
824+
domain_fields[argp++] = TypeX_X; // size lower
825+
LP64_ONLY(domain_fields[argp++] = Type::HALF); // size upper
826+
assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
827+
const TypeTuple* const domain = TypeTuple::make(TypeFunc::Parms + argcnt, domain_fields);
828+
829+
// Create result type (range)
830+
const Type** const range_fields = TypeTuple::fields(0);
831+
const TypeTuple* const range = TypeTuple::make(TypeFunc::Parms + 0, range_fields);
832+
833+
return TypeFunc::make(domain, range);
834+
}
835+
817836
#define XTOP LP64_ONLY(COMMA phase->top())
818837

838+
void BarrierSetC2::clone_in_runtime(PhaseMacroExpand* phase, ArrayCopyNode* ac,
839+
address clone_addr, const char* clone_name) const {
840+
Node* const ctrl = ac->in(TypeFunc::Control);
841+
Node* const mem = ac->in(TypeFunc::Memory);
842+
Node* const src = ac->in(ArrayCopyNode::Src);
843+
Node* const dst = ac->in(ArrayCopyNode::Dest);
844+
Node* const size = ac->in(ArrayCopyNode::Length);
845+
846+
assert(size->bottom_type()->base() == Type_X,
847+
"Should be of object size type (int for 32 bits, long for 64 bits)");
848+
849+
// The native clone we are calling here expects the object size in words.
850+
// Add header/offset size to payload size to get object size.
851+
Node* const base_offset = phase->MakeConX(arraycopy_payload_base_offset(ac->is_clone_array()) >> LogBytesPerLong);
852+
Node* const full_size = phase->transform_later(new AddXNode(size, base_offset));
853+
// HeapAccess<>::clone expects size in heap words.
854+
// For 64-bits platforms, this is a no-operation.
855+
// For 32-bits platforms, we need to multiply full_size by HeapWordsPerLong (2).
856+
Node* const full_size_in_heap_words = phase->transform_later(new LShiftXNode(full_size, phase->intcon(LogHeapWordsPerLong)));
857+
858+
Node* const call = phase->make_leaf_call(ctrl,
859+
mem,
860+
clone_type(),
861+
clone_addr,
862+
clone_name,
863+
TypeRawPtr::BOTTOM,
864+
src, dst, full_size_in_heap_words XTOP);
865+
phase->transform_later(call);
866+
phase->igvn().replace_node(ac, call);
867+
}
868+
819869
void BarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
820870
Node* ctrl = ac->in(TypeFunc::Control);
821871
Node* mem = ac->in(TypeFunc::Memory);

src/hotspot/share/gc/shared/c2/barrierSetC2.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,8 @@ class BarrierSetC2: public CHeapObj<mtGC> {
280280
virtual Node* atomic_xchg_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* val_type) const;
281281
virtual Node* atomic_add_at_resolved(C2AtomicParseAccess& access, Node* new_val, const Type* val_type) const;
282282
void pin_atomic_op(C2AtomicParseAccess& access) const;
283+
void clone_in_runtime(PhaseMacroExpand* phase, ArrayCopyNode* ac,
284+
address call_addr, const char* call_name) const;
283285

284286
public:
285287
// This is the entry-point for the backend to perform accesses through the Access API.

src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp

Lines changed: 4 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -407,23 +407,6 @@ bool ZBarrierSetC2::array_copy_requires_gc_barriers(bool tightly_coupled_alloc,
407407
return type == T_OBJECT || type == T_ARRAY;
408408
}
409409

410-
// This TypeFunc assumes a 64bit system
411-
static const TypeFunc* clone_type() {
412-
// Create input type (domain)
413-
const Type** const domain_fields = TypeTuple::fields(4);
414-
domain_fields[TypeFunc::Parms + 0] = TypeInstPtr::NOTNULL; // src
415-
domain_fields[TypeFunc::Parms + 1] = TypeInstPtr::NOTNULL; // dst
416-
domain_fields[TypeFunc::Parms + 2] = TypeLong::LONG; // size lower
417-
domain_fields[TypeFunc::Parms + 3] = Type::HALF; // size upper
418-
const TypeTuple* const domain = TypeTuple::make(TypeFunc::Parms + 4, domain_fields);
419-
420-
// Create result type (range)
421-
const Type** const range_fields = TypeTuple::fields(0);
422-
const TypeTuple* const range = TypeTuple::make(TypeFunc::Parms + 0, range_fields);
423-
424-
return TypeFunc::make(domain, range);
425-
}
426-
427410
#define XTOP LP64_ONLY(COMMA phase->top())
428411

429412
void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
@@ -479,31 +462,10 @@ void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* a
479462
return;
480463
}
481464

482-
// Clone instance
483-
Node* const ctrl = ac->in(TypeFunc::Control);
484-
Node* const mem = ac->in(TypeFunc::Memory);
485-
Node* const dst = ac->in(ArrayCopyNode::Dest);
486-
Node* const size = ac->in(ArrayCopyNode::Length);
487-
488-
assert(size->bottom_type()->is_long(), "Should be long");
489-
490-
// The native clone we are calling here expects the instance size in words
491-
// Add header/offset size to payload size to get instance size.
492-
Node* const base_offset = phase->longcon(arraycopy_payload_base_offset(ac->is_clone_array()) >> LogBytesPerLong);
493-
Node* const full_size = phase->transform_later(new AddLNode(size, base_offset));
494-
495-
Node* const call = phase->make_leaf_call(ctrl,
496-
mem,
497-
clone_type(),
498-
ZBarrierSetRuntime::clone_addr(),
499-
"ZBarrierSetRuntime::clone",
500-
TypeRawPtr::BOTTOM,
501-
src,
502-
dst,
503-
full_size,
504-
phase->top());
505-
phase->transform_later(call);
506-
phase->igvn().replace_node(ac, call);
465+
// Clone instance or array where 'src' is only known to be an object (ary_ptr
466+
// is null). This can happen in bytecode generated dynamically to implement
467+
// reflective array clones.
468+
clone_in_runtime(phase, ac, ZBarrierSetRuntime::clone_addr(), "ZBarrierSetRuntime::clone");
507469
}
508470

509471
#undef XTOP

0 commit comments

Comments
 (0)