1 /*
   2  * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 #ifndef SHARE_JVMCI_METADATAHANDLES_HPP
  25 #define SHARE_JVMCI_METADATAHANDLES_HPP
  26 
  27 #include "oops/constantPool.hpp"
  28 #include "oops/metadata.hpp"
  29 #include "oops/method.hpp"
  30 #include "runtime/handles.hpp"
  31 #include "runtime/os.hpp"
  32 
  33 #ifdef ASSERT
  34 #define METADATA_TRACK_NAMES
  35 #endif
  36 
  37 struct _jmetadata {
  38  private:
  39   Metadata* _value;
  40 #ifdef METADATA_TRACK_NAMES
  41   // Debug data for tracking stale metadata
  42   const char* _name;
  43 #endif
  44 
  45  public:
  46   Metadata* value() { return _value; }
  47 
  48 #ifdef METADATA_TRACK_NAMES
  49   void initialize() {
  50     _value = NULL;
  51     _name = NULL;
  52   }
  53 #endif
  54 
  55   void set_value(Metadata* value) {
  56     _value = value;
  57   }
  58 
  59 #ifdef METADATA_TRACK_NAMES
  60   const char* name() { return _name; }
  61   void set_name(const char* name) {
  62     if (_name != NULL) {
  63       os::free((void*) _name);
  64       _name = NULL;
  65     }
  66     if (name != NULL) {
  67       _name = os::strdup(name);
  68     }
  69   }
  70 #endif
  71 };
  72 
  73 typedef struct _jmetadata HandleRecord;
  74 typedef struct _jmetadata *jmetadata;
  75 class MetadataHandles;
  76 






  77 class MetadataHandleBlock : public CHeapObj<mtJVMCI> {
  78   friend class MetadataHandles;
  79  private:
  80   enum SomeConstants {
  81     block_size_in_handles  = 32 // Number of handles per handle block


  82   };
  83 

  84   // Free handles always have their low bit set so those pointers can
  85   // be distinguished from handles which are in use.  The last handle
  86   // on the free list has a NULL pointer with the tag bit set, so it's
  87   // clear that the handle has been reclaimed.  The _free_list is
  88   // always a real pointer to a handle.
  89 
  90   HandleRecord    _handles[block_size_in_handles]; // The handles
  91   int             _top;                         // Index of next unused handle
  92   MetadataHandleBlock* _next;                   // Link to next block
  93 






  94   MetadataHandleBlock() {
  95     _top = 0;
  96     _next = NULL;
  97 #ifdef METADATA_TRACK_NAMES
  98     for (int i = 0; i < block_size_in_handles; i++) {
  99       _handles[i].initialize();
 100     }
 101 #endif
 102   }
 103 
 104   const char* get_name(int index) {
 105 #ifdef METADATA_TRACK_NAMES
 106     return _handles[index].name();
 107 #else
 108     return "<missing>";
 109 #endif
 110   }
 111 };
 112 
 113 // JVMCI maintains direct references to metadata. To make these references safe in the face of
 114 // class redefinition, they are held in handles so they can be scanned during GC. They are
 115 // managed in a cooperative way between the Java code and HotSpot. A handle is filled in and
 116 // passed back to the Java code which is responsible for setting the handle to NULL when it
 117 // is no longer in use. This is done by jdk.vm.ci.hotspot.HandleCleaner. The
 118 // rebuild_free_list function notices when the handle is clear and reclaims it for re-use.
 119 class MetadataHandles : public CHeapObj<mtJVMCI> {
 120  private:
 121   enum SomeConstants {
 122     ptr_tag = 1,
 123     ptr_mask = ~((intptr_t)ptr_tag)
 124   };
 125 
 126   MetadataHandleBlock*   _head; // First block
 127   MetadataHandleBlock*   _last; // Last block in use
 128   intptr_t          _free_list; // Handle free list
 129   int _allocate_before_rebuild; // Number of blocks to allocate before rebuilding free list
 130   int              _num_blocks; // Number of blocks
 131   int             _num_handles;
 132   int        _num_free_handles;
 133 
 134   HandleRecord* get_free_handle() {
 135     HandleRecord* handle = (HandleRecord*) (_free_list & ptr_mask);
 136     _free_list = (ptr_mask & (intptr_t) (handle->value()));
 137     assert(_free_list != ptr_tag, "should be null");
 138     _num_free_handles--;
 139     return handle;
 140   }
 141 
 142   HandleRecord* get_handle() {
 143     assert(_last != NULL, "sanity");
 144     // Try last block
 145     if (_last->_top < MetadataHandleBlock::block_size_in_handles) {
 146       _num_handles++;
 147       return &(_last->_handles)[_last->_top++];
 148     } else if (_free_list != 0) {
 149       // Try free list
 150       return get_free_handle();
 151     }
 152     return NULL;
 153   }
 154 
 155   void rebuild_free_list();
 156 
 157   jmetadata allocate_metadata_handle(Metadata* metadata);
 158 
 159  public:
 160   MetadataHandles() {
 161     _head = NULL;
 162     _last = NULL;
 163     _free_list = 0;
 164     _allocate_before_rebuild = 0;
 165     _num_blocks = 0;
 166     _num_handles = 0;
 167     _num_free_handles = 0;
 168   }
 169 
 170   int num_handles() const { return _num_handles; }
 171   int num_free_handles() const { return _num_free_handles; }
 172   int num_blocks() const { return _num_blocks; }
 173 
 174   jmetadata allocate_handle(const methodHandle& handle)       { return allocate_metadata_handle(handle()); }
 175   jmetadata allocate_handle(const constantPoolHandle& handle) { return allocate_metadata_handle(handle()); }
 176 
 177   // Adds `handle` to the free list
 178   void chain_free_list(HandleRecord* handle) {


 179     handle->set_value((Metadata*) (ptr_tag | _free_list));
 180 #ifdef METADATA_TRACK_NAMES
 181     handle->set_name(NULL);
 182 #endif
 183     _free_list = (intptr_t) handle;
 184     _num_free_handles++;
 185   }
 186 
 187   // Clears all handles without releasing any handle memory.
 188   void clear();
 189 
 190   void metadata_do(void f(Metadata*));
 191 
 192   void do_unloading();
 193 };
 194 
 195 #endif // SHARE_JVMCI_METADATAHANDLES_HPP
--- EOF ---