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