7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
27 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
28 #include "runtime/interfaceSupport.hpp"
29
30 class UpdateRefsForOopClosure: public ExtendedOopClosure {
31
32 private:
33 ShenandoahHeap* _heap;
34 template <class T>
35 inline void do_oop_work(T* p) {
36 _heap->maybe_update_oop_ref(p);
37 }
38 public:
39 UpdateRefsForOopClosure() {
40 _heap = ShenandoahHeap::heap();
41 }
42
43 void do_oop(oop* p) {
44 do_oop_work(p);
45 }
46
47 void do_oop(narrowOop* p) {
48 do_oop_work(p);
49 }
50
51 };
52
53 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
54 BarrierSet(BarrierSet::FakeRtti(BarrierSet::ShenandoahBarrierSet)),
55 _heap(heap)
56 {
57 }
58
59 void ShenandoahBarrierSet::print_on(outputStream* st) const {
60 st->print("ShenandoahBarrierSet");
61 }
62
63 bool ShenandoahBarrierSet::is_a(BarrierSet::Name bsn) {
64 return bsn == BarrierSet::ShenandoahBarrierSet;
65 }
66
67 bool ShenandoahBarrierSet::has_read_prim_array_opt() {
68 return true;
69 }
70
71 bool ShenandoahBarrierSet::has_read_prim_barrier() {
72 return false;
143 }
144
145 void ShenandoahBarrierSet::resize_covered_region(MemRegion mr) {
146 Unimplemented();
147 }
148
149 void ShenandoahBarrierSet::write_prim_array(MemRegion mr) {
150 Unimplemented();
151 }
152
153 void ShenandoahBarrierSet::write_prim_field(HeapWord* hw, size_t s , juint x, juint y) {
154 Unimplemented();
155 }
156
157 bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
158 Unimplemented();
159 return false;
160 }
161
162 bool ShenandoahBarrierSet::need_update_refs_barrier() {
163 return _heap->concurrent_mark_in_progress() && _heap->need_update_refs();
164 }
165
166 void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
167 ShouldNotReachHere();
168 }
169
170 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
171 if (! need_update_refs_barrier()) return;
172 if (UseCompressedOops) {
173 narrowOop* dst = (narrowOop*) start;
174 for (size_t i = 0; i < count; i++, dst++) {
175 _heap->maybe_update_oop_ref(dst);
176 }
177 } else {
178 oop* dst = (oop*) start;
179 for (size_t i = 0; i < count; i++, dst++) {
180 _heap->maybe_update_oop_ref(dst);
181 }
182 }
183 }
184
185 template <class T>
186 void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, int count) {
187
188 #ifdef ASSERT
189 if (_heap->is_in(dst) &&
190 _heap->in_collection_set(dst) &&
191 ! _heap->cancelled_concgc()) {
192 tty->print_cr("dst = "PTR_FORMAT, p2i(dst));
193 _heap->heap_region_containing((HeapWord*) dst)->print();
194 assert(false, "We should have fixed this earlier");
195 }
196 #endif
197
198 if (! JavaThread::satb_mark_queue_set().is_active()) return;
199 T* elem_ptr = dst;
200 for (int i = 0; i < count; i++, elem_ptr++) {
201 T heap_oop = oopDesc::load_heap_oop(elem_ptr);
202 if (!oopDesc::is_null(heap_oop)) {
203 G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
204 }
205 }
206 }
207
208 void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
209 if (! dest_uninitialized) {
210 write_ref_array_pre_work(dst, count);
211 }
212 }
213
214 void ShenandoahBarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
215 if (! dest_uninitialized) {
216 write_ref_array_pre_work(dst, count);
217 }
218 }
219
220 template <class T>
221 void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop newVal) {
222 T heap_oop = oopDesc::load_heap_oop(field);
223
224 #ifdef ASSERT
225 ShenandoahHeap* heap = ShenandoahHeap::heap();
226 if (heap->is_in(field) &&
227 heap->in_collection_set(field) &&
228 ! heap->cancelled_concgc()) {
229 tty->print_cr("field = "PTR_FORMAT, p2i(field));
230 tty->print_cr("in_cset: %s", BOOL_TO_STR(heap->in_collection_set(field)));
231 heap->heap_region_containing((HeapWord*)field)->print();
232 tty->print_cr("marking: %s, evacuating: %s",
233 BOOL_TO_STR(heap->concurrent_mark_in_progress()),
234 BOOL_TO_STR(heap->is_evacuation_in_progress()));
235 assert(false, "We should have fixed this earlier");
236 }
237 #endif
238
239 if (!oopDesc::is_null(heap_oop)) {
240 G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop(heap_oop));
241 }
242 }
243
244 template <class T>
245 inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
246 write_ref_field_pre_static(field, newVal);
247 }
248
249 // These are the more general virtual versions.
250 void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
251 write_ref_field_pre_static(field, new_val);
252 }
253
254 void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
255 write_ref_field_pre_static(field, new_val);
256 }
257
258 void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
259 guarantee(false, "Not needed");
260 }
261
262 void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
263 #ifdef ASSERT
264 ShenandoahHeap* heap = ShenandoahHeap::heap();
265 if (!(heap->cancelled_concgc() || !heap->in_collection_set(v))) {
266 tty->print_cr("field not in collection set: "PTR_FORMAT, p2i(v));
267 tty->print_cr("containing heap region:");
268 ShenandoahHeap::heap()->heap_region_containing(v)->print();
269 }
270 assert(heap->cancelled_concgc() || !heap->in_collection_set(v), "only write to to-space");
271 if (! need_update_refs_barrier()) return;
272 assert(o == NULL || oopDesc::unsafe_equals(o, resolve_oop_static(o)), "only write to-space values");
273 assert(o == NULL || !heap->in_collection_set(o), "only write to-space values");
274 #endif
275 }
276
277 void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
278
279 if (! need_update_refs_barrier()) return;
280
281 // This is called for cloning an object (see jvm.cpp) after the clone
282 // has been made. We are not interested in any 'previous value' because
283 // it would be NULL in any case. But we *are* interested in any oop*
284 // that potentially need to be updated.
285
286 oop obj = oop(mr.start());
287 assert(obj->is_oop(), "must be an oop");
288 UpdateRefsForOopClosure cl;
289 obj->oop_iterate(&cl);
290 }
291
292 oop ShenandoahBarrierSet::read_barrier(oop src) {
293 if (ShenandoahReadBarrier) {
294 return ShenandoahBarrierSet::resolve_oop_static(src);
295 } else {
296 return src;
297 }
298 }
299
300 bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
301 bool eq = oopDesc::unsafe_equals(obj1, obj2);
302 if (! eq && ShenandoahAcmpBarrier) {
303 OrderAccess::loadload();
304 obj1 = resolve_oop_static(obj1);
305 obj2 = resolve_oop_static(obj2);
306 eq = oopDesc::unsafe_equals(obj1, obj2);
307 }
308 return eq;
309 }
|
7 *
8 * This code is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
11 * version 2 for more details (a copy is included in the LICENSE file that
12 * accompanied this code).
13 *
14 * You should have received a copy of the GNU General Public License version
15 * 2 along with this work; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19 * or visit www.oracle.com if you need additional information or have any
20 * questions.
21 *
22 */
23
24 #include "precompiled.hpp"
25 #include "gc/g1/g1SATBCardTableModRefBS.hpp"
26 #include "gc/shenandoah/shenandoahBarrierSet.hpp"
27 #include "gc/shenandoah/shenandoahConnectionMatrix.hpp"
28 #include "gc/shenandoah/shenandoahHeap.inline.hpp"
29 #include "runtime/interfaceSupport.hpp"
30
31 class UpdateRefsForOopClosure: public ExtendedOopClosure {
32
33 private:
34 ShenandoahHeap* _heap;
35 template <class T>
36 inline void do_oop_work(T* p) {
37 _heap->maybe_update_oop_ref(p);
38 }
39 public:
40 UpdateRefsForOopClosure() {
41 _heap = ShenandoahHeap::heap();
42 }
43
44 void do_oop(oop* p) {
45 do_oop_work(p);
46 }
47
48 void do_oop(narrowOop* p) {
49 do_oop_work(p);
50 }
51
52 };
53
54 class UpdateRefsForOopMatrixClosure: public ExtendedOopClosure {
55
56 private:
57 ShenandoahHeap* _heap;
58 template <class T>
59 inline void do_oop_work(T* p) {
60 oop o = _heap->maybe_update_oop_ref(p);
61 if (! oopDesc::is_null(o)) {
62 _heap->connection_matrix()->set_connected(_heap->heap_region_index_containing(p), _heap->heap_region_index_containing(o), true);
63 }
64 }
65 public:
66 UpdateRefsForOopMatrixClosure() {
67 _heap = ShenandoahHeap::heap();
68 }
69
70 void do_oop(oop* p) {
71 do_oop_work(p);
72 }
73
74 void do_oop(narrowOop* p) {
75 do_oop_work(p);
76 }
77
78 };
79
80 ShenandoahBarrierSet::ShenandoahBarrierSet(ShenandoahHeap* heap) :
81 BarrierSet(BarrierSet::FakeRtti(BarrierSet::ShenandoahBarrierSet)),
82 _heap(heap)
83 {
84 }
85
86 void ShenandoahBarrierSet::print_on(outputStream* st) const {
87 st->print("ShenandoahBarrierSet");
88 }
89
90 bool ShenandoahBarrierSet::is_a(BarrierSet::Name bsn) {
91 return bsn == BarrierSet::ShenandoahBarrierSet;
92 }
93
94 bool ShenandoahBarrierSet::has_read_prim_array_opt() {
95 return true;
96 }
97
98 bool ShenandoahBarrierSet::has_read_prim_barrier() {
99 return false;
170 }
171
172 void ShenandoahBarrierSet::resize_covered_region(MemRegion mr) {
173 Unimplemented();
174 }
175
176 void ShenandoahBarrierSet::write_prim_array(MemRegion mr) {
177 Unimplemented();
178 }
179
180 void ShenandoahBarrierSet::write_prim_field(HeapWord* hw, size_t s , juint x, juint y) {
181 Unimplemented();
182 }
183
184 bool ShenandoahBarrierSet::write_prim_needs_barrier(HeapWord* hw, size_t s, juint x, juint y) {
185 Unimplemented();
186 return false;
187 }
188
189 bool ShenandoahBarrierSet::need_update_refs_barrier() {
190 return UseShenandoahMatrix || (_heap->concurrent_mark_in_progress() && _heap->need_update_refs());
191 }
192
193 void ShenandoahBarrierSet::write_ref_array_work(MemRegion r) {
194 ShouldNotReachHere();
195 }
196
197 void ShenandoahBarrierSet::write_ref_array(HeapWord* start, size_t count) {
198 if (! need_update_refs_barrier()) return;
199 ShenandoahHeap* heap = ShenandoahHeap::heap();
200 ShenandoahConnectionMatrix* matrix = heap->connection_matrix();
201 // TODO: Use templated loop and split on oop/narrowOop and UseShenandoahMatrix.
202 if (UseCompressedOops) {
203 narrowOop* dst = (narrowOop*) start;
204 for (size_t i = 0; i < count; i++, dst++) {
205 oop o = _heap->maybe_update_oop_ref(dst);
206 if (UseShenandoahMatrix && ! oopDesc::is_null(o)) {
207 matrix->set_connected(heap->heap_region_index_containing(dst), heap->heap_region_index_containing(o), true);
208 }
209 }
210 } else {
211 oop* dst = (oop*) start;
212 for (size_t i = 0; i < count; i++, dst++) {
213 oop o = _heap->maybe_update_oop_ref(dst);
214 if (UseShenandoahMatrix && ! oopDesc::is_null(o)) {
215 matrix->set_connected(heap->heap_region_index_containing(dst), heap->heap_region_index_containing(o), true);
216 }
217 }
218 }
219 }
220
221 template <class T>
222 void ShenandoahBarrierSet::write_ref_array_pre_work(T* dst, int count) {
223
224 #ifdef ASSERT
225 if (_heap->is_in(dst) &&
226 _heap->in_collection_set(dst) &&
227 ! _heap->cancelled_concgc()) {
228 tty->print_cr("dst = "PTR_FORMAT, p2i(dst));
229 _heap->heap_region_containing((HeapWord*) dst)->print();
230 assert(false, "We should have fixed this earlier");
231 }
232 #endif
233
234 if (! JavaThread::satb_mark_queue_set().is_active()) return;
235 T* elem_ptr = dst;
236 for (int i = 0; i < count; i++, elem_ptr++) {
237 T heap_oop = oopDesc::load_heap_oop(elem_ptr);
238 if (!oopDesc::is_null(heap_oop)) {
239 G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop_not_null(heap_oop));
240 }
241 }
242 }
243
244 void ShenandoahBarrierSet::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
245 if (! dest_uninitialized) {
246 write_ref_array_pre_work(dst, count);
247 }
248 }
249
250 void ShenandoahBarrierSet::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
251 if (! dest_uninitialized) {
252 write_ref_array_pre_work(dst, count);
253 }
254 }
255
256 template <class T>
257 void ShenandoahBarrierSet::write_ref_field_pre_static(T* field, oop new_val) {
258 T heap_oop = oopDesc::load_heap_oop(field);
259
260 #ifdef ASSERT
261 {
262 ShenandoahHeap* heap = ShenandoahHeap::heap();
263 if (heap->is_in(field) &&
264 heap->in_collection_set(field) &&
265 ! heap->cancelled_concgc()) {
266 tty->print_cr("field = "PTR_FORMAT, p2i(field));
267 tty->print_cr("in_cset: %s", BOOL_TO_STR(heap->in_collection_set(field)));
268 heap->heap_region_containing((HeapWord*)field)->print();
269 tty->print_cr("marking: %s, evacuating: %s",
270 BOOL_TO_STR(heap->concurrent_mark_in_progress()),
271 BOOL_TO_STR(heap->is_evacuation_in_progress()));
272 assert(false, "We should have fixed this earlier");
273 }
274 }
275 #endif
276
277 if (!oopDesc::is_null(heap_oop)) {
278 G1SATBCardTableModRefBS::enqueue(oopDesc::decode_heap_oop(heap_oop));
279 }
280 if (UseShenandoahMatrix && ! oopDesc::is_null(new_val)) {
281 ShenandoahHeap* heap = ShenandoahHeap::heap();
282 ShenandoahConnectionMatrix* matrix = heap->connection_matrix();
283 matrix->set_connected(heap->heap_region_index_containing(field), heap->heap_region_index_containing(new_val), true);
284 }
285 }
286
287 template <class T>
288 inline void ShenandoahBarrierSet::inline_write_ref_field_pre(T* field, oop newVal) {
289 write_ref_field_pre_static(field, newVal);
290 }
291
292 // These are the more general virtual versions.
293 void ShenandoahBarrierSet::write_ref_field_pre_work(oop* field, oop new_val) {
294 write_ref_field_pre_static(field, new_val);
295 }
296
297 void ShenandoahBarrierSet::write_ref_field_pre_work(narrowOop* field, oop new_val) {
298 write_ref_field_pre_static(field, new_val);
299 }
300
301 void ShenandoahBarrierSet::write_ref_field_pre_work(void* field, oop new_val) {
302 guarantee(false, "Not needed");
303 }
304
305 void ShenandoahBarrierSet::write_ref_field_work(void* v, oop o, bool release) {
306 #ifdef ASSERT
307 ShenandoahHeap* heap = ShenandoahHeap::heap();
308 if (!(heap->cancelled_concgc() || !heap->in_collection_set(v))) {
309 tty->print_cr("field not in collection set: "PTR_FORMAT, p2i(v));
310 tty->print_cr("containing heap region:");
311 ShenandoahHeap::heap()->heap_region_containing(v)->print();
312 }
313 assert(heap->cancelled_concgc() || !heap->in_collection_set(v), "only write to to-space");
314 if (_heap->concurrent_mark_in_progress()) {
315 assert(o == NULL || oopDesc::unsafe_equals(o, resolve_oop_static(o)), "only write to-space values");
316 assert(o == NULL || !heap->in_collection_set(o), "only write to-space values");
317 }
318 #endif
319 if (UseShenandoahMatrix && ! oopDesc::is_null(o)) {
320 ShenandoahHeap* heap = ShenandoahHeap::heap();
321 ShenandoahConnectionMatrix* matrix = heap->connection_matrix();
322 matrix->set_connected(heap->heap_region_index_containing(v), heap->heap_region_index_containing(o), true);
323 }
324 }
325
326 void ShenandoahBarrierSet::write_region_work(MemRegion mr) {
327
328 if (! need_update_refs_barrier()) return;
329
330 // This is called for cloning an object (see jvm.cpp) after the clone
331 // has been made. We are not interested in any 'previous value' because
332 // it would be NULL in any case. But we *are* interested in any oop*
333 // that potentially need to be updated.
334
335 oop obj = oop(mr.start());
336 assert(obj->is_oop(), "must be an oop");
337 if (UseShenandoahMatrix) {
338 UpdateRefsForOopMatrixClosure cl;
339 obj->oop_iterate(&cl);
340 } else {
341 UpdateRefsForOopClosure cl;
342 obj->oop_iterate(&cl);
343 }
344 }
345
346 oop ShenandoahBarrierSet::read_barrier(oop src) {
347 if (ShenandoahReadBarrier) {
348 return ShenandoahBarrierSet::resolve_oop_static(src);
349 } else {
350 return src;
351 }
352 }
353
354 bool ShenandoahBarrierSet::obj_equals(oop obj1, oop obj2) {
355 bool eq = oopDesc::unsafe_equals(obj1, obj2);
356 if (! eq && ShenandoahAcmpBarrier) {
357 OrderAccess::loadload();
358 obj1 = resolve_oop_static(obj1);
359 obj2 = resolve_oop_static(obj2);
360 eq = oopDesc::unsafe_equals(obj1, obj2);
361 }
362 return eq;
363 }
|