8226411: C2: Avoid memory barriers around off-heap unsafe accesses

Reviewed-by: kvn, thartmann, eosterlund, jrose, rkennke
This commit is contained in:
Vladimir Ivanov 2019-12-09 19:29:35 +03:00
parent 12e43e216e
commit eabb5cc21f
4 changed files with 26 additions and 14 deletions

@ -597,12 +597,15 @@ Node* G1BarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) c
Node* adr = access.addr().node();
Node* obj = access.base();
bool anonymous = (decorators & C2_UNSAFE_ACCESS) != 0;
bool mismatched = (decorators & C2_MISMATCHED) != 0;
bool unknown = (decorators & ON_UNKNOWN_OOP_REF) != 0;
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_native = (decorators & IN_NATIVE) != 0;
bool on_weak = (decorators & ON_WEAK_OOP_REF) != 0;
bool is_unordered = (decorators & MO_UNORDERED) != 0;
bool need_cpu_mem_bar = !is_unordered || mismatched || !in_heap;
bool is_mixed = !in_heap && !in_native;
bool need_cpu_mem_bar = !is_unordered || mismatched || is_mixed;
Node* top = Compile::current()->top();
Node* offset = adr->is_AddP() ? adr->in(AddPNode::Offset) : top;

@ -43,13 +43,16 @@ void* C2ParseAccess::barrier_set_state() const {
PhaseGVN& C2ParseAccess::gvn() const { return _kit->gvn(); }
bool C2Access::needs_cpu_membar() const {
bool mismatched = (_decorators & C2_MISMATCHED) != 0;
bool mismatched = (_decorators & C2_MISMATCHED) != 0;
bool is_unordered = (_decorators & MO_UNORDERED) != 0;
bool anonymous = (_decorators & C2_UNSAFE_ACCESS) != 0;
bool in_heap = (_decorators & IN_HEAP) != 0;
bool is_write = (_decorators & C2_WRITE_ACCESS) != 0;
bool is_read = (_decorators & C2_READ_ACCESS) != 0;
bool anonymous = (_decorators & C2_UNSAFE_ACCESS) != 0;
bool in_heap = (_decorators & IN_HEAP) != 0;
bool in_native = (_decorators & IN_NATIVE) != 0;
bool is_mixed = !in_heap && !in_native;
bool is_write = (_decorators & C2_WRITE_ACCESS) != 0;
bool is_read = (_decorators & C2_READ_ACCESS) != 0;
bool is_atomic = is_read && is_write;
if (is_atomic) {
@ -63,9 +66,11 @@ bool C2Access::needs_cpu_membar() const {
// the barriers get omitted and the unsafe reference begins to "pollute"
// the alias analysis of the rest of the graph, either Compile::can_alias
// or Compile::must_alias will throw a diagnostic assert.)
if (!in_heap || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) {
if (is_mixed || !is_unordered || (mismatched && !_addr.type()->isa_aryptr())) {
return true;
}
} else {
assert(!is_mixed, "not unsafe");
}
return false;
@ -80,7 +85,7 @@ Node* BarrierSetC2::store_at_resolved(C2Access& access, C2AccessValue& val) cons
bool requires_atomic_access = (decorators & MO_UNORDERED) == 0;
bool in_native = (decorators & IN_NATIVE) != 0;
assert(!in_native, "not supported yet");
assert(!in_native || (unsafe && !access.is_oop()), "not supported yet");
MemNode::MemOrd mo = access.mem_node_mo();

@ -176,11 +176,11 @@ const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF |
ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF;
// === Access Location ===
// Accesses can take place in, e.g. the heap, old or young generation and different native roots.
// Accesses can take place in, e.g. the heap, old or young generation, different native roots, or native memory off the heap.
// The location is important to the GC as it may imply different actions. The following decorators are used:
// * IN_HEAP: The access is performed in the heap. Many barriers such as card marking will
// be omitted if this decorator is not set.
// * IN_NATIVE: The access is performed in an off-heap data structure pointing into the Java heap.
// * IN_NATIVE: The access is performed in an off-heap data structure.
const DecoratorSet IN_HEAP = UCONST64(1) << 19;
const DecoratorSet IN_NATIVE = UCONST64(1) << 20;
const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE;

@ -2447,10 +2447,14 @@ bool LibraryCallKit::inline_unsafe_access(bool is_store, const BasicType type, c
offset = ConvL2X(offset);
adr = make_unsafe_address(base, offset, is_store ? ACCESS_WRITE : ACCESS_READ, type, kind == Relaxed);
if (_gvn.type(base)->isa_ptr() != TypePtr::NULL_PTR) {
heap_base_oop = base;
} else if (type == T_OBJECT) {
return false; // off-heap oop accesses are not supported
if (_gvn.type(base)->isa_ptr() == TypePtr::NULL_PTR) {
if (type != T_OBJECT) {
decorators |= IN_NATIVE; // off-heap primitive access
} else {
return false; // off-heap oop accesses are not supported
}
} else {
heap_base_oop = base; // on-heap or mixed access
}
// Can base be NULL? Otherwise, always on-heap access.