8205559: Remove IN_CONCURRENT_ROOT Access decorator

Removed decorator and made all NativeAccess use barriers.

Reviewed-by: pliden, stefank
This commit is contained in:
Kim Barrett 2018-06-26 16:59:38 -04:00
parent ed24b806f1
commit 8a2170dad7
18 changed files with 54 additions and 80 deletions

View File

@ -2127,8 +2127,7 @@ void MacroAssembler::resolve_jobject(Register value, Register thread, Register t
bind(not_weak);
// Resolve (untagged) jobject.
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT, value, Address(value, 0), tmp,
thread);
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp, thread);
verify_oop(value);
bind(done);
}
@ -3643,8 +3642,7 @@ void MacroAssembler::load_klass(Register dst, Register src) {
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result, Register tmp) {
// OopHandle::resolve is an indirection.
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT,
result, Address(result, 0), tmp, noreg);
access_load_at(T_OBJECT, IN_NATIVE, result, Address(result, 0), tmp, noreg);
}
void MacroAssembler::load_mirror(Register dst, Register method, Register tmp) {

View File

@ -321,9 +321,10 @@ void G1BarrierSetAssembler::load_at(MacroAssembler* masm, DecoratorSet decorator
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0;
bool as_normal = (decorators & AS_NORMAL) != 0;
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
bool needs_pre_barrier = in_heap || in_concurrent_root;
bool needs_pre_barrier = as_normal;
bool needs_post_barrier = (new_val != noreg) && in_heap;
// flatten object address if needed
@ -360,7 +361,7 @@ void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet deco
g1_write_barrier_post(masm, store_addr, new_val, tmp1, tmp2, tmp3);
}
}
};
}
#ifdef COMPILER1

View File

@ -2140,7 +2140,7 @@ void MacroAssembler::resolve_jobject(Register value,
b(done);
bind(not_weak);
// Resolve (untagged) jobject.
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT,
access_load_at(T_OBJECT, IN_NATIVE,
Address(value, 0), value, tmp1, tmp2, noreg);
verify_oop(value);
bind(done);

View File

@ -400,9 +400,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm, Register
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Register val, Address dst, Register tmp) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0;
bool as_normal = (decorators & AS_NORMAL) != 0;
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
bool needs_pre_barrier = in_heap || in_concurrent_root;
bool needs_pre_barrier = as_normal;
// No need for post barrier if storing NULL
bool needs_post_barrier = val != G0 && in_heap;

View File

