< prev index next >
src/hotspot/share/jvmci/metadataHandles.hpp
Print this page
*** 19,30 ****
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
! #ifndef SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
! #define SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
#include "oops/constantPool.hpp"
#include "oops/metadata.hpp"
#include "oops/method.hpp"
#include "runtime/handles.hpp"
--- 19,30 ----
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
! #ifndef SHARE_JVMCI_METADATAHANDLES_HPP
! #define SHARE_JVMCI_METADATAHANDLES_HPP
#include "oops/constantPool.hpp"
#include "oops/metadata.hpp"
#include "oops/method.hpp"
#include "runtime/handles.hpp"
*** 70,111 ****
#endif
};
typedef struct _jmetadata HandleRecord;
typedef struct _jmetadata *jmetadata;
- // JVMCI maintains direct references to metadata. To make these references safe in the face of
- // class redefinition, they are held in handles so they can be scanned during GC. They are
- // managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
- // passed back to the Java code which is responsible for setting the handle to NULL when it
- // is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
- // rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
private:
enum SomeConstants {
! block_size_in_handles = 32, // Number of handles per handle block
! ptr_tag = 1,
! ptr_mask = ~((intptr_t)ptr_tag)
};
-
// Free handles always have their low bit set so those pointers can
// be distinguished from handles which are in use. The last handle
// on the free list has a NULL pointer with the tag bit set, so it's
// clear that the handle has been reclaimed. The _free_list is
// always a real pointer to a handle.
HandleRecord _handles[block_size_in_handles]; // The handles
int _top; // Index of next unused handle
MetadataHandleBlock* _next; // Link to next block
- // The following instance variables are only used by the first block in a chain.
- // Having two types of blocks complicates the code and the space overhead is negligible.
- static MetadataHandleBlock* _last; // Last block in use
- static intptr_t _free_list; // Handle free list
- static int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
-
MetadataHandleBlock() {
_top = 0;
_next = NULL;
#ifdef METADATA_TRACK_NAMES
for (int i = 0; i < block_size_in_handles; i++) {
--- 70,98 ----
#endif
};
typedef struct _jmetadata HandleRecord;
typedef struct _jmetadata *jmetadata;
+ class MetadataHandles;
class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
+ friend class MetadataHandles;
private:
enum SomeConstants {
! block_size_in_handles = 32 // Number of handles per handle block
};
// Free handles always have their low bit set so those pointers can
// be distinguished from handles which are in use. The last handle
// on the free list has a NULL pointer with the tag bit set, so it's
// clear that the handle has been reclaimed. The _free_list is
// always a real pointer to a handle.
HandleRecord _handles[block_size_in_handles]; // The handles
int _top; // Index of next unused handle
MetadataHandleBlock* _next; // Link to next block
MetadataHandleBlock() {
_top = 0;
_next = NULL;
#ifdef METADATA_TRACK_NAMES
for (int i = 0; i < block_size_in_handles; i++) {
*** 119,142 ****
return _handles[index].name();
#else
return "<missing>";
#endif
}
! static HandleRecord* get_free_handle() {
! assert(_free_list != 0, "should check before calling");
HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
_free_list = (ptr_mask & (intptr_t) (handle->value()));
assert(_free_list != ptr_tag, "should be null");
! handle->set_value(NULL);
return handle;
}
! static HandleRecord* get_handle() {
assert(_last != NULL, "sanity");
// Try last block
! if (_last->_top < block_size_in_handles) {
return &(_last->_handles)[_last->_top++];
} else if (_free_list != 0) {
// Try free list
return get_free_handle();
}
--- 106,151 ----
return _handles[index].name();
#else
return "<missing>";
#endif
}
+ };
! // JVMCI maintains direct references to metadata. To make these references safe in the face of
! // class redefinition, they are held in handles so they can be scanned during GC. They are
! // managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
! // passed back to the Java code which is responsible for setting the handle to NULL when it
! // is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
! // rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
! class MetadataHandles : public CHeapObj<mtJVMCI> {
! private:
! enum SomeConstants {
! ptr_tag = 1,
! ptr_mask = ~((intptr_t)ptr_tag)
! };
!
! MetadataHandleBlock* _head; // First block
! MetadataHandleBlock* _last; // Last block in use
! intptr_t _free_list; // Handle free list
! int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
! int _num_blocks; // Number of blocks
! int _num_handles;
! int _num_free_handles;
!
! HandleRecord* get_free_handle() {
HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
_free_list = (ptr_mask & (intptr_t) (handle->value()));
assert(_free_list != ptr_tag, "should be null");
! _num_free_handles--;
return handle;
}
! HandleRecord* get_handle() {
assert(_last != NULL, "sanity");
// Try last block
! if (_last->_top < MetadataHandleBlock::block_size_in_handles) {
! _num_handles++;
return &(_last->_handles)[_last->_top++];
} else if (_free_list != 0) {
// Try free list
return get_free_handle();
}
*** 146,170 ****
void rebuild_free_list();
jmetadata allocate_metadata_handle(Metadata* metadata);
public:
jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); }
jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
! static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); }
!
! // Adds `handle` to the free list in this block
! static void chain_free_list(HandleRecord* handle) {
handle->set_value((Metadata*) (ptr_tag | _free_list));
#ifdef METADATA_TRACK_NAMES
handle->set_name(NULL);
#endif
_free_list = (intptr_t) handle;
}
void metadata_do(void f(Metadata*));
void do_unloading();
};
! #endif // SHARE_JVMCI_METADATAHANDLEBLOCK_HPP
--- 155,195 ----
void rebuild_free_list();
jmetadata allocate_metadata_handle(Metadata* metadata);
public:
+ MetadataHandles() {
+ _head = NULL;
+ _last = NULL;
+ _free_list = 0;
+ _allocate_before_rebuild = 0;
+ _num_blocks = 0;
+ _num_handles = 0;
+ _num_free_handles = 0;
+ }
+
+ int num_handles() const { return _num_handles; }
+ int num_free_handles() const { return _num_free_handles; }
+ int num_blocks() const { return _num_blocks; }
+
jmetadata allocate_handle(const methodHandle& handle) { return allocate_metadata_handle(handle()); }
jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
! // Adds `handle` to the free list
! void chain_free_list(HandleRecord* handle) {
handle->set_value((Metadata*) (ptr_tag | _free_list));
#ifdef METADATA_TRACK_NAMES
handle->set_name(NULL);
#endif
_free_list = (intptr_t) handle;
+ _num_free_handles++;
}
+ // Clears all handles without releasing any handle memory.
+ void clear();
+
void metadata_do(void f(Metadata*));
void do_unloading();
};
! #endif // SHARE_JVMCI_METADATAHANDLES_HPP
< prev index next >