1 /*
  2  * Copyright (c) 2019, 2022, 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 
 25 #ifndef SHARE_UTILITIES_OBJECTBITSET_INLINE_HPP
 26 #define SHARE_UTILITIES_OBJECTBITSET_INLINE_HPP
 27 
 28 #include "utilities/objectBitSet.hpp"
 29 
 30 #include "memory/memRegion.hpp"
 31 #include "utilities/bitMap.inline.hpp"
 32 #include "utilities/hashtable.inline.hpp"
 33 
 34 template<MEMFLAGS F>
 35 ObjectBitSet<F>::BitMapFragment::BitMapFragment(uintptr_t granule, BitMapFragment* next) :
 36         _bits(_bitmap_granularity_size >> LogMinObjAlignmentInBytes, F, true /* clear */),
 37         _next(next) {
 38 }
 39 
 40 template<MEMFLAGS F>
 41 ObjectBitSet<F>::ObjectBitSet() :
 42         _bitmap_fragments(32),
 43         _fragment_list(NULL),
 44         _last_fragment_bits(NULL),
 45         _last_fragment_granule(UINTPTR_MAX) {
 46 }
 47 
 48 template<MEMFLAGS F>
 49 ObjectBitSet<F>::~ObjectBitSet() {
 50   BitMapFragment* current = _fragment_list;
 51   while (current != NULL) {
 52     BitMapFragment* next = current->next();
 53     delete current;
 54     current = next;
 55   }
 56 }
 57 
 58 template<MEMFLAGS F>
 59 ObjectBitSet<F>::BitMapFragmentTable::~BitMapFragmentTable() {
 60   for (int index = 0; index < BasicHashtable<F>::table_size(); index ++) {
 61     Entry* e = bucket(index);
 62     while (e != nullptr) {
 63       Entry* tmp = e;
 64       e = e->next();
 65       BasicHashtable<F>::free_entry(tmp);
 66     }
 67   }
 68 }
 69 
 70 template<MEMFLAGS F>
 71 inline typename ObjectBitSet<F>::BitMapFragmentTable::Entry* ObjectBitSet<F>::BitMapFragmentTable::bucket(int i) const {
 72   return (Entry*)BasicHashtable<F>::bucket(i);
 73 }
 74 
 75 template<MEMFLAGS F>
 76 inline typename ObjectBitSet<F>::BitMapFragmentTable::Entry*
 77   ObjectBitSet<F>::BitMapFragmentTable::new_entry(unsigned int hash, uintptr_t key, CHeapBitMap* value) {
 78 
 79   Entry* entry = (Entry*)BasicHashtable<F>::new_entry(hash);
 80   entry->_key = key;
 81   entry->_value = value;
 82   return entry;
 83 }
 84 
 85 template<MEMFLAGS F>
 86 inline void ObjectBitSet<F>::BitMapFragmentTable::add(uintptr_t key, CHeapBitMap* value) {
 87   unsigned hash = hash_segment(key);
 88   Entry* entry = new_entry(hash, key, value);
 89   BasicHashtable<F>::add_entry(hash_to_index(hash), entry);
 90 }
 91 
 92 template<MEMFLAGS F>
 93 inline CHeapBitMap** ObjectBitSet<F>::BitMapFragmentTable::lookup(uintptr_t key) {
 94   unsigned hash = hash_segment(key);
 95   int index = hash_to_index(hash);
 96   for (Entry* e = bucket(index); e != NULL; e = e->next()) {
 97     if (e->hash() == hash && e->_key == key) {
 98       return &(e->_value);
 99     }
100   }
101   return NULL;
102 }
103 
104 template<MEMFLAGS F>
105 inline BitMap::idx_t ObjectBitSet<F>::addr_to_bit(uintptr_t addr) const {
106   return (addr & _bitmap_granularity_mask) >> LogMinObjAlignmentInBytes;
107 }
108 
109 template<MEMFLAGS F>
110 inline CHeapBitMap* ObjectBitSet<F>::get_fragment_bits(uintptr_t addr) {
111   uintptr_t granule = addr >> _bitmap_granularity_shift;
112   if (granule == _last_fragment_granule) {
113     return _last_fragment_bits;
114   }
115   CHeapBitMap* bits = NULL;
116 
117   CHeapBitMap** found = _bitmap_fragments.lookup(granule);
118   if (found != NULL) {
119     bits = *found;
120   } else {
121     BitMapFragment* fragment = new BitMapFragment(granule, _fragment_list);
122     bits = fragment->bits();
123     _fragment_list = fragment;
124     if (_bitmap_fragments.number_of_entries() * 100 / _bitmap_fragments.table_size() > 25) {
125       _bitmap_fragments.resize(_bitmap_fragments.table_size() * 2);
126     }
127     _bitmap_fragments.add(granule, bits);
128   }
129 
130   _last_fragment_bits = bits;
131   _last_fragment_granule = granule;
132 
133   return bits;
134 }
135 
136 template<MEMFLAGS F>
137 inline void ObjectBitSet<F>::mark_obj(uintptr_t addr) {
138   CHeapBitMap* bits = get_fragment_bits(addr);
139   const BitMap::idx_t bit = addr_to_bit(addr);
140   bits->set_bit(bit);
141 }
142 
143 template<MEMFLAGS F>
144 inline bool ObjectBitSet<F>::is_marked(uintptr_t addr) {
145   CHeapBitMap* bits = get_fragment_bits(addr);
146   const BitMap::idx_t bit = addr_to_bit(addr);
147   return bits->at(bit);
148 }
149 
150 #endif // SHARE_UTILITIES_OBJECTBITSET_INLINE_HPP