< 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 >