1 /* 2 * Copyright (c) 2013, 2015, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #include "gc/shenandoah/shenandoahHeap.hpp" 25 #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" 26 #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" 27 #include "utilities/quickSort.hpp" 28 29 ShenandoahHeapRegionSet::ShenandoahHeapRegionSet(size_t max_regions): 30 _reserved_end(max_regions), 31 _active_end(0), 32 _regions(NEW_C_HEAP_ARRAY(ShenandoahHeapRegion*, max_regions, mtGC)), 33 _current_index(0) 34 { 35 } 36 37 ShenandoahHeapRegionSet::~ShenandoahHeapRegionSet() { 38 FREE_C_HEAP_ARRAY(ShenandoahHeapRegion*, _regions); 39 } 40 41 class PrintHeapRegionClosure : public ShenandoahHeapRegionClosure { 42 public: 43 bool doHeapRegion(ShenandoahHeapRegion* r) { 44 r->print(); 45 return false; 46 } 47 }; 48 49 class PrintHeapRegionSummaryClosure : public ShenandoahHeapRegionClosure { 50 public: 51 bool doHeapRegion(ShenandoahHeapRegion* r) { 52 tty->print(""SIZE_FORMAT, r->region_number()); 53 return false; 54 } 55 }; 56 57 58 size_t ShenandoahHeapRegionSet::count() const { 59 return _active_end - _current_index; 60 } 61 62 void ShenandoahHeapRegionSet::clear() { 63 _active_end = 0; 64 _current_index = 0; 65 } 66 67 void ShenandoahHeapRegionSet::add_region(ShenandoahHeapRegion* r) { 68 if (_active_end < _reserved_end) { 69 _regions[_active_end] = r; 70 _active_end++; 71 } 72 } 73 74 void ShenandoahHeapRegionSet::add_region_check_for_duplicates(ShenandoahHeapRegion* r) { 75 // FIXME There's a bug where the zeroth region is not checked, so check it here 76 if (_active_end < _reserved_end && !contains(r) && _regions[0] != r) { 77 _regions[_active_end] = r; 78 _active_end++; 79 } 80 } 81 82 // Apply blk->doHeapRegion() on all committed regions in address order, 83 // terminating the iteration early if doHeapRegion() returns true. 84 void ShenandoahHeapRegionSet::active_heap_region_iterate(ShenandoahHeapRegionClosure* blk, 85 bool skip_dirty_regions, 86 bool skip_humongous_continuation) const { 87 size_t i; 88 for (i = 0; i < _active_end; i++) { 89 ShenandoahHeapRegion* current = _regions[i]; 90 assert(current->region_number() <= _reserved_end, "Tautology"); 91 92 if (skip_humongous_continuation && current->is_humongous_continuation()) { 93 continue; 94 } 95 if (skip_dirty_regions && current->in_collection_set()) { 96 continue; 97 } 98 if (blk->doHeapRegion(current)) { 99 return; 100 } 101 } 102 } 103 104 void ShenandoahHeapRegionSet::unclaimed_heap_region_iterate(ShenandoahHeapRegionClosure* blk, 105 bool skip_dirty_regions, 106 bool skip_humongous_continuation) const { 107 size_t i; 108 109 // There's a bug here where the zeroth region is missed --chf 110 for (i = _current_index + 1; i < _active_end; i++) { 111 ShenandoahHeapRegion* current = _regions[i]; 112 assert(current->region_number() <= _reserved_end, "Tautology"); 113 114 if (skip_humongous_continuation && current->is_humongous_continuation()) { 115 continue; 116 } 117 if (skip_dirty_regions && current->in_collection_set()) { 118 continue; 119 } 120 if (blk->doHeapRegion(current)) { 121 return; 122 } 123 } 124 } 125 126 // Iterates over all of the regions. 127 void ShenandoahHeapRegionSet::heap_region_iterate(ShenandoahHeapRegionClosure* blk, 128 bool skip_dirty_regions, 129 bool skip_humongous_continuation) const { 130 active_heap_region_iterate(blk, skip_dirty_regions, skip_humongous_continuation); 131 } 132 133 class PrintHeapRegionsClosure : public 134 ShenandoahHeapRegionClosure { 135 private: 136 outputStream* _st; 137 public: 138 PrintHeapRegionsClosure() : _st(tty) {} 139 PrintHeapRegionsClosure(outputStream* st) : _st(st) {} 140 141 bool doHeapRegion(ShenandoahHeapRegion* r) { 142 r->print_on(_st); 143 return false; 144 } 145 }; 146 147 void ShenandoahHeapRegionSet::print(outputStream* out) { 148 out->print_cr("_current_index: "SIZE_FORMAT" current region: %p, _active_end: "SIZE_FORMAT, _current_index, _regions[_current_index], _active_end); 149 150 PrintHeapRegionsClosure pc1(out); 151 heap_region_iterate(&pc1, false, false); 152 } 153 154 void ShenandoahHeapRegionSet::next() { 155 if (_current_index < _active_end) { 156 _current_index++; 157 } 158 } 159 160 ShenandoahHeapRegion* ShenandoahHeapRegionSet::claim_next() { 161 size_t next = Atomic::add(1, &_current_index) - 1; 162 if (next < _active_end) { 163 return get(next); 164 } else { 165 return NULL; 166 } 167 return NULL; 168 } 169 170 class FindRegionClosure : public ShenandoahHeapRegionClosure { 171 ShenandoahHeapRegion* _query; 172 bool _result; 173 public: 174 175 FindRegionClosure(ShenandoahHeapRegion* query) : _query(query), _result(false) {} 176 177 bool doHeapRegion(ShenandoahHeapRegion* r) { 178 _result = (r == _query); 179 return _result; 180 } 181 182 bool result() { return _result;} 183 }; 184 185 bool ShenandoahHeapRegionSet::contains(ShenandoahHeapRegion* r) { 186 FindRegionClosure cl(r); 187 active_heap_region_iterate(&cl); 188 return cl.result(); 189 } 190 191 HeapWord* ShenandoahHeapRegionSet::bottom() const { 192 return get(0)->bottom(); 193 } 194 195 HeapWord* ShenandoahHeapRegionSet::end() const { 196 return get(_active_end - 1)->end(); 197 } 198 199 ShenandoahHeapRegion* ShenandoahHeapRegionSet::get(size_t i) const { 200 if (i < _active_end) { 201 return _regions[i]; 202 } else { 203 return NULL; 204 } 205 } 206 207 ShenandoahHeapRegion* ShenandoahHeapRegionSet::current() const { 208 if (_current_index < _active_end) { 209 return get(_current_index); 210 } else { 211 return NULL; 212 } 213 }