< prev index next >

src/hotspot/share/jvmci/metadataHandles.cpp

Print this page

        

@@ -20,22 +20,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
 #include "precompiled.hpp"
-#include "jvmci/metadataHandleBlock.hpp"
+#include "jvmci/metadataHandles.hpp"
 
-MetadataHandleBlock* MetadataHandleBlock::_last = NULL;
-intptr_t             MetadataHandleBlock::_free_list = 0;
-int                  MetadataHandleBlock::_allocate_before_rebuild = 0;
-
-jmetadata MetadataHandleBlock::allocate_metadata_handle(Metadata* obj) {
+jmetadata MetadataHandles::allocate_metadata_handle(Metadata* obj) {
   assert(obj->is_valid() && obj->is_metadata(), "must be");
 
-  if (_last == NULL) {
+  if (_head == NULL) {
     // This is the first allocation.
-    _last = this;
+    _head = new MetadataHandleBlock();
+    _last = _head;
+    _num_blocks++;
   }
 
   HandleRecord* handle = get_handle();
 
   if (handle != NULL) {

@@ -44,11 +42,11 @@
     handle->set_name(obj->print_value_string());
 #endif
     return (jmetadata) handle;
   }
 
-  // Check if unused block follow last
+  // Check if an unused block follows last
   if (_last->_next != NULL) {
     // update last and retry
     _last = _last->_next;
     return allocate_metadata_handle(obj);
   }

@@ -56,70 +54,84 @@
   // No space available, we have to rebuild free list or expand
   if (_allocate_before_rebuild == 0) {
     rebuild_free_list();        // updates _allocate_before_rebuild counter
   } else {
     // Append new block
-    // This can block, but the caller has a metadata handle around this object.
-    _last->_next = allocate_block();
+    _last->_next = new MetadataHandleBlock();
     _last = _last->_next;
     _allocate_before_rebuild--;
+    _num_blocks++;
   }
   return allocate_metadata_handle(obj);  // retry
 }
 
 
-void MetadataHandleBlock::rebuild_free_list() {
+void MetadataHandles::rebuild_free_list() {
   assert(_allocate_before_rebuild == 0 && _free_list == 0, "just checking");
   int free = 0;
   int blocks = 0;
-  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+  for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
     for (int index = 0; index < current->_top; index++) {
       HandleRecord* handle = &(current->_handles)[index];
       if (handle->value() == NULL) {
         // this handle was cleared out by a delete call, reuse it
         chain_free_list(handle);
         free++;
       }
     }
     // we should not rebuild free list if there are unused handles at the end
-    assert(current->_top == block_size_in_handles, "just checking");
+    assert(current->_top == MetadataHandleBlock::block_size_in_handles, "just checking");
     blocks++;
   }
+  assert(_num_blocks == blocks, "%d != %d", _num_blocks, blocks);
+  assert(_num_free_handles == free, "%d != %d", _num_free_handles, free);
   // Heuristic: if more than half of the handles are NOT free we rebuild next time
   // as well, otherwise we append a corresponding number of new blocks before
   // attempting a free list rebuild again.
-  int total = blocks * block_size_in_handles;
+  int total = blocks * MetadataHandleBlock::block_size_in_handles;
   int extra = total - 2*free;
   if (extra > 0) {
     // Not as many free handles as we would like - compute number of new blocks to append
-    _allocate_before_rebuild = (extra + block_size_in_handles - 1) / block_size_in_handles;
+    _allocate_before_rebuild = (extra + MetadataHandleBlock::block_size_in_handles - 1) / MetadataHandleBlock::block_size_in_handles;
+  }
+}
+
+void MetadataHandles::clear() {
+  _free_list = 0;
+  _last = _head;
+  if (_head != NULL) {
+    for (MetadataHandleBlock* block = _head; block != NULL; block = block->_next) {
+      block->_top = 0;
+    }
   }
+  _num_handles = 0;
+  _num_free_handles = 0;
 }
 
-void MetadataHandleBlock::metadata_do(void f(Metadata*)) {
-  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+void MetadataHandles::metadata_do(void f(Metadata*)) {
+  for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
     for (int index = 0; index < current->_top; index++) {
       HandleRecord* root = &(current->_handles)[index];
       Metadata* value = root->value();
       // traverse heap pointers only, not deleted handles or free list
       // pointers
       if (value != NULL && ((intptr_t) value & ptr_tag) == 0) {
-        assert(value->is_valid(), "invalid metadata %s", get_name(index));
+        assert(value->is_valid(), "invalid metadata %s", current->get_name(index));
         f(value);
       }
     }
     // the next handle block is valid only if current block is full
-    if (current->_top < block_size_in_handles) {
+    if (current->_top < MetadataHandleBlock::block_size_in_handles) {
       break;
     }
   }
 }
 
 // Visit any live metadata handles and clean them up.  Since clearing of these handles is driven by
 // weak references they will be cleared at some point in the future when the reference cleaning logic is run.
-void MetadataHandleBlock::do_unloading() {
-  for (MetadataHandleBlock* current = this; current != NULL; current = current->_next) {
+void MetadataHandles::do_unloading() {
+  for (MetadataHandleBlock* current = _head; current != NULL; current = current->_next) {
     for (int index = 0; index < current->_top; index++) {
       HandleRecord* handle = &(current->_handles)[index];
       Metadata* value = handle->value();
       // traverse heap pointers only, not deleted handles or free list
       // pointers

@@ -149,10 +161,10 @@
           }
         }
       }
     }
     // the next handle block is valid only if current block is full
-    if (current->_top < block_size_in_handles) {
+    if (current->_top < MetadataHandleBlock::block_size_in_handles) {
       break;
     }
   }
 }
< prev index next >