8229027: Improve how JNIHandleBlock::oops_do distinguishes oops from non-oops

Reviewed-by: pliden, stuefe, dlong
This commit is contained in:
Erik Österlund 2019-08-09 10:06:44 +02:00
parent c11080efd9
commit 98fb7b85e5
2 changed files with 31 additions and 12 deletions

View File

@ -347,6 +347,24 @@ JNIHandleBlock* JNIHandleBlock::_block_free_list = NULL;
JNIHandleBlock* JNIHandleBlock::_block_list = NULL;
#endif
static inline bool is_tagged_free_list(uintptr_t value) {
return (value & 1u) != 0;
}
static inline uintptr_t tag_free_list(uintptr_t value) {
return value | 1u;
}
static inline uintptr_t untag_free_list(uintptr_t value) {
return value & ~(uintptr_t)1u;
}
// There is a freelist of handles running through the JNIHandleBlock
// with a tagged next pointer, distinguishing these next pointers from
// oops. The freelist handling currently relies on the size of oops
// being the same as a native pointer. If this ever changes, then
// this freelist handling must change too.
STATIC_ASSERT(sizeof(oop) == sizeof(uintptr_t));
#ifdef ASSERT
void JNIHandleBlock::zap() {
@ -355,7 +373,7 @@ void JNIHandleBlock::zap() {
for (int index = 0; index < block_size_in_oops; index++) {
// NOT using Access here; just bare clobbering to NULL, since the
// block no longer contains valid oops.
_handles[index] = NULL;
_handles[index] = 0;
}
}
#endif // ASSERT
@ -459,11 +477,12 @@ void JNIHandleBlock::oops_do(OopClosure* f) {
assert(current == current_chain || current->pop_frame_link() == NULL,
"only blocks first in chain should have pop frame link set");
for (int index = 0; index < current->_top; index++) {
oop* root = &(current->_handles)[index];
oop value = *root;
uintptr_t* addr = &(current->_handles)[index];
uintptr_t value = *addr;
// traverse heap pointers only, not deleted handles or free list
// pointers
if (value != NULL && Universe::heap()->is_in_reserved(value)) {
if (value != 0 && !is_tagged_free_list(value)) {
oop* root = (oop*)addr;
f->do_oop(root);
}
}
@ -509,15 +528,15 @@ jobject JNIHandleBlock::allocate_handle(oop obj) {
// Try last block
if (_last->_top < block_size_in_oops) {
oop* handle = &(_last->_handles)[_last->_top++];
oop* handle = (oop*)&(_last->_handles)[_last->_top++];
NativeAccess<IS_DEST_UNINITIALIZED>::oop_store(handle, obj);
return (jobject) handle;
}
// Try free list
if (_free_list != NULL) {
oop* handle = _free_list;
_free_list = (oop*) *_free_list;
oop* handle = (oop*)_free_list;
_free_list = (uintptr_t*) untag_free_list(*_free_list);
NativeAccess<IS_DEST_UNINITIALIZED>::oop_store(handle, obj);
return (jobject) handle;
}
@ -550,10 +569,10 @@ void JNIHandleBlock::rebuild_free_list() {
int blocks = 0;
for (JNIHandleBlock* current = this; current != NULL; current = current->_next) {
for (int index = 0; index < current->_top; index++) {
oop* handle = &(current->_handles)[index];
if (*handle == NULL) {
uintptr_t* handle = &(current->_handles)[index];
if (*handle == 0) {
// this handle was cleared out by a delete call, reuse it
*handle = (oop) _free_list;
*handle = _free_list == NULL ? 0 : tag_free_list((uintptr_t)_free_list);
_free_list = handle;
free++;
}

View File

@ -140,7 +140,7 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
block_size_in_oops = 32 // Number of handles per handle block
};
oop _handles[block_size_in_oops]; // The handles
uintptr_t _handles[block_size_in_oops]; // The handles
int _top; // Index of next unused handle
JNIHandleBlock* _next; // Link to next block
@ -148,7 +148,7 @@ class JNIHandleBlock : public CHeapObj<mtInternal> {
// Having two types of blocks complicates the code and the space overhead in negligible.
JNIHandleBlock* _last; // Last block in use
JNIHandleBlock* _pop_frame_link; // Block to restore on PopLocalFrame call
oop* _free_list; // Handle free list
uintptr_t* _free_list; // Handle free list
int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
// Check JNI, "planned capacity" for current frame (or push/ensure)