blob: ca8f675e6dfd7e09582a34120172e862520c5abc [file] [log] [blame]
/*
* Copyright (c) 1997, 2020, 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.
*
*/
#ifndef SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
#define SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP
#include "gc/g1/heapRegionRemSet.hpp"
#include "gc/g1/g1CardSet.inline.hpp"
#include "gc/g1/g1CollectedHeap.inline.hpp"
#include "gc/g1/heapRegion.inline.hpp"
#include "runtime/atomic.hpp"
#include "utilities/bitMap.inline.hpp"
void HeapRegionRemSet::set_state_untracked() {
guarantee(SafepointSynchronize::is_at_safepoint() || !is_tracked(),
"Should only set to Untracked during safepoint but is %s.", get_state_str());
if (_state == Untracked) {
return;
}
clear_fcc();
_state = Untracked;
}
void HeapRegionRemSet::set_state_updating() {
guarantee(SafepointSynchronize::is_at_safepoint() && !is_tracked(),
"Should only set to Updating from Untracked during safepoint but is %s", get_state_str());
clear_fcc();
_state = Updating;
}
void HeapRegionRemSet::set_state_complete() {
clear_fcc();
_state = Complete;
}
template <typename Closure>
class G1ContainerCardsOrRanges {
Closure& _cl;
uint _region_idx;
uint _offset;
public:
G1ContainerCardsOrRanges(Closure& cl, uint region_idx, uint offset) : _cl(cl), _region_idx(region_idx), _offset(offset) { }
bool start_iterate(uint tag) {
return _cl.start_iterate(tag, _region_idx);
}
void operator()(uint card_idx) {
_cl.do_card(card_idx + _offset);
}
void operator()(uint card_idx, uint length) {
_cl.do_card_range(card_idx + _offset, length);
}
};
template <typename Closure, template <typename> class CardOrRanges>
class G1HeapRegionRemSetMergeCardClosure : public G1CardSet::ContainerPtrClosure {
G1CardSet* _card_set;
Closure& _cl;
uint _log_card_regions_per_region;
uint _card_regions_per_region_mask;
uint _log_card_region_size;
public:
G1HeapRegionRemSetMergeCardClosure(G1CardSet* card_set,
Closure& cl,
uint log_card_regions_per_region,
uint log_card_region_size) :
_card_set(card_set),
_cl(cl),
_log_card_regions_per_region(log_card_regions_per_region),
_card_regions_per_region_mask((1 << log_card_regions_per_region) - 1),
_log_card_region_size(log_card_region_size) {
}
void do_containerptr(uint card_region_idx, size_t num_occupied, G1CardSet::ContainerPtr container) override {
CardOrRanges<Closure> cl(_cl,
card_region_idx >> _log_card_regions_per_region,
(card_region_idx & _card_regions_per_region_mask) << _log_card_region_size);
_card_set->iterate_cards_or_ranges_in_container(container, cl);
}
};
template <class CardOrRangeVisitor>
inline void HeapRegionRemSet::iterate_for_merge(CardOrRangeVisitor& cl) {
G1HeapRegionRemSetMergeCardClosure<CardOrRangeVisitor, G1ContainerCardsOrRanges> cl2(&_card_set,
cl,
_card_set.config()->log2_card_regions_per_heap_region(),
_card_set.config()->log2_cards_per_card_region());
_card_set.iterate_containers(&cl2, true /* at_safepoint */);
}
uintptr_t HeapRegionRemSet::to_card(OopOrNarrowOopStar from) const {
return pointer_delta(from, _heap_base_address, 1) >> CardTable::card_shift();
}
void HeapRegionRemSet::add_reference(OopOrNarrowOopStar from, uint tid) {
assert(_state != Untracked, "must be");
uint cur_idx = _hr->hrm_index();
uintptr_t from_card = uintptr_t(from) >> CardTable::card_shift();
if (G1FromCardCache::contains_or_replace(tid, cur_idx, from_card)) {
// We can't check whether the card is in the remembered set - the card container
// may be coarsened just now.
//assert(contains_reference(from), "We just found " PTR_FORMAT " in the FromCardCache", p2i(from));
return;
}
_card_set.add_card(to_card(from));
}
bool HeapRegionRemSet::contains_reference(OopOrNarrowOopStar from) {
return _card_set.contains_card(to_card(from));
}
void HeapRegionRemSet::print_info(outputStream* st, OopOrNarrowOopStar from) {
_card_set.print_info(st, to_card(from));
}
#endif // SHARE_VM_GC_G1_HEAPREGIONREMSET_INLINE_HPP