1 /* 2 * Copyright (c) 2018, 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_GC_G1_G1REGIONMARKSTATSCACHE_HPP 26 #define SHARE_GC_G1_G1REGIONMARKSTATSCACHE_HPP 27 28 #include "memory/allocation.hpp" 29 #include "utilities/debug.hpp" 30 #include "utilities/globalDefinitions.hpp" 31 #include "utilities/pair.hpp" 32 33 // Per-Region statistics gathered during marking. 34 // 35 // This includes 36 // * the number of live words gathered during marking for the area from bottom 37 // to ntams. This is an exact measure. 38 // The code corrects later for the live data between ntams and top. 39 struct G1RegionMarkStats { 40 size_t _live_words; 41 42 // Clear all members. 43 void clear() { 44 _live_words = 0; 45 } 46 // Clear all members after a marking overflow. Nothing to do as the live words 47 // are updated by the atomic mark. We do not remark objects after overflow. 48 void clear_during_overflow() { 49 } 50 51 bool is_clear() const { return _live_words == 0; } 52 }; 53 54 // Per-marking thread cache for the region mark statistics. 55 // 56 // Each cache is a larg'ish map of region-idx -> G1RegionMarkStats entries that cache 57 // currently gathered statistics; entries are evicted to the global statistics array 58 // on every collision. This minimizes synchronization overhead which would be required 59 // every time statistics change, as marking is very localized. 60 // The map entry number is a power of two to allow simple and fast hashing using 61 // logical and. 62 class G1RegionMarkStatsCache { 63 private: 64 // The array of statistics entries to evict to; the global array. 65 G1RegionMarkStats* _target; 66 67 // An entry of the statistics cache. 68 struct G1RegionMarkStatsCacheEntry { 69 uint _region_idx; 70 G1RegionMarkStats _stats; 71 72 void clear() { 73 _region_idx = 0; 74 _stats.clear(); 75 } 76 77 bool is_clear() const { 78 return _region_idx == 0 && _stats.is_clear(); 79 } 80 }; 81 82 // The actual cache and its number of entries. 83 G1RegionMarkStatsCacheEntry* _cache; 84 uint _num_cache_entries; 85 86 // Cache hits/miss counters. 87 size_t _cache_hits; 88 size_t _cache_misses; 89 90 // Evict a given element of the statistics cache. 91 void evict(uint idx); 92 93 size_t _num_cache_entries_mask; 94 95 uint hash(uint idx) { 96 return idx & _num_cache_entries_mask; 97 } 98 99 G1RegionMarkStatsCacheEntry* find_for_add(uint region_idx); 100 public: 101 G1RegionMarkStatsCache(G1RegionMarkStats* target, uint num_cache_entries); 102 103 ~G1RegionMarkStatsCache(); 104 105 void add_live_words(uint region_idx, size_t live_words) { 106 G1RegionMarkStatsCacheEntry* const cur = find_for_add(region_idx); 107 cur->_stats._live_words += live_words; 108 } 109 110 void reset(uint region_idx) { 111 uint const cache_idx = hash(region_idx); 112 G1RegionMarkStatsCacheEntry* cur = &_cache[cache_idx]; 113 if (cur->_region_idx == region_idx) { 114 _cache[cache_idx].clear(); 115 } 116 } 117 118 // Evict all remaining statistics, returning cache hits and misses. 119 Pair<size_t, size_t> evict_all(); 120 121 // Reset all cache entries to their default values. 122 void reset(); 123 124 size_t hits() const { return _cache_hits; } 125 size_t misses() const { return _cache_misses; } 126 }; 127 128 #endif // SHARE_GC_G1_G1REGIONMARKSTATSCACHE_HPP