# HG changeset patch # User rkennke # Date 1569855616 -7200 # Node ID 752bf4d5fbb7f7ee01b52c746db81a40dc083862 # Parent ff559f979c4be66db540a901f05f7f2cd66dde18 8231499: Shenandoah: compiler/arraycopy/TestDefaultMethodArrayCloneDeoptC2 fails Reviewed-by: shade, roland diff -r ff559f979c4b -r 752bf4d5fbb7 src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Mon Sep 30 14:04:42 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp Mon Sep 30 17:00:16 2019 +0200 @@ -38,6 +38,7 @@ #include "opto/movenode.hpp" #include "opto/narrowptrnode.hpp" #include "opto/rootnode.hpp" +#include "opto/runtime.hpp" ShenandoahBarrierSetC2* ShenandoahBarrierSetC2::bsc2() { return reinterpret_cast(BarrierSet::barrier_set()->barrier_set_c2()); @@ -461,12 +462,9 @@ } const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() { - const Type **fields = TypeTuple::fields(4); - fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // src oop - fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // src - fields[TypeFunc::Parms+2] = TypeRawPtr::NOTNULL; // dst - fields[TypeFunc::Parms+3] = TypeInt::INT; // length - const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+4, fields); + const Type **fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = TypeOopPtr::NOTNULL; // src oop + const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); // create result type (range) fields = TypeTuple::fields(0); @@ -797,8 +795,6 @@ return false; } -#define XTOP LP64_ONLY(COMMA phase->top()) - void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCopyNode* ac) const { Node* ctrl = ac->in(TypeFunc::Control); Node* mem = ac->in(TypeFunc::Memory); @@ -812,13 +808,62 @@ assert (dest->is_AddP(), "for clone the dst should be the interior ptr"); if (ShenandoahCloneBarrier && clone_needs_barrier(src, phase->igvn())) { - Node* call = phase->make_leaf_call(ctrl, mem, + // Check if heap is has forwarded objects. If it does, we need to call into the special + // routine that would fix up source references before we can continue. + + enum { _heap_stable = 1, _heap_unstable, PATH_LIMIT }; + Node* region = new RegionNode(PATH_LIMIT); + Node* mem_phi = new PhiNode(region, Type::MEMORY, TypeRawPtr::BOTTOM); + + Node* thread = phase->transform_later(new ThreadLocalNode()); + Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset())); + Node* gc_state_addr = phase->transform_later(new AddPNode(phase->C->top(), thread, offset)); + + uint gc_state_idx = Compile::AliasIdxRaw; + const TypePtr* gc_state_adr_type = NULL; // debug-mode-only argument + debug_only(gc_state_adr_type = phase->C->get_adr_type(gc_state_idx)); + + Node* gc_state = phase->transform_later(new LoadBNode(ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered)); + Node* stable_and = phase->transform_later(new AndINode(gc_state, phase->igvn().intcon(ShenandoahHeap::HAS_FORWARDED))); + Node* stable_cmp = phase->transform_later(new CmpINode(stable_and, phase->igvn().zerocon(T_INT))); + Node* stable_test = phase->transform_later(new BoolNode(stable_cmp, BoolTest::ne)); + + IfNode* stable_iff = phase->transform_later(new IfNode(ctrl, stable_test, PROB_UNLIKELY(0.999), COUNT_UNKNOWN))->as_If(); + Node* stable_ctrl = phase->transform_later(new IfFalseNode(stable_iff)); + Node* unstable_ctrl = phase->transform_later(new IfTrueNode(stable_iff)); + + // Heap is stable, no need to do anything additional + region->init_req(_heap_stable, stable_ctrl); + mem_phi->init_req(_heap_stable, mem); + + // Heap is unstable, call into clone barrier stub + Node* call = phase->make_leaf_call(unstable_ctrl, mem, ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(), CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier), "shenandoah_clone", TypeRawPtr::BOTTOM, - src->in(AddPNode::Base), src, dest, length); + src->in(AddPNode::Base)); call = phase->transform_later(call); + + ctrl = phase->transform_later(new ProjNode(call, TypeFunc::Control)); + mem = phase->transform_later(new ProjNode(call, TypeFunc::Memory)); + region->init_req(_heap_unstable, ctrl); + mem_phi->init_req(_heap_unstable, mem); + + // Wire up the actual arraycopy stub now + ctrl = phase->transform_later(region); + mem = phase->transform_later(mem_phi); + + const char* name = "arraycopy"; + call = phase->make_leaf_call(ctrl, mem, + OptoRuntime::fast_arraycopy_Type(), + phase->basictype2arraycopy(T_LONG, NULL, NULL, true, name, true), + name, TypeRawPtr::BOTTOM, + src, dest, length + LP64_ONLY(COMMA phase->top())); + call = phase->transform_later(call); + + // Hook up the whole thing into the graph phase->igvn().replace_node(ac, call); } else { BarrierSetC2::clone_at_expansion(phase, ac); diff -r ff559f979c4b -r 752bf4d5fbb7 src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Mon Sep 30 14:04:42 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp Mon Sep 30 17:00:16 2019 +0200 @@ -286,6 +286,8 @@ } void ShenandoahBarrierSet::clone_barrier_runtime(oop src) { - clone_barrier(src); + if (_heap->has_forwarded_objects()) { + clone_barrier(src); + } } diff -r ff559f979c4b -r 752bf4d5fbb7 src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp Mon Sep 30 14:04:42 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp Mon Sep 30 17:00:16 2019 +0200 @@ -73,7 +73,7 @@ void ShenandoahBarrierSet::clone_barrier(oop obj) { assert(ShenandoahCloneBarrier, "only get here with clone barriers enabled"); - if (!_heap->has_forwarded_objects()) return; + assert(_heap->has_forwarded_objects(), "only when heap is unstable"); // This is called for cloning an object (see jvm.cpp) after the clone // has been made. We are not interested in any 'previous value' because diff -r ff559f979c4b -r 752bf4d5fbb7 src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp Mon Sep 30 14:04:42 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp Mon Sep 30 17:00:16 2019 +0200 @@ -76,13 +76,10 @@ // Shenandoah clone barrier: makes sure that references point to to-space // in cloned objects. -JRT_LEAF(void, ShenandoahRuntime::shenandoah_clone_barrier(oopDesc* src, void* src_ptr, void* dst_ptr, size_t length)) +JRT_LEAF(void, ShenandoahRuntime::shenandoah_clone_barrier(oopDesc* src)) oop s = oop(src); shenandoah_assert_correct(NULL, s); ShenandoahBarrierSet::barrier_set()->clone_barrier(s); - Copy::conjoint_jlongs_atomic(reinterpret_cast(src_ptr), - reinterpret_cast(dst_ptr), - length); JRT_END JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_native(oopDesc * src)) diff -r ff559f979c4b -r 752bf4d5fbb7 src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Mon Sep 30 14:04:42 2019 +0200 +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp Mon Sep 30 17:00:16 2019 +0200 @@ -44,7 +44,7 @@ static oopDesc* load_reference_barrier_native(oopDesc* src); - static void shenandoah_clone_barrier(oopDesc* src, void* src_ptr, void* dst_ptr, size_t length); + static void shenandoah_clone_barrier(oopDesc* src); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHRUNTIME_HPP