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