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

Thu, 07 Apr 2011 09:53:20 -0700

author
johnc
date
Thu, 07 Apr 2011 09:53:20 -0700
changeset 2781
e1162778c1c8
parent 2314
f95d63e2154a
child 2974
e8b0b0392037
permissions
-rw-r--r--

7009266: G1: assert(obj->is_oop_or_null(true )) failed: Error
Summary: A referent object that is only weakly reachable at the start of concurrent marking but is re-attached to the strongly reachable object graph during marking may not be marked as live. This can cause the reference object to be processed prematurely and leave dangling pointers to the referent object. Implement a read barrier for the java.lang.ref.Reference::referent field by intrinsifying the Reference.get() method, and intercepting accesses though JNI, reflection, and Unsafe, so that when a non-null referent object is read it is also logged in an SATB buffer.
Reviewed-by: kvn, iveresov, never, tonyp, dholmes

ysr@777 1 /*
johnc@2060 2 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
ysr@777 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ysr@777 4 *
ysr@777 5 * This code is free software; you can redistribute it and/or modify it
ysr@777 6 * under the terms of the GNU General Public License version 2 only, as
ysr@777 7 * published by the Free Software Foundation.
ysr@777 8 *
ysr@777 9 * This code is distributed in the hope that it will be useful, but WITHOUT
ysr@777 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ysr@777 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ysr@777 12 * version 2 for more details (a copy is included in the LICENSE file that
ysr@777 13 * accompanied this code).
ysr@777 14 *
ysr@777 15 * You should have received a copy of the GNU General Public License version
ysr@777 16 * 2 along with this work; if not, write to the Free Software Foundation,
ysr@777 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ysr@777 18 *
trims@1907 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907 20 * or visit www.oracle.com if you need additional information or have any
trims@1907 21 * questions.
ysr@777 22 *
ysr@777 23 */
ysr@777 24
stefank@2314 25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP
stefank@2314 27
ysr@777 28 // A G1RemSet provides ways of iterating over pointers into a selected
ysr@777 29 // collection set.
ysr@777 30
ysr@777 31 class G1CollectedHeap;
ysr@777 32 class CardTableModRefBarrierSet;
ysr@777 33 class ConcurrentG1Refine;
ysr@777 34
johnc@2216 35 // A G1RemSet in which each heap region has a rem set that records the
johnc@2216 36 // external heap references into it. Uses a mod ref bs to track updates,
johnc@2216 37 // so that they can be used to update the individual region remsets.
johnc@2216 38
apetrusenko@984 39 class G1RemSet: public CHeapObj {
ysr@777 40 protected:
ysr@777 41 G1CollectedHeap* _g1;
ysr@777 42 unsigned _conc_refine_cards;
ysr@777 43 size_t n_workers();
ysr@777 44
ysr@777 45 protected:
ysr@777 46 enum SomePrivateConstants {
ysr@777 47 UpdateRStoMergeSync = 0,
ysr@777 48 MergeRStoDoDirtySync = 1,
ysr@777 49 DoDirtySync = 2,
ysr@777 50 LastSync = 3,
ysr@777 51
ysr@777 52 SeqTask = 0,
ysr@777 53 NumSeqTasks = 1
ysr@777 54 };
ysr@777 55
ysr@777 56 CardTableModRefBS* _ct_bs;
ysr@777 57 SubTasksDone* _seq_task;
ysr@777 58 G1CollectorPolicy* _g1p;
ysr@777 59
ysr@777 60 ConcurrentG1Refine* _cg1r;
ysr@777 61
ysr@777 62 size_t* _cards_scanned;
ysr@777 63 size_t _total_cards_scanned;
ysr@777 64
johnc@2060 65 // Used for caching the closure that is responsible for scanning
johnc@2060 66 // references into the collection set.
johnc@2060 67 OopsInHeapRegionClosure** _cset_rs_update_cl;
ysr@1280 68
johnc@1325 69 // The routine that performs the actual work of refining a dirty
johnc@1325 70 // card.
johnc@2060 71 // If check_for_refs_into_refs is true then a true result is returned
johnc@2060 72 // if the card contains oops that have references into the current
johnc@2060 73 // collection set.
johnc@2060 74 bool concurrentRefineOneCard_impl(jbyte* card_ptr, int worker_i,
johnc@2060 75 bool check_for_refs_into_cset);
johnc@1325 76
ysr@777 77 public:
ysr@777 78 // This is called to reset dual hash tables after the gc pause
ysr@777 79 // is finished and the initial hash table is no longer being
ysr@777 80 // scanned.
ysr@777 81 void cleanupHRRS();
ysr@777 82
johnc@2216 83 G1RemSet(G1CollectedHeap* g1, CardTableModRefBS* ct_bs);
johnc@2216 84 ~G1RemSet();
ysr@777 85
johnc@2216 86 // Invoke "blk->do_oop" on all pointers into the CS in objects in regions
johnc@2216 87 // outside the CS (having invoked "blk->set_region" to set the "from"
johnc@2216 88 // region correctly beforehand.) The "worker_i" param is for the
johnc@2216 89 // parallel case where the number of the worker thread calling this
johnc@2216 90 // function can be helpful in partitioning the work to be done. It
johnc@2216 91 // should be the same as the "i" passed to the calling thread's
johnc@2216 92 // work(i) function. In the sequential case this param will be ingored.
ysr@777 93 void oops_into_collection_set_do(OopsInHeapRegionClosure* blk,
ysr@777 94 int worker_i);
ysr@777 95
johnc@2216 96 // Prepare for and cleanup after an oops_into_collection_set_do
johnc@2216 97 // call. Must call each of these once before and after (in sequential
johnc@2216 98 // code) any threads call oops_into_collection_set_do. (This offers an
johnc@2216 99 // opportunity to sequential setup and teardown of structures needed by a
johnc@2216 100 // parallel iteration over the CS's RS.)
ysr@777 101 void prepare_for_oops_into_collection_set_do();
ysr@777 102 void cleanup_after_oops_into_collection_set_do();
johnc@2216 103
ysr@777 104 void scanRS(OopsInHeapRegionClosure* oc, int worker_i);
johnc@2060 105 void updateRS(DirtyCardQueue* into_cset_dcq, int worker_i);
johnc@2216 106
ysr@777 107 HeapRegion* calculateStartRegion(int i);
ysr@777 108
ysr@777 109 CardTableModRefBS* ct_bs() { return _ct_bs; }
ysr@777 110 size_t cardsScanned() { return _total_cards_scanned; }
ysr@777 111
ysr@777 112 // Record, if necessary, the fact that *p (where "p" is in region "from",
ysr@777 113 // which is required to be non-NULL) has changed to a new non-NULL value.
johnc@2302 114 template <class T> void write_ref(HeapRegion* from, T* p);
johnc@2302 115 template <class T> void par_write_ref(HeapRegion* from, T* p, int tid);
ysr@777 116
johnc@2216 117 // Requires "region_bm" and "card_bm" to be bitmaps with 1 bit per region
johnc@2216 118 // or card, respectively, such that a region or card with a corresponding
johnc@2216 119 // 0 bit contains no part of any live object. Eliminates any remembered
johnc@2216 120 // set entries that correspond to dead heap ranges.
ysr@777 121 void scrub(BitMap* region_bm, BitMap* card_bm);
johnc@2216 122
johnc@2216 123 // Like the above, but assumes is called in parallel: "worker_num" is the
johnc@2216 124 // parallel thread id of the current thread, and "claim_val" is the
johnc@2216 125 // value that should be used to claim heap regions.
ysr@777 126 void scrub_par(BitMap* region_bm, BitMap* card_bm,
ysr@777 127 int worker_num, int claim_val);
ysr@777 128
johnc@2216 129 // Refine the card corresponding to "card_ptr". If "sts" is non-NULL,
johnc@2216 130 // join and leave around parts that must be atomic wrt GC. (NULL means
johnc@2216 131 // being done at a safepoint.)
johnc@2216 132 // If check_for_refs_into_cset is true, a true result is returned
johnc@2216 133 // if the given card contains oops that have references into the
johnc@2216 134 // current collection set.
johnc@2060 135 virtual bool concurrentRefineOneCard(jbyte* card_ptr, int worker_i,
johnc@2060 136 bool check_for_refs_into_cset);
ysr@777 137
johnc@2216 138 // Print any relevant summary info.
ysr@777 139 virtual void print_summary_info();
johnc@2216 140
johnc@2216 141 // Prepare remembered set for verification.
ysr@777 142 virtual void prepare_for_verify();
ysr@777 143 };
ysr@777 144
ysr@777 145 #define G1_REM_SET_LOGGING 0
ysr@777 146
ysr@777 147 class CountNonCleanMemRegionClosure: public MemRegionClosure {
ysr@777 148 G1CollectedHeap* _g1;
ysr@777 149 int _n;
ysr@777 150 HeapWord* _start_first;
ysr@777 151 public:
ysr@777 152 CountNonCleanMemRegionClosure(G1CollectedHeap* g1) :
ysr@777 153 _g1(g1), _n(0), _start_first(NULL)
ysr@777 154 {}
ysr@777 155 void do_MemRegion(MemRegion mr);
ysr@777 156 int n() { return _n; };
ysr@777 157 HeapWord* start_first() { return _start_first; }
ysr@777 158 };
apetrusenko@1061 159
apetrusenko@1061 160 class UpdateRSOopClosure: public OopClosure {
apetrusenko@1061 161 HeapRegion* _from;
johnc@2216 162 G1RemSet* _rs;
apetrusenko@1061 163 int _worker_i;
ysr@1280 164
ysr@1280 165 template <class T> void do_oop_work(T* p);
ysr@1280 166
apetrusenko@1061 167 public:
johnc@2216 168 UpdateRSOopClosure(G1RemSet* rs, int worker_i = 0) :
johnc@2302 169 _from(NULL), _rs(rs), _worker_i(worker_i)
johnc@2302 170 {}
apetrusenko@1061 171
apetrusenko@1061 172 void set_from(HeapRegion* from) {
apetrusenko@1061 173 assert(from != NULL, "from region must be non-NULL");
apetrusenko@1061 174 _from = from;
apetrusenko@1061 175 }
apetrusenko@1061 176
ysr@1280 177 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
ysr@1280 178 virtual void do_oop(oop* p) { do_oop_work(p); }
apetrusenko@1061 179
apetrusenko@1061 180 // Override: this closure is idempotent.
apetrusenko@1061 181 // bool idempotent() { return true; }
apetrusenko@1061 182 bool apply_to_weak_ref_discovered_field() { return true; }
apetrusenko@1061 183 };
johnc@2060 184
johnc@2060 185 class UpdateRSetImmediate: public OopsInHeapRegionClosure {
johnc@2060 186 private:
johnc@2060 187 G1RemSet* _g1_rem_set;
johnc@2060 188
johnc@2060 189 template <class T> void do_oop_work(T* p);
johnc@2060 190 public:
johnc@2060 191 UpdateRSetImmediate(G1RemSet* rs) :
johnc@2060 192 _g1_rem_set(rs) {}
johnc@2060 193
johnc@2060 194 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
johnc@2060 195 virtual void do_oop( oop* p) { do_oop_work(p); }
johnc@2060 196 };
johnc@2302 197
johnc@2302 198 class UpdateRSOrPushRefOopClosure: public OopClosure {
johnc@2302 199 G1CollectedHeap* _g1;
johnc@2302 200 G1RemSet* _g1_rem_set;
johnc@2302 201 HeapRegion* _from;
johnc@2302 202 OopsInHeapRegionClosure* _push_ref_cl;
johnc@2302 203 bool _record_refs_into_cset;
johnc@2302 204 int _worker_i;
johnc@2302 205
johnc@2302 206 template <class T> void do_oop_work(T* p);
johnc@2302 207
johnc@2302 208 public:
johnc@2302 209 UpdateRSOrPushRefOopClosure(G1CollectedHeap* g1h,
johnc@2302 210 G1RemSet* rs,
johnc@2302 211 OopsInHeapRegionClosure* push_ref_cl,
johnc@2302 212 bool record_refs_into_cset,
johnc@2302 213 int worker_i = 0) :
johnc@2302 214 _g1(g1h),
johnc@2302 215 _g1_rem_set(rs),
johnc@2302 216 _from(NULL),
johnc@2302 217 _record_refs_into_cset(record_refs_into_cset),
johnc@2302 218 _push_ref_cl(push_ref_cl),
johnc@2302 219 _worker_i(worker_i) { }
johnc@2302 220
johnc@2302 221 void set_from(HeapRegion* from) {
johnc@2302 222 assert(from != NULL, "from region must be non-NULL");
johnc@2302 223 _from = from;
johnc@2302 224 }
johnc@2302 225
johnc@2302 226 bool self_forwarded(oop obj) {
johnc@2302 227 bool result = (obj->is_forwarded() && (obj->forwardee()== obj));
johnc@2302 228 return result;
johnc@2302 229 }
johnc@2302 230
johnc@2302 231 virtual void do_oop(narrowOop* p) { do_oop_work(p); }
johnc@2302 232 virtual void do_oop(oop* p) { do_oop_work(p); }
johnc@2302 233
johnc@2302 234 bool apply_to_weak_ref_discovered_field() { return true; }
johnc@2302 235 };
johnc@2302 236
stefank@2314 237
stefank@2314 238 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_HPP

mercurial