Wed, 27 Apr 2016 01:25:04 +0800
Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/
changeset: 6782:28b50d07f6f8
tag: jdk8u25-b17
aoqi@0 | 1 | /* |
aoqi@0 | 2 | * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. |
aoqi@0 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
aoqi@0 | 4 | * |
aoqi@0 | 5 | * This code is free software; you can redistribute it and/or modify it |
aoqi@0 | 6 | * under the terms of the GNU General Public License version 2 only, as |
aoqi@0 | 7 | * published by the Free Software Foundation. |
aoqi@0 | 8 | * |
aoqi@0 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
aoqi@0 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
aoqi@0 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
aoqi@0 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
aoqi@0 | 13 | * accompanied this code). |
aoqi@0 | 14 | * |
aoqi@0 | 15 | * You should have received a copy of the GNU General Public License version |
aoqi@0 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
aoqi@0 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
aoqi@0 | 18 | * |
aoqi@0 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
aoqi@0 | 20 | * or visit www.oracle.com if you need additional information or have any |
aoqi@0 | 21 | * questions. |
aoqi@0 | 22 | * |
aoqi@0 | 23 | */ |
aoqi@0 | 24 | |
aoqi@0 | 25 | #include "precompiled.hpp" |
aoqi@0 | 26 | #include "gc_implementation/g1/heapRegion.hpp" |
aoqi@0 | 27 | #include "gc_implementation/g1/heapRegionRemSet.hpp" |
aoqi@0 | 28 | #include "gc_implementation/g1/sparsePRT.hpp" |
aoqi@0 | 29 | #include "memory/allocation.inline.hpp" |
aoqi@0 | 30 | #include "memory/cardTableModRefBS.hpp" |
aoqi@0 | 31 | #include "memory/space.inline.hpp" |
aoqi@0 | 32 | #include "runtime/mutexLocker.hpp" |
aoqi@0 | 33 | |
aoqi@0 | 34 | #define SPARSE_PRT_VERBOSE 0 |
aoqi@0 | 35 | |
aoqi@0 | 36 | #define UNROLL_CARD_LOOPS 1 |
aoqi@0 | 37 | |
aoqi@0 | 38 | void SparsePRTEntry::init(RegionIdx_t region_ind) { |
aoqi@0 | 39 | _region_ind = region_ind; |
aoqi@0 | 40 | _next_index = NullEntry; |
aoqi@0 | 41 | |
aoqi@0 | 42 | #if UNROLL_CARD_LOOPS |
aoqi@0 | 43 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
aoqi@0 | 44 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
aoqi@0 | 45 | _cards[i] = NullEntry; |
aoqi@0 | 46 | _cards[i + 1] = NullEntry; |
aoqi@0 | 47 | _cards[i + 2] = NullEntry; |
aoqi@0 | 48 | _cards[i + 3] = NullEntry; |
aoqi@0 | 49 | } |
aoqi@0 | 50 | #else |
aoqi@0 | 51 | for (int i = 0; i < cards_num(); i++) |
aoqi@0 | 52 | _cards[i] = NullEntry; |
aoqi@0 | 53 | #endif |
aoqi@0 | 54 | } |
aoqi@0 | 55 | |
aoqi@0 | 56 | bool SparsePRTEntry::contains_card(CardIdx_t card_index) const { |
aoqi@0 | 57 | #if UNROLL_CARD_LOOPS |
aoqi@0 | 58 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
aoqi@0 | 59 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
aoqi@0 | 60 | if (_cards[i] == card_index || |
aoqi@0 | 61 | _cards[i + 1] == card_index || |
aoqi@0 | 62 | _cards[i + 2] == card_index || |
aoqi@0 | 63 | _cards[i + 3] == card_index) return true; |
aoqi@0 | 64 | } |
aoqi@0 | 65 | #else |
aoqi@0 | 66 | for (int i = 0; i < cards_num(); i++) { |
aoqi@0 | 67 | if (_cards[i] == card_index) return true; |
aoqi@0 | 68 | } |
aoqi@0 | 69 | #endif |
aoqi@0 | 70 | // Otherwise, we're full. |
aoqi@0 | 71 | return false; |
aoqi@0 | 72 | } |
aoqi@0 | 73 | |
aoqi@0 | 74 | int SparsePRTEntry::num_valid_cards() const { |
aoqi@0 | 75 | int sum = 0; |
aoqi@0 | 76 | #if UNROLL_CARD_LOOPS |
aoqi@0 | 77 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
aoqi@0 | 78 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
aoqi@0 | 79 | sum += (_cards[i] != NullEntry); |
aoqi@0 | 80 | sum += (_cards[i + 1] != NullEntry); |
aoqi@0 | 81 | sum += (_cards[i + 2] != NullEntry); |
aoqi@0 | 82 | sum += (_cards[i + 3] != NullEntry); |
aoqi@0 | 83 | } |
aoqi@0 | 84 | #else |
aoqi@0 | 85 | for (int i = 0; i < cards_num(); i++) { |
aoqi@0 | 86 | sum += (_cards[i] != NullEntry); |
aoqi@0 | 87 | } |
aoqi@0 | 88 | #endif |
aoqi@0 | 89 | // Otherwise, we're full. |
aoqi@0 | 90 | return sum; |
aoqi@0 | 91 | } |
aoqi@0 | 92 | |
aoqi@0 | 93 | SparsePRTEntry::AddCardResult SparsePRTEntry::add_card(CardIdx_t card_index) { |
aoqi@0 | 94 | #if UNROLL_CARD_LOOPS |
aoqi@0 | 95 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
aoqi@0 | 96 | CardIdx_t c; |
aoqi@0 | 97 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
aoqi@0 | 98 | c = _cards[i]; |
aoqi@0 | 99 | if (c == card_index) return found; |
aoqi@0 | 100 | if (c == NullEntry) { _cards[i] = card_index; return added; } |
aoqi@0 | 101 | c = _cards[i + 1]; |
aoqi@0 | 102 | if (c == card_index) return found; |
aoqi@0 | 103 | if (c == NullEntry) { _cards[i + 1] = card_index; return added; } |
aoqi@0 | 104 | c = _cards[i + 2]; |
aoqi@0 | 105 | if (c == card_index) return found; |
aoqi@0 | 106 | if (c == NullEntry) { _cards[i + 2] = card_index; return added; } |
aoqi@0 | 107 | c = _cards[i + 3]; |
aoqi@0 | 108 | if (c == card_index) return found; |
aoqi@0 | 109 | if (c == NullEntry) { _cards[i + 3] = card_index; return added; } |
aoqi@0 | 110 | } |
aoqi@0 | 111 | #else |
aoqi@0 | 112 | for (int i = 0; i < cards_num(); i++) { |
aoqi@0 | 113 | CardIdx_t c = _cards[i]; |
aoqi@0 | 114 | if (c == card_index) return found; |
aoqi@0 | 115 | if (c == NullEntry) { _cards[i] = card_index; return added; } |
aoqi@0 | 116 | } |
aoqi@0 | 117 | #endif |
aoqi@0 | 118 | // Otherwise, we're full. |
aoqi@0 | 119 | return overflow; |
aoqi@0 | 120 | } |
aoqi@0 | 121 | |
aoqi@0 | 122 | void SparsePRTEntry::copy_cards(CardIdx_t* cards) const { |
aoqi@0 | 123 | #if UNROLL_CARD_LOOPS |
aoqi@0 | 124 | assert((cards_num() & (UnrollFactor - 1)) == 0, "Invalid number of cards in the entry"); |
aoqi@0 | 125 | for (int i = 0; i < cards_num(); i += UnrollFactor) { |
aoqi@0 | 126 | cards[i] = _cards[i]; |
aoqi@0 | 127 | cards[i + 1] = _cards[i + 1]; |
aoqi@0 | 128 | cards[i + 2] = _cards[i + 2]; |
aoqi@0 | 129 | cards[i + 3] = _cards[i + 3]; |
aoqi@0 | 130 | } |
aoqi@0 | 131 | #else |
aoqi@0 | 132 | for (int i = 0; i < cards_num(); i++) { |
aoqi@0 | 133 | cards[i] = _cards[i]; |
aoqi@0 | 134 | } |
aoqi@0 | 135 | #endif |
aoqi@0 | 136 | } |
aoqi@0 | 137 | |
aoqi@0 | 138 | void SparsePRTEntry::copy_cards(SparsePRTEntry* e) const { |
aoqi@0 | 139 | copy_cards(&e->_cards[0]); |
aoqi@0 | 140 | } |
aoqi@0 | 141 | |
aoqi@0 | 142 | // ---------------------------------------------------------------------- |
aoqi@0 | 143 | |
aoqi@0 | 144 | RSHashTable::RSHashTable(size_t capacity) : |
aoqi@0 | 145 | _capacity(capacity), _capacity_mask(capacity-1), |
aoqi@0 | 146 | _occupied_entries(0), _occupied_cards(0), |
aoqi@0 | 147 | _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity, mtGC)), |
aoqi@0 | 148 | _buckets(NEW_C_HEAP_ARRAY(int, capacity, mtGC)), |
aoqi@0 | 149 | _free_list(NullEntry), _free_region(0) |
aoqi@0 | 150 | { |
aoqi@0 | 151 | clear(); |
aoqi@0 | 152 | } |
aoqi@0 | 153 | |
aoqi@0 | 154 | RSHashTable::~RSHashTable() { |
aoqi@0 | 155 | if (_entries != NULL) { |
aoqi@0 | 156 | FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries, mtGC); |
aoqi@0 | 157 | _entries = NULL; |
aoqi@0 | 158 | } |
aoqi@0 | 159 | if (_buckets != NULL) { |
aoqi@0 | 160 | FREE_C_HEAP_ARRAY(int, _buckets, mtGC); |
aoqi@0 | 161 | _buckets = NULL; |
aoqi@0 | 162 | } |
aoqi@0 | 163 | } |
aoqi@0 | 164 | |
aoqi@0 | 165 | void RSHashTable::clear() { |
aoqi@0 | 166 | _occupied_entries = 0; |
aoqi@0 | 167 | _occupied_cards = 0; |
aoqi@0 | 168 | guarantee(_entries != NULL, "INV"); |
aoqi@0 | 169 | guarantee(_buckets != NULL, "INV"); |
aoqi@0 | 170 | |
aoqi@0 | 171 | guarantee(_capacity <= ((size_t)1 << (sizeof(int)*BitsPerByte-1)) - 1, |
aoqi@0 | 172 | "_capacity too large"); |
aoqi@0 | 173 | |
aoqi@0 | 174 | // This will put -1 == NullEntry in the key field of all entries. |
aoqi@0 | 175 | memset(_entries, NullEntry, _capacity * SparsePRTEntry::size()); |
aoqi@0 | 176 | memset(_buckets, NullEntry, _capacity * sizeof(int)); |
aoqi@0 | 177 | _free_list = NullEntry; |
aoqi@0 | 178 | _free_region = 0; |
aoqi@0 | 179 | } |
aoqi@0 | 180 | |
aoqi@0 | 181 | bool RSHashTable::add_card(RegionIdx_t region_ind, CardIdx_t card_index) { |
aoqi@0 | 182 | SparsePRTEntry* e = entry_for_region_ind_create(region_ind); |
aoqi@0 | 183 | assert(e != NULL && e->r_ind() == region_ind, |
aoqi@0 | 184 | "Postcondition of call above."); |
aoqi@0 | 185 | SparsePRTEntry::AddCardResult res = e->add_card(card_index); |
aoqi@0 | 186 | if (res == SparsePRTEntry::added) _occupied_cards++; |
aoqi@0 | 187 | #if SPARSE_PRT_VERBOSE |
aoqi@0 | 188 | gclog_or_tty->print_cr(" after add_card[%d]: valid-cards = %d.", |
aoqi@0 | 189 | pointer_delta(e, _entries, SparsePRTEntry::size()), |
aoqi@0 | 190 | e->num_valid_cards()); |
aoqi@0 | 191 | #endif |
aoqi@0 | 192 | assert(e->num_valid_cards() > 0, "Postcondition"); |
aoqi@0 | 193 | return res != SparsePRTEntry::overflow; |
aoqi@0 | 194 | } |
aoqi@0 | 195 | |
aoqi@0 | 196 | bool RSHashTable::get_cards(RegionIdx_t region_ind, CardIdx_t* cards) { |
aoqi@0 | 197 | int ind = (int) (region_ind & capacity_mask()); |
aoqi@0 | 198 | int cur_ind = _buckets[ind]; |
aoqi@0 | 199 | SparsePRTEntry* cur; |
aoqi@0 | 200 | while (cur_ind != NullEntry && |
aoqi@0 | 201 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
aoqi@0 | 202 | cur_ind = cur->next_index(); |
aoqi@0 | 203 | } |
aoqi@0 | 204 | |
aoqi@0 | 205 | if (cur_ind == NullEntry) return false; |
aoqi@0 | 206 | // Otherwise... |
aoqi@0 | 207 | assert(cur->r_ind() == region_ind, "Postcondition of loop + test above."); |
aoqi@0 | 208 | assert(cur->num_valid_cards() > 0, "Inv"); |
aoqi@0 | 209 | cur->copy_cards(cards); |
aoqi@0 | 210 | return true; |
aoqi@0 | 211 | } |
aoqi@0 | 212 | |
aoqi@0 | 213 | SparsePRTEntry* RSHashTable::get_entry(RegionIdx_t region_ind) { |
aoqi@0 | 214 | int ind = (int) (region_ind & capacity_mask()); |
aoqi@0 | 215 | int cur_ind = _buckets[ind]; |
aoqi@0 | 216 | SparsePRTEntry* cur; |
aoqi@0 | 217 | while (cur_ind != NullEntry && |
aoqi@0 | 218 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
aoqi@0 | 219 | cur_ind = cur->next_index(); |
aoqi@0 | 220 | } |
aoqi@0 | 221 | |
aoqi@0 | 222 | if (cur_ind == NullEntry) return NULL; |
aoqi@0 | 223 | // Otherwise... |
aoqi@0 | 224 | assert(cur->r_ind() == region_ind, "Postcondition of loop + test above."); |
aoqi@0 | 225 | assert(cur->num_valid_cards() > 0, "Inv"); |
aoqi@0 | 226 | return cur; |
aoqi@0 | 227 | } |
aoqi@0 | 228 | |
aoqi@0 | 229 | bool RSHashTable::delete_entry(RegionIdx_t region_ind) { |
aoqi@0 | 230 | int ind = (int) (region_ind & capacity_mask()); |
aoqi@0 | 231 | int* prev_loc = &_buckets[ind]; |
aoqi@0 | 232 | int cur_ind = *prev_loc; |
aoqi@0 | 233 | SparsePRTEntry* cur; |
aoqi@0 | 234 | while (cur_ind != NullEntry && |
aoqi@0 | 235 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
aoqi@0 | 236 | prev_loc = cur->next_index_addr(); |
aoqi@0 | 237 | cur_ind = *prev_loc; |
aoqi@0 | 238 | } |
aoqi@0 | 239 | |
aoqi@0 | 240 | if (cur_ind == NullEntry) return false; |
aoqi@0 | 241 | // Otherwise, splice out "cur". |
aoqi@0 | 242 | *prev_loc = cur->next_index(); |
aoqi@0 | 243 | _occupied_cards -= cur->num_valid_cards(); |
aoqi@0 | 244 | free_entry(cur_ind); |
aoqi@0 | 245 | _occupied_entries--; |
aoqi@0 | 246 | return true; |
aoqi@0 | 247 | } |
aoqi@0 | 248 | |
aoqi@0 | 249 | SparsePRTEntry* |
aoqi@0 | 250 | RSHashTable::entry_for_region_ind(RegionIdx_t region_ind) const { |
aoqi@0 | 251 | assert(occupied_entries() < capacity(), "Precondition"); |
aoqi@0 | 252 | int ind = (int) (region_ind & capacity_mask()); |
aoqi@0 | 253 | int cur_ind = _buckets[ind]; |
aoqi@0 | 254 | SparsePRTEntry* cur; |
aoqi@0 | 255 | while (cur_ind != NullEntry && |
aoqi@0 | 256 | (cur = entry(cur_ind))->r_ind() != region_ind) { |
aoqi@0 | 257 | cur_ind = cur->next_index(); |
aoqi@0 | 258 | } |
aoqi@0 | 259 | |
aoqi@0 | 260 | if (cur_ind != NullEntry) { |
aoqi@0 | 261 | assert(cur->r_ind() == region_ind, "Loop postcondition + test"); |
aoqi@0 | 262 | return cur; |
aoqi@0 | 263 | } else { |
aoqi@0 | 264 | return NULL; |
aoqi@0 | 265 | } |
aoqi@0 | 266 | } |
aoqi@0 | 267 | |
aoqi@0 | 268 | SparsePRTEntry* |
aoqi@0 | 269 | RSHashTable::entry_for_region_ind_create(RegionIdx_t region_ind) { |
aoqi@0 | 270 | SparsePRTEntry* res = entry_for_region_ind(region_ind); |
aoqi@0 | 271 | if (res == NULL) { |
aoqi@0 | 272 | int new_ind = alloc_entry(); |
aoqi@0 | 273 | assert(0 <= new_ind && (size_t)new_ind < capacity(), "There should be room."); |
aoqi@0 | 274 | res = entry(new_ind); |
aoqi@0 | 275 | res->init(region_ind); |
aoqi@0 | 276 | // Insert at front. |
aoqi@0 | 277 | int ind = (int) (region_ind & capacity_mask()); |
aoqi@0 | 278 | res->set_next_index(_buckets[ind]); |
aoqi@0 | 279 | _buckets[ind] = new_ind; |
aoqi@0 | 280 | _occupied_entries++; |
aoqi@0 | 281 | } |
aoqi@0 | 282 | return res; |
aoqi@0 | 283 | } |
aoqi@0 | 284 | |
aoqi@0 | 285 | int RSHashTable::alloc_entry() { |
aoqi@0 | 286 | int res; |
aoqi@0 | 287 | if (_free_list != NullEntry) { |
aoqi@0 | 288 | res = _free_list; |
aoqi@0 | 289 | _free_list = entry(res)->next_index(); |
aoqi@0 | 290 | return res; |
aoqi@0 | 291 | } else if ((size_t) _free_region+1 < capacity()) { |
aoqi@0 | 292 | res = _free_region; |
aoqi@0 | 293 | _free_region++; |
aoqi@0 | 294 | return res; |
aoqi@0 | 295 | } else { |
aoqi@0 | 296 | return NullEntry; |
aoqi@0 | 297 | } |
aoqi@0 | 298 | } |
aoqi@0 | 299 | |
aoqi@0 | 300 | void RSHashTable::free_entry(int fi) { |
aoqi@0 | 301 | entry(fi)->set_next_index(_free_list); |
aoqi@0 | 302 | _free_list = fi; |
aoqi@0 | 303 | } |
aoqi@0 | 304 | |
aoqi@0 | 305 | void RSHashTable::add_entry(SparsePRTEntry* e) { |
aoqi@0 | 306 | assert(e->num_valid_cards() > 0, "Precondition."); |
aoqi@0 | 307 | SparsePRTEntry* e2 = entry_for_region_ind_create(e->r_ind()); |
aoqi@0 | 308 | e->copy_cards(e2); |
aoqi@0 | 309 | _occupied_cards += e2->num_valid_cards(); |
aoqi@0 | 310 | assert(e2->num_valid_cards() > 0, "Postcondition."); |
aoqi@0 | 311 | } |
aoqi@0 | 312 | |
aoqi@0 | 313 | CardIdx_t RSHashTableIter::find_first_card_in_list() { |
aoqi@0 | 314 | CardIdx_t res; |
aoqi@0 | 315 | while (_bl_ind != RSHashTable::NullEntry) { |
aoqi@0 | 316 | res = _rsht->entry(_bl_ind)->card(0); |
aoqi@0 | 317 | if (res != SparsePRTEntry::NullEntry) { |
aoqi@0 | 318 | return res; |
aoqi@0 | 319 | } else { |
aoqi@0 | 320 | _bl_ind = _rsht->entry(_bl_ind)->next_index(); |
aoqi@0 | 321 | } |
aoqi@0 | 322 | } |
aoqi@0 | 323 | // Otherwise, none found: |
aoqi@0 | 324 | return SparsePRTEntry::NullEntry; |
aoqi@0 | 325 | } |
aoqi@0 | 326 | |
aoqi@0 | 327 | size_t RSHashTableIter::compute_card_ind(CardIdx_t ci) { |
aoqi@0 | 328 | return (_rsht->entry(_bl_ind)->r_ind() * HeapRegion::CardsPerRegion) + ci; |
aoqi@0 | 329 | } |
aoqi@0 | 330 | |
aoqi@0 | 331 | bool RSHashTableIter::has_next(size_t& card_index) { |
aoqi@0 | 332 | _card_ind++; |
aoqi@0 | 333 | CardIdx_t ci; |
aoqi@0 | 334 | if (_card_ind < SparsePRTEntry::cards_num() && |
aoqi@0 | 335 | ((ci = _rsht->entry(_bl_ind)->card(_card_ind)) != |
aoqi@0 | 336 | SparsePRTEntry::NullEntry)) { |
aoqi@0 | 337 | card_index = compute_card_ind(ci); |
aoqi@0 | 338 | return true; |
aoqi@0 | 339 | } |
aoqi@0 | 340 | // Otherwise, must find the next valid entry. |
aoqi@0 | 341 | _card_ind = 0; |
aoqi@0 | 342 | |
aoqi@0 | 343 | if (_bl_ind != RSHashTable::NullEntry) { |
aoqi@0 | 344 | _bl_ind = _rsht->entry(_bl_ind)->next_index(); |
aoqi@0 | 345 | ci = find_first_card_in_list(); |
aoqi@0 | 346 | if (ci != SparsePRTEntry::NullEntry) { |
aoqi@0 | 347 | card_index = compute_card_ind(ci); |
aoqi@0 | 348 | return true; |
aoqi@0 | 349 | } |
aoqi@0 | 350 | } |
aoqi@0 | 351 | // If we didn't return above, must go to the next non-null table index. |
aoqi@0 | 352 | _tbl_ind++; |
aoqi@0 | 353 | while ((size_t)_tbl_ind < _rsht->capacity()) { |
aoqi@0 | 354 | _bl_ind = _rsht->_buckets[_tbl_ind]; |
aoqi@0 | 355 | ci = find_first_card_in_list(); |
aoqi@0 | 356 | if (ci != SparsePRTEntry::NullEntry) { |
aoqi@0 | 357 | card_index = compute_card_ind(ci); |
aoqi@0 | 358 | return true; |
aoqi@0 | 359 | } |
aoqi@0 | 360 | // Otherwise, try next entry. |
aoqi@0 | 361 | _tbl_ind++; |
aoqi@0 | 362 | } |
aoqi@0 | 363 | // Otherwise, there were no entry. |
aoqi@0 | 364 | return false; |
aoqi@0 | 365 | } |
aoqi@0 | 366 | |
aoqi@0 | 367 | bool RSHashTable::contains_card(RegionIdx_t region_index, CardIdx_t card_index) const { |
aoqi@0 | 368 | SparsePRTEntry* e = entry_for_region_ind(region_index); |
aoqi@0 | 369 | return (e != NULL && e->contains_card(card_index)); |
aoqi@0 | 370 | } |
aoqi@0 | 371 | |
aoqi@0 | 372 | size_t RSHashTable::mem_size() const { |
aoqi@0 | 373 | return sizeof(this) + |
aoqi@0 | 374 | capacity() * (SparsePRTEntry::size() + sizeof(int)); |
aoqi@0 | 375 | } |
aoqi@0 | 376 | |
aoqi@0 | 377 | // ---------------------------------------------------------------------- |
aoqi@0 | 378 | |
aoqi@0 | 379 | SparsePRT* SparsePRT::_head_expanded_list = NULL; |
aoqi@0 | 380 | |
aoqi@0 | 381 | void SparsePRT::add_to_expanded_list(SparsePRT* sprt) { |
aoqi@0 | 382 | // We could expand multiple times in a pause -- only put on list once. |
aoqi@0 | 383 | if (sprt->expanded()) return; |
aoqi@0 | 384 | sprt->set_expanded(true); |
aoqi@0 | 385 | SparsePRT* hd = _head_expanded_list; |
aoqi@0 | 386 | while (true) { |
aoqi@0 | 387 | sprt->_next_expanded = hd; |
aoqi@0 | 388 | SparsePRT* res = |
aoqi@0 | 389 | (SparsePRT*) |
aoqi@0 | 390 | Atomic::cmpxchg_ptr(sprt, &_head_expanded_list, hd); |
aoqi@0 | 391 | if (res == hd) return; |
aoqi@0 | 392 | else hd = res; |
aoqi@0 | 393 | } |
aoqi@0 | 394 | } |
aoqi@0 | 395 | |
aoqi@0 | 396 | |
aoqi@0 | 397 | SparsePRT* SparsePRT::get_from_expanded_list() { |
aoqi@0 | 398 | SparsePRT* hd = _head_expanded_list; |
aoqi@0 | 399 | while (hd != NULL) { |
aoqi@0 | 400 | SparsePRT* next = hd->next_expanded(); |
aoqi@0 | 401 | SparsePRT* res = |
aoqi@0 | 402 | (SparsePRT*) |
aoqi@0 | 403 | Atomic::cmpxchg_ptr(next, &_head_expanded_list, hd); |
aoqi@0 | 404 | if (res == hd) { |
aoqi@0 | 405 | hd->set_next_expanded(NULL); |
aoqi@0 | 406 | return hd; |
aoqi@0 | 407 | } else { |
aoqi@0 | 408 | hd = res; |
aoqi@0 | 409 | } |
aoqi@0 | 410 | } |
aoqi@0 | 411 | return NULL; |
aoqi@0 | 412 | } |
aoqi@0 | 413 | |
aoqi@0 | 414 | void SparsePRT::reset_for_cleanup_tasks() { |
aoqi@0 | 415 | _head_expanded_list = NULL; |
aoqi@0 | 416 | } |
aoqi@0 | 417 | |
aoqi@0 | 418 | void SparsePRT::do_cleanup_work(SparsePRTCleanupTask* sprt_cleanup_task) { |
aoqi@0 | 419 | if (should_be_on_expanded_list()) { |
aoqi@0 | 420 | sprt_cleanup_task->add(this); |
aoqi@0 | 421 | } |
aoqi@0 | 422 | } |
aoqi@0 | 423 | |
aoqi@0 | 424 | void SparsePRT::finish_cleanup_task(SparsePRTCleanupTask* sprt_cleanup_task) { |
aoqi@0 | 425 | assert(ParGCRareEvent_lock->owned_by_self(), "pre-condition"); |
aoqi@0 | 426 | SparsePRT* head = sprt_cleanup_task->head(); |
aoqi@0 | 427 | SparsePRT* tail = sprt_cleanup_task->tail(); |
aoqi@0 | 428 | if (head != NULL) { |
aoqi@0 | 429 | assert(tail != NULL, "if head is not NULL, so should tail"); |
aoqi@0 | 430 | |
aoqi@0 | 431 | tail->set_next_expanded(_head_expanded_list); |
aoqi@0 | 432 | _head_expanded_list = head; |
aoqi@0 | 433 | } else { |
aoqi@0 | 434 | assert(tail == NULL, "if head is NULL, so should tail"); |
aoqi@0 | 435 | } |
aoqi@0 | 436 | } |
aoqi@0 | 437 | |
aoqi@0 | 438 | bool SparsePRT::should_be_on_expanded_list() { |
aoqi@0 | 439 | if (_expanded) { |
aoqi@0 | 440 | assert(_cur != _next, "if _expanded is true, cur should be != _next"); |
aoqi@0 | 441 | } else { |
aoqi@0 | 442 | assert(_cur == _next, "if _expanded is false, cur should be == _next"); |
aoqi@0 | 443 | } |
aoqi@0 | 444 | return expanded(); |
aoqi@0 | 445 | } |
aoqi@0 | 446 | |
aoqi@0 | 447 | void SparsePRT::cleanup_all() { |
aoqi@0 | 448 | // First clean up all expanded tables so they agree on next and cur. |
aoqi@0 | 449 | SparsePRT* sprt = get_from_expanded_list(); |
aoqi@0 | 450 | while (sprt != NULL) { |
aoqi@0 | 451 | sprt->cleanup(); |
aoqi@0 | 452 | sprt = get_from_expanded_list(); |
aoqi@0 | 453 | } |
aoqi@0 | 454 | } |
aoqi@0 | 455 | |
aoqi@0 | 456 | |
aoqi@0 | 457 | SparsePRT::SparsePRT(HeapRegion* hr) : |
aoqi@0 | 458 | _hr(hr), _expanded(false), _next_expanded(NULL) |
aoqi@0 | 459 | { |
aoqi@0 | 460 | _cur = new RSHashTable(InitialCapacity); |
aoqi@0 | 461 | _next = _cur; |
aoqi@0 | 462 | } |
aoqi@0 | 463 | |
aoqi@0 | 464 | |
aoqi@0 | 465 | SparsePRT::~SparsePRT() { |
aoqi@0 | 466 | assert(_next != NULL && _cur != NULL, "Inv"); |
aoqi@0 | 467 | if (_cur != _next) { delete _cur; } |
aoqi@0 | 468 | delete _next; |
aoqi@0 | 469 | } |
aoqi@0 | 470 | |
aoqi@0 | 471 | |
aoqi@0 | 472 | size_t SparsePRT::mem_size() const { |
aoqi@0 | 473 | // We ignore "_cur" here, because it either = _next, or else it is |
aoqi@0 | 474 | // on the deleted list. |
aoqi@0 | 475 | return sizeof(this) + _next->mem_size(); |
aoqi@0 | 476 | } |
aoqi@0 | 477 | |
aoqi@0 | 478 | bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) { |
aoqi@0 | 479 | #if SPARSE_PRT_VERBOSE |
aoqi@0 | 480 | gclog_or_tty->print_cr(" Adding card %d from region %d to region %u sparse.", |
aoqi@0 | 481 | card_index, region_id, _hr->hrs_index()); |
aoqi@0 | 482 | #endif |
aoqi@0 | 483 | if (_next->occupied_entries() * 2 > _next->capacity()) { |
aoqi@0 | 484 | expand(); |
aoqi@0 | 485 | } |
aoqi@0 | 486 | return _next->add_card(region_id, card_index); |
aoqi@0 | 487 | } |
aoqi@0 | 488 | |
aoqi@0 | 489 | bool SparsePRT::get_cards(RegionIdx_t region_id, CardIdx_t* cards) { |
aoqi@0 | 490 | return _next->get_cards(region_id, cards); |
aoqi@0 | 491 | } |
aoqi@0 | 492 | |
aoqi@0 | 493 | SparsePRTEntry* SparsePRT::get_entry(RegionIdx_t region_id) { |
aoqi@0 | 494 | return _next->get_entry(region_id); |
aoqi@0 | 495 | } |
aoqi@0 | 496 | |
aoqi@0 | 497 | bool SparsePRT::delete_entry(RegionIdx_t region_id) { |
aoqi@0 | 498 | return _next->delete_entry(region_id); |
aoqi@0 | 499 | } |
aoqi@0 | 500 | |
aoqi@0 | 501 | void SparsePRT::clear() { |
aoqi@0 | 502 | // If they differ, _next is bigger then cur, so next has no chance of |
aoqi@0 | 503 | // being the initial size. |
aoqi@0 | 504 | if (_next != _cur) { |
aoqi@0 | 505 | delete _next; |
aoqi@0 | 506 | } |
aoqi@0 | 507 | |
aoqi@0 | 508 | if (_cur->capacity() != InitialCapacity) { |
aoqi@0 | 509 | delete _cur; |
aoqi@0 | 510 | _cur = new RSHashTable(InitialCapacity); |
aoqi@0 | 511 | } else { |
aoqi@0 | 512 | _cur->clear(); |
aoqi@0 | 513 | } |
aoqi@0 | 514 | _next = _cur; |
aoqi@0 | 515 | _expanded = false; |
aoqi@0 | 516 | } |
aoqi@0 | 517 | |
aoqi@0 | 518 | void SparsePRT::cleanup() { |
aoqi@0 | 519 | // Make sure that the current and next tables agree. |
aoqi@0 | 520 | if (_cur != _next) { |
aoqi@0 | 521 | delete _cur; |
aoqi@0 | 522 | } |
aoqi@0 | 523 | _cur = _next; |
aoqi@0 | 524 | set_expanded(false); |
aoqi@0 | 525 | } |
aoqi@0 | 526 | |
aoqi@0 | 527 | void SparsePRT::expand() { |
aoqi@0 | 528 | RSHashTable* last = _next; |
aoqi@0 | 529 | _next = new RSHashTable(last->capacity() * 2); |
aoqi@0 | 530 | |
aoqi@0 | 531 | #if SPARSE_PRT_VERBOSE |
aoqi@0 | 532 | gclog_or_tty->print_cr(" Expanded sparse table for %u to %d.", |
aoqi@0 | 533 | _hr->hrs_index(), _next->capacity()); |
aoqi@0 | 534 | #endif |
aoqi@0 | 535 | for (size_t i = 0; i < last->capacity(); i++) { |
aoqi@0 | 536 | SparsePRTEntry* e = last->entry((int)i); |
aoqi@0 | 537 | if (e->valid_entry()) { |
aoqi@0 | 538 | #if SPARSE_PRT_VERBOSE |
aoqi@0 | 539 | gclog_or_tty->print_cr(" During expansion, transferred entry for %d.", |
aoqi@0 | 540 | e->r_ind()); |
aoqi@0 | 541 | #endif |
aoqi@0 | 542 | _next->add_entry(e); |
aoqi@0 | 543 | } |
aoqi@0 | 544 | } |
aoqi@0 | 545 | if (last != _cur) { |
aoqi@0 | 546 | delete last; |
aoqi@0 | 547 | } |
aoqi@0 | 548 | add_to_expanded_list(this); |
aoqi@0 | 549 | } |
aoqi@0 | 550 | |
aoqi@0 | 551 | void SparsePRTCleanupTask::add(SparsePRT* sprt) { |
aoqi@0 | 552 | assert(sprt->should_be_on_expanded_list(), "pre-condition"); |
aoqi@0 | 553 | |
aoqi@0 | 554 | sprt->set_next_expanded(NULL); |
aoqi@0 | 555 | if (_tail != NULL) { |
aoqi@0 | 556 | _tail->set_next_expanded(sprt); |
aoqi@0 | 557 | } else { |
aoqi@0 | 558 | _head = sprt; |
aoqi@0 | 559 | } |
aoqi@0 | 560 | _tail = sprt; |
aoqi@0 | 561 | } |