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