Mon, 24 Mar 2014 15:30:14 +0100
8035406: Improve data structure for Code Cache remembered sets
Summary: Change the code cache remembered sets data structure from a GrowableArray to a chunked list of nmethods. This makes the data structure more amenable to parallelization, and decreases freeing time.
Reviewed-by: mgerdin, brutisso
johnc@5078 | 1 | /* |
johnc@5078 | 2 | * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. |
johnc@5078 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
johnc@5078 | 4 | * |
johnc@5078 | 5 | * This code is free software; you can redistribute it and/or modify it |
johnc@5078 | 6 | * under the terms of the GNU General Public License version 2 only, as |
johnc@5078 | 7 | * published by the Free Software Foundation. |
johnc@5078 | 8 | * |
johnc@5078 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
johnc@5078 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
johnc@5078 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
johnc@5078 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
johnc@5078 | 13 | * accompanied this code). |
johnc@5078 | 14 | * |
johnc@5078 | 15 | * You should have received a copy of the GNU General Public License version |
johnc@5078 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
johnc@5078 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
johnc@5078 | 18 | * |
johnc@5078 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
johnc@5078 | 20 | * or visit www.oracle.com if you need additional information or have any |
johnc@5078 | 21 | * questions. |
johnc@5078 | 22 | * |
johnc@5078 | 23 | */ |
johnc@5078 | 24 | |
johnc@5078 | 25 | #include "precompiled.hpp" |
johnc@5078 | 26 | #include "gc_implementation/g1/g1CardCounts.hpp" |
johnc@5078 | 27 | #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" |
johnc@5078 | 28 | #include "gc_implementation/g1/g1CollectorPolicy.hpp" |
johnc@5078 | 29 | #include "gc_implementation/g1/g1GCPhaseTimes.hpp" |
johnc@5078 | 30 | #include "memory/cardTableModRefBS.hpp" |
johnc@5078 | 31 | #include "services/memTracker.hpp" |
johnc@5078 | 32 | #include "utilities/copy.hpp" |
johnc@5078 | 33 | |
johnc@5078 | 34 | void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) { |
johnc@5078 | 35 | if (has_count_table()) { |
shade@5709 | 36 | assert(from_card_num >= 0 && from_card_num < _committed_max_card_num, |
shade@5709 | 37 | err_msg("from card num out of range: "SIZE_FORMAT, from_card_num)); |
johnc@5078 | 38 | assert(from_card_num < to_card_num, |
johnc@5078 | 39 | err_msg("Wrong order? from: " SIZE_FORMAT ", to: "SIZE_FORMAT, |
johnc@5078 | 40 | from_card_num, to_card_num)); |
johnc@5078 | 41 | assert(to_card_num <= _committed_max_card_num, |
johnc@5078 | 42 | err_msg("to card num out of range: " |
johnc@5078 | 43 | "to: "SIZE_FORMAT ", " |
johnc@5078 | 44 | "max: "SIZE_FORMAT, |
johnc@5078 | 45 | to_card_num, _committed_max_card_num)); |
johnc@5078 | 46 | |
johnc@5078 | 47 | to_card_num = MIN2(_committed_max_card_num, to_card_num); |
johnc@5078 | 48 | |
johnc@5078 | 49 | Copy::fill_to_bytes(&_card_counts[from_card_num], (to_card_num - from_card_num)); |
johnc@5078 | 50 | } |
johnc@5078 | 51 | } |
johnc@5078 | 52 | |
johnc@5078 | 53 | G1CardCounts::G1CardCounts(G1CollectedHeap *g1h): |
johnc@5078 | 54 | _g1h(g1h), _card_counts(NULL), |
johnc@5078 | 55 | _reserved_max_card_num(0), _committed_max_card_num(0), |
johnc@5078 | 56 | _committed_size(0) {} |
johnc@5078 | 57 | |
johnc@5078 | 58 | void G1CardCounts::initialize() { |
johnc@5078 | 59 | assert(_g1h->max_capacity() > 0, "initialization order"); |
johnc@5078 | 60 | assert(_g1h->capacity() == 0, "initialization order"); |
johnc@5078 | 61 | |
johnc@5078 | 62 | if (G1ConcRSHotCardLimit > 0) { |
johnc@5078 | 63 | // The max value we can store in the counts table is |
johnc@5078 | 64 | // max_jubyte. Guarantee the value of the hot |
johnc@5078 | 65 | // threshold limit is no more than this. |
johnc@5078 | 66 | guarantee(G1ConcRSHotCardLimit <= max_jubyte, "sanity"); |
johnc@5078 | 67 | |
mgerdin@5811 | 68 | _ct_bs = _g1h->g1_barrier_set(); |
johnc@5078 | 69 | _ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start()); |
johnc@5078 | 70 | |
johnc@5078 | 71 | // Allocate/Reserve the counts table |
johnc@5078 | 72 | size_t reserved_bytes = _g1h->max_capacity(); |
johnc@5078 | 73 | _reserved_max_card_num = reserved_bytes >> CardTableModRefBS::card_shift; |
johnc@5078 | 74 | |
johnc@5078 | 75 | size_t reserved_size = _reserved_max_card_num * sizeof(jbyte); |
johnc@5078 | 76 | ReservedSpace rs(ReservedSpace::allocation_align_size_up(reserved_size)); |
johnc@5078 | 77 | if (!rs.is_reserved()) { |
johnc@5078 | 78 | warning("Could not reserve enough space for the card counts table"); |
johnc@5078 | 79 | guarantee(!has_reserved_count_table(), "should be NULL"); |
johnc@5078 | 80 | return; |
johnc@5078 | 81 | } |
johnc@5078 | 82 | |
johnc@5078 | 83 | MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); |
johnc@5078 | 84 | |
johnc@5078 | 85 | _card_counts_storage.initialize(rs, 0); |
johnc@5078 | 86 | _card_counts = (jubyte*) _card_counts_storage.low(); |
johnc@5078 | 87 | } |
johnc@5078 | 88 | } |
johnc@5078 | 89 | |
johnc@5078 | 90 | void G1CardCounts::resize(size_t heap_capacity) { |
johnc@5078 | 91 | // Expand the card counts table to handle a heap with the given capacity. |
johnc@5078 | 92 | |
johnc@5078 | 93 | if (!has_reserved_count_table()) { |
johnc@5078 | 94 | // Don't expand if we failed to reserve the card counts table. |
johnc@5078 | 95 | return; |
johnc@5078 | 96 | } |
johnc@5078 | 97 | |
johnc@5078 | 98 | assert(_committed_size == |
johnc@5078 | 99 | ReservedSpace::allocation_align_size_up(_committed_size), |
johnc@5078 | 100 | err_msg("Unaligned? committed_size: " SIZE_FORMAT, _committed_size)); |
johnc@5078 | 101 | |
johnc@5121 | 102 | // Verify that the committed space for the card counts matches our |
johnc@5121 | 103 | // committed max card num. Note for some allocation alignments, the |
johnc@5121 | 104 | // amount of space actually committed for the counts table will be able |
johnc@5121 | 105 | // to span more cards than the number spanned by the maximum heap. |
johnc@5078 | 106 | size_t prev_committed_size = _committed_size; |
johnc@5121 | 107 | size_t prev_committed_card_num = committed_to_card_num(prev_committed_size); |
johnc@5121 | 108 | |
johnc@5078 | 109 | assert(prev_committed_card_num == _committed_max_card_num, |
johnc@5078 | 110 | err_msg("Card mismatch: " |
johnc@5078 | 111 | "prev: " SIZE_FORMAT ", " |
johnc@5121 | 112 | "committed: "SIZE_FORMAT", " |
johnc@5121 | 113 | "reserved: "SIZE_FORMAT, |
johnc@5121 | 114 | prev_committed_card_num, _committed_max_card_num, _reserved_max_card_num)); |
johnc@5078 | 115 | |
johnc@5078 | 116 | size_t new_size = (heap_capacity >> CardTableModRefBS::card_shift) * sizeof(jbyte); |
johnc@5078 | 117 | size_t new_committed_size = ReservedSpace::allocation_align_size_up(new_size); |
johnc@5121 | 118 | size_t new_committed_card_num = committed_to_card_num(new_committed_size); |
johnc@5078 | 119 | |
johnc@5078 | 120 | if (_committed_max_card_num < new_committed_card_num) { |
johnc@5078 | 121 | // we need to expand the backing store for the card counts |
johnc@5078 | 122 | size_t expand_size = new_committed_size - prev_committed_size; |
johnc@5078 | 123 | |
johnc@5078 | 124 | if (!_card_counts_storage.expand_by(expand_size)) { |
johnc@5078 | 125 | warning("Card counts table backing store commit failure"); |
johnc@5078 | 126 | return; |
johnc@5078 | 127 | } |
johnc@5078 | 128 | assert(_card_counts_storage.committed_size() == new_committed_size, |
johnc@5078 | 129 | "expansion commit failure"); |
johnc@5078 | 130 | |
johnc@5078 | 131 | _committed_size = new_committed_size; |
johnc@5078 | 132 | _committed_max_card_num = new_committed_card_num; |
johnc@5078 | 133 | |
johnc@5078 | 134 | clear_range(prev_committed_card_num, _committed_max_card_num); |
johnc@5078 | 135 | } |
johnc@5078 | 136 | } |
johnc@5078 | 137 | |
johnc@5078 | 138 | uint G1CardCounts::add_card_count(jbyte* card_ptr) { |
johnc@5078 | 139 | // Returns the number of times the card has been refined. |
johnc@5078 | 140 | // If we failed to reserve/commit the counts table, return 0. |
johnc@5078 | 141 | // If card_ptr is beyond the committed end of the counts table, |
johnc@5078 | 142 | // return 0. |
johnc@5078 | 143 | // Otherwise return the actual count. |
johnc@5078 | 144 | // Unless G1ConcRSHotCardLimit has been set appropriately, |
johnc@5078 | 145 | // returning 0 will result in the card being considered |
johnc@5078 | 146 | // cold and will be refined immediately. |
johnc@5078 | 147 | uint count = 0; |
johnc@5078 | 148 | if (has_count_table()) { |
johnc@5078 | 149 | size_t card_num = ptr_2_card_num(card_ptr); |
johnc@5078 | 150 | if (card_num < _committed_max_card_num) { |
johnc@5078 | 151 | count = (uint) _card_counts[card_num]; |
johnc@5078 | 152 | if (count < G1ConcRSHotCardLimit) { |
johnc@5342 | 153 | _card_counts[card_num] = |
johnc@5342 | 154 | (jubyte)(MIN2((uintx)(_card_counts[card_num] + 1), G1ConcRSHotCardLimit)); |
johnc@5078 | 155 | } |
johnc@5078 | 156 | } |
johnc@5078 | 157 | } |
johnc@5078 | 158 | return count; |
johnc@5078 | 159 | } |
johnc@5078 | 160 | |
johnc@5078 | 161 | bool G1CardCounts::is_hot(uint count) { |
johnc@5078 | 162 | return (count >= G1ConcRSHotCardLimit); |
johnc@5078 | 163 | } |
johnc@5078 | 164 | |
johnc@5078 | 165 | void G1CardCounts::clear_region(HeapRegion* hr) { |
johnc@5078 | 166 | assert(!hr->isHumongous(), "Should have been cleared"); |
johnc@5078 | 167 | if (has_count_table()) { |
johnc@5078 | 168 | HeapWord* bottom = hr->bottom(); |
johnc@5078 | 169 | |
johnc@5078 | 170 | // We use the last address in hr as hr could be the |
johnc@5078 | 171 | // last region in the heap. In which case trying to find |
johnc@5078 | 172 | // the card for hr->end() will be an OOB accesss to the |
johnc@5078 | 173 | // card table. |
johnc@5078 | 174 | HeapWord* last = hr->end() - 1; |
johnc@5078 | 175 | assert(_g1h->g1_committed().contains(last), |
johnc@5078 | 176 | err_msg("last not in committed: " |
johnc@5078 | 177 | "last: " PTR_FORMAT ", " |
johnc@5078 | 178 | "committed: [" PTR_FORMAT ", " PTR_FORMAT ")", |
johnc@5078 | 179 | last, |
johnc@5078 | 180 | _g1h->g1_committed().start(), |
johnc@5078 | 181 | _g1h->g1_committed().end())); |
johnc@5078 | 182 | |
johnc@5078 | 183 | const jbyte* from_card_ptr = _ct_bs->byte_for_const(bottom); |
johnc@5078 | 184 | const jbyte* last_card_ptr = _ct_bs->byte_for_const(last); |
johnc@5078 | 185 | |
johnc@5078 | 186 | #ifdef ASSERT |
johnc@5078 | 187 | HeapWord* start_addr = _ct_bs->addr_for(from_card_ptr); |
johnc@5078 | 188 | assert(start_addr == hr->bottom(), "alignment"); |
johnc@5078 | 189 | HeapWord* last_addr = _ct_bs->addr_for(last_card_ptr); |
johnc@5078 | 190 | assert((last_addr + CardTableModRefBS::card_size_in_words) == hr->end(), "alignment"); |
johnc@5078 | 191 | #endif // ASSERT |
johnc@5078 | 192 | |
johnc@5078 | 193 | // Clear the counts for the (exclusive) card range. |
johnc@5078 | 194 | size_t from_card_num = ptr_2_card_num(from_card_ptr); |
johnc@5078 | 195 | size_t to_card_num = ptr_2_card_num(last_card_ptr) + 1; |
johnc@5078 | 196 | clear_range(from_card_num, to_card_num); |
johnc@5078 | 197 | } |
johnc@5078 | 198 | } |
johnc@5078 | 199 | |
johnc@5078 | 200 | void G1CardCounts::clear_all() { |
johnc@5078 | 201 | assert(SafepointSynchronize::is_at_safepoint(), "don't call this otherwise"); |
johnc@5078 | 202 | clear_range((size_t)0, _committed_max_card_num); |
johnc@5078 | 203 | } |
johnc@5078 | 204 | |
johnc@5078 | 205 | G1CardCounts::~G1CardCounts() { |
johnc@5078 | 206 | if (has_reserved_count_table()) { |
johnc@5078 | 207 | _card_counts_storage.release(); |
johnc@5078 | 208 | } |
johnc@5078 | 209 | } |
johnc@5078 | 210 |