src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp

Tue, 30 Sep 2014 09:44:36 +0200

author
tschatzl
date
Tue, 30 Sep 2014 09:44:36 +0200
changeset 7218
6948da6d7c13
parent 7118
227a9e5e4b4a
child 7645
f2e3f0e1f97d
permissions
-rw-r--r--

8052172: Evacuation failure handling in G1 does not evacuate all objects if -XX:-G1DeferredRSUpdate is set
Summary: Remove -XX:-G1DeferredRSUpdate functionality as it is racy. During evacuation failure handling, threads where evacuation failure handling occurred may try to add remembered sets to regions which remembered sets are currently being scanned. The iterator to handle the remembered set scan does not support addition of entries during scan and so may skip valid references.
Reviewed-by: iveresov, brutisso, mgerdin

tschatzl@6937 1 /*
tschatzl@6937 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
tschatzl@6937 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
tschatzl@6937 4 *
tschatzl@6937 5 * This code is free software; you can redistribute it and/or modify it
tschatzl@6937 6 * under the terms of the GNU General Public License version 2 only, as
tschatzl@6937 7 * published by the Free Software Foundation.
tschatzl@6937 8 *
tschatzl@6937 9 * This code is distributed in the hope that it will be useful, but WITHOUT
tschatzl@6937 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
tschatzl@6937 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
tschatzl@6937 12 * version 2 for more details (a copy is included in the LICENSE file that
tschatzl@6937 13 * accompanied this code).
tschatzl@6937 14 *
tschatzl@6937 15 * You should have received a copy of the GNU General Public License version
tschatzl@6937 16 * 2 along with this work; if not, write to the Free Software Foundation,
tschatzl@6937 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
tschatzl@6937 18 *
tschatzl@6937 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
tschatzl@6937 20 * or visit www.oracle.com if you need additional information or have any
tschatzl@6937 21 * questions.
tschatzl@6937 22 *
tschatzl@6937 23 */
tschatzl@6937 24
tschatzl@6937 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP
tschatzl@6937 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP
tschatzl@6937 27
tschatzl@6937 28 #include "gc_implementation/g1/dirtyCardQueue.hpp"
tschatzl@6937 29 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
tschatzl@6937 30 #include "gc_implementation/g1/g1CollectedHeap.hpp"
tschatzl@6937 31 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
tschatzl@6937 32 #include "gc_implementation/g1/g1OopClosures.hpp"
tschatzl@6937 33 #include "gc_implementation/g1/g1RemSet.hpp"
tschatzl@6937 34 #include "gc_implementation/shared/ageTable.hpp"
tschatzl@6937 35 #include "memory/allocation.hpp"
tschatzl@6937 36 #include "oops/oop.hpp"
tschatzl@6937 37
tschatzl@6937 38 class HeapRegion;
tschatzl@6937 39 class outputStream;
tschatzl@6937 40
tschatzl@6937 41 class G1ParScanThreadState : public StackObj {
tschatzl@6938 42 private:
tschatzl@6937 43 G1CollectedHeap* _g1h;
tschatzl@6937 44 RefToScanQueue* _refs;
tschatzl@6937 45 DirtyCardQueue _dcq;
tschatzl@6937 46 G1SATBCardTableModRefBS* _ct_bs;
tschatzl@6937 47 G1RemSet* _g1_rem;
tschatzl@6937 48
sjohanss@7118 49 G1ParGCAllocator* _g1_par_allocator;
sjohanss@7118 50
tschatzl@6937 51 ageTable _age_table;
tschatzl@6937 52
tschatzl@6937 53 G1ParScanClosure _scanner;
tschatzl@6937 54
tschatzl@6937 55 size_t _alloc_buffer_waste;
tschatzl@6937 56 size_t _undo_waste;
tschatzl@6937 57
tschatzl@6937 58 OopsInHeapRegionClosure* _evac_failure_cl;
tschatzl@6937 59
tschatzl@6937 60 int _hash_seed;
tschatzl@6937 61 uint _queue_num;
tschatzl@6937 62
tschatzl@6937 63 size_t _term_attempts;
tschatzl@6937 64
tschatzl@6937 65 double _start;
tschatzl@6937 66 double _start_strong_roots;
tschatzl@6937 67 double _strong_roots_time;
tschatzl@6937 68 double _start_term;
tschatzl@6937 69 double _term_time;
tschatzl@6937 70
tschatzl@6937 71 // Map from young-age-index (0 == not young, 1 is youngest) to
tschatzl@6937 72 // surviving words. base is what we get back from the malloc call
tschatzl@6937 73 size_t* _surviving_young_words_base;
tschatzl@6937 74 // this points into the array, as we use the first few entries for padding
tschatzl@6937 75 size_t* _surviving_young_words;
tschatzl@6937 76
tschatzl@6937 77 #define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
tschatzl@6937 78
tschatzl@6937 79 void add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
tschatzl@6937 80 void add_to_undo_waste(size_t waste) { _undo_waste += waste; }
tschatzl@6937 81
tschatzl@6937 82 DirtyCardQueue& dirty_card_queue() { return _dcq; }
tschatzl@6937 83 G1SATBCardTableModRefBS* ctbs() { return _ct_bs; }
tschatzl@6937 84
tschatzl@6938 85 public:
tschatzl@6937 86 G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
tschatzl@6938 87 ~G1ParScanThreadState();
tschatzl@6937 88
tschatzl@6937 89 ageTable* age_table() { return &_age_table; }
tschatzl@6937 90
tschatzl@6937 91 #ifdef ASSERT
tschatzl@6938 92 bool queue_is_empty() const { return _refs->is_empty(); }
tschatzl@6938 93
tschatzl@6937 94 bool verify_ref(narrowOop* ref) const;
tschatzl@6937 95 bool verify_ref(oop* ref) const;
tschatzl@6937 96 bool verify_task(StarTask ref) const;
tschatzl@6937 97 #endif // ASSERT
tschatzl@6937 98
tschatzl@6937 99 template <class T> void push_on_queue(T* ref) {
tschatzl@6937 100 assert(verify_ref(ref), "sanity");
tschatzl@6938 101 _refs->push(ref);
tschatzl@6937 102 }
tschatzl@6937 103
tschatzl@7218 104 template <class T> void update_rs(HeapRegion* from, T* p, int tid) {
tschatzl@7218 105 // If the new value of the field points to the same region or
tschatzl@7218 106 // is the to-space, we don't need to include it in the Rset updates.
tschatzl@7218 107 if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
tschatzl@7218 108 size_t card_index = ctbs()->index_for(p);
tschatzl@7218 109 // If the card hasn't been added to the buffer, do it.
tschatzl@7218 110 if (ctbs()->mark_card_deferred(card_index)) {
tschatzl@7218 111 dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
tschatzl@7218 112 }
tschatzl@7218 113 }
tschatzl@7218 114 }
tschatzl@6938 115 public:
tschatzl@6937 116
tschatzl@6937 117 void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
tschatzl@6937 118 _evac_failure_cl = evac_failure_cl;
tschatzl@6937 119 }
tschatzl@6938 120
tschatzl@6938 121 OopsInHeapRegionClosure* evac_failure_closure() { return _evac_failure_cl; }
tschatzl@6937 122
tschatzl@6937 123 int* hash_seed() { return &_hash_seed; }
tschatzl@6937 124 uint queue_num() { return _queue_num; }
tschatzl@6937 125
tschatzl@6937 126 size_t term_attempts() const { return _term_attempts; }
tschatzl@6937 127 void note_term_attempt() { _term_attempts++; }
tschatzl@6937 128
tschatzl@6937 129 void start_strong_roots() {
tschatzl@6937 130 _start_strong_roots = os::elapsedTime();
tschatzl@6937 131 }
tschatzl@6937 132 void end_strong_roots() {
tschatzl@6937 133 _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
tschatzl@6937 134 }
tschatzl@6937 135 double strong_roots_time() const { return _strong_roots_time; }
tschatzl@6937 136
tschatzl@6937 137 void start_term_time() {
tschatzl@6937 138 note_term_attempt();
tschatzl@6937 139 _start_term = os::elapsedTime();
tschatzl@6937 140 }
tschatzl@6937 141 void end_term_time() {
tschatzl@6937 142 _term_time += (os::elapsedTime() - _start_term);
tschatzl@6937 143 }
tschatzl@6937 144 double term_time() const { return _term_time; }
tschatzl@6937 145
tschatzl@6937 146 double elapsed_time() const {
tschatzl@6937 147 return os::elapsedTime() - _start;
tschatzl@6937 148 }
tschatzl@6937 149
tschatzl@6938 150 static void print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
tschatzl@6938 151 void print_termination_stats(int i, outputStream* const st = gclog_or_tty) const;
tschatzl@6937 152
tschatzl@6937 153 size_t* surviving_young_words() {
tschatzl@6937 154 // We add on to hide entry 0 which accumulates surviving words for
tschatzl@6937 155 // age -1 regions (i.e. non-young ones)
tschatzl@6937 156 return _surviving_young_words;
tschatzl@6937 157 }
tschatzl@6937 158
tschatzl@6937 159 private:
tschatzl@6937 160 #define G1_PARTIAL_ARRAY_MASK 0x2
tschatzl@6937 161
tschatzl@6937 162 inline bool has_partial_array_mask(oop* ref) const {
tschatzl@6937 163 return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
tschatzl@6937 164 }
tschatzl@6937 165
tschatzl@6937 166 // We never encode partial array oops as narrowOop*, so return false immediately.
tschatzl@6937 167 // This allows the compiler to create optimized code when popping references from
tschatzl@6937 168 // the work queue.
tschatzl@6937 169 inline bool has_partial_array_mask(narrowOop* ref) const {
tschatzl@6937 170 assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*");
tschatzl@6937 171 return false;
tschatzl@6937 172 }
tschatzl@6937 173
tschatzl@6937 174 // Only implement set_partial_array_mask() for regular oops, not for narrowOops.
tschatzl@6937 175 // We always encode partial arrays as regular oop, to allow the
tschatzl@6937 176 // specialization for has_partial_array_mask() for narrowOops above.
tschatzl@6937 177 // This means that unintentional use of this method with narrowOops are caught
tschatzl@6937 178 // by the compiler.
tschatzl@6937 179 inline oop* set_partial_array_mask(oop obj) const {
tschatzl@6937 180 assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!");
tschatzl@6937 181 return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK);
tschatzl@6937 182 }
tschatzl@6937 183
tschatzl@6937 184 inline oop clear_partial_array_mask(oop* ref) const {
tschatzl@6937 185 return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
tschatzl@6937 186 }
tschatzl@6937 187
tschatzl@6937 188 inline void do_oop_partial_array(oop* p);
tschatzl@6937 189
tschatzl@6937 190 // This method is applied to the fields of the objects that have just been copied.
tschatzl@6938 191 template <class T> inline void do_oop_evac(T* p, HeapRegion* from);
tschatzl@6937 192
tschatzl@6938 193 template <class T> inline void deal_with_reference(T* ref_to_scan);
tschatzl@6937 194
tschatzl@6938 195 inline void dispatch_reference(StarTask ref);
tschatzl@6938 196 public:
tschatzl@6937 197
tschatzl@6937 198 oop copy_to_survivor_space(oop const obj);
tschatzl@6937 199
tschatzl@6938 200 void trim_queue();
tschatzl@6937 201
tschatzl@6938 202 inline void steal_and_trim_queue(RefToScanQueueSet *task_queues);
tschatzl@6937 203 };
tschatzl@6937 204
tschatzl@6937 205 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP

mercurial