8229027: Improve how JNIHandleBlock::oops_do distinguishes oops from non-oops
Reviewed-by: pliden, stuefe, dlong
This commit is contained in:
parent
c11080efd9
commit
98fb7b85e5
@ -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++;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user