--- /dev/null 2013-01-15 13:59:16.000000000 -0800 +++ new/src/share/vm/gc_implementation/g1/g1CardCounts.cpp 2013-01-15 13:59:16.091922693 -0800 @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/g1CardCounts.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/g1/g1CollectorPolicy.hpp" +#include "gc_implementation/g1/g1GCPhaseTimes.hpp" +#include "memory/cardTableModRefBS.hpp" +#include "services/memTracker.hpp" + +void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) { + if (_committed_max_card_num > 0) { + check_card_num(from_card_num, + err_msg("from card num out of range: "SIZE_FORMAT, from_card_num)); + assert(from_card_num < to_card_num, "ordering?"); + assert(to_card_num <= _committed_max_card_num, + err_msg("to card num out of range: "SIZE_FORMAT, to_card_num)); + + assert(_card_counts != NULL, "must be"); + assert(G1ConcRSHotCardLimit > 0, "must be"); + + to_card_num = MIN2(_committed_max_card_num, to_card_num); + + for (size_t card_num = from_card_num; + card_num < to_card_num; card_num += 1) { + _card_counts[card_num] = 0; + } + } +} + +int G1CardCounts::add_card_count(jbyte* card_ptr) { + assert(_committed_max_card_num > 0, "sanity"); + assert(_card_counts != NULL, "sanity"); + assert(G1ConcRSHotCardLimit <= max_jubyte, "check"); + + size_t card_num = ptr_2_card_num(card_ptr); + int count = 0; + if (card_num < _committed_max_card_num) { + count = (int) _card_counts[card_num]; + if (count < G1ConcRSHotCardLimit) { + _card_counts[card_num] += 1; + } + assert(_card_counts[card_num] <= G1ConcRSHotCardLimit, "overflow"); + } + return count; +} + +G1CardCounts::G1CardCounts(G1CollectedHeap *g1h): + _g1h(g1h), _card_counts(NULL), + _reserved_max_card_num(0), _committed_max_card_num(0), + _committed_size(0) {} + +void G1CardCounts::initialize() { + assert(_g1h->max_capacity() > 0, "initialization order"); + assert(_g1h->capacity() == 0, "initialization order"); + + if (G1ConcRSHotCardLimit > 0) { + // The max value we can store in the counts table is + // max_jubyte. Guarantee the value of the hot + // threshold limit is no more than this. + guarantee(G1ConcRSHotCardLimit <= max_jubyte, "sanity"); + + ModRefBarrierSet* bs = _g1h->mr_bs(); + guarantee(bs->is_a(BarrierSet::CardTableModRef), "Precondition"); + _ct_bs = (CardTableModRefBS*)bs; + _ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start()); + + // Allocate/Reserve the counts table + size_t reserved_bytes = _g1h->max_capacity(); + _reserved_max_card_num = reserved_bytes >> CardTableModRefBS::card_shift; + + size_t reserved_size = _reserved_max_card_num * sizeof(jbyte); + ReservedSpace rs(ReservedSpace::allocation_align_size_up(reserved_size)); + if (!rs.is_reserved()) { + warning("Could not reserve enough space for the card counts table"); + guarantee(_card_counts == NULL, "should be NULL"); + return; + } + + MemTracker::record_virtual_memory_type((address)rs.base(), mtGC); + + _card_counts_storage.initialize(rs, 0); + _card_counts = (jbyte*) _card_counts_storage.low(); + } +} + +void G1CardCounts::resize(size_t heap_capacity) { + // Expand the card counts table to handle a heap with the given capacity. + + if (_card_counts == NULL) { + // Don't expand if we failed to reserve the card counts table. + return; + } + + assert(_committed_size == + ReservedSpace::allocation_align_size_up(_committed_size), "sanity"); + + // Verify that the committed space for the card counts + // matches our committed max card num. + size_t prev_committed_size = _committed_size; + size_t prev_committed_card_num = prev_committed_size / sizeof(jbyte); + assert(prev_committed_card_num == _committed_max_card_num, "mismatch"); + + size_t new_size = (heap_capacity >> CardTableModRefBS::card_shift) * sizeof(jbyte); + size_t new_committed_size = ReservedSpace::allocation_align_size_up(new_size); + size_t new_committed_card_num = + MIN2(_reserved_max_card_num, new_committed_size / sizeof(jbyte)); + + if (_committed_max_card_num < new_committed_card_num) { + // we need to expand the backing store for the card counts + size_t expand_size = new_committed_size - prev_committed_size; + + if (!_card_counts_storage.expand_by(expand_size)) { + warning("Card counts table backing store commit failure"); + return; + } + assert(_card_counts_storage.committed_size() == new_committed_size, + "expansion commit failure"); + + _committed_size = new_committed_size; + _committed_max_card_num = new_committed_card_num; + + clear_range(prev_committed_card_num, _committed_max_card_num); + } +} + +bool G1CardCounts::is_hot(jbyte* card_ptr) { + if (_committed_max_card_num > 0) { + assert(_card_counts != NULL, "must be"); + assert(G1ConcRSHotCardLimit > 0, "must be"); + + int count = add_card_count(card_ptr); + if (count >= G1ConcRSHotCardLimit) { + return true; + } + } + // Failed to allocate the counts table (always cold), the card_ptr + // is beyond the committed end of the counts table (always cold), + // or the card is actually cold. + return false; +} + +void G1CardCounts::clear_region(HeapRegion* hr) { + assert(!hr->isHumongous(), "unexpected"); + HeapWord* bottom = hr->bottom(); + + // We use the last address in hr as hr could be the + // last region in the heap. In which case trying to find + // the card for hr->end() will be an OOB accesss to the + // card table. + HeapWord* last = hr->end() - 1; + assert(_g1h->g1_committed().contains(last), "not in committed"); + + const jbyte* from_card_ptr = _ct_bs->byte_for_const(bottom); + const jbyte* last_card_ptr = _ct_bs->byte_for_const(last); + +#ifdef ASSERT + HeapWord* start_addr = _ct_bs->addr_for(from_card_ptr); + assert(start_addr == hr->bottom(), "alignment"); + HeapWord* last_addr = _ct_bs->addr_for(last_card_ptr); + assert((last_addr + CardTableModRefBS::card_size_in_words) == hr->end(), "alignment"); +#endif // ASSERT + + // Clear the counts for the (exclusive) card range. + size_t from_card_num = ptr_2_card_num((jbyte*)from_card_ptr); + size_t to_card_num = ptr_2_card_num((jbyte*)last_card_ptr) + 1; + clear_range(from_card_num, to_card_num); +} + +void G1CardCounts::clear_all() { + assert(SafepointSynchronize::is_at_safepoint(), "don't call this otherwise"); + clear_range((size_t)0, _committed_max_card_num); +} + +G1CardCounts::~G1CardCounts() { + if (_card_counts != NULL) { + assert(G1ConcRSHotCardLimit > 0, "must be"); + _card_counts_storage.release(); + } +} +