< prev index next >
src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp
Print this page
rev 58543 : 8241605: Shenandoah: More aggressive reference discovery
*** 858,869 ****
phase->lazy_replace(outer, new_outer);
phase->lazy_replace(le, new_le);
inner->clear_strip_mined();
}
! void ShenandoahBarrierC2Support::test_heap_stable(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
! PhaseIdealLoop* phase) {
IdealLoopTree* loop = phase->get_loop(ctrl);
Node* thread = new ThreadLocalNode();
phase->register_new_node(thread, ctrl);
Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
phase->set_ctrl(offset, phase->C->root());
--- 858,869 ----
phase->lazy_replace(outer, new_outer);
phase->lazy_replace(le, new_le);
inner->clear_strip_mined();
}
! void ShenandoahBarrierC2Support::test_heap_state(Node*& ctrl, Node* raw_mem, Node*& heap_stable_ctrl,
! PhaseIdealLoop* phase, int flags) {
IdealLoopTree* loop = phase->get_loop(ctrl);
Node* thread = new ThreadLocalNode();
phase->register_new_node(thread, ctrl);
Node* offset = phase->igvn().MakeConX(in_bytes(ShenandoahThreadLocalData::gc_state_offset()));
phase->set_ctrl(offset, phase->C->root());
*** 873,883 ****
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 = new LoadBNode(ctrl, raw_mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered);
phase->register_new_node(gc_state, ctrl);
! Node* heap_stable_and = new AndINode(gc_state, phase->igvn().intcon(ShenandoahHeap::HAS_FORWARDED));
phase->register_new_node(heap_stable_and, ctrl);
Node* heap_stable_cmp = new CmpINode(heap_stable_and, phase->igvn().zerocon(T_INT));
phase->register_new_node(heap_stable_cmp, ctrl);
Node* heap_stable_test = new BoolNode(heap_stable_cmp, BoolTest::ne);
phase->register_new_node(heap_stable_test, ctrl);
--- 873,883 ----
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 = new LoadBNode(ctrl, raw_mem, gc_state_addr, gc_state_adr_type, TypeInt::BYTE, MemNode::unordered);
phase->register_new_node(gc_state, ctrl);
! Node* heap_stable_and = new AndINode(gc_state, phase->igvn().intcon(flags));
phase->register_new_node(heap_stable_and, ctrl);
Node* heap_stable_cmp = new CmpINode(heap_stable_and, phase->igvn().zerocon(T_INT));
phase->register_new_node(heap_stable_cmp, ctrl);
Node* heap_stable_test = new BoolNode(heap_stable_cmp, BoolTest::ne);
phase->register_new_node(heap_stable_test, ctrl);
*** 887,897 ****
heap_stable_ctrl = new IfFalseNode(heap_stable_iff);
phase->register_control(heap_stable_ctrl, loop, heap_stable_iff);
ctrl = new IfTrueNode(heap_stable_iff);
phase->register_control(ctrl, loop, heap_stable_iff);
! assert(is_heap_stable_test(heap_stable_iff), "Should match the shape");
}
void ShenandoahBarrierC2Support::test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase) {
const Type* val_t = phase->igvn().type(val);
if (val_t->meet(TypePtr::NULL_PTR) == val_t) {
--- 887,897 ----
heap_stable_ctrl = new IfFalseNode(heap_stable_iff);
phase->register_control(heap_stable_ctrl, loop, heap_stable_iff);
ctrl = new IfTrueNode(heap_stable_iff);
phase->register_control(ctrl, loop, heap_stable_iff);
! assert(is_heap_state_test(heap_stable_iff, flags), "Should match the shape");
}
void ShenandoahBarrierC2Support::test_null(Node*& ctrl, Node* val, Node*& null_ctrl, PhaseIdealLoop* phase) {
const Type* val_t = phase->igvn().type(val);
if (val_t->meet(TypePtr::NULL_PTR) == val_t) {
*** 1435,1445 ****
Node* region = new RegionNode(PATH_LIMIT);
Node* val_phi = new PhiNode(region, uncasted_val->bottom_type()->is_oopptr());
Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
// Stable path.
! test_heap_stable(ctrl, raw_mem, heap_stable_ctrl, phase);
IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If();
// Heap stable case
region->init_req(_heap_stable, heap_stable_ctrl);
val_phi->init_req(_heap_stable, uncasted_val);
--- 1435,1445 ----
Node* region = new RegionNode(PATH_LIMIT);
Node* val_phi = new PhiNode(region, uncasted_val->bottom_type()->is_oopptr());
Node* raw_mem_phi = PhiNode::make(region, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
// Stable path.
! test_heap_state(ctrl, raw_mem, heap_stable_ctrl, phase, ShenandoahHeap::HAS_FORWARDED);
IfNode* heap_stable_iff = heap_stable_ctrl->in(0)->as_If();
// Heap stable case
region->init_req(_heap_stable, heap_stable_ctrl);
val_phi->init_req(_heap_stable, uncasted_val);
*** 1568,1582 ****
}
// Done expanding load-reference-barriers.
assert(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0, "all load reference barrier nodes should have been replaced");
for (int i = state->enqueue_barriers_count() - 1; i >= 0; i--) {
! Node* barrier = state->enqueue_barrier(i);
Node* pre_val = barrier->in(1);
! if (phase->igvn().type(pre_val)->higher_equal(TypePtr::NULL_PTR)) {
! ShouldNotReachHere();
continue;
}
Node* ctrl = phase->get_ctrl(barrier);
--- 1568,1584 ----
}
// Done expanding load-reference-barriers.
assert(ShenandoahBarrierSetC2::bsc2()->state()->load_reference_barriers_count() == 0, "all load reference barrier nodes should have been replaced");
for (int i = state->enqueue_barriers_count() - 1; i >= 0; i--) {
! ShenandoahEnqueueBarrierNode* barrier = state->enqueue_barrier(i);
Node* pre_val = barrier->in(1);
! assert(!phase->igvn().type(pre_val)->higher_equal(TypePtr::NULL_PTR), "no known-NULLs here");
!
! if (barrier->can_eliminate(phase)) {
! phase->igvn().replace_node(barrier, pre_val);
continue;
}
Node* ctrl = phase->get_ctrl(barrier);
*** 1606,1616 ****
enum { _fast_path = 1, _slow_path, _null_path, PATH_LIMIT2 };
Node* region2 = new RegionNode(PATH_LIMIT2);
Node* phi2 = PhiNode::make(region2, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
// Stable path.
! test_heap_stable(ctrl, raw_mem, heap_stable_ctrl, phase);
region->init_req(_heap_stable, heap_stable_ctrl);
phi->init_req(_heap_stable, raw_mem);
// Null path
Node* reg2_ctrl = NULL;
--- 1608,1618 ----
enum { _fast_path = 1, _slow_path, _null_path, PATH_LIMIT2 };
Node* region2 = new RegionNode(PATH_LIMIT2);
Node* phi2 = PhiNode::make(region2, raw_mem, Type::MEMORY, TypeRawPtr::BOTTOM);
// Stable path.
! test_heap_state(ctrl, raw_mem, heap_stable_ctrl, phase, ShenandoahHeap::TRAVERSAL | ShenandoahHeap::MARKING);
region->init_req(_heap_stable, heap_stable_ctrl);
phi->init_req(_heap_stable, raw_mem);
// Null path
Node* reg2_ctrl = NULL;
*** 2169,2178 ****
--- 2171,2261 ----
}
ShouldNotReachHere();
return NULL;
}
+ bool ShenandoahEnqueueBarrierNode::can_eliminate(PhaseIdealLoop* phase) {
+ return ShenandoahHeap::heap()->traversal_gc() == NULL &&
+ is_redundant() && ShenandoahAggressiveReferenceDiscovery;
+ }
+
+ bool ShenandoahEnqueueBarrierNode::is_redundant() {
+ Unique_Node_List visited;
+ Node_Stack stack(0);
+ stack.push(this, 0);
+
+ while (stack.size() > 0) {
+ Node* n = stack.node();
+ if (visited.member(n)) {
+ stack.pop();
+ continue;
+ }
+ visited.push(n);
+ bool visit_users = false;
+ switch (n->Opcode()) {
+ case Op_CallStaticJava:
+ if (n->as_CallStaticJava()->uncommon_trap_request() == 0) {
+ return false;
+ }
+ break;
+ case Op_CallDynamicJava:
+ case Op_CompareAndExchangeN:
+ case Op_CompareAndExchangeP:
+ case Op_CompareAndSwapN:
+ case Op_CompareAndSwapP:
+ case Op_ShenandoahCompareAndSwapN:
+ case Op_ShenandoahCompareAndSwapP:
+ case Op_GetAndSetN:
+ case Op_GetAndSetP:
+ case Op_Return:
+ case Op_StoreN:
+ case Op_StoreP:
+ return false;
+ break;
+ case Op_AddP:
+ case Op_Allocate:
+ case Op_AllocateArray:
+ case Op_ArrayCopy:
+ case Op_CmpP:
+ case Op_LoadL:
+ case Op_SafePoint:
+ case Op_SubTypeCheck:
+ case Op_StoreLConditional:
+ case Op_StoreIConditional:
+ case Op_FastUnlock:
+ break;
+ case Op_CastPP:
+ case Op_CheckCastPP:
+ case Op_CMoveN:
+ case Op_CMoveP:
+ case Op_EncodeP:
+ case Op_Phi:
+ case Op_ShenandoahEnqueueBarrier:
+ visit_users = true;
+ break;
+ default: {
+ #ifdef ASSERT
+ fatal("Unknown node in is_redundant: %s", NodeClassNames[n->Opcode()]);
+ #endif
+ // Default to useful: better to have excess barriers, rather than miss some.
+ return false;
+ }
+ }
+
+ stack.pop();
+ if (visit_users) {
+ for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) {
+ Node* user = n->fast_out(i);
+ if (user != NULL) {
+ stack.push(user, 0);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
Node* ShenandoahEnqueueBarrierNode::Identity(PhaseGVN* phase) {
PhaseIterGVN* igvn = phase->is_IterGVN();
Node* n = next(in(1));
*** 3243,3253 ****
case Op_GetAndSetN:
case Op_GetAndAddL:
case Op_GetAndAddI:
case Op_GetAndAddB:
case Op_GetAndAddS:
- case Op_ShenandoahEnqueueBarrier:
case Op_FastLock:
case Op_FastUnlock:
case Op_Rethrow:
case Op_Return:
case Op_StoreB:
--- 3326,3335 ----
*** 3320,3329 ****
--- 3402,3412 ----
case Op_CheckCastPP:
case Op_CastPP:
case Op_CMoveP:
case Op_Phi:
case Op_ShenandoahLoadReferenceBarrier:
+ case Op_ShenandoahEnqueueBarrier:
// Whether or not these need the barriers depends on their users
visit_users = true;
break;
default: {
#ifdef ASSERT
< prev index next >