--- old/src/share/vm/opto/loopopts.cpp 2015-10-08 22:15:51.875203520 +0200 +++ new/src/share/vm/opto/loopopts.cpp 2015-10-08 22:15:51.818204881 +0200 @@ -33,6 +33,7 @@ #include "opto/movenode.hpp" #include "opto/opaquenode.hpp" #include "opto/rootnode.hpp" +#include "opto/shenandoahSupport.hpp" #include "opto/subnode.hpp" //============================================================================= @@ -67,6 +68,9 @@ if (region->in(i) == C->top()) { x = C->top(); // Dead path? Use a dead data op } else { +#ifdef ASSERT + if (n->is_ShenandoahBarrier()) { n->as_ShenandoahBarrier()->check_invariants(); } +#endif x = n->clone(); // Else clone up the data op the_clone = x; // Remember for possible deletion. // Alter data node to use pre-phi inputs @@ -111,21 +115,26 @@ // otherwise it will be not updated during igvn->transform since // igvn->type(x) is set to x->Value() already. x->raise_bottom_type(t); - Node *y = x->Identity(&_igvn); - if (y != x) { - wins++; - x = y; - } else { - y = _igvn.hash_find(x); - if (y) { + if (x->Opcode() != Op_ShenandoahWriteBarrier) { + Node *y = x->Identity(&_igvn); + if (y != x) { wins++; x = y; } else { - // Else x is a new node we are keeping - // We do not need register_new_node_with_optimizer - // because set_type has already been called. - _igvn._worklist.push(x); + y = _igvn.hash_find(x); + if (y) { + wins++; + x = y; + } else { + // Else x is a new node we are keeping + // We do not need register_new_node_with_optimizer + // because set_type has already been called. + _igvn._worklist.push(x); + } } + } else { + // wins++; + _igvn._worklist.push(x); } } if (x != the_clone && the_clone != NULL) @@ -194,6 +203,38 @@ return phi; } +void PhaseIdealLoop::split_mem_thru_phi(Node* n, Node* r, Node* phi) { + if (n->Opcode() == Op_ShenandoahWriteBarrier) { +#ifdef ASSERT + n->as_ShenandoahBarrier()->check_invariants(); +#endif + if (n->has_out_with(Op_ShenandoahWBMemProj)) { + Node* old_mem_phi = n->in(ShenandoahBarrierNode::Memory); + assert(r->is_Region(), "need region to control phi"); + assert(phi->is_Phi(), "expect phi"); + Node* memphi = PhiNode::make(r, old_mem_phi, Type::MEMORY, C->alias_type(n->adr_type())->adr_type()); + for (uint i = 1; i < r->req(); i++) { + Node* wb = phi->in(i); + if (wb->Opcode() == Op_ShenandoahWriteBarrier) { + assert(! wb->has_out_with(Op_ShenandoahWBMemProj), "new clone does not have mem proj"); + Node* new_proj = new ShenandoahWBMemProjNode(wb); + register_new_node(new_proj, r->in(i)); + memphi->set_req(i, new_proj); + } else { + if (old_mem_phi->is_Phi() && old_mem_phi->in(0) == r) { + memphi->set_req(i, old_mem_phi->in(i)); + } + } + } + register_new_node(memphi, r); + Node* old_mem_out = n->find_out_with(Op_ShenandoahWBMemProj); + assert(old_mem_out != NULL, "expect memory projection"); + _igvn.replace_node(old_mem_out, memphi); + } + assert(! n->has_out_with(Op_ShenandoahWBMemProj), "no more memory outs"); + } +} + //------------------------------dominated_by------------------------------------ // Replace the dominated test with an obvious true or false. Place it on the // IGVN worklist for later cleanup. Move control-dependent data Nodes on the @@ -934,12 +975,18 @@ // Found a Phi to split thru! // Replace 'n' with the new phi + split_mem_thru_phi(n, n_blk, phi); _igvn.replace_node( n, phi ); // Moved a load around the loop, 'en-registering' something. if (n_blk->is_Loop() && n->is_Load() && !phi->in(LoopNode::LoopBackControl)->is_Load()) C->set_major_progress(); + // Moved a barrier around the loop, 'en-registering' something. + if (n_blk->is_Loop() && n->is_ShenandoahBarrier() && + !phi->in(LoopNode::LoopBackControl)->is_ShenandoahBarrier()) + C->set_major_progress(); + return phi; } @@ -1082,9 +1129,11 @@ // Found a Phi to split thru! // Replace 'n' with the new phi + assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet"); _igvn.replace_node( n, phi ); // Now split the bool up thru the phi + assert(bol->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet"); Node *bolphi = split_thru_phi( bol, n_ctrl, -1 ); guarantee(bolphi != NULL, "null boolean phi node"); @@ -1096,6 +1145,7 @@ // Conditional-move? Must split up now if( !iff->is_If() ) { + assert(iff->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet"); Node *cmovphi = split_thru_phi( iff, n_ctrl, -1 ); _igvn.replace_node( iff, cmovphi ); return; @@ -1229,7 +1279,7 @@ // to fold a StoreP and an AddP together (as part of an // address expression) and the AddP and StoreP have // different controls. - if (!x->is_Load() && !x->is_DecodeNarrowPtr()) _igvn._worklist.yank(x); + if (!x->is_Load() && !x->is_DecodeNarrowPtr() && !x->is_ShenandoahBarrier()) _igvn._worklist.yank(x); } _igvn.remove_dead_node(n); } @@ -1502,6 +1552,16 @@ uint i; for( i = 0; i < loop->_body.size(); i++ ) { Node *old = loop->_body.at(i); +#ifdef ASSERT + if (old->Opcode() == Op_ShenandoahWriteBarrier) { + Node* memproj = old->find_out_with(Op_ShenandoahWBMemProj); + assert(memproj == NULL || (loop->is_member(get_loop(has_ctrl(memproj) ? get_ctrl(memproj) : memproj))), "WB's mem-proj must be in loop too"); + } + if (old->Opcode() == Op_ShenandoahWBMemProj) { + Node* wb = old->in(0); + assert(loop->is_member(get_loop(has_ctrl(wb) ? get_ctrl(wb) : wb)), "WB must be in loop too"); + } +#endif Node *nnn = old->clone(); old_new.map( old->_idx, nnn ); if (C->do_vector_loop()) { @@ -1692,12 +1752,13 @@ // private Phi and those Phis need to be merged here. Node *phi; if( prev->is_Region() ) { - if( idx == 0 ) { // Updating control edge? + if( idx == 0 && use->Opcode() != Op_ShenandoahWBMemProj) { // Updating control edge? phi = prev; // Just use existing control } else { // Else need a new Phi phi = PhiNode::make( prev, old ); // Now recursively fix up the new uses of old! - for( uint i = 1; i < prev->req(); i++ ) { + uint first = use->Opcode() != Op_ShenandoahWBMemProj ? 1 : 0; + for( uint i = first; i < prev->req(); i++ ) { worklist.push(phi); // Onto worklist once for each 'old' input } } @@ -1705,7 +1766,7 @@ // Get new RegionNode merging old and new loop exits prev = old_new[prev->_idx]; assert( prev, "just made this in step 7" ); - if( idx == 0 ) { // Updating control edge? + if( idx == 0 && use->Opcode() != Op_ShenandoahWBMemProj) { // Updating control edge? phi = prev; // Just use existing control } else { // Else need a new Phi // Make a new Phi merging data values properly @@ -2188,6 +2249,7 @@ int PhaseIdealLoop::clone_for_use_outside_loop( IdealLoopTree *loop, Node* n, Node_List& worklist ) { int cloned = 0; assert(worklist.size() == 0, "should be empty"); + assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers yet"); for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* use = n->fast_out(j); if( !loop->is_member(get_loop(has_ctrl(use) ? get_ctrl(use) : use)) ) { @@ -2204,6 +2266,7 @@ assert(j < use->req(), "must be there"); // clone "n" and insert it between the inputs of "n" and the use outside the loop + assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers"); Node* n_clone = n->clone(); _igvn.replace_input_of(use, j, n_clone); cloned++; @@ -2250,6 +2313,7 @@ } if (worklist.size() > 0) { // clone "n" and insert it between inputs of "n" and the use + assert(n->Opcode() != Op_ShenandoahWriteBarrier, "not with write barriers"); Node* n_clone = n->clone(); loop->_body.push(n_clone); _igvn.register_new_node_with_optimizer(n_clone);