src/hotspot/share/gc/shared/cardTableBarrierSet.cpp
changeset 49455 848864ed9b17
parent 49390 95f0b54a3024
child 49484 ee8fa73b90f9
equal deleted inserted replaced
49454:689ebcfe04fd 49455:848864ed9b17
       
     1 /*
       
     2  * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  *
       
    23  */
       
    24 
       
    25 #include "precompiled.hpp"
       
    26 #include "gc/shared/cardTableBarrierSet.inline.hpp"
       
    27 #include "gc/shared/collectedHeap.hpp"
       
    28 #include "gc/shared/genCollectedHeap.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 
       
    38 // This kind of "BarrierSet" allows a "CollectedHeap" to detect and
       
    39 // enumerate ref fields that have been modified (since the last
       
    40 // enumeration.)
       
    41 
       
    42 CardTableBarrierSet::CardTableBarrierSet(
       
    43   CardTable* card_table,
       
    44   const BarrierSet::FakeRtti& fake_rtti) :
       
    45   ModRefBarrierSet(fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)),
       
    46   _defer_initial_card_mark(false),
       
    47   _card_table(card_table)
       
    48 {}
       
    49 
       
    50 CardTableBarrierSet::CardTableBarrierSet(CardTable* card_table) :
       
    51   ModRefBarrierSet(BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)),
       
    52   _defer_initial_card_mark(false),
       
    53   _card_table(card_table)
       
    54 {}
       
    55 
       
    56 void CardTableBarrierSet::initialize() {
       
    57   initialize_deferred_card_mark_barriers();
       
    58 }
       
    59 
       
    60 CardTableBarrierSet::~CardTableBarrierSet() {
       
    61   delete _card_table;
       
    62 }
       
    63 
       
    64 void CardTableBarrierSet::write_ref_array_work(MemRegion mr) {
       
    65   _card_table->dirty_MemRegion(mr);
       
    66 }
       
    67 
       
    68 void CardTableBarrierSet::invalidate(MemRegion mr) {
       
    69   _card_table->invalidate(mr);
       
    70 }
       
    71 
       
    72 void CardTableBarrierSet::print_on(outputStream* st) const {
       
    73   _card_table->print_on(st);
       
    74 }
       
    75 
       
    76 // Helper for ReduceInitialCardMarks. For performance,
       
    77 // compiled code may elide card-marks for initializing stores
       
    78 // to a newly allocated object along the fast-path. We
       
    79 // compensate for such elided card-marks as follows:
       
    80 // (a) Generational, non-concurrent collectors, such as
       
    81 //     GenCollectedHeap(ParNew,DefNew,Tenured) and
       
    82 //     ParallelScavengeHeap(ParallelGC, ParallelOldGC)
       
    83 //     need the card-mark if and only if the region is
       
    84 //     in the old gen, and do not care if the card-mark
       
    85 //     succeeds or precedes the initializing stores themselves,
       
    86 //     so long as the card-mark is completed before the next
       
    87 //     scavenge. For all these cases, we can do a card mark
       
    88 //     at the point at which we do a slow path allocation
       
    89 //     in the old gen, i.e. in this call.
       
    90 // (b) GenCollectedHeap(ConcurrentMarkSweepGeneration) requires
       
    91 //     in addition that the card-mark for an old gen allocated
       
    92 //     object strictly follow any associated initializing stores.
       
    93 //     In these cases, the memRegion remembered below is
       
    94 //     used to card-mark the entire region either just before the next
       
    95 //     slow-path allocation by this thread or just before the next scavenge or
       
    96 //     CMS-associated safepoint, whichever of these events happens first.
       
    97 //     (The implicit assumption is that the object has been fully
       
    98 //     initialized by this point, a fact that we assert when doing the
       
    99 //     card-mark.)
       
   100 // (c) G1CollectedHeap(G1) uses two kinds of write barriers. When a
       
   101 //     G1 concurrent marking is in progress an SATB (pre-write-)barrier
       
   102 //     is used to remember the pre-value of any store. Initializing
       
   103 //     stores will not need this barrier, so we need not worry about
       
   104 //     compensating for the missing pre-barrier here. Turning now
       
   105 //     to the post-barrier, we note that G1 needs a RS update barrier
       
   106 //     which simply enqueues a (sequence of) dirty cards which may
       
   107 //     optionally be refined by the concurrent update threads. Note
       
   108 //     that this barrier need only be applied to a non-young write,
       
   109 //     but, like in CMS, because of the presence of concurrent refinement
       
   110 //     (much like CMS' precleaning), must strictly follow the oop-store.
       
   111 //     Thus, using the same protocol for maintaining the intended
       
   112 //     invariants turns out, serendepitously, to be the same for both
       
   113 //     G1 and CMS.
       
   114 //
       
   115 // For any future collector, this code should be reexamined with
       
   116 // that specific collector in mind, and the documentation above suitably
       
   117 // extended and updated.
       
   118 void CardTableBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) {
       
   119 #if defined(COMPILER2) || INCLUDE_JVMCI
       
   120   if (!ReduceInitialCardMarks) {
       
   121     return;
       
   122   }
       
   123   // If a previous card-mark was deferred, flush it now.
       
   124   flush_deferred_card_mark_barrier(thread);
       
   125   if (new_obj->is_typeArray() || _card_table->is_in_young(new_obj)) {
       
   126     // Arrays of non-references don't need a post-barrier.
       
   127     // The deferred_card_mark region should be empty
       
   128     // following the flush above.
       
   129     assert(thread->deferred_card_mark().is_empty(), "Error");
       
   130   } else {
       
   131     MemRegion mr((HeapWord*)new_obj, new_obj->size());
       
   132     assert(!mr.is_empty(), "Error");
       
   133     if (_defer_initial_card_mark) {
       
   134       // Defer the card mark
       
   135       thread->set_deferred_card_mark(mr);
       
   136     } else {
       
   137       // Do the card mark
       
   138       invalidate(mr);
       
   139     }
       
   140   }
       
   141 #endif // COMPILER2 || JVMCI
       
   142 }
       
   143 
       
   144 void CardTableBarrierSet::initialize_deferred_card_mark_barriers() {
       
   145   // Used for ReduceInitialCardMarks (when COMPILER2 or JVMCI is used);
       
   146   // otherwise remains unused.
       
   147 #if defined(COMPILER2) || INCLUDE_JVMCI
       
   148   _defer_initial_card_mark = is_server_compilation_mode_vm() && ReduceInitialCardMarks && can_elide_tlab_store_barriers()
       
   149                              && (DeferInitialCardMark || card_mark_must_follow_store());
       
   150 #else
       
   151   assert(_defer_initial_card_mark == false, "Who would set it?");
       
   152 #endif
       
   153 }
       
   154 
       
   155 void CardTableBarrierSet::flush_deferred_card_mark_barrier(JavaThread* thread) {
       
   156 #if defined(COMPILER2) || INCLUDE_JVMCI
       
   157   MemRegion deferred = thread->deferred_card_mark();
       
   158   if (!deferred.is_empty()) {
       
   159     assert(_defer_initial_card_mark, "Otherwise should be empty");
       
   160     {
       
   161       // Verify that the storage points to a parsable object in heap
       
   162       DEBUG_ONLY(oop old_obj = oop(deferred.start());)
       
   163       assert(!_card_table->is_in_young(old_obj),
       
   164              "Else should have been filtered in on_slowpath_allocation_exit()");
       
   165       assert(oopDesc::is_oop(old_obj, true), "Not an oop");
       
   166       assert(deferred.word_size() == (size_t)(old_obj->size()),
       
   167              "Mismatch: multiple objects?");
       
   168     }
       
   169     write_region(deferred);
       
   170     // "Clear" the deferred_card_mark field
       
   171     thread->set_deferred_card_mark(MemRegion());
       
   172   }
       
   173   assert(thread->deferred_card_mark().is_empty(), "invariant");
       
   174 #else
       
   175   assert(!_defer_initial_card_mark, "Should be false");
       
   176   assert(thread->deferred_card_mark().is_empty(), "Should be empty");
       
   177 #endif
       
   178 }
       
   179 
       
   180 void CardTableBarrierSet::on_thread_detach(JavaThread* thread) {
       
   181   // The deferred store barriers must all have been flushed to the
       
   182   // card-table (or other remembered set structure) before GC starts
       
   183   // processing the card-table (or other remembered set).
       
   184   flush_deferred_card_mark_barrier(thread);
       
   185 }
       
   186 
       
   187 bool CardTableBarrierSet::card_mark_must_follow_store() const {
       
   188  return _card_table->scanned_concurrently();
       
   189 }