Path: blob/master/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp
40957 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "gc/shared/cardTable.hpp"26#include "gc/shared/cardTableBarrierSetAssembler.hpp"27#include "gc/shared/cardTableBarrierSet.inline.hpp"28#include "gc/shared/collectedHeap.hpp"29#include "gc/shared/space.inline.hpp"30#include "logging/log.hpp"31#include "memory/virtualspace.hpp"32#include "oops/oop.inline.hpp"33#include "runtime/thread.hpp"34#include "services/memTracker.hpp"35#include "utilities/align.hpp"36#include "utilities/macros.hpp"37#ifdef COMPILER138#include "gc/shared/c1/cardTableBarrierSetC1.hpp"39#endif40#ifdef COMPILER241#include "gc/shared/c2/cardTableBarrierSetC2.hpp"42#endif4344class CardTableBarrierSetC1;45class CardTableBarrierSetC2;4647// This kind of "BarrierSet" allows a "CollectedHeap" to detect and48// enumerate ref fields that have been modified (since the last49// enumeration.)5051CardTableBarrierSet::CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler,52BarrierSetC1* barrier_set_c1,53BarrierSetC2* barrier_set_c2,54CardTable* card_table,55const BarrierSet::FakeRtti& fake_rtti) :56ModRefBarrierSet(barrier_set_assembler,57barrier_set_c1,58barrier_set_c2,59fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)),60_defer_initial_card_mark(false),61_card_table(card_table)62{}6364CardTableBarrierSet::CardTableBarrierSet(CardTable* card_table) :65ModRefBarrierSet(make_barrier_set_assembler<CardTableBarrierSetAssembler>(),66make_barrier_set_c1<CardTableBarrierSetC1>(),67make_barrier_set_c2<CardTableBarrierSetC2>(),68BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)),69_defer_initial_card_mark(false),70_card_table(card_table)71{}7273void CardTableBarrierSet::initialize() {74initialize_deferred_card_mark_barriers();75}7677CardTableBarrierSet::~CardTableBarrierSet() {78delete _card_table;79}8081void CardTableBarrierSet::write_ref_array_work(MemRegion mr) {82_card_table->dirty_MemRegion(mr);83}8485void CardTableBarrierSet::invalidate(MemRegion mr) {86_card_table->invalidate(mr);87}8889void CardTableBarrierSet::print_on(outputStream* st) const {90_card_table->print_on(st);91}9293// Helper for ReduceInitialCardMarks. For performance,94// compiled code may elide card-marks for initializing stores95// to a newly allocated object along the fast-path. We96// compensate for such elided card-marks as follows:97// (a) Generational, non-concurrent collectors, such as98// GenCollectedHeap(DefNew,Tenured) and99// ParallelScavengeHeap(ParallelGC, ParallelOldGC)100// need the card-mark if and only if the region is101// in the old gen, and do not care if the card-mark102// succeeds or precedes the initializing stores themselves,103// so long as the card-mark is completed before the next104// scavenge. For all these cases, we can do a card mark105// at the point at which we do a slow path allocation106// in the old gen, i.e. in this call.107// (b) G1CollectedHeap(G1) uses two kinds of write barriers. When a108// G1 concurrent marking is in progress an SATB (pre-write-)barrier109// is used to remember the pre-value of any store. Initializing110// stores will not need this barrier, so we need not worry about111// compensating for the missing pre-barrier here. Turning now112// to the post-barrier, we note that G1 needs a RS update barrier113// which simply enqueues a (sequence of) dirty cards which may114// optionally be refined by the concurrent update threads. Note115// that this barrier need only be applied to a non-young write,116// but, because of the presence of concurrent refinement,117// must strictly follow the oop-store.118//119// For any future collector, this code should be reexamined with120// that specific collector in mind, and the documentation above suitably121// extended and updated.122void CardTableBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {123#if COMPILER2_OR_JVMCI124if (!ReduceInitialCardMarks) {125return;126}127// If a previous card-mark was deferred, flush it now.128flush_deferred_card_mark_barrier(thread);129if (new_obj->is_typeArray() || _card_table->is_in_young(new_obj)) {130// Arrays of non-references don't need a post-barrier.131// The deferred_card_mark region should be empty132// following the flush above.133assert(thread->deferred_card_mark().is_empty(), "Error");134} else {135MemRegion mr(cast_from_oop<HeapWord*>(new_obj), new_obj->size());136assert(!mr.is_empty(), "Error");137if (_defer_initial_card_mark) {138// Defer the card mark139thread->set_deferred_card_mark(mr);140} else {141// Do the card mark142invalidate(mr);143}144}145#endif // COMPILER2_OR_JVMCI146}147148void CardTableBarrierSet::initialize_deferred_card_mark_barriers() {149// Used for ReduceInitialCardMarks (when COMPILER2 or JVMCI is used);150// otherwise remains unused.151#if COMPILER2_OR_JVMCI152_defer_initial_card_mark = CompilerConfig::is_c2_or_jvmci_compiler_enabled() && ReduceInitialCardMarks153&& (DeferInitialCardMark || card_mark_must_follow_store());154#else155assert(_defer_initial_card_mark == false, "Who would set it?");156#endif157}158159void CardTableBarrierSet::flush_deferred_card_mark_barrier(JavaThread* thread) {160#if COMPILER2_OR_JVMCI161MemRegion deferred = thread->deferred_card_mark();162if (!deferred.is_empty()) {163assert(_defer_initial_card_mark, "Otherwise should be empty");164{165// Verify that the storage points to a parsable object in heap166DEBUG_ONLY(oop old_obj = cast_to_oop(deferred.start());)167assert(!_card_table->is_in_young(old_obj),168"Else should have been filtered in on_slowpath_allocation_exit()");169assert(oopDesc::is_oop(old_obj, true), "Not an oop");170assert(deferred.word_size() == (size_t)(old_obj->size()),171"Mismatch: multiple objects?");172}173write_region(deferred);174// "Clear" the deferred_card_mark field175thread->set_deferred_card_mark(MemRegion());176}177assert(thread->deferred_card_mark().is_empty(), "invariant");178#else179assert(!_defer_initial_card_mark, "Should be false");180assert(thread->deferred_card_mark().is_empty(), "Should be empty");181#endif182}183184void CardTableBarrierSet::on_thread_detach(Thread* thread) {185// The deferred store barriers must all have been flushed to the186// card-table (or other remembered set structure) before GC starts187// processing the card-table (or other remembered set).188if (thread->is_Java_thread()) { // Only relevant for Java threads.189flush_deferred_card_mark_barrier(thread->as_Java_thread());190}191}192193bool CardTableBarrierSet::card_mark_must_follow_store() const {194return false;195}196197198