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

Thu, 22 Sep 2011 10:57:37 -0700

author
johnc
date
Thu, 22 Sep 2011 10:57:37 -0700
changeset 3175
4dfb2df418f2
parent 2974
e8b0b0392037
child 3357
441e946dc1af
permissions
-rw-r--r--

6484982: G1: process references during evacuation pauses
Summary: G1 now uses two reference processors - one is used by concurrent marking and the other is used by STW GCs (both full and incremental evacuation pauses). In an evacuation pause, the reference processor is embedded into the closures used to scan objects. Doing so causes causes reference objects to be 'discovered' by the reference processor. At the end of the evacuation pause, these discovered reference objects are processed - preserving (and copying) referent objects (and their reachable graphs) as appropriate.
Reviewed-by: ysr, jwilhelm, brutisso, stefank, tonyp

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_INLINE_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_INLINE_HPP
stefank@2314 27
stefank@2314 28 #include "gc_implementation/g1/g1RemSet.hpp"
stefank@2314 29 #include "gc_implementation/g1/heapRegionRemSet.hpp"
stefank@2314 30 #include "oops/oop.inline.hpp"
stefank@2314 31
ysr@777 32 inline size_t G1RemSet::n_workers() {
ysr@777 33 if (_g1->workers() != NULL) {
ysr@777 34 return _g1->workers()->total_workers();
ysr@777 35 } else {
ysr@777 36 return 1;
ysr@777 37 }
ysr@777 38 }
ysr@777 39
johnc@2216 40 template <class T>
johnc@2302 41 inline void G1RemSet::write_ref(HeapRegion* from, T* p) {
johnc@2302 42 par_write_ref(from, p, 0);
ysr@777 43 }
ysr@777 44
johnc@2216 45 template <class T>
johnc@2302 46 inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) {
ysr@1280 47 oop obj = oopDesc::load_decode_heap_oop(p);
ysr@777 48 #ifdef ASSERT
ysr@777 49 // can't do because of races
ysr@777 50 // assert(obj == NULL || obj->is_oop(), "expected an oop");
ysr@777 51
ysr@777 52 // Do the safe subset of is_oop
ysr@777 53 if (obj != NULL) {
ysr@777 54 #ifdef CHECK_UNHANDLED_OOPS
ysr@777 55 oopDesc* o = obj.obj();
ysr@777 56 #else
ysr@777 57 oopDesc* o = obj;
ysr@777 58 #endif // CHECK_UNHANDLED_OOPS
ysr@777 59 assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
ysr@777 60 assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
ysr@777 61 }
ysr@777 62 #endif // ASSERT
johnc@2060 63
johnc@2060 64 assert(from == NULL || from->is_in_reserved(p), "p is not in from");
johnc@2060 65
ysr@777 66 HeapRegion* to = _g1->heap_region_containing(obj);
johnc@2302 67 if (to != NULL && from != to) {
johnc@2302 68 assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
johnc@2302 69 to->rem_set()->add_reference(p, tid);
ysr@777 70 }
ysr@777 71 }
apetrusenko@1061 72
johnc@2216 73 template <class T>
johnc@2216 74 inline void UpdateRSOopClosure::do_oop_work(T* p) {
apetrusenko@1061 75 assert(_from != NULL, "from region must be non-NULL");
apetrusenko@1061 76 _rs->par_write_ref(_from, p, _worker_i);
apetrusenko@1061 77 }
johnc@2060 78
johnc@2216 79 template <class T>
johnc@2216 80 inline void UpdateRSetImmediate::do_oop_work(T* p) {
johnc@2060 81 assert(_from->is_in_reserved(p), "paranoia");
johnc@2060 82 T heap_oop = oopDesc::load_heap_oop(p);
johnc@2060 83 if (!oopDesc::is_null(heap_oop) && !_from->is_survivor()) {
johnc@2060 84 _g1_rem_set->par_write_ref(_from, p, 0);
johnc@2060 85 }
johnc@2060 86 }
johnc@2060 87
johnc@2302 88 template <class T>
johnc@2302 89 inline void UpdateRSOrPushRefOopClosure::do_oop_work(T* p) {
johnc@2302 90 oop obj = oopDesc::load_decode_heap_oop(p);
johnc@2302 91 #ifdef ASSERT
johnc@2302 92 // can't do because of races
johnc@2302 93 // assert(obj == NULL || obj->is_oop(), "expected an oop");
johnc@2302 94
johnc@2302 95 // Do the safe subset of is_oop
johnc@2302 96 if (obj != NULL) {
johnc@2302 97 #ifdef CHECK_UNHANDLED_OOPS
johnc@2302 98 oopDesc* o = obj.obj();
johnc@2302 99 #else
johnc@2302 100 oopDesc* o = obj;
johnc@2302 101 #endif // CHECK_UNHANDLED_OOPS
johnc@2302 102 assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
johnc@2302 103 assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
johnc@2302 104 }
johnc@2302 105 #endif // ASSERT
johnc@2302 106
johnc@2302 107 assert(_from != NULL, "from region must be non-NULL");
johnc@2302 108
johnc@2302 109 HeapRegion* to = _g1->heap_region_containing(obj);
johnc@2302 110 if (to != NULL && _from != to) {
johnc@2302 111 // The _record_refs_into_cset flag is true during the RSet
johnc@2302 112 // updating part of an evacuation pause. It is false at all
johnc@2302 113 // other times:
johnc@2302 114 // * rebuilding the rembered sets after a full GC
johnc@2302 115 // * during concurrent refinement.
johnc@2302 116 // * updating the remembered sets of regions in the collection
johnc@2302 117 // set in the event of an evacuation failure (when deferred
johnc@2302 118 // updates are enabled).
johnc@2302 119
johnc@2302 120 if (_record_refs_into_cset && to->in_collection_set()) {
johnc@2302 121 // We are recording references that point into the collection
johnc@2302 122 // set and this particular reference does exactly that...
johnc@2302 123 // If the referenced object has already been forwarded
johnc@2302 124 // to itself, we are handling an evacuation failure and
johnc@2302 125 // we have already visited/tried to copy this object
johnc@2302 126 // there is no need to retry.
johnc@2302 127 if (!self_forwarded(obj)) {
johnc@2302 128 assert(_push_ref_cl != NULL, "should not be null");
johnc@2302 129 // Push the reference in the refs queue of the G1ParScanThreadState
johnc@2302 130 // instance for this worker thread.
johnc@2302 131 _push_ref_cl->do_oop(p);
johnc@2302 132 }
johnc@2302 133
johnc@2302 134 // Deferred updates to the CSet are either discarded (in the normal case),
johnc@2302 135 // or processed (if an evacuation failure occurs) at the end
johnc@2302 136 // of the collection.
johnc@2302 137 // See G1RemSet::cleanup_after_oops_into_collection_set_do().
johnc@2302 138 } else {
johnc@2302 139 // We either don't care about pushing references that point into the
johnc@2302 140 // collection set (i.e. we're not during an evacuation pause) _or_
johnc@2302 141 // the reference doesn't point into the collection set. Either way
johnc@2302 142 // we add the reference directly to the RSet of the region containing
johnc@2302 143 // the referenced object.
johnc@2302 144 _g1_rem_set->par_write_ref(_from, p, _worker_i);
johnc@2302 145 }
johnc@2302 146 }
johnc@2302 147 }
johnc@2302 148
stefank@2314 149
stefank@2314 150 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_INLINE_HPP

mercurial