src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp

Tue, 08 Oct 2013 17:35:51 +0200

author
mgerdin
date
Tue, 08 Oct 2013 17:35:51 +0200
changeset 5860
69944b868a32
parent 5811
d55c004e1d4d
child 6198
55fb97c4c58d
permissions
-rw-r--r--

8014555: G1: Memory ordering problem with Conc refinement and card marking
Summary: Add a StoreLoad barrier in the G1 post-barrier to fix a race with concurrent refinement. Also-reviewed-by: martin.doerr@sap.com
Reviewed-by: iveresov, tschatzl, brutisso, roland, kvn

     1 /*
     2  * Copyright (c) 2001, 2012, 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  */
    25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP
    28 #include "gc_implementation/g1/concurrentMark.hpp"
    29 #include "gc_implementation/g1/g1CollectedHeap.hpp"
    30 #include "gc_implementation/g1/g1AllocRegion.inline.hpp"
    31 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
    32 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
    33 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
    34 #include "utilities/taskqueue.hpp"
    36 // Inline functions for G1CollectedHeap
    38 template <class T>
    39 inline HeapRegion*
    40 G1CollectedHeap::heap_region_containing(const T addr) const {
    41   HeapRegion* hr = _hrs.addr_to_region((HeapWord*) addr);
    42   // hr can be null if addr in perm_gen
    43   if (hr != NULL && hr->continuesHumongous()) {
    44     hr = hr->humongous_start_region();
    45   }
    46   return hr;
    47 }
    49 template <class T>
    50 inline HeapRegion*
    51 G1CollectedHeap::heap_region_containing_raw(const T addr) const {
    52   assert(_g1_reserved.contains((const void*) addr), "invariant");
    53   HeapRegion* res = _hrs.addr_to_region_unsafe((HeapWord*) addr);
    54   return res;
    55 }
    57 inline bool G1CollectedHeap::obj_in_cs(oop obj) {
    58   HeapRegion* r = _hrs.addr_to_region((HeapWord*) obj);
    59   return r != NULL && r->in_collection_set();
    60 }
    62 inline HeapWord*
    63 G1CollectedHeap::attempt_allocation(size_t word_size,
    64                                     unsigned int* gc_count_before_ret,
    65                                     int* gclocker_retry_count_ret) {
    66   assert_heap_not_locked_and_not_at_safepoint();
    67   assert(!isHumongous(word_size), "attempt_allocation() should not "
    68          "be called for humongous allocation requests");
    70   HeapWord* result = _mutator_alloc_region.attempt_allocation(word_size,
    71                                                       false /* bot_updates */);
    72   if (result == NULL) {
    73     result = attempt_allocation_slow(word_size,
    74                                      gc_count_before_ret,
    75                                      gclocker_retry_count_ret);
    76   }
    77   assert_heap_not_locked();
    78   if (result != NULL) {
    79     dirty_young_block(result, word_size);
    80   }
    81   return result;
    82 }
    84 inline HeapWord* G1CollectedHeap::survivor_attempt_allocation(size_t
    85                                                               word_size) {
    86   assert(!isHumongous(word_size),
    87          "we should not be seeing humongous-size allocations in this path");
    89   HeapWord* result = _survivor_gc_alloc_region.attempt_allocation(word_size,
    90                                                       false /* bot_updates */);
    91   if (result == NULL) {
    92     MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
    93     result = _survivor_gc_alloc_region.attempt_allocation_locked(word_size,
    94                                                       false /* bot_updates */);
    95   }
    96   if (result != NULL) {
    97     dirty_young_block(result, word_size);
    98   }
    99   return result;
   100 }
   102 inline HeapWord* G1CollectedHeap::old_attempt_allocation(size_t word_size) {
   103   assert(!isHumongous(word_size),
   104          "we should not be seeing humongous-size allocations in this path");
   106   HeapWord* result = _old_gc_alloc_region.attempt_allocation(word_size,
   107                                                        true /* bot_updates */);
   108   if (result == NULL) {
   109     MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
   110     result = _old_gc_alloc_region.attempt_allocation_locked(word_size,
   111                                                        true /* bot_updates */);
   112   }
   113   return result;
   114 }
   116 // It dirties the cards that cover the block so that so that the post
   117 // write barrier never queues anything when updating objects on this
   118 // block. It is assumed (and in fact we assert) that the block
   119 // belongs to a young region.
   120 inline void
   121 G1CollectedHeap::dirty_young_block(HeapWord* start, size_t word_size) {
   122   assert_heap_not_locked();
   124   // Assign the containing region to containing_hr so that we don't
   125   // have to keep calling heap_region_containing_raw() in the
   126   // asserts below.
   127   DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing_raw(start);)
   128   assert(containing_hr != NULL && start != NULL && word_size > 0,
   129          "pre-condition");
   130   assert(containing_hr->is_in(start), "it should contain start");
   131   assert(containing_hr->is_young(), "it should be young");
   132   assert(!containing_hr->isHumongous(), "it should not be humongous");
   134   HeapWord* end = start + word_size;
   135   assert(containing_hr->is_in(end - 1), "it should also contain end - 1");
   137   MemRegion mr(start, end);
   138   g1_barrier_set()->g1_mark_as_young(mr);
   139 }
   141 inline RefToScanQueue* G1CollectedHeap::task_queue(int i) const {
   142   return _task_queues->queue(i);
   143 }
   145 inline bool G1CollectedHeap::isMarkedPrev(oop obj) const {
   146   return _cm->prevMarkBitMap()->isMarked((HeapWord *)obj);
   147 }
   149 inline bool G1CollectedHeap::isMarkedNext(oop obj) const {
   150   return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj);
   151 }
   153 #ifndef PRODUCT
   154 // Support for G1EvacuationFailureALot
   156 inline bool
   157 G1CollectedHeap::evacuation_failure_alot_for_gc_type(bool gcs_are_young,
   158                                                      bool during_initial_mark,
   159                                                      bool during_marking) {
   160   bool res = false;
   161   if (during_marking) {
   162     res |= G1EvacuationFailureALotDuringConcMark;
   163   }
   164   if (during_initial_mark) {
   165     res |= G1EvacuationFailureALotDuringInitialMark;
   166   }
   167   if (gcs_are_young) {
   168     res |= G1EvacuationFailureALotDuringYoungGC;
   169   } else {
   170     // GCs are mixed
   171     res |= G1EvacuationFailureALotDuringMixedGC;
   172   }
   173   return res;
   174 }
   176 inline void
   177 G1CollectedHeap::set_evacuation_failure_alot_for_current_gc() {
   178   if (G1EvacuationFailureALot) {
   179     // Note we can't assert that _evacuation_failure_alot_for_current_gc
   180     // is clear here. It may have been set during a previous GC but that GC
   181     // did not copy enough objects (i.e. G1EvacuationFailureALotCount) to
   182     // trigger an evacuation failure and clear the flags and and counts.
   184     // Check if we have gone over the interval.
   185     const size_t gc_num = total_collections();
   186     const size_t elapsed_gcs = gc_num - _evacuation_failure_alot_gc_number;
   188     _evacuation_failure_alot_for_current_gc = (elapsed_gcs >= G1EvacuationFailureALotInterval);
   190     // Now check if G1EvacuationFailureALot is enabled for the current GC type.
   191     const bool gcs_are_young = g1_policy()->gcs_are_young();
   192     const bool during_im = g1_policy()->during_initial_mark_pause();
   193     const bool during_marking = mark_in_progress();
   195     _evacuation_failure_alot_for_current_gc &=
   196       evacuation_failure_alot_for_gc_type(gcs_are_young,
   197                                           during_im,
   198                                           during_marking);
   199   }
   200 }
   202 inline bool
   203 G1CollectedHeap::evacuation_should_fail() {
   204   if (!G1EvacuationFailureALot || !_evacuation_failure_alot_for_current_gc) {
   205     return false;
   206   }
   207   // G1EvacuationFailureALot is in effect for current GC
   208   // Access to _evacuation_failure_alot_count is not atomic;
   209   // the value does not have to be exact.
   210   if (++_evacuation_failure_alot_count < G1EvacuationFailureALotCount) {
   211     return false;
   212   }
   213   _evacuation_failure_alot_count = 0;
   214   return true;
   215 }
   217 inline void G1CollectedHeap::reset_evacuation_should_fail() {
   218   if (G1EvacuationFailureALot) {
   219     _evacuation_failure_alot_gc_number = total_collections();
   220     _evacuation_failure_alot_count = 0;
   221     _evacuation_failure_alot_for_current_gc = false;
   222   }
   223 }
   224 #endif  // #ifndef PRODUCT
   226 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_INLINE_HPP

mercurial