1 /* 2 * Copyright (c) 2001, 2017, 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 */ 24 25 #ifndef SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP 26 #define SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP 27 28 #include "gc/g1/g1CollectedHeap.inline.hpp" 29 #include "gc/g1/g1ConcurrentMark.hpp" 30 #include "gc/g1/g1ConcurrentMarkBitMap.inline.hpp" 31 #include "gc/g1/g1ConcurrentMarkObjArrayProcessor.inline.hpp" 32 #include "gc/g1/suspendibleThreadSet.hpp" 33 #include "gc/shared/taskqueue.inline.hpp" 34 #include "utilities/bitMap.inline.hpp" 35 36 inline bool G1ConcurrentMark::par_mark(oop obj) { 37 return _nextMarkBitMap->par_mark((HeapWord*)obj); 38 } 39 40 #ifndef PRODUCT 41 template<typename Fn> 42 inline void G1CMMarkStack::iterate(Fn fn) const { 43 assert_at_safepoint(true); 44 45 size_t num_chunks = 0; 46 47 TaskQueueEntryChunk* cur = _chunk_list; 48 while (cur != NULL) { 49 guarantee(num_chunks <= _chunks_in_chunk_list, "Found " SIZE_FORMAT " oop chunks which is more than there should be", num_chunks); 50 51 for (size_t i = 0; i < EntriesPerChunk; ++i) { 52 if (cur->data[i].is_null()) { 53 break; 54 } 55 fn(cur->data[i]); 56 } 57 cur = cur->next; 58 num_chunks++; 59 } 60 } 61 #endif 62 63 // It scans an object and visits its children. 64 inline void G1CMTask::scan_task_entry(G1TaskQueueEntry task_entry) { process_grey_task_entry<true>(task_entry); } 65 66 inline void G1CMTask::push(G1TaskQueueEntry task_entry) { 67 assert(task_entry.is_array_slice() || _g1h->is_in_g1_reserved(task_entry.obj()), "invariant"); 68 assert(task_entry.is_array_slice() || !_g1h->is_on_master_free_list( 69 _g1h->heap_region_containing(task_entry.obj())), "invariant"); 70 assert(task_entry.is_array_slice() || !_g1h->is_obj_ill(task_entry.obj()), "invariant"); // FIXME!!! 71 assert(task_entry.is_array_slice() || _nextMarkBitMap->is_marked((HeapWord*)task_entry.obj()), "invariant"); 72 73 if (!_task_queue->push(task_entry)) { 74 // The local task queue looks full. We need to push some entries 75 // to the global stack. 76 move_entries_to_global_stack(); 77 78 // this should succeed since, even if we overflow the global 79 // stack, we should have definitely removed some entries from the 80 // local queue. So, there must be space on it. 81 bool success = _task_queue->push(task_entry); 82 assert(success, "invariant"); 83 } 84 } 85 86 inline bool G1CMTask::is_below_finger(oop obj, HeapWord* global_finger) const { 87 // If obj is above the global finger, then the mark bitmap scan 88 // will find it later, and no push is needed. Similarly, if we have 89 // a current region and obj is between the local finger and the 90 // end of the current region, then no push is needed. The tradeoff 91 // of checking both vs only checking the global finger is that the 92 // local check will be more accurate and so result in fewer pushes, 93 // but may also be a little slower. 94 HeapWord* objAddr = (HeapWord*)obj; 95 if (_finger != NULL) { 96 // We have a current region. 97 98 // Finger and region values are all NULL or all non-NULL. We 99 // use _finger to check since we immediately use its value. 100 assert(_curr_region != NULL, "invariant"); 101 assert(_region_limit != NULL, "invariant"); 102 assert(_region_limit <= global_finger, "invariant"); 103 104 // True if obj is less than the local finger, or is between 105 // the region limit and the global finger. 106 if (objAddr < _finger) { 107 return true; 108 } else if (objAddr < _region_limit) { 109 return false; 110 } // Else check global finger. 111 } 112 // Check global finger. 113 return objAddr < global_finger; 114 } 115 116 template<bool scan> 117 inline void G1CMTask::process_grey_task_entry(G1TaskQueueEntry task_entry) { 118 assert(scan || (task_entry.is_oop() && task_entry.obj()->is_typeArray()), "Skipping scan of grey non-typeArray"); 119 assert(task_entry.is_array_slice() || _nextMarkBitMap->is_marked((HeapWord*)task_entry.obj()), 120 "Any stolen object should be a slice or marked"); 121 122 if (scan) { 123 if (task_entry.is_array_slice()) { 124 _words_scanned += _objArray_processor.process_slice(task_entry.slice()); 125 } else { 126 oop obj = task_entry.obj(); 127 if (G1CMObjArrayProcessor::should_be_sliced(obj)) { 128 _words_scanned += _objArray_processor.process_obj(obj); 129 } else { 130 _words_scanned += obj->oop_iterate_size(_cm_oop_closure);; 131 } 132 } 133 } 134 check_limits(); 135 } 136 137 inline size_t G1CMTask::scan_objArray(objArrayOop obj, MemRegion mr) { 138 obj->oop_iterate(_cm_oop_closure, mr); 139 return mr.word_size(); 140 } 141 142 inline void G1CMTask::make_reference_grey(oop obj) { 143 if (_cm->par_mark(obj)) { 144 // No OrderAccess:store_load() is needed. It is implicit in the 145 // CAS done in G1CMBitMap::parMark() call in the routine above. 146 HeapWord* global_finger = _cm->finger(); 147 148 // We only need to push a newly grey object on the mark 149 // stack if it is in a section of memory the mark bitmap 150 // scan has already examined. Mark bitmap scanning 151 // maintains progress "fingers" for determining that. 152 // 153 // Notice that the global finger might be moving forward 154 // concurrently. This is not a problem. In the worst case, we 155 // mark the object while it is above the global finger and, by 156 // the time we read the global finger, it has moved forward 157 // past this object. In this case, the object will probably 158 // be visited when a task is scanning the region and will also 159 // be pushed on the stack. So, some duplicate work, but no 160 // correctness problems. 161 if (is_below_finger(obj, global_finger)) { 162 G1TaskQueueEntry entry = G1TaskQueueEntry::from_oop(obj); 163 if (obj->is_typeArray()) { 164 // Immediately process arrays of primitive types, rather 165 // than pushing on the mark stack. This keeps us from 166 // adding humongous objects to the mark stack that might 167 // be reclaimed before the entry is processed - see 168 // selection of candidates for eager reclaim of humongous 169 // objects. The cost of the additional type test is 170 // mitigated by avoiding a trip through the mark stack, 171 // by only doing a bookkeeping update and avoiding the 172 // actual scan of the object - a typeArray contains no 173 // references, and the metadata is built-in. 174 process_grey_task_entry<false>(entry); 175 } else { 176 push(entry); 177 } 178 } 179 } 180 } 181 182 inline void G1CMTask::deal_with_reference(oop obj) { 183 increment_refs_reached(); 184 185 HeapWord* objAddr = (HeapWord*) obj; 186 assert(obj->is_oop_or_null(true /* ignore mark word */), "Expected an oop or NULL at " PTR_FORMAT, p2i(obj)); 187 if (_g1h->is_in_g1_reserved(objAddr)) { 188 assert(obj != NULL, "null check is implicit"); 189 if (!_nextMarkBitMap->is_marked(objAddr)) { 190 // Only get the containing region if the object is not marked on the 191 // bitmap (otherwise, it's a waste of time since we won't do 192 // anything with it). 193 HeapRegion* hr = _g1h->heap_region_containing(obj); 194 if (!hr->obj_allocated_since_next_marking(obj)) { 195 make_reference_grey(obj); 196 } 197 } 198 } 199 } 200 201 inline void G1ConcurrentMark::markPrev(oop p) { 202 assert(!_prevMarkBitMap->is_marked((HeapWord*) p), "sanity"); 203 _prevMarkBitMap->mark((HeapWord*) p); 204 } 205 206 bool G1ConcurrentMark::isPrevMarked(oop p) const { 207 assert(p != NULL && p->is_oop(), "expected an oop"); 208 return _prevMarkBitMap->is_marked((HeapWord*)p); 209 } 210 211 inline void G1ConcurrentMark::grayRoot(oop obj, HeapRegion* hr) { 212 assert(obj != NULL, "pre-condition"); 213 HeapWord* addr = (HeapWord*) obj; 214 if (hr == NULL) { 215 hr = _g1h->heap_region_containing(addr); 216 } else { 217 assert(hr->is_in(addr), "pre-condition"); 218 } 219 assert(hr != NULL, "sanity"); 220 // Given that we're looking for a region that contains an object 221 // header it's impossible to get back a HC region. 222 assert(!hr->is_continues_humongous(), "sanity"); 223 224 if (addr < hr->next_top_at_mark_start()) { 225 if (!_nextMarkBitMap->is_marked(addr)) { 226 par_mark(obj); 227 } 228 } 229 } 230 231 inline bool G1ConcurrentMark::do_yield_check() { 232 if (SuspendibleThreadSet::should_yield()) { 233 SuspendibleThreadSet::yield(); 234 return true; 235 } else { 236 return false; 237 } 238 } 239 240 #endif // SHARE_VM_GC_G1_G1CONCURRENTMARK_INLINE_HPP