< prev index next >
src/hotspot/share/jvmci/metadataHandles.hpp
Print this page
@@ -19,12 +19,12 @@
* 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
+#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,42 +70,29 @@
#endif
};
typedef struct _jmetadata HandleRecord;
typedef struct _jmetadata *jmetadata;
+class MetadataHandles;
-// 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> {
+ friend class MetadataHandles;
private:
enum SomeConstants {
- block_size_in_handles = 32, // Number of handles per handle block
- ptr_tag = 1,
- ptr_mask = ~((intptr_t)ptr_tag)
+ 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
- // 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++) {
@@ -119,24 +106,46 @@
return _handles[index].name();
#else
return "<missing>";
#endif
}
+};
- static HandleRecord* get_free_handle() {
- assert(_free_list != 0, "should check before calling");
+// 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");
- handle->set_value(NULL);
+ _num_free_handles--;
return handle;
}
- static HandleRecord* get_handle() {
+ HandleRecord* get_handle() {
assert(_last != NULL, "sanity");
// Try last block
- if (_last->_top < block_size_in_handles) {
+ 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,25 +155,41 @@
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()); }
- static MetadataHandleBlock* allocate_block() { return new MetadataHandleBlock(); }
-
- // Adds `handle` to the free list in this block
- static void chain_free_list(HandleRecord* 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_METADATAHANDLEBLOCK_HPP
+#endif // SHARE_JVMCI_METADATAHANDLES_HPP
< prev index next >