src/share/vm/opto/library_call.cpp
Print this page
rev 5127 : 8023597: Optimize G1 barriers code for unsafe load_store
Summary: Avoid loading old values in G1 pre-barriers for inlined unsafe load_store nodes.
*** 2753,2767 ****
// could be delayed during Parse (for example, in adjust_map_after_if()).
// Execute transformation here to avoid barrier generation in such case.
if (_gvn.type(newval) == TypePtr::NULL_PTR)
newval = _gvn.makecon(TypePtr::NULL_PTR);
! // Reference stores need a store barrier.
! pre_barrier(true /* do_load*/,
! control(), base, adr, alias_idx, newval, value_type->make_oopptr(),
! NULL /* pre_val*/,
T_OBJECT);
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop()));
if (kind == LS_xchg) {
load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr,
--- 2753,2775 ----
// could be delayed during Parse (for example, in adjust_map_after_if()).
// Execute transformation here to avoid barrier generation in such case.
if (_gvn.type(newval) == TypePtr::NULL_PTR)
newval = _gvn.makecon(TypePtr::NULL_PTR);
! if (kind == LS_cmpxchg) {
! if (_gvn.type(oldval) == TypePtr::NULL_PTR) {
! oldval = _gvn.makecon(TypePtr::NULL_PTR);
! } else {
! // The only known value which might get overwritten is oldval.
! pre_barrier(false /* do_load */,
! control(), NULL, NULL, max_juint, NULL, NULL,
! oldval /* pre_val */,
T_OBJECT);
+ }
+ }
+ // LS_xchg: see below.
+
#ifdef _LP64
if (adr->bottom_type()->is_ptr_to_narrowoop()) {
Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop()));
if (kind == LS_xchg) {
load_store = _gvn.transform(new (C) GetAndSetNNode(control(), mem, adr,
*** 2793,2811 ****
// main role is to prevent LoadStore nodes from being optimized away
// when their results aren't used.
Node* proj = _gvn.transform(new (C) SCMemProjNode(load_store));
set_memory(proj, alias_idx);
! // Add the trailing membar surrounding the access
! insert_mem_bar(Op_MemBarCPUOrder);
! insert_mem_bar(Op_MemBarAcquire);
!
#ifdef _LP64
! if (type == T_OBJECT && adr->bottom_type()->is_ptr_to_narrowoop() && kind == LS_xchg) {
load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type()));
}
#endif
assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match");
set_result(load_store);
return true;
}
--- 2801,2828 ----
// main role is to prevent LoadStore nodes from being optimized away
// when their results aren't used.
Node* proj = _gvn.transform(new (C) SCMemProjNode(load_store));
set_memory(proj, alias_idx);
! if (type == T_OBJECT && kind == LS_xchg) {
#ifdef _LP64
! if (adr->bottom_type()->is_ptr_to_narrowoop()) {
load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type()));
}
#endif
+ // G1: Don't need to load pre_val. The old value is returned by load_store.
+ // The pre_barrier can execute after the xchg as long as no safepoint
+ // gets inserted between them.
+ pre_barrier(false /* do_load */,
+ control(), NULL, NULL, max_juint, NULL, NULL,
+ load_store /* pre_val */,
+ T_OBJECT);
+ }
+
+ // Add the trailing membar surrounding the access
+ insert_mem_bar(Op_MemBarCPUOrder);
+ insert_mem_bar(Op_MemBarAcquire);
assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match");
set_result(load_store);
return true;
}