38
38
#include " opto/movenode.hpp"
39
39
#include " opto/narrowptrnode.hpp"
40
40
#include " opto/rootnode.hpp"
41
+ #include " opto/runtime.hpp"
41
42
42
43
ShenandoahBarrierSetC2* ShenandoahBarrierSetC2::bsc2 () {
43
44
return reinterpret_cast <ShenandoahBarrierSetC2*>(BarrierSet::barrier_set ()->barrier_set_c2 ());
@@ -461,12 +462,9 @@ const TypeFunc* ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type() {
461
462
}
462
463
463
464
const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type () {
464
- const Type **fields = TypeTuple::fields (4 );
465
- fields[TypeFunc::Parms+0 ] = TypeInstPtr::NOTNULL; // src oop
466
- fields[TypeFunc::Parms+1 ] = TypeRawPtr::NOTNULL; // src
467
- fields[TypeFunc::Parms+2 ] = TypeRawPtr::NOTNULL; // dst
468
- fields[TypeFunc::Parms+3 ] = TypeInt::INT; // length
469
- const TypeTuple *domain = TypeTuple::make (TypeFunc::Parms+4 , fields);
465
+ const Type **fields = TypeTuple::fields (1 );
466
+ fields[TypeFunc::Parms+0 ] = TypeOopPtr::NOTNULL; // src oop
467
+ const TypeTuple *domain = TypeTuple::make (TypeFunc::Parms+1 , fields);
470
468
471
469
// create result type (range)
472
470
fields = TypeTuple::fields (0 );
@@ -797,8 +795,6 @@ bool ShenandoahBarrierSetC2::clone_needs_barrier(Node* src, PhaseGVN& gvn) {
797
795
return false ;
798
796
}
799
797
800
- #define XTOP LP64_ONLY (COMMA phase->top ())
801
-
802
798
void ShenandoahBarrierSetC2::clone_at_expansion (PhaseMacroExpand* phase, ArrayCopyNode* ac) const {
803
799
Node* ctrl = ac->in (TypeFunc::Control);
804
800
Node* mem = ac->in (TypeFunc::Memory);
@@ -812,13 +808,62 @@ void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCo
812
808
assert (dest->is_AddP (), " for clone the dst should be the interior ptr" );
813
809
814
810
if (ShenandoahCloneBarrier && clone_needs_barrier (src, phase->igvn ())) {
815
- Node* call = phase->make_leaf_call (ctrl, mem,
811
+ // Check if heap is has forwarded objects. If it does, we need to call into the special
812
+ // routine that would fix up source references before we can continue.
813
+
814
+ enum { _heap_stable = 1 , _heap_unstable, PATH_LIMIT };
815
+ Node* region = new RegionNode (PATH_LIMIT);
816
+ Node* mem_phi = new PhiNode (region, Type::MEMORY, TypeRawPtr::BOTTOM);
817
+
818
+ Node* thread = phase->transform_later (new ThreadLocalNode ());
819
+ Node* offset = phase->igvn ().MakeConX (in_bytes (ShenandoahThreadLocalData::gc_state_offset ()));
820
+ Node* gc_state_addr = phase->transform_later (new AddPNode (phase->C ->top (), thread, offset));
821
+
822
+ uint gc_state_idx = Compile::AliasIdxRaw;
823
+ const TypePtr* gc_state_adr_type = NULL ; // debug-mode-only argument
824
+ debug_only (gc_state_adr_type = phase->C ->get_adr_type (gc_state_idx));
825
+
826
+ Node* gc_state = phase->transform_later (new LoadBNode (ctrl, mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered));
827
+ Node* stable_and = phase->transform_later (new AndINode (gc_state, phase->igvn ().intcon (ShenandoahHeap::HAS_FORWARDED)));
828
+ Node* stable_cmp = phase->transform_later (new CmpINode (stable_and, phase->igvn ().zerocon (T_INT)));
829
+ Node* stable_test = phase->transform_later (new BoolNode (stable_cmp, BoolTest::ne));
830
+
831
+ IfNode* stable_iff = phase->transform_later (new IfNode (ctrl, stable_test, PROB_UNLIKELY (0.999 ), COUNT_UNKNOWN))->as_If ();
832
+ Node* stable_ctrl = phase->transform_later (new IfFalseNode (stable_iff));
833
+ Node* unstable_ctrl = phase->transform_later (new IfTrueNode (stable_iff));
834
+
835
+ // Heap is stable, no need to do anything additional
836
+ region->init_req (_heap_stable, stable_ctrl);
837
+ mem_phi->init_req (_heap_stable, mem);
838
+
839
+ // Heap is unstable, call into clone barrier stub
840
+ Node* call = phase->make_leaf_call (unstable_ctrl, mem,
816
841
ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type (),
817
842
CAST_FROM_FN_PTR (address, ShenandoahRuntime::shenandoah_clone_barrier),
818
843
" shenandoah_clone" ,
819
844
TypeRawPtr::BOTTOM,
820
- src->in (AddPNode::Base), src, dest, length );
845
+ src->in (AddPNode::Base));
821
846
call = phase->transform_later (call);
847
+
848
+ ctrl = phase->transform_later (new ProjNode (call, TypeFunc::Control));
849
+ mem = phase->transform_later (new ProjNode (call, TypeFunc::Memory));
850
+ region->init_req (_heap_unstable, ctrl);
851
+ mem_phi->init_req (_heap_unstable, mem);
852
+
853
+ // Wire up the actual arraycopy stub now
854
+ ctrl = phase->transform_later (region);
855
+ mem = phase->transform_later (mem_phi);
856
+
857
+ const char * name = " arraycopy" ;
858
+ call = phase->make_leaf_call (ctrl, mem,
859
+ OptoRuntime::fast_arraycopy_Type (),
860
+ phase->basictype2arraycopy (T_LONG, NULL , NULL , true , name, true ),
861
+ name, TypeRawPtr::BOTTOM,
862
+ src, dest, length
863
+ LP64_ONLY (COMMA phase->top ()));
864
+ call = phase->transform_later (call);
865
+
866
+ // Hook up the whole thing into the graph
822
867
phase->igvn ().replace_node (ac, call);
823
868
} else {
824
869
BarrierSetC2::clone_at_expansion (phase, ac);
0 commit comments