@ -182,8 +182,7 @@ void MacroAssembler::resolve_jobject(Register value, Register tmp) {
br (Assembler::always, true, Assembler::pt, done);
delayed()->nop();
bind(not_weak);
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT,
Address(value, 0), value, tmp);
access_load_at(T_OBJECT, IN_NATIVE, Address(value, 0), value, tmp);
verify_oop(value);
bind(done);
}
@ -3402,8 +3401,7 @@ void MacroAssembler::reserved_stack_check() {
// ((OopHandle)result).resolve();
void MacroAssembler::resolve_oop_handle(Register result, Register tmp) {
// OopHandle::resolve is an indirection.
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT,
Address(result, 0), result, tmp);
access_load_at(T_OBJECT, IN_NATIVE, Address(result, 0), result, tmp);
}
void MacroAssembler::load_mirror(Register mirror, Register method, Register tmp) {

View File

@ -349,9 +349,10 @@ void G1BarrierSetAssembler::g1_write_barrier_post(MacroAssembler* masm,
void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
Address dst, Register val, Register tmp1, Register tmp2) {
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_concurrent_root = (decorators & IN_CONCURRENT_ROOT) != 0;
bool as_normal = (decorators & AS_NORMAL) != 0;
assert((decorators & IS_DEST_UNINITIALIZED) == 0, "unsupported");
bool needs_pre_barrier = in_heap || in_concurrent_root;
bool needs_pre_barrier = as_normal;
bool needs_post_barrier = val != noreg && in_heap;
Register tmp3 = LP64_ONLY(r8) NOT_LP64(rsi);

View File

@ -5238,8 +5238,7 @@ void MacroAssembler::resolve_jobject(Register value,
jmp(done);
bind(not_weak);
// Resolve (untagged) jobject.
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT,
value, Address(value, 0), tmp, thread);
access_load_at(T_OBJECT, IN_NATIVE, value, Address(value, 0), tmp, thread);
verify_oop(value);
bind(done);
}
@ -6216,7 +6215,7 @@ void MacroAssembler::resolve_oop_handle(Register result, Register tmp) {
// Only 64 bit platforms support GCs that require a tmp register
// Only IN_HEAP loads require a thread_tmp register
// OopHandle::resolve is an indirection like jobject.
access_load_at(T_OBJECT, IN_CONCURRENT_ROOT,
access_load_at(T_OBJECT, IN_NATIVE,
result, Address(result, 0), tmp, /*tmp_thread*/noreg);
}

View File

@ -832,9 +832,7 @@ void ClassLoaderData::remove_handle(OopHandle h) {
oop* ptr = h.ptr_raw();
if (ptr != NULL) {
assert(_handles.owner_of(ptr), "Got unexpected handle " PTR_FORMAT, p2i(ptr));
// This root is not walked in safepoints, and hence requires an appropriate
// decorator that e.g. maintains the SATB invariant in SATB collectors.
NativeAccess<IN_CONCURRENT_ROOT>::oop_store(ptr, oop(NULL));
NativeAccess<>::oop_store(ptr, oop(NULL));
}
}

View File

@ -52,11 +52,6 @@ void G1BarrierSetC1::pre_barrier(LIRAccess& access, LIR_Opr addr_opr,
LIR_Opr pre_val, CodeEmitInfo* info) {
LIRGenerator* gen = access.gen();
DecoratorSet decorators = access.decorators();
bool in_heap = (decorators & IN_HEAP) != 0;
bool in_conc_root = (decorators & IN_CONCURRENT_ROOT) != 0;
if (!in_heap && !in_conc_root) {
return;
}
// First we test whether marking is in progress.
BasicType flag_type;

View File

@ -98,12 +98,10 @@ template <DecoratorSet decorators, typename BarrierSetT>
template <typename T>
inline void G1BarrierSet::AccessBarrier<decorators, BarrierSetT>::
oop_store_not_in_heap(T* addr, oop new_value) {
if (HasDecorator<decorators, IN_CONCURRENT_ROOT>::value) {
// For roots not scanned in a safepoint, we have to apply SATB barriers
// even for roots.
G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
bs->write_ref_field_pre<decorators>(addr);
}
// Apply SATB barriers for all non-heap references, to allow
// concurrent scanning of such references.
G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set());
bs->write_ref_field_pre<decorators>(addr);
Raw::oop_store(addr, new_value);
}

View File

@ -281,13 +281,11 @@ typeArrayOop StringDedupTable::lookup(typeArrayOop value, bool latin1, unsigned
StringDedupEntry** list, uintx &count) {
for (StringDedupEntry* entry = *list; entry != NULL; entry = entry->next()) {
if (entry->hash() == hash && entry->latin1() == latin1) {
typeArrayOop existing_value = entry->obj();
if (equals(value, existing_value)) {
// Apply proper barrier to make sure it is kept alive. Concurrent mark might
// otherwise declare it dead if there are no other strong references to this object.
oop* obj_addr = (oop*)entry->obj_addr();
oop obj = NativeAccess<IN_CONCURRENT_ROOT | ON_WEAK_OOP_REF>::oop_load(obj_addr);
return typeArrayOop(obj);
oop* obj_addr = (oop*)entry->obj_addr();
oop obj = NativeAccess<ON_PHANTOM_OOP_REF | AS_NO_KEEPALIVE>::oop_load(obj_addr);
if (equals(value, static_cast<typeArrayOop>(obj))) {
obj = NativeAccess<ON_PHANTOM_OOP_REF>::oop_load(obj_addr);
return static_cast<typeArrayOop>(obj);
}
}
count++;

View File

@ -653,7 +653,6 @@ Node* ZBarrierSetC2::load_at_resolved(C2Access& access, const Type* val_type) co
return p;
}
bool conc_root = (access.decorators() & IN_CONCURRENT_ROOT) != 0;
bool weak = (access.decorators() & ON_WEAK_OOP_REF) != 0;
GraphKit* kit = access.kit();

View File

@ -48,12 +48,9 @@ bool ZBarrierSet::barrier_needed(DecoratorSet decorators, BasicType type) {
//assert((decorators & ON_UNKNOWN_OOP_REF) == 0, "Unexpected decorator");
if (type == T_OBJECT || type == T_ARRAY) {
if (((decorators & IN_HEAP) != 0) ||
((decorators & IN_CONCURRENT_ROOT) != 0) ||
((decorators & ON_PHANTOM_OOP_REF) != 0)) {
// Barrier needed
return true;
}
assert((decorators & (IN_HEAP | IN_NATIVE)) != 0, "Where is reference?");
// Barrier needed even when IN_NATIVE, to allow concurrent scanning.
return true;
}
// Barrier not neeed

View File

@ -375,8 +375,7 @@ void Access<decorators>::verify_decorators() {
const DecoratorSet location_decorators = decorators & IN_DECORATOR_MASK;
STATIC_ASSERT(location_decorators == 0 || ( // make sure location decorators are disjoint if set
(location_decorators ^ IN_NATIVE) == 0 ||
(location_decorators ^ IN_HEAP) == 0 ||
(location_decorators ^ (IN_NATIVE | IN_CONCURRENT_ROOT)) == 0
(location_decorators ^ IN_HEAP) == 0
));
}

View File

@ -153,8 +153,8 @@ const DecoratorSet MO_DECORATOR_MASK = MO_UNORDERED | MO_VOLATILE | MO_RELAXED |
// Note that primitive accesses will only be resolved on the barrier set if the appropriate build-time
// decorator for enabling primitive barriers is enabled for the build.
const DecoratorSet AS_RAW = UCONST64(1) << 12;
const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 14;
const DecoratorSet AS_NORMAL = UCONST64(1) << 15;
const DecoratorSet AS_NO_KEEPALIVE = UCONST64(1) << 13;
const DecoratorSet AS_NORMAL = UCONST64(1) << 14;
const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_NO_KEEPALIVE | AS_NORMAL;
// === Reference Strength Decorators ===
@ -166,10 +166,10 @@ const DecoratorSet AS_DECORATOR_MASK = AS_RAW | AS_NO_KEEPALIVE | AS_NORMA
// * ON_UNKNOWN_OOP_REF: The memory access is performed on a reference of unknown strength.
// This could for example come from the unsafe API.
// * Default (no explicit reference strength specified): ON_STRONG_OOP_REF
const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 16;
const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 17;
const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 18;
const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 19;
const DecoratorSet ON_STRONG_OOP_REF = UCONST64(1) << 15;
const DecoratorSet ON_WEAK_OOP_REF = UCONST64(1) << 16;
const DecoratorSet ON_PHANTOM_OOP_REF = UCONST64(1) << 17;
const DecoratorSet ON_UNKNOWN_OOP_REF = UCONST64(1) << 18;
const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF |
ON_PHANTOM_OOP_REF | ON_UNKNOWN_OOP_REF;
@ -179,13 +179,9 @@ const DecoratorSet ON_DECORATOR_MASK = ON_STRONG_OOP_REF | ON_WEAK_OOP_REF |
// * 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_CONCURRENT_ROOT: The access is performed in an off-heap data structure pointing into the Java heap,
// but is notably not scanned during safepoints. This is sometimes a special case for some GCs and
// implies that it is also an IN_NATIVE.
const DecoratorSet IN_HEAP = UCONST64(1) << 20;
const DecoratorSet IN_NATIVE = UCONST64(1) << 22;
const DecoratorSet IN_CONCURRENT_ROOT = UCONST64(1) << 23;
const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE | IN_CONCURRENT_ROOT;
const DecoratorSet IN_HEAP = UCONST64(1) << 19;
const DecoratorSet IN_NATIVE = UCONST64(1) << 20;
const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE;
// == Boolean Flag Decorators ==
// * IS_ARRAY: The access is performed on a heap allocated array. This is sometimes a special case
@ -194,8 +190,8 @@ const DecoratorSet IN_DECORATOR_MASK = IN_HEAP | IN_NATIVE | IN_CONCURRENT_ROOT
// marking that the previous value is uninitialized nonsense rather than a real value.
// * IS_NOT_NULL: This property can make certain barriers faster such as compressing oops.
const DecoratorSet IS_ARRAY = UCONST64(1) << 21;
const DecoratorSet IS_DEST_UNINITIALIZED = UCONST64(1) << 13;
const DecoratorSet IS_NOT_NULL = UCONST64(1) << 25;
const DecoratorSet IS_DEST_UNINITIALIZED = UCONST64(1) << 22;
const DecoratorSet IS_NOT_NULL = UCONST64(1) << 23;
// == Arraycopy Decorators ==
// * ARRAYCOPY_CHECKCAST: This property means that the class of the objects in source
@ -207,17 +203,17 @@ const DecoratorSet IS_NOT_NULL = UCONST64(1) << 25;
// * ARRAYCOPY_ARRAYOF: The copy is in the arrayof form.
// * ARRAYCOPY_ATOMIC: The accesses have to be atomic over the size of its elements.
// * ARRAYCOPY_ALIGNED: The accesses have to be aligned on a HeapWord.
const DecoratorSet ARRAYCOPY_CHECKCAST = UCONST64(1) << 26;
const DecoratorSet ARRAYCOPY_DISJOINT = UCONST64(1) << 27;
const DecoratorSet ARRAYCOPY_ARRAYOF = UCONST64(1) << 28;
const DecoratorSet ARRAYCOPY_ATOMIC = UCONST64(1) << 29;
const DecoratorSet ARRAYCOPY_ALIGNED = UCONST64(1) << 30;
const DecoratorSet ARRAYCOPY_CHECKCAST = UCONST64(1) << 24;
const DecoratorSet ARRAYCOPY_DISJOINT = UCONST64(1) << 25;
const DecoratorSet ARRAYCOPY_ARRAYOF = UCONST64(1) << 26;
const DecoratorSet ARRAYCOPY_ATOMIC = UCONST64(1) << 27;
const DecoratorSet ARRAYCOPY_ALIGNED = UCONST64(1) << 28;
const DecoratorSet ARRAYCOPY_DECORATOR_MASK = ARRAYCOPY_CHECKCAST | ARRAYCOPY_DISJOINT |
ARRAYCOPY_DISJOINT | ARRAYCOPY_ARRAYOF |
ARRAYCOPY_ATOMIC | ARRAYCOPY_ALIGNED;
// Keep track of the last decorator.
const DecoratorSet DECORATOR_LAST = UCONST64(1) << 30;
const DecoratorSet DECORATOR_LAST = UCONST64(1) << 28;
namespace AccessInternal {
// This class adds implied decorators that follow according to decorator rules.
@ -235,9 +231,7 @@ namespace AccessInternal {
// If no barrier strength has been picked, normal will be used
static const DecoratorSet barrier_strength_default = memory_ordering_default |
((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
static const DecoratorSet conc_root_is_root = barrier_strength_default |
((IN_CONCURRENT_ROOT & barrier_strength_default) != 0 ? IN_NATIVE : INTERNAL_EMPTY);
static const DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS;
static const DecoratorSet value = barrier_strength_default | BT_BUILDTIME_DECORATORS;
};
// This function implements the above DecoratorFixup rules, but without meta
@ -253,9 +247,7 @@ namespace AccessInternal {
// If no barrier strength has been picked, normal will be used
DecoratorSet barrier_strength_default = memory_ordering_default |
((AS_DECORATOR_MASK & memory_ordering_default) == 0 ? AS_NORMAL : INTERNAL_EMPTY);
DecoratorSet conc_root_is_root = barrier_strength_default |
((IN_CONCURRENT_ROOT & barrier_strength_default) != 0 ? IN_NATIVE : INTERNAL_EMPTY);
DecoratorSet value = conc_root_is_root | BT_BUILDTIME_DECORATORS;
DecoratorSet value = barrier_strength_default | BT_BUILDTIME_DECORATORS;
return value;
}
}

View File

@ -29,7 +29,7 @@
#include "oops/oopHandle.hpp"
inline oop OopHandle::resolve() const {
return (_obj == NULL) ? (oop)NULL : NativeAccess<IN_CONCURRENT_ROOT>::oop_load(_obj);
return (_obj == NULL) ? (oop)NULL : NativeAccess<>::oop_load(_obj);
}
#endif // SHARE_VM_OOPS_OOPHANDLE_INLINE_HPP

View File

@ -109,7 +109,7 @@ jobject JNIHandles::make_global(Handle obj, AllocFailType alloc_failmode) {
// Return NULL on allocation failure.
if (ptr != NULL) {
assert(*ptr == NULL, "invariant");
NativeAccess<IN_CONCURRENT_ROOT>::oop_store(ptr, obj());
NativeAccess<>::oop_store(ptr, obj());
res = reinterpret_cast<jobject>(ptr);
} else {
report_handle_allocation_failure(alloc_failmode, "global");
@ -175,7 +175,7 @@ void JNIHandles::destroy_global(jobject handle) {
if (handle != NULL) {
assert(!is_jweak(handle), "wrong method for detroying jweak");
oop* oop_ptr = jobject_ptr(handle);
NativeAccess<IN_CONCURRENT_ROOT>::oop_store(oop_ptr, (oop)NULL);
NativeAccess<>::oop_store(oop_ptr, (oop)NULL);
global_handles()->release(oop_ptr);
}
}

View File

@ -57,7 +57,7 @@ inline oop JNIHandles::resolve_impl(jobject handle) {
if (is_jweak(handle)) { // Unlikely
result = resolve_jweak(handle);
} else {
result = NativeAccess<IN_CONCURRENT_ROOT>::oop_load(jobject_ptr(handle));
result = NativeAccess<>::oop_load(jobject_ptr(handle));
// Construction of jobjects canonicalize a null value into a null
// jobject, so for non-jweak the pointee should never be null.
assert(external_guard || result != NULL, "Invalid JNI handle");