diff -r a4ddd1667c72 -r 304c63b17b07 src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp --- a/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Tue Nov 05 10:11:18 2019 +0000 +++ b/src/hotspot/share/gc/z/c2/zBarrierSetC2.cpp Thu Oct 31 17:16:36 2019 +0100 @@ -27,14 +27,17 @@ #include "gc/z/zBarrierSet.hpp" #include "gc/z/zBarrierSetAssembler.hpp" #include "gc/z/zBarrierSetRuntime.hpp" +#include "opto/arraycopynode.hpp" #include "opto/block.hpp" #include "opto/compile.hpp" #include "opto/graphKit.hpp" #include "opto/machnode.hpp" +#include "opto/macro.hpp" #include "opto/memnode.hpp" #include "opto/node.hpp" #include "opto/regalloc.hpp" #include "opto/rootnode.hpp" +#include "opto/runtime.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" @@ -429,3 +432,50 @@ } } } + +const TypeFunc *oop_clone_Type() { + // create input type (domain) + const Type **fields = TypeTuple::fields(3); + fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // src Object + fields[TypeFunc::Parms+1] = TypeInstPtr::NOTNULL; // dst Object + fields[TypeFunc::Parms+2] = TypeInt::INT; // Object size + const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+3, fields); + + // create result type (range) + fields = TypeTuple::fields(0); + + const TypeTuple *range = TypeTuple::make(TypeFunc::Parms+0, fields); + + return TypeFunc::make(domain, range); +} + +void ZBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const { + Node *ctrl = ac->in(TypeFunc::Control); + Node *mem = ac->in(TypeFunc::Memory); + Node *src = ac->in(ArrayCopyNode::Src); + Node *src_offset = ac->in(ArrayCopyNode::SrcPos); + Node *dest = ac->in(ArrayCopyNode::Dest); + Node *dest_offset = ac->in(ArrayCopyNode::DestPos); + Node *length = ac->in(ArrayCopyNode::Length); + + assert (src_offset == NULL, "for clone offsets should be null"); + assert (dest_offset == NULL, "for clone offsets should be null"); + + if (src->bottom_type()->isa_instptr()) { + // Instances must have all oop fiels healed before cloning - call runtime leaf + const char *clonefunc_name = "clone_oop"; + address clonefunc_addr = ZBarrierSetRuntime::clone_oop_addr(); + const TypePtr *raw_adr_type = TypeRawPtr::BOTTOM; + const TypeFunc *call_type = oop_clone_Type(); + + Node *call = phase->make_leaf_call(ctrl, mem, call_type, clonefunc_addr, clonefunc_name, raw_adr_type, src, dest, + length); + phase->transform_later(call); + phase->igvn().replace_node(ac, call); + } else { + assert(src->bottom_type()->isa_aryptr() != NULL, "Only arrays"); + + // Clones of primitive arrays go here + BarrierSetC2::clone_at_expansion(phase, ac); + } +}