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

Fri, 10 Oct 2014 15:51:58 +0200

author
tschatzl
date
Fri, 10 Oct 2014 15:51:58 +0200
changeset 7257
e7d0505c8a30
parent 7049
eec72fa4b108
child 7535
7ae4e26cb1e0
child 7651
c132be0fb74d
permissions
-rw-r--r--

8059758: Footprint regressions with JDK-8038423
Summary: Changes in JDK-8038423 always initialize (zero out) virtual memory used for auxiliary data structures. This causes a footprint regression for G1 in startup benchmarks. This is because they do not touch that memory at all, so the operating system does not actually commit these pages. The fix is to, if the initialization value of the data structures matches the default value of just committed memory (=0), do not do anything.
Reviewed-by: jwilhelm, brutisso

ysr@777 1 /*
drchase@6680 2 * Copyright (c) 2001, 2014, 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_G1OOPCLOSURES_INLINE_HPP
stefank@2314 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP
stefank@2314 27
tonyp@2968 28 #include "gc_implementation/g1/concurrentMark.inline.hpp"
stefank@2314 29 #include "gc_implementation/g1/g1CollectedHeap.hpp"
stefank@2314 30 #include "gc_implementation/g1/g1OopClosures.hpp"
tschatzl@6937 31 #include "gc_implementation/g1/g1ParScanThreadState.inline.hpp"
stefank@2314 32 #include "gc_implementation/g1/g1RemSet.hpp"
goetz@6441 33 #include "gc_implementation/g1/g1RemSet.inline.hpp"
johnc@3954 34 #include "gc_implementation/g1/heapRegionRemSet.hpp"
stefank@6992 35 #include "memory/iterator.inline.hpp"
goetz@6912 36 #include "runtime/prefetch.inline.hpp"
stefank@2314 37
ysr@777 38 /*
ysr@777 39 * This really ought to be an inline function, but apparently the C++
ysr@777 40 * compiler sometimes sees fit to ignore inline declarations. Sigh.
ysr@777 41 */
ysr@777 42
tonyp@3464 43 template <class T>
tonyp@3464 44 inline void FilterIntoCSClosure::do_oop_nv(T* p) {
ysr@1280 45 T heap_oop = oopDesc::load_heap_oop(p);
ysr@1280 46 if (!oopDesc::is_null(heap_oop) &&
tschatzl@7010 47 _g1->is_in_cset_or_humongous(oopDesc::decode_heap_oop_not_null(heap_oop))) {
ysr@777 48 _oc->do_oop(p);
ysr@777 49 }
ysr@777 50 }
ysr@777 51
tonyp@3464 52 template <class T>
tonyp@3464 53 inline void FilterOutOfRegionClosure::do_oop_nv(T* p) {
ysr@1280 54 T heap_oop = oopDesc::load_heap_oop(p);
ysr@1280 55 if (!oopDesc::is_null(heap_oop)) {
ysr@1280 56 HeapWord* obj_hw = (HeapWord*)oopDesc::decode_heap_oop_not_null(heap_oop);
ysr@1280 57 if (obj_hw < _r_bottom || obj_hw >= _r_end) {
ysr@1280 58 _oc->do_oop(p);
ysr@1280 59 }
ysr@777 60 }
ysr@777 61 }
ysr@777 62
ysr@1280 63 // This closure is applied to the fields of the objects that have just been copied.
tonyp@3464 64 template <class T>
tonyp@3464 65 inline void G1ParScanClosure::do_oop_nv(T* p) {
ysr@1280 66 T heap_oop = oopDesc::load_heap_oop(p);
ysr@1280 67
ysr@1280 68 if (!oopDesc::is_null(heap_oop)) {
ysr@1280 69 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
tschatzl@7010 70 G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj);
tschatzl@7010 71 if (state == G1CollectedHeap::InCSet) {
ysr@1280 72 // We're not going to even bother checking whether the object is
ysr@1280 73 // already forwarded or not, as this usually causes an immediate
ysr@1280 74 // stall. We'll try to prefetch the object (for write, given that
ysr@1280 75 // we might need to install the forwarding reference) and we'll
ysr@1280 76 // get back to it when pop it from the queue
ysr@1280 77 Prefetch::write(obj->mark_addr(), 0);
ysr@1280 78 Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
ysr@1280 79
ysr@1280 80 // slightly paranoid test; I'm trying to catch potential
ysr@1280 81 // problems before we go into push_on_queue to know where the
ysr@1280 82 // problem is coming from
johnc@3322 83 assert((obj == oopDesc::load_decode_heap_oop(p)) ||
johnc@3322 84 (obj->is_forwarded() &&
johnc@3322 85 obj->forwardee() == oopDesc::load_decode_heap_oop(p)),
johnc@3322 86 "p should still be pointing to obj or to its forwardee");
johnc@3322 87
ysr@1280 88 _par_scan_state->push_on_queue(p);
ysr@1280 89 } else {
tschatzl@7010 90 if (state == G1CollectedHeap::IsHumongous) {
tschatzl@7010 91 _g1->set_humongous_is_live(obj);
tschatzl@7010 92 }
tschatzl@6329 93 _par_scan_state->update_rs(_from, p, _worker_id);
ysr@1280 94 }
ysr@1280 95 }
ysr@777 96 }
iveresov@1696 97
tonyp@3464 98 template <class T>
tonyp@3464 99 inline void G1ParPushHeapRSClosure::do_oop_nv(T* p) {
iveresov@1696 100 T heap_oop = oopDesc::load_heap_oop(p);
iveresov@1696 101
iveresov@1696 102 if (!oopDesc::is_null(heap_oop)) {
iveresov@1696 103 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
tschatzl@7010 104 if (_g1->is_in_cset_or_humongous(obj)) {
iveresov@1696 105 Prefetch::write(obj->mark_addr(), 0);
iveresov@1696 106 Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
johnc@2060 107
johnc@2060 108 // Place on the references queue
iveresov@1696 109 _par_scan_state->push_on_queue(p);
tschatzl@7010 110 } else {
tschatzl@7010 111 assert(!_g1->obj_in_cs(obj), "checking");
iveresov@1696 112 }
iveresov@1696 113 }
iveresov@1696 114 }
johnc@2060 115
tonyp@3464 116 template <class T>
tonyp@3464 117 inline void G1CMOopClosure::do_oop_nv(T* p) {
tonyp@2968 118 oop obj = oopDesc::load_decode_heap_oop(p);
tonyp@2968 119 if (_cm->verbose_high()) {
johnc@4173 120 gclog_or_tty->print_cr("[%u] we're looking at location "
tonyp@2968 121 "*"PTR_FORMAT" = "PTR_FORMAT,
drchase@6680 122 _task->worker_id(), p2i(p), p2i((void*) obj));
tonyp@2968 123 }
tonyp@2968 124 _task->deal_with_reference(obj);
tonyp@2968 125 }
stefank@2314 126
tonyp@3464 127 template <class T>
tonyp@3464 128 inline void G1RootRegionScanClosure::do_oop_nv(T* p) {
tonyp@3464 129 T heap_oop = oopDesc::load_heap_oop(p);
tonyp@3464 130 if (!oopDesc::is_null(heap_oop)) {
tonyp@3464 131 oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
tonyp@3464 132 HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj);
brutisso@7049 133 _cm->grayRoot(obj, obj->size(), _worker_id, hr);
tonyp@3464 134 }
tonyp@3464 135 }
tonyp@3464 136
johnc@3466 137 template <class T>
johnc@3466 138 inline void G1Mux2Closure::do_oop_nv(T* p) {
johnc@3466 139 // Apply first closure; then apply the second.
johnc@3466 140 _c1->do_oop(p);
johnc@3466 141 _c2->do_oop(p);
johnc@3466 142 }
johnc@3466 143
johnc@3466 144 template <class T>
johnc@3466 145 inline void G1TriggerClosure::do_oop_nv(T* p) {
johnc@3466 146 // Record that this closure was actually applied (triggered).
johnc@3466 147 _triggered = true;
johnc@3466 148 }
johnc@3466 149
johnc@3466 150 template <class T>
johnc@3466 151 inline void G1InvokeIfNotTriggeredClosure::do_oop_nv(T* p) {
johnc@3466 152 if (!_trigger_cl->triggered()) {
johnc@3466 153 _oop_cl->do_oop(p);
johnc@3466 154 }
johnc@3466 155 }
johnc@3466 156
johnc@3466 157 template <class T>
johnc@3466 158 inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) {
johnc@3466 159 oop obj = oopDesc::load_decode_heap_oop(p);
brutisso@7049 160 if (obj == NULL) {
brutisso@7049 161 return;
brutisso@7049 162 }
johnc@3466 163 #ifdef ASSERT
johnc@3466 164 // can't do because of races
johnc@3466 165 // assert(obj == NULL || obj->is_oop(), "expected an oop");
johnc@3466 166
johnc@3466 167 // Do the safe subset of is_oop
johnc@3466 168 #ifdef CHECK_UNHANDLED_OOPS
brutisso@7049 169 oopDesc* o = obj.obj();
johnc@3466 170 #else
brutisso@7049 171 oopDesc* o = obj;
johnc@3466 172 #endif // CHECK_UNHANDLED_OOPS
brutisso@7049 173 assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
brutisso@7049 174 assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
johnc@3466 175 #endif // ASSERT
johnc@3466 176
johnc@3466 177 assert(_from != NULL, "from region must be non-NULL");
johnc@3954 178 assert(_from->is_in_reserved(p), "p is not in from");
johnc@3466 179
johnc@3466 180 HeapRegion* to = _g1->heap_region_containing(obj);
brutisso@7049 181 if (_from == to) {
brutisso@7049 182 // Normally this closure should only be called with cross-region references.
brutisso@7049 183 // But since Java threads are manipulating the references concurrently and we
brutisso@7049 184 // reload the values things may have changed.
brutisso@7049 185 return;
brutisso@7049 186 }
brutisso@7049 187 // The _record_refs_into_cset flag is true during the RSet
brutisso@7049 188 // updating part of an evacuation pause. It is false at all
brutisso@7049 189 // other times:
brutisso@7049 190 // * rebuilding the remembered sets after a full GC
brutisso@7049 191 // * during concurrent refinement.
brutisso@7049 192 // * updating the remembered sets of regions in the collection
brutisso@7049 193 // set in the event of an evacuation failure (when deferred
brutisso@7049 194 // updates are enabled).
johnc@3466 195
brutisso@7049 196 if (_record_refs_into_cset && to->in_collection_set()) {
brutisso@7049 197 // We are recording references that point into the collection
brutisso@7049 198 // set and this particular reference does exactly that...
brutisso@7049 199 // If the referenced object has already been forwarded
brutisso@7049 200 // to itself, we are handling an evacuation failure and
brutisso@7049 201 // we have already visited/tried to copy this object
brutisso@7049 202 // there is no need to retry.
brutisso@7049 203 if (!self_forwarded(obj)) {
brutisso@7049 204 assert(_push_ref_cl != NULL, "should not be null");
brutisso@7049 205 // Push the reference in the refs queue of the G1ParScanThreadState
brutisso@7049 206 // instance for this worker thread.
brutisso@7049 207 _push_ref_cl->do_oop(p);
brutisso@7049 208 }
johnc@3466 209
brutisso@7049 210 // Deferred updates to the CSet are either discarded (in the normal case),
brutisso@7049 211 // or processed (if an evacuation failure occurs) at the end
brutisso@7049 212 // of the collection.
brutisso@7049 213 // See G1RemSet::cleanup_after_oops_into_collection_set_do().
brutisso@7049 214 } else {
johnc@3954 215 // We either don't care about pushing references that point into the
johnc@3954 216 // collection set (i.e. we're not during an evacuation pause) _or_
johnc@3954 217 // the reference doesn't point into the collection set. Either way
johnc@3954 218 // we add the reference directly to the RSet of the region containing
johnc@3954 219 // the referenced object.
johnc@3954 220 assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
johnc@3954 221 to->rem_set()->add_reference(p, _worker_i);
johnc@3466 222 }
johnc@3466 223 }
johnc@3466 224
stefank@2314 225 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_INLINE_HPP

mercurial