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 
 25 #ifndef SHARE_JFR_LEAKPROFILER_CHAINS_BITSET_INLINE_HPP
 26 #define SHARE_JFR_LEAKPROFILER_CHAINS_BITSET_INLINE_HPP
 27 
 28 #include "jfr/leakprofiler/chains/bitset.hpp"
 29 
 30 #include "jfr/recorder/storage/jfrVirtualMemory.hpp"
 31 #include "memory/memRegion.hpp"
 32 #include "utilities/bitMap.inline.hpp"
 33 #include "utilities/hashtable.inline.hpp"
 34 
 35 inline BitSet::BitMapFragmentTable::Entry* BitSet::BitMapFragmentTable::bucket(int i) const {
 36   return (Entry*)BasicHashtable<mtTracing>::bucket(i);
 37 }
 38 
 39 inline BitSet::BitMapFragmentTable::Entry* BitSet::BitMapFragmentTable::new_entry(unsigned int hash,
 40                                                                                   uintptr_t key,
 41                                                                                   CHeapBitMap* value) {
 42   Entry* entry = (Entry*)BasicHashtable<mtTracing>::new_entry(hash);
 43   entry->_key = key;
 44   entry->_value = value;
 45   return entry;
 46 }
 47 
 48 inline void BitSet::BitMapFragmentTable::add(uintptr_t key, CHeapBitMap* value) {
 49   unsigned hash = hash_segment(key);
 50   Entry* entry = new_entry(hash, key, value);
 51   BasicHashtable<mtTracing>::add_entry(hash_to_index(hash), entry);
 52 }
 53 
 54 inline CHeapBitMap** BitSet::BitMapFragmentTable::lookup(uintptr_t key) {
 55   unsigned hash = hash_segment(key);
 56   int index = hash_to_index(hash);
 57   for (Entry* e = bucket(index); e != NULL; e = e->next()) {
 58     if (e->hash() == hash && e->_key == key) {
 59       return &(e->_value);
 60     }
 61   }
 62   return NULL;
 63 }
 64 
 65 inline BitMap::idx_t BitSet::addr_to_bit(uintptr_t addr) const {
 66   return (addr & _bitmap_granularity_mask) >> LogMinObjAlignmentInBytes;
 67 }
 68 
 69 inline CHeapBitMap* BitSet::get_fragment_bits(uintptr_t addr) {
 70   uintptr_t granule = addr >> _bitmap_granularity_shift;
 71   if (granule == _last_fragment_granule) {
 72     return _last_fragment_bits;
 73   }
 74   CHeapBitMap* bits = NULL;
 75 
 76   CHeapBitMap** found = _bitmap_fragments.lookup(granule);
 77   if (found != NULL) {
 78     bits = *found;
 79   } else {
 80     BitMapFragment* fragment = new BitMapFragment(granule, _fragment_list);
 81     bits = fragment->bits();
 82     _fragment_list = fragment;
 83     if (_bitmap_fragments.number_of_entries() * 100 / _bitmap_fragments.table_size() > 25) {
 84       _bitmap_fragments.resize(_bitmap_fragments.table_size() * 2);
 85     }
 86     _bitmap_fragments.add(granule, bits);
 87   }
 88 
 89   _last_fragment_bits = bits;
 90   _last_fragment_granule = granule;
 91 
 92   return bits;
 93 }
 94 
 95 inline void BitSet::mark_obj(uintptr_t addr) {
 96   CHeapBitMap* bits = get_fragment_bits(addr);
 97   const BitMap::idx_t bit = addr_to_bit(addr);
 98   bits->set_bit(bit);
 99 }
100 
101 inline bool BitSet::is_marked(uintptr_t addr) {
102   CHeapBitMap* bits = get_fragment_bits(addr);
103   const BitMap::idx_t bit = addr_to_bit(addr);
104   return bits->at(bit);
105 }
106 
107 #endif // SHARE_JFR_LEAKPROFILER_CHAINS_BITSET_INLINE_HPP