1 /* 2 * Copyright (c) 2015, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 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 #ifndef SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP 25 #define SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP 26 27 #include "gc/shenandoah/brooksPointer.hpp" 28 #include "gc/shenandoah/shenandoahConcurrentMark.hpp" 29 #include "memory/iterator.inline.hpp" 30 #include "oops/oop.inline.hpp" 31 #include "runtime/prefetch.inline.hpp" 32 33 void ShenandoahMarkRefsClosure::do_oop(oop* p) { 34 // We piggy-back reference updating to the marking tasks. 35 #ifdef ASSERT 36 oop* old = p; 37 #endif 38 oop obj; 39 if (_update_refs) { 40 obj = _heap->maybe_update_oop_ref(p); 41 } else { 42 obj = oopDesc::load_heap_oop(p); 43 } 44 assert(obj == ShenandoahBarrierSet::resolve_oop_static(obj), "need to-space object here"); 45 46 #ifdef ASSERT 47 if (ShenandoahTraceUpdates) { 48 if (p != old) 49 tty->print_cr("Update "PTR_FORMAT" => "PTR_FORMAT" to "PTR_FORMAT" => "PTR_FORMAT, p2i(p), p2i((HeapWord*) *p), p2i(old), p2i((HeapWord*) *old)); 50 else 51 tty->print_cr("Not updating "PTR_FORMAT" => "PTR_FORMAT" to "PTR_FORMAT" => "PTR_FORMAT, p2i(p), p2i((HeapWord*) *p), p2i(old), p2i((HeapWord*) *old)); 52 } 53 #endif 54 55 // NOTE: We used to assert the following here. This does not always work because 56 // a concurrent Java thread could change the the field after we updated it. 57 // oop obj = oopDesc::load_heap_oop(p); 58 // assert(oopDesc::bs()->resolve_oop(obj) == *p, "we just updated the referrer"); 59 // assert(obj == NULL || ! _heap->heap_region_containing(obj)->is_dirty(), "must not point to dirty region"); 60 61 // ShenandoahExtendedMarkObjsClosure cl(_heap->ref_processor(), _worker_id); 62 // ShenandoahMarkObjsClosure mocl(cl, _worker_id); 63 64 if (obj != NULL) { 65 if (_update_refs) { 66 Prefetch::write(obj, 128); 67 } else { 68 Prefetch::read(obj, 128); 69 } 70 71 #ifdef ASSERT 72 uint region_idx = _heap->heap_region_index_containing(obj); 73 ShenandoahHeapRegion* r = _heap->heap_regions()[region_idx]; 74 assert(r->bottom() < (HeapWord*) obj && r->top() > (HeapWord*) obj, "object must be in region"); 75 #endif 76 77 bool pushed = _queue->push(obj); 78 assert(pushed, "overflow queue should always succeed pushing"); 79 } 80 } 81 82 void ShenandoahMarkObjsClosure::do_object(oop obj) { 83 84 assert(obj != NULL, "expect non-null object"); 85 86 assert(obj == ShenandoahBarrierSet::resolve_oop_static_not_null(obj), "expect forwarded obj in queue"); 87 88 #ifdef ASSERT 89 if (_heap->heap_region_containing(obj)->is_in_collection_set()) { 90 tty->print_cr("trying to mark obj: "PTR_FORMAT" (%s) in dirty region: ", p2i((HeapWord*) obj), BOOL_TO_STR(_heap->is_marked_current(obj))); 91 // _heap->heap_region_containing(obj)->print(); 92 // _heap->print_heap_regions(); 93 } 94 #endif 95 assert(_heap->cancelled_concgc() 96 || ! _heap->heap_region_containing(obj)->is_in_collection_set(), 97 "we don't want to mark objects in from-space"); 98 assert(_heap->is_in(obj), "referenced objects must be in the heap. No?"); 99 if (_heap->mark_current(obj)) { 100 #ifdef ASSERT 101 if (ShenandoahTraceConcurrentMarking) { 102 tty->print_cr("marked obj: "PTR_FORMAT, p2i((HeapWord*) obj)); 103 } 104 #endif 105 106 // Calculate liveness of heap region containing object. 107 uint region_idx = _heap->heap_region_index_containing(obj); 108 #ifdef ASSERT 109 ShenandoahHeapRegion* r = _heap->heap_regions()[region_idx]; 110 assert(r->bottom() < (HeapWord*) obj && r->top() > (HeapWord*) obj, "object must be in region"); 111 #endif 112 _live_data[region_idx] += (obj->size() + BrooksPointer::BROOKS_POINTER_OBJ_SIZE) * HeapWordSize; 113 obj->oop_iterate(&_mark_refs); 114 } 115 116 #ifdef ASSERT 117 else { 118 if (ShenandoahTraceConcurrentMarking) { 119 tty->print_cr("failed to mark obj (already marked): "PTR_FORMAT, p2i((HeapWord*) obj)); 120 } 121 assert(_heap->is_marked_current(obj), "make sure object is marked"); 122 } 123 #endif 124 } 125 126 inline bool ShenandoahConcurrentMark::try_queue(SCMObjToScanQueue* q, ShenandoahMarkObjsClosure* cl) { 127 oop obj; 128 if (q->pop_local(obj)) { 129 assert(obj != NULL, "Can't mark null"); 130 cl->do_object(obj); 131 return true; 132 } else if (q->pop_overflow(obj)) { 133 cl->do_object(obj); 134 return true; 135 } else { 136 return false; 137 } 138 } 139 140 inline bool ShenandoahConcurrentMark::try_to_steal(uint worker_id, ShenandoahMarkObjsClosure* cl, int *seed) { 141 oop obj; 142 if (task_queues()->steal(worker_id, seed, obj)) { 143 cl->do_object(obj); 144 return true; 145 } else 146 return false; 147 } 148 149 inline bool ShenandoahConcurrentMark:: try_draining_an_satb_buffer(uint worker_id) { 150 return drain_one_satb_buffer(worker_id); 151 } 152 153 #endif // SHARE_VM_GC_SHENANDOAH_SHENANDOAHCONCURRENTMARK_INLINE_HPP