# HG changeset patch # User eosterlund # Date 1565338004 -7200 # Node ID 9dc92e89243afeec18b734ca020f22838b2cd65c # Parent 2e38a71e60381e92d56a1e8fa688e36a5401ab3b 8229027: Improve how JNIHandleBlock::oops_do distinguishes oops from non-oops Reviewed-by: pliden, stuefe, dlong diff -r 2e38a71e6038 -r 9dc92e89243a src/hotspot/share/runtime/jniHandles.cpp --- a/src/hotspot/share/runtime/jniHandles.cpp Fri Aug 09 03:51:20 2019 +0200 +++ b/src/hotspot/share/runtime/jniHandles.cpp Fri Aug 09 10:06:44 2019 +0200 @@ -347,6 +347,24 @@ 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 @@ 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 @@ 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 @@ // Try last block if (_last->_top < block_size_in_oops) { - oop* handle = &(_last->_handles)[_last->_top++]; + oop* handle = (oop*)&(_last->_handles)[_last->_top++]; NativeAccess::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::oop_store(handle, obj); return (jobject) handle; } @@ -550,10 +569,10 @@ 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++; } diff -r 2e38a71e6038 -r 9dc92e89243a src/hotspot/share/runtime/jniHandles.hpp --- a/src/hotspot/share/runtime/jniHandles.hpp Fri Aug 09 03:51:20 2019 +0200 +++ b/src/hotspot/share/runtime/jniHandles.hpp Fri Aug 09 10:06:44 2019 +0200 @@ -140,7 +140,7 @@ 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 @@ // 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